fx.GPUSimulationTextureSizeY

fx.GPUSimulationTextureSizeY

#Overview

name: fx.GPUSimulationTextureSizeY

The value of this variable can be defined or overridden in .ini config files. 1 .ini config file referencing this setting variable.

This variable is created as a Console Variable (cvar).

It is referenced in 11 C++ source files.

#Summary

#Usage in the C++ source code

The purpose of fx.GPUSimulationTextureSizeY is to define the Y dimension of the GPU particle simulation texture. This setting is crucial for the particle system in Unreal Engine 5, specifically for GPU-based particle simulations.

The Unreal Engine subsystem that relies on this setting variable is primarily the particle system, particularly the GPU-based particle simulation component. This can be seen from the file name ParticleGpuSimulation.cpp where most of the references are located.

The value of this variable is set through a console variable (CVar) system. It’s initialized with a default value of 1024 and can be modified through project renderer settings or potentially overridden by device profiles.

This variable interacts closely with several other variables:

  1. GParticleSimulationTextureSizeX: The X dimension of the simulation texture.
  2. GParticleSimulationDynTextureSizeXY: Used when dynamic allocation is allowed.
  3. GParticleSimulationTileSize: Defines the size of individual tiles within the simulation texture.

Developers must be aware of several important aspects when using this variable:

  1. The value must be a power of two, as checked in the code.
  2. It must be greater than or equal to GParticleSimulationTileSize.
  3. It affects the maximum number of particles that can be simulated.
  4. Changing this value impacts memory usage and potentially performance.

Best practices when using this variable include:

  1. Carefully consider the balance between performance and the number of particles needed.
  2. Ensure the value is appropriate for the target hardware, especially for mobile platforms.
  3. Test thoroughly after changing the value to ensure it doesn’t negatively impact performance or visual quality.
  4. Consider using dynamic allocation (GFXCascadeGpuSpriteAllowDynAllocs) for more flexible resource management.

Regarding the associated variable GParticleSimulationTextureSizeY: This is the C++ variable that directly corresponds to the console variable fx.GPUSimulationTextureSizeY. It’s used throughout the code to actually implement the functionality controlled by the setting. The same considerations and best practices apply to this variable as well. Developers should be aware that modifying fx.GPUSimulationTextureSizeY through the console or settings will directly affect GParticleSimulationTextureSizeY in the code.

#Setting Variables

#References In INI files

Location: <Workspace>/Projects/Lyra/Config/DefaultDeviceProfiles.ini:38, section: [Mobile DeviceProfile]

#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:64

Scope: file

Source code excerpt:

int32 GParticleSimulationTextureSizeY = 1024;
FAutoConsoleVariableRef CVarParticleSimulationSizeY(
	TEXT("fx.GPUSimulationTextureSizeY"),
	GParticleSimulationTextureSizeY,
	TEXT("GPU Particle simulation texture Y dimension (default=1024); set in project renderer settings, potentially overridden by device profile."),
	ECVF_ReadOnly
);

static bool GFXCascadeGpuSpriteRenderingEnabled = true;

#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/Particles/ParticleGpuSimulation.cpp:532

Scope (from outer to inner):

file
class        class FParticleSimulationResources
function     void Init

Source code excerpt:

		
		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 GParticleSimulationTextureSizeY. They share the same value. See the following C++ source code.

#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/Particles/ParticleGpuSimulation.cpp:62

Scope: file

Source code excerpt:

);

int32 GParticleSimulationTextureSizeY = 1024;
FAutoConsoleVariableRef CVarParticleSimulationSizeY(
	TEXT("fx.GPUSimulationTextureSizeY"),
	GParticleSimulationTextureSizeY,
	TEXT("GPU Particle simulation texture Y dimension (default=1024); set in project renderer settings, potentially overridden by device profile."),
	ECVF_ReadOnly
);

static bool GFXCascadeGpuSpriteRenderingEnabled = true;
static FAutoConsoleVariableRef CVarFXCascadeGpuSpriteRenderingEnabled(

#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/Particles/ParticleGpuSimulation.cpp:186

Scope (from outer to inner):

file
class        class FParticleTileAllocator
function     bool Resize

Source code excerpt:

		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)
		if(ResizedTileCount <= MaxTileCount && ResizedTileCount <= MaxMortonIndex)
		{ 
			FreeTiles.AddUninitialized(ResizedTileCount - OldTileCount);

			for (uint32 TileIndex = 0; TileIndex < (ResizedTileCount - OldTileCount); ++TileIndex)

#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/Particles/ParticleGpuSimulation.cpp:529

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:542

Scope (from outer to inner):

file
class        class FParticleSimulationResources
function     void Init

Source code excerpt:


		// Compute max tile count resizing (only valid when bAllowTileResizing == true)
		uint32 MaxParticleSimulationTileCount = GParticleSimulationTextureSizeX / GParticleSimulationTileSize * GParticleSimulationTextureSizeY / GParticleSimulationTileSize;

		// check if we support tile resizing for this particle simulation resources
		TileAllocator.Init(bAllowTileResizing, ParticleSimulationTileCount, MaxParticleSimulationTileCount);

		// Help debugging by identifying each state :
		StateTextures[0].ParticleStateIndex = 0;

#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/Particles/ParticleGpuSimulation.cpp:2145

Scope (from outer to inner):

file
function     static void BuildParticleVertexBuffer

Source code excerpt:

	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:4057

Scope (from outer to inner):

file
class        class FGPUSpriteParticleEmitterInstance : public FParticleEmitterInstance
function     int32 AllocateTilesForParticles

Source code excerpt:

		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();
}

#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/Particles/ParticleSimulationGPU.h:14

Scope: file

Source code excerpt:

/** The texture size allocated for GPU simulation. */
extern int32 GParticleSimulationTextureSizeX;
extern int32 GParticleSimulationTextureSizeY;

/** The tile size. Texture space is allocated in TileSize x TileSize units. */
extern const int32 GParticleSimulationTileSize;
extern const int32 GParticlesPerTile;

#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/Particles/ParticleSortingGPU.cpp:51

Scope (from outer to inner):

file
class        class FParticleSortKeyGenCS : public FGlobalShader
function     static void ModifyCompilationEnvironment

Source code excerpt:

		OutEnvironment.SetDefine( TEXT("THREAD_COUNT"), PARTICLE_KEY_GEN_THREAD_COUNT );
		OutEnvironment.SetDefine( TEXT("TEXTURE_SIZE_X"), GParticleSimulationTextureSizeX );
		OutEnvironment.SetDefine( TEXT("TEXTURE_SIZE_Y"), GParticleSimulationTextureSizeY );
	}

	static bool ShouldCompilePermutation(const FGlobalShaderPermutationParameters& Parameters)
	{
		// this shader writes to a 2 component RWBuffer, which is not supported in GLES
		return !IsMobilePlatform(Parameters.Platform);