We use a Deferred Decal material on many of our assets, including as a substitute to the Decal Component.
When using the ISM Runtime Cell Transformer, we found a lot of flickering. We discovered this was due to having static mesh and instanced static mesh components in frame using the same decal material instance.
Video and sample project are attached.
OBSERVATIONS:
- Flickering occurs whenever an ISM component and a SM component of the same deferred decal Material Instance are both within frustum
- Only the SM component will flicker
- This can be observed in editor, PIE and package
- The issue can be introduced by ISM transformer, or by manually creating ISMs
- Fast geometry appears not to impact this behaviour (flickering is neither introduced nor resolved by it)
Steps to Reproduce
(I have provided a Repro Project you can use)
Project setup: substrate disabled, fast geometry plugin enabled and prerequisites met
NOTE: these steps may not be necessary but they better match our own project
Create a Material using Deferred Decal
Place several Shape > Cube actors into the scene and set their material to the above
Use Actor > Merge Actors > Batch to convert some of them to ISM
Observe flickering on the ones you have not merged, whenever the ISM is also within frustum
In the repro project provided, I extend the steps to investigate ISM and Fast Geo Runtime Cell Transformers, and how they contribute to this problem by converting things to ISM (but are more complex steps to achieve the same as above)
This is an issue with cached mesh draw commands (r.MeshDrawCommands.UseCachedCommands). If you want to workaround the issue without a code change you can set a Translucent Sort Priority on the Static Meshes so they aren’t the same as the ISMs. Using r.MeshDrawCommands.UseCachedCommands=0 will also fix it but at the cost of performance.
It’s likely we just need to update the logic in InstanceCullingContext.cpp
...
void FInstanceCullingContext::SetupDrawCommands(
{
...
// Used to detect when we change between direct and indirect draws and break auto instancing there. ...
bool bPrevUseIndirectDraw = false;
+++ bool bPrevFetchInstanceCountFromScene = false;
...
const bool bChangedFromDirectToIndirect = !bPrevUseIndirectDraw && bUseIndirectDraw;
+++const bool bChangedInstanceCountSource =
bPrevFetchInstanceCountFromScene != bFetchInstanceCountFromScene;
bPrevUseIndirectDraw = bUseIndirectDraw;
+++bPrevFetchInstanceCountFromScene = bFetchInstanceCountFromScene;
...
---if (bCompactIdenticalCommands && CurrentStateBucketId != -1 && bMeshDrawCommandMatch && !bChangedFromDirectToIndirect)
+++if (bCompactIdenticalCommands && CurrentStateBucketId != -1 && bMeshDrawCommandMatch && !bChangedFromDirectToIndirect && !bChangedInstanceCountSource)
Hi Alex, I’ve implemented your change on behalf of Mike. Looks like it’s working correctly for us in PIE. We’ll let you know if it solves the issue in builds shortly.