Optimize Global SDF cascades updates intervals (max 1 cascade per frame)
This commit is contained in:
@@ -489,6 +489,95 @@ int32 RenderTools::ComputeSkinnedModelLOD(const SkinnedModel* model, const Float
|
||||
return 0;
|
||||
}
|
||||
|
||||
void RenderTools::ComputeCascadeUpdateFrequency(int32 cascadeIndex, int32 cascadeCount, int32& updateFrequency, int32& updatePhrase, int32 updateMaxCountPerFrame)
|
||||
{
|
||||
switch (updateMaxCountPerFrame)
|
||||
{
|
||||
case 1: // 1 cascade update per frame
|
||||
switch (cascadeIndex)
|
||||
{
|
||||
case 0: // Cascade 0
|
||||
updateFrequency = 2;
|
||||
updatePhrase = 0;
|
||||
break;
|
||||
case 1: // Cascade 1
|
||||
updateFrequency = 4;
|
||||
updatePhrase = 1;
|
||||
break;
|
||||
case 2: // Cascade 2
|
||||
updateFrequency = 8;
|
||||
updatePhrase = 3;
|
||||
break;
|
||||
default:
|
||||
if (cascadeCount > 4)
|
||||
{
|
||||
if (cascadeIndex == 3)
|
||||
{
|
||||
// Cascade 3
|
||||
updateFrequency = 16;
|
||||
updatePhrase = 7;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Other
|
||||
updateFrequency = 16;
|
||||
updatePhrase = 15;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Cascade 3
|
||||
updateFrequency = 8;
|
||||
updatePhrase = 7;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 2: // 2 cascade2 update per frame
|
||||
switch (cascadeIndex)
|
||||
{
|
||||
case 0: // Cascade 0
|
||||
updateFrequency = 1;
|
||||
updatePhrase = 0;
|
||||
break;
|
||||
case 1: // Cascade 1
|
||||
updateFrequency = 2;
|
||||
updatePhrase = 0;
|
||||
break;
|
||||
case 2: // Cascade 2
|
||||
updateFrequency = 4;
|
||||
updatePhrase = 1;
|
||||
break;
|
||||
default:
|
||||
if (cascadeCount > 4)
|
||||
{
|
||||
if (cascadeIndex == 3)
|
||||
{
|
||||
// Cascade 3
|
||||
updateFrequency = 8;
|
||||
updatePhrase = 3;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Other
|
||||
updateFrequency = 8;
|
||||
updatePhrase = 7;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Cascade 3
|
||||
updateFrequency = 4;
|
||||
updatePhrase = 3;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default: // Every frame
|
||||
updateFrequency = 1;
|
||||
updatePhrase = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int32 MipLevelsCount(int32 width, bool useMipLevels)
|
||||
{
|
||||
if (!useMipLevels)
|
||||
|
||||
@@ -108,6 +108,17 @@ public:
|
||||
const uint32 distanceI = *((uint32*)&distance);
|
||||
return ((uint32)(-(int32)(distanceI >> 31)) | 0x80000000) ^ distanceI;
|
||||
}
|
||||
|
||||
// Calculates the update frequency and phrase for the given cached data (eg. cascaded shadow map or global sdf cascade contents). Lower data indices are updated first and more frequent.
|
||||
static void ComputeCascadeUpdateFrequency(int32 cascadeIndex, int32 cascadeCount, int32& updateFrequency, int32& updatePhrase, int32 updateMaxCountPerFrame = 1);
|
||||
|
||||
// Checks if cached data should be updated during the given frame.
|
||||
FORCE_INLINE static bool ShouldUpdateCascade(int32 frameIndex, int32 cascadeIndex, int32 cascadeCount, int32 updateMaxCountPerFrame = 1, bool updateForce = false)
|
||||
{
|
||||
int32 updateFrequency, updatePhrase;
|
||||
ComputeCascadeUpdateFrequency(cascadeIndex, cascadeCount, updateFrequency, updatePhrase, updateMaxCountPerFrame);
|
||||
return (frameIndex % updateFrequency == updatePhrase) || updateForce;
|
||||
}
|
||||
};
|
||||
|
||||
// Calculate mip levels count for a texture 1D
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include "Engine/Graphics/RenderTask.h"
|
||||
#include "Engine/Graphics/RenderBuffers.h"
|
||||
#include "Engine/Graphics/RenderTargetPool.h"
|
||||
#include "Engine/Graphics/RenderTools.h"
|
||||
#include "Engine/Graphics/Shaders/GPUShader.h"
|
||||
#include "Engine/Level/Scene/SceneRendering.h"
|
||||
#include "Engine/Level/Actors/StaticModel.h"
|
||||
@@ -171,6 +172,7 @@ struct CascadeData
|
||||
class GlobalSignDistanceFieldCustomBuffer : public RenderBuffers::CustomBuffer, public ISceneRenderingListener
|
||||
{
|
||||
public:
|
||||
int32 FrameIndex = 0;
|
||||
int32 Resolution = 0;
|
||||
GPUTexture* Texture = nullptr;
|
||||
GPUTexture* TextureMip = nullptr;
|
||||
@@ -415,6 +417,7 @@ bool GlobalSignDistanceFieldPass::Render(RenderContext& renderContext, GPUContex
|
||||
{
|
||||
sdfData.Cascades.Resize(cascadesCount);
|
||||
sdfData.Resolution = resolution;
|
||||
sdfData.FrameIndex = 0;
|
||||
updated = true;
|
||||
auto desc = GPUTextureDescription::New3D(resolution * cascadesCount, resolution, resolution, GLOBAL_SDF_FORMAT, GPUTextureFlags::ShaderResource | GPUTextureFlags::UnorderedAccess, 1);
|
||||
{
|
||||
@@ -489,14 +492,16 @@ bool GlobalSignDistanceFieldPass::Render(RenderContext& renderContext, GPUContex
|
||||
auto& chunks = ChunksCache;
|
||||
chunks.EnsureCapacity(rasterizeChunks * rasterizeChunks, false);
|
||||
bool anyDraw = false;
|
||||
const uint64 cascadeFrequencies[] = { 2, 3, 5, 11 };
|
||||
//const uint64 cascadeFrequencies[] = { 1, 1, 1, 1 };
|
||||
const bool updateEveryFrame = false; // true if update all cascades every frame
|
||||
const int32 maxCascadeUpdatesPerFrame = 1; // maximum cascades to update at a single frame
|
||||
GPUTextureView* textureView = sdfData.Texture->ViewVolume();
|
||||
GPUTextureView* textureMipView = sdfData.TextureMip->ViewVolume();
|
||||
if (sdfData.FrameIndex++ > 128)
|
||||
sdfData.FrameIndex = 0;
|
||||
for (int32 cascadeIndex = 0; cascadeIndex < cascadesCount; cascadeIndex++)
|
||||
{
|
||||
// Reduce frequency of the updates
|
||||
if (useCache && (Engine::FrameCount % cascadeFrequencies[cascadeIndex]) != 0)
|
||||
if (useCache && !RenderTools::ShouldUpdateCascade(sdfData.FrameIndex, cascadeIndex, cascadesCount, maxCascadeUpdatesPerFrame, updateEveryFrame))
|
||||
continue;
|
||||
auto& cascade = sdfData.Cascades[cascadeIndex];
|
||||
const float cascadeDistance = distanceExtent * cascadesDistanceScales[cascadeIndex];
|
||||
|
||||
Reference in New Issue
Block a user