fx.GPUSimulationDynTextureSizeXY
fx.GPUSimulationDynTextureSizeXY
#Overview
name: fx.GPUSimulationDynTextureSizeXY
This variable is created as a Console Variable (cvar).
- type:
Var
- help:
GPU Particle simulation texture XY dimension when dynamic resizing is enabled (default=16)
It is referenced in 13
C++ source files.
#Summary
#Usage in the C++ source code
The purpose of fx.GPUSimulationDynTextureSizeXY is to define the GPU particle simulation texture XY dimension when dynamic resizing is enabled. This setting variable is primarily used in the particle system’s GPU simulation subsystem within Unreal Engine 5.
Key points about fx.GPUSimulationDynTextureSizeXY:
-
It is used by the particle simulation module in Unreal Engine’s rendering system.
-
The value is set through an FAutoConsoleVariableRef, which means it can be adjusted at runtime through console commands.
-
The default value is 16, and it’s marked as read-only (ECVF_ReadOnly).
-
This variable is used when dynamic resizing of particle simulation textures is enabled.
-
It interacts with other variables such as GParticleSimulationTextureSizeX and GParticleSimulationTextureSizeY, which are used when dynamic resizing is not enabled.
-
The value must be a power of two, as checked in the FParticleSimulationResources::Init() function.
-
It’s used to calculate tile sizes, texture dimensions, and scaling factors in various parts of the particle simulation code.
Best practices when using this variable:
- Ensure that the value remains a power of two to avoid assertion failures.
- Be aware that changing this value will affect the initial size of particle simulation textures when dynamic resizing is enabled.
- Consider the performance implications of adjusting this value, as it directly affects texture sizes and memory usage.
Developers should be aware that:
- This variable is used only when dynamic resizing is enabled (controlled by GFXCascadeGpuSpriteAllowDynAllocs).
- Changing this value may impact performance and memory usage of GPU particle simulations.
- The actual texture size may grow beyond this initial value if resizing occurs during runtime.
The associated variable GParticleSimulationDynTextureSizeXY is an integer that directly holds the value set by fx.GPUSimulationDynTextureSizeXY. It’s used throughout the code to access the current dynamic texture size. The same considerations and best practices apply to this variable as well.
#References in C++ code
#Callsites
This variable is referenced in the following C++ source code:
#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/Particles/ParticleGpuSimulation.cpp:80
Scope: file
Source code excerpt:
int32 GParticleSimulationDynTextureSizeXY = 16;
FAutoConsoleVariableRef CVarParticleSimulationDynTextureSizeXY(
TEXT("fx.GPUSimulationDynTextureSizeXY"),
GParticleSimulationDynTextureSizeXY,
TEXT("GPU Particle simulation texture XY dimension when dynamic resizing is enabled (default=16)"),
ECVF_ReadOnly
);
static bool GFXCascadeGpuSpriteAllowDynAllocs = false;
#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/Particles/ParticleGpuSimulation.cpp:531
Scope (from outer to inner):
file
class class FParticleSimulationResources
function void Init
Source code excerpt:
SimulationResourcesSize.Y = bAllowTileResizing ? GParticleSimulationDynTextureSizeXY : GParticleSimulationTextureSizeY;
check((SimulationResourcesSize.X & (SimulationResourcesSize.X - 1)) == 0); // fx.GPUSimulationTextureSizeX,or fx.GPUSimulationDynTextureSizeXY is not a power of two.
check((SimulationResourcesSize.Y & (SimulationResourcesSize.Y - 1)) == 0); // fx.GPUSimulationTextureSizeY,or fx.GPUSimulationDynTextureSizeXY is not a power of two.
check(GParticleSimulationTileSize <= SimulationResourcesSize.X); // Particle simulation tile size is larger than fx.GPUSimulationTextureSizeX, or fx.GPUSimulationDynTextureSizeXY.
check(GParticleSimulationTileSize <= SimulationResourcesSize.Y); // Particle simulation tile size is larger than fx.GPUSimulationTextureSizeY, or fx.GPUSimulationDynTextureSizeXY.
/** How many tiles are in the simulation textures. */
ParticleSimulationTileCountX = SimulationResourcesSize.X / GParticleSimulationTileSize;
ParticleSimulationTileCountY = SimulationResourcesSize.Y / GParticleSimulationTileSize;
ParticleSimulationTileCount = ParticleSimulationTileCountX * ParticleSimulationTileCountY;
#Associated Variable and Callsites
This variable is associated with another variable named GParticleSimulationDynTextureSizeXY
. They share the same value. See the following C++ source code.
#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/Particles/ParticleGpuSimulation.cpp:78
Scope: file
Source code excerpt:
);
int32 GParticleSimulationDynTextureSizeXY = 16;
FAutoConsoleVariableRef CVarParticleSimulationDynTextureSizeXY(
TEXT("fx.GPUSimulationDynTextureSizeXY"),
GParticleSimulationDynTextureSizeXY,
TEXT("GPU Particle simulation texture XY dimension when dynamic resizing is enabled (default=16)"),
ECVF_ReadOnly
);
static bool GFXCascadeGpuSpriteAllowDynAllocs = false;
static FAutoConsoleVariableRef CVarFXCascadeGpuSpriteDynamicAllocations(
#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/Particles/ParticleGpuSimulation.cpp:172
Scope (from outer to inner):
file
class class FParticleTileAllocator
Source code excerpt:
* Each time we resize, the associated textures width and height are multiplied by 2.
* This means that each time we increase the tile allocator, the tile count will grow
* by a 4 ^ (resizecount) factor. Ex: Initial textures is driven by GParticleSimulationDynTextureSizeXY,
* and contains one tile. The first resize will contain 4 tiles, the second resize will have 16 tiles, and so on.
* The tile allocated from a resize are allocated following a Morton Z curve pattern.
*
*/
bool Resize()
{
check(bAllowResizing);
static uint32 MaxMortonIndex = 65535;// (2 ^ 16) -1
uint32 OldTileCount = InitialTileCount * FMath::Pow(4, (float)ResizeTileAllocCount);
uint32 ResizedTileCount = OldTileCount * 4;
// 1-check to make sure we dont bust the maximum tile allocation allowed (see GParticleSimulationTextureSizeX, GParticleSimulationTextureSizeY).
// 2-check to make sure we dont bust the morton index capacity (16 bits for each X,Y coord -> 2^16 - 1) == 65535)
#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/Particles/ParticleGpuSimulation.cpp:528
Scope (from outer to inner):
file
class class FParticleSimulationResources
function void Init
Source code excerpt:
{
bool bAllowTileResizing = GFXCascadeGpuSpriteAllowDynAllocs;
SimulationResourcesSize.X = bAllowTileResizing ? GParticleSimulationDynTextureSizeXY : GParticleSimulationTextureSizeX;
SimulationResourcesSize.Y = bAllowTileResizing ? GParticleSimulationDynTextureSizeXY : GParticleSimulationTextureSizeY;
check((SimulationResourcesSize.X & (SimulationResourcesSize.X - 1)) == 0); // fx.GPUSimulationTextureSizeX,or fx.GPUSimulationDynTextureSizeXY is not a power of two.
check((SimulationResourcesSize.Y & (SimulationResourcesSize.Y - 1)) == 0); // fx.GPUSimulationTextureSizeY,or fx.GPUSimulationDynTextureSizeXY is not a power of two.
check(GParticleSimulationTileSize <= SimulationResourcesSize.X); // Particle simulation tile size is larger than fx.GPUSimulationTextureSizeX, or fx.GPUSimulationDynTextureSizeXY.
check(GParticleSimulationTileSize <= SimulationResourcesSize.Y); // Particle simulation tile size is larger than fx.GPUSimulationTextureSizeY, or fx.GPUSimulationDynTextureSizeXY.
#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/Particles/ParticleGpuSimulation.cpp:584
Scope (from outer to inner):
file
class class FParticleSimulationResources
function void Resize
Source code excerpt:
uint32 ScaleFactor = TileAllocator.GetResizeFactor();
SimulationResourcesSize.X = GParticleSimulationDynTextureSizeXY * ScaleFactor;
SimulationResourcesSize.Y = GParticleSimulationDynTextureSizeXY * ScaleFactor;
// resize position and velocity
StateTextures[0].ResizeRHI(RHICmdList, SimulationResourcesSize.X, SimulationResourcesSize.Y);
StateTextures[1].ResizeRHI(RHICmdList, SimulationResourcesSize.X, SimulationResourcesSize.Y);
// resize attributes
RenderAttributesTexture.ResizeRHI(RHICmdList, SimulationResourcesSize.X, SimulationResourcesSize.Y);
#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/Particles/ParticleGpuSimulation.cpp:1159
Scope: file
Source code excerpt:
if(ParticleSimulationResources->SupportTileResizing())
{
Result.TilePageScale.X = (float)GParticleSimulationDynTextureSizeXY / (float)ParticleSimulationResources->SimulationResourcesSize.X;
Result.TilePageScale.Y = (float)GParticleSimulationDynTextureSizeXY / (float)ParticleSimulationResources->SimulationResourcesSize.Y;
}
Result.TileOffsets = TileOffsetsRef;
return Result;
}
};
#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/Particles/ParticleGpuSimulation.cpp:1765
Scope (from outer to inner):
file
class class FParticleInjectionVS : public FGlobalShader
function void SetParameters
Source code excerpt:
if (ParticleSimulationResources->SupportTileResizing())
{
Parameters.TilePageScale.X = (float)GParticleSimulationDynTextureSizeXY / (float)ParticleSimulationResources->SimulationResourcesSize.X;
Parameters.TilePageScale.Y = (float)GParticleSimulationDynTextureSizeXY / (float)ParticleSimulationResources->SimulationResourcesSize.Y;
}
FParticleInjectionBufferRef UniformBuffer = FParticleInjectionBufferRef::CreateUniformBufferImmediate( Parameters, UniformBuffer_SingleDraw );
SetUniformBufferParameter(BatchedParameters, GetUniformBufferParameter<FParticleInjectionParameters>(), UniformBuffer );
}
};
#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/Particles/ParticleGpuSimulation.cpp:2144
Scope (from outer to inner):
file
function static void BuildParticleVertexBuffer
Source code excerpt:
float TileCountX = (float)ParticleSimulationResources->ParticleSimulationTileCountX;
float TileCountY = (float)ParticleSimulationResources->ParticleSimulationTileCountY;
float TextureSizeX = bAllowResizing ? GParticleSimulationDynTextureSizeXY: GParticleSimulationTextureSizeX;
float TextureSizeY = bAllowResizing ? GParticleSimulationDynTextureSizeXY : GParticleSimulationTextureSizeY;
for ( int32 Index = 0; Index < TileCount; ++Index )
{
// Take the mod of the tile index with the tile count of the first allocation. In case the gpu resources are resized, the
// tile coordinate will be ajusted by the TilePageIndex.
const uint32 TileIndex = InTiles[Index] % ParticleSimulationResources->ParticleSimulationTileCount;
#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/Particles/ParticleGpuSimulation.cpp:2302
Scope (from outer to inner):
file
function static FBox ComputeParticleBounds
Source code excerpt:
if (bSupportTileResizing)
{
TilePageScale.X = (float)GParticleSimulationDynTextureSizeXY / (float)ParticleSimulationResources->SimulationResourcesSize.X;
TilePageScale.Y = (float)GParticleSimulationDynTextureSizeXY / (float)ParticleSimulationResources->SimulationResourcesSize.Y;
}
Parameters.TilePageScale = TilePageScale;
SetShaderParameters(RHICmdList, ParticleBoundsCS, ParticleBoundsCS.GetComputeShader(), Parameters);
}
#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/Particles/ParticleGpuSimulation.cpp:3044
Scope (from outer to inner):
file
function virtual void GetDynamicMeshElementsEmitter
Source code excerpt:
FVector3f TilePageScale;
TilePageScale.X = SimulationResources->SupportTileResizing() ? ((float)(GParticleSimulationDynTextureSizeXY) / (float)SimulationResources->SimulationResourcesSize.X) : 1.0f;
TilePageScale.Y = SimulationResources->SupportTileResizing() ? ((float)(GParticleSimulationDynTextureSizeXY) / (float)SimulationResources->SimulationResourcesSize.Y) : 1.0f;
TilePageScale.Z = SimulationResources->SupportTileResizing() ? 1.0f : 0.0f;
VertexFactory.TilePageScale = TilePageScale;
FMeshBatch& Mesh = Collector.AllocateMesh();
FMeshBatchElement& BatchElement = Mesh.Elements[0];
BatchElement.IndexBuffer = &GParticleIndexBuffer;
#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/Particles/ParticleGpuSimulation.cpp:4056
Scope (from outer to inner):
file
class class FGPUSpriteParticleEmitterInstance : public FParticleEmitterInstance
function int32 AllocateTilesForParticles
Source code excerpt:
float TileCountX = ParticleSimulationResources->ParticleSimulationTileCountX;
float TileCountY = ParticleSimulationResources->ParticleSimulationTileCountY;
float TextureSizeX = bAllowResizing ? GParticleSimulationDynTextureSizeXY : GParticleSimulationTextureSizeX;
float TextureSizeY = bAllowResizing ? GParticleSimulationDynTextureSizeXY : GParticleSimulationTextureSizeY;
// Need to allocate space in tiles for all new particles.
FParticleSimulationResources* SimulationResources = FXSystem->GetParticleSimulationResources();
uint32 TileIndex = (AllocatedTiles.IsValidIndex(TileToAllocateFrom)) ? AllocatedTiles[TileToAllocateFrom] % ParticleSimulationResources->ParticleSimulationTileCount : INDEX_NONE;
FVector2D TileOffset(
FMath::Fractional((float)TileIndex / TileCountX),
#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/Particles/ParticleGpuSimulation.cpp:4503
Scope (from outer to inner):
file
function void FFXSystem::InitGPUSimulation
Source code excerpt:
check(ParticleSimulationResources == NULL);
ensure(GParticleSimulationTextureSizeX > 0 && GParticleSimulationTextureSizeY > 0 && GParticleSimulationDynTextureSizeXY > 0);
ParticleSimulationResources = new FParticleSimulationResources();
InitGPUResources();
}