Thanks, you’re right that running with more PSOs in memory runs a higher risk of the GPU crash related to shader compilation. The defaults are
r.PSOPrecache.KeepInMemoryGraphicsMaxNum = 2000
r.PSOPrecache.KeepInMemoryComputeMaxNum = 1000
I’m sure you’re trying to strike a good balance between number of shaders, shader complexity and quality/content so I’m assuming you’re already working on the content side optimizations but I will add a couple other thoughts.
In 5.7+ we added mode 2 for r.PSOPrecache.KeepInMemoryUntilUsed and made it the default which may be worth integrating:
CL#43263054 (c721a5) Cleanup used precached PSOs, when they are kept in memory to workaround driver cache inefficiencies.
Once a PSO is needed for rendering, the PSO precache system sets a flag that marks the precached PSO (if existing) as used, and enqueues it for cleanup if it is currently being held in memory. This is enabled with r.PSOPrecache.KeepInMemoryUntilUsed=2.
Also remove some unnecessary duplicated code now that we have compute initializers, and clearly separate the implementation for the compile task between graphics and compute. This clean up work should be a “no fuctional change” cleanup but comes with opportunities to simplify the code further down the line.
int32 GPSOPrecacheKeepInMemoryUntilUsed = 2;
static FAutoConsoleVariableRef CVarPSOPrecacheKeepInMemoryUntilUsed(
TEXT("r.PSOPrecache.KeepInMemoryUntilUsed"),
GPSOPrecacheKeepInMemoryUntilUsed,
TEXT("If enabled and if the underlying GPU vendor is NVIDIA or Qualcomm, precached PSOs will be kept in memory instead of being deleted immediately after creation, and will only be deleted once they are actually used for rendering or when the maximum limit of in-memory PSOs is reached.\n")
TEXT("This can speed up the re-creation of precached PSOs for NVIDIA and Qualcomm drivers and avoid small hitches, at the cost of memory.\n")
TEXT("It's recommended to set r.PSOPrecache.KeepInMemoryGraphicsMaxNum and r.PSOPrecache.KeepInMemoryComputeMaxNum to a non-zero value to ensure the number of in-memory PSOs is bounded.\n")
TEXT("Valid options:\n")
TEXT("0 = off (default)\n")
TEXT("1 = PSOs are kept in memory after precaching but not deleted immediately when used by the renderer. They are instead only evicted when the limit of in-memory PSOs is reached\n")
TEXT("2 = PSOs are kept in memory after precaching and deleted when used by the renderer"),
ECVF_ReadOnly);
In 5.8 we reduced number of PSOs in general in some areas with these changelists:
CL#45891754 (72f889) Add special Slate shader version that uses dynamic branching instead of static specializations. This new variant will be the only path, replacing most of the above after performance and correctness testing.
The purpose of the change is to reduce the…
CL#46233751 (f87999) Add project setting to switch Slate material shaders between fully static specializations, hybrid and fully dynamic. This allows for a balance between GPU performance and the number of shaders compiled / PSOs created.
slate.MaterialShaderMode=1
CL#47605509 (7d7454) Translucent Materials no long compile the non-skylight version of base pass pixel shader to reduce shader permutations and instead always use the skylight version w/ a dynamic branch.
CL#47744412 (2b50c5) Refactor and combine some ShadowDepth permutations to reduce permutation explosion
- Standardize and move the relevant shader logic under “SUPPORTS_XYZ” defines, and dynamic branches on ShadowDepthType
- Renaming some functions to make it clear whi…
CL#45895072 (5ea2c0) Strip Nanite vertex shader HW rasterization from certain platforms by default (reducing 50% of HW raster shader counts). Re-enable with r.Nanite.StripVertexShaders=0 and recooking
CL#48654180 (06ad62) Add a VS specific material Uniform Buffer
Use r.ShaderCompiler.UseMaterialVSUniformBuffer=0 and r.MaterialEditor.AllowSkipAlphaComputationForMaterialBlend=0 to restore the previous behaviour
CL#48668307 (0308b1) Conditionally removed Instanced Static Mesh Vertex Factory for platforms supporting full GPU-Scene (r.InstancedStaticMeshes.UseInstancedStaticMeshVertexFactory, on by default).
CL#50053320 (20a6c6) Allow for stripping Nanite mesh shaders from the build (if desired by the title)
To do this set r.Nanite.AllowMeshShaders=0
CL#49201554 (1de844) Allow shader deduplication for frequencies that access only vertex material properties.
This includes Mesh shaders, and some Nanite rasterization Compute shaders. These last ones must not use the programmable pixel path (used by masked materials and…
CL#47316522 (849b80) Add Material Instance Usage Flag overrides.Moved usage flag setter/getter functions from UMaterial to virtual on UMaterialInterface.
UMaterialInstance versions are based on the contained FMaterialInstanceBasePropertyOverrides.
Added a couple of missing EMaterialUsage entries for bUsedWithEditorCompositing and bUsedWithNeuralNetworks.
Marked bUsedWith… properties as deprecated on UMaterial since any direct access to them is a potential bug as it ignores per instance overrides. After a deprecation period we should probably convert these to a private uint32 bitmask.
Fixed up places in code that accessed these properties directly.
[Attachment Removed]