Refactor Global SDF to use a single texture for all cascades
This commit is contained in:
@@ -502,7 +502,7 @@ void MaterialParameter::Bind(BindMeta& meta) const
|
||||
GlobalSignDistanceFieldPass::BindingData bindingData;
|
||||
if (GlobalSignDistanceFieldPass::Instance()->Get(meta.Buffers, bindingData))
|
||||
Platform::MemoryClear(&bindingData, sizeof(bindingData));
|
||||
bindingData.BindCascades(meta.Context, _registerIndex);
|
||||
meta.Context->BindSR(_registerIndex, bindingData.Texture ? bindingData.Texture->ViewVolume() : nullptr);
|
||||
*((GlobalSignDistanceFieldPass::ConstantsData*)(meta.Constants.Get() + _offset)) = bindingData.Constants;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -486,8 +486,8 @@ bool DynamicDiffuseGlobalIlluminationPass::Render(RenderContext& renderContext,
|
||||
{
|
||||
PROFILE_GPU_CPU("Probes Classification");
|
||||
uint32 threadGroups = Math::DivideAndRoundUp(probesCountCascade, DDGI_PROBE_CLASSIFY_GROUP_SIZE);
|
||||
bindingDataSDF.BindCascades(context, 0);
|
||||
bindingDataSDF.BindCascadeMips(context, 4);
|
||||
context->BindSR(0, bindingDataSDF.Texture ? bindingDataSDF.Texture->ViewVolume() : nullptr);
|
||||
context->BindSR(1, bindingDataSDF.TextureMip ? bindingDataSDF.TextureMip->ViewVolume() : nullptr);
|
||||
context->BindUA(0, ddgiData.Result.ProbesState);
|
||||
for (int32 cascadeIndex = 0; cascadeIndex < cascadesCount; cascadeIndex++)
|
||||
{
|
||||
@@ -529,14 +529,14 @@ bool DynamicDiffuseGlobalIlluminationPass::Render(RenderContext& renderContext,
|
||||
|
||||
// Global SDF with Global Surface Atlas software raytracing (thread X - per probe ray, thread Y - per probe)
|
||||
ASSERT_LOW_LAYER((probeRaysCount % DDGI_TRACE_RAYS_GROUP_SIZE_X) == 0);
|
||||
bindingDataSDF.BindCascades(context, 0);
|
||||
bindingDataSDF.BindCascadeMips(context, 4);
|
||||
context->BindSR(8, bindingDataSurfaceAtlas.Chunks ? bindingDataSurfaceAtlas.Chunks->View() : nullptr);
|
||||
context->BindSR(9, bindingDataSurfaceAtlas.CulledObjects ? bindingDataSurfaceAtlas.CulledObjects->View() : nullptr);
|
||||
context->BindSR(10, bindingDataSurfaceAtlas.AtlasDepth->View());
|
||||
context->BindSR(11, bindingDataSurfaceAtlas.AtlasLighting->View());
|
||||
context->BindSR(12, ddgiData.Result.ProbesState);
|
||||
context->BindSR(13, skybox);
|
||||
context->BindSR(0, bindingDataSDF.Texture ? bindingDataSDF.Texture->ViewVolume() : nullptr);
|
||||
context->BindSR(1, bindingDataSDF.TextureMip ? bindingDataSDF.TextureMip->ViewVolume() : nullptr);
|
||||
context->BindSR(2, bindingDataSurfaceAtlas.Chunks ? bindingDataSurfaceAtlas.Chunks->View() : nullptr);
|
||||
context->BindSR(3, bindingDataSurfaceAtlas.CulledObjects ? bindingDataSurfaceAtlas.CulledObjects->View() : nullptr);
|
||||
context->BindSR(4, bindingDataSurfaceAtlas.AtlasDepth->View());
|
||||
context->BindSR(5, bindingDataSurfaceAtlas.AtlasLighting->View());
|
||||
context->BindSR(6, ddgiData.Result.ProbesState);
|
||||
context->BindSR(7, skybox);
|
||||
context->BindUA(0, ddgiData.ProbesTrace->View());
|
||||
context->Dispatch(_csTraceRays, probeRaysCount / DDGI_TRACE_RAYS_GROUP_SIZE_X, probesBatchSize, 1);
|
||||
context->ResetUA();
|
||||
|
||||
@@ -754,8 +754,8 @@ bool GlobalSurfaceAtlasPass::Render(RenderContext& renderContext, GPUContext* co
|
||||
context->BindSR(2, surfaceAtlasData.AtlasGBuffer2->View());
|
||||
context->BindSR(3, surfaceAtlasData.AtlasDepth->View());
|
||||
context->BindSR(4, _objectsBuffer->GetBuffer()->View());
|
||||
bindingDataSDF.BindCascades(context, 5);
|
||||
bindingDataSDF.BindCascadeMips(context, 9);
|
||||
context->BindSR(5, bindingDataSDF.Texture ? bindingDataSDF.Texture->ViewVolume() : nullptr);
|
||||
context->BindSR(6, bindingDataSDF.TextureMip ? bindingDataSDF.TextureMip->ViewVolume() : nullptr);
|
||||
context->BindCB(0, _cb0);
|
||||
Data0 data;
|
||||
data.ViewWorldPos = renderContext.View.Position;
|
||||
@@ -927,12 +927,12 @@ void GlobalSurfaceAtlasPass::RenderDebug(RenderContext& renderContext, GPUContex
|
||||
context->UpdateCB(_cb0, &data);
|
||||
context->BindCB(0, _cb0);
|
||||
}
|
||||
bindingDataSDF.BindCascades(context, 0);
|
||||
bindingDataSDF.BindCascadeMips(context, 4);
|
||||
context->BindSR(8, bindingData.Chunks ? bindingData.Chunks->View() : nullptr);
|
||||
context->BindSR(9, bindingData.CulledObjects ? bindingData.CulledObjects->View() : nullptr);
|
||||
context->BindSR(10, bindingData.AtlasDepth->View());
|
||||
context->BindSR(12, skybox);
|
||||
context->BindSR(0, bindingDataSDF.Texture ? bindingDataSDF.Texture->ViewVolume() : nullptr);
|
||||
context->BindSR(1, bindingDataSDF.TextureMip ? bindingDataSDF.TextureMip->ViewVolume() : nullptr);
|
||||
context->BindSR(2, bindingData.Chunks ? bindingData.Chunks->View() : nullptr);
|
||||
context->BindSR(3, bindingData.CulledObjects ? bindingData.CulledObjects->View() : nullptr);
|
||||
context->BindSR(4, bindingData.AtlasDepth->View());
|
||||
context->BindSR(6, skybox);
|
||||
context->SetState(_psDebug);
|
||||
{
|
||||
Float2 outputSizeThird = outputSize * 0.333f;
|
||||
@@ -943,7 +943,7 @@ void GlobalSurfaceAtlasPass::RenderDebug(RenderContext& renderContext, GPUContex
|
||||
context->SetRenderTarget(tempBuffer->View());
|
||||
|
||||
// Full screen - direct light
|
||||
context->BindSR(11, bindingData.AtlasLighting->View());
|
||||
context->BindSR(5, bindingData.AtlasLighting->View());
|
||||
context->SetViewport(outputSize.X, outputSize.Y);
|
||||
context->SetScissor(Rectangle(0, 0, outputSizeTwoThird.X, outputSize.Y));
|
||||
context->DrawFullscreenTriangle();
|
||||
@@ -957,12 +957,12 @@ void GlobalSurfaceAtlasPass::RenderDebug(RenderContext& renderContext, GPUContex
|
||||
context->ResetRenderTarget();
|
||||
|
||||
// Rebind resources
|
||||
bindingDataSDF.BindCascades(context, 0);
|
||||
bindingDataSDF.BindCascadeMips(context, 4);
|
||||
context->BindSR(8, bindingData.Chunks ? bindingData.Chunks->View() : nullptr);
|
||||
context->BindSR(9, bindingData.CulledObjects ? bindingData.CulledObjects->View() : nullptr);
|
||||
context->BindSR(10, bindingData.AtlasDepth->View());
|
||||
context->BindSR(12, skybox);
|
||||
context->BindSR(0, bindingDataSDF.Texture ? bindingDataSDF.Texture->ViewVolume() : nullptr);
|
||||
context->BindSR(1, bindingDataSDF.TextureMip ? bindingDataSDF.TextureMip->ViewVolume() : nullptr);
|
||||
context->BindSR(2, bindingData.Chunks ? bindingData.Chunks->View() : nullptr);
|
||||
context->BindSR(3, bindingData.CulledObjects ? bindingData.CulledObjects->View() : nullptr);
|
||||
context->BindSR(4, bindingData.AtlasDepth->View());
|
||||
context->BindSR(6, skybox);
|
||||
context->BindCB(0, _cb0);
|
||||
context->SetState(_psDebug);
|
||||
context->SetRenderTarget(output->View());
|
||||
@@ -972,17 +972,17 @@ void GlobalSurfaceAtlasPass::RenderDebug(RenderContext& renderContext, GPUContex
|
||||
context->UpdateCB(_cb0, &data);
|
||||
|
||||
// Bottom left - diffuse
|
||||
context->BindSR(11, bindingData.AtlasGBuffer0->View());
|
||||
context->BindSR(5, bindingData.AtlasGBuffer0->View());
|
||||
context->SetViewportAndScissors(Viewport(outputSizeTwoThird.X, 0, outputSizeThird.X, outputSizeThird.Y));
|
||||
context->DrawFullscreenTriangle();
|
||||
|
||||
// Bottom middle - normals
|
||||
context->BindSR(11, bindingData.AtlasGBuffer1->View());
|
||||
context->BindSR(5, bindingData.AtlasGBuffer1->View());
|
||||
context->SetViewportAndScissors(Viewport(outputSizeTwoThird.X, outputSizeThird.Y, outputSizeThird.X, outputSizeThird.Y));
|
||||
context->DrawFullscreenTriangle();
|
||||
|
||||
// Bottom right - roughness/metalness/ao
|
||||
context->BindSR(11, bindingData.AtlasGBuffer2->View());
|
||||
context->BindSR(5, bindingData.AtlasGBuffer2->View());
|
||||
context->SetViewportAndScissors(Viewport(outputSizeTwoThird.X, outputSizeTwoThird.Y, outputSizeThird.X, outputSizeThird.Y));
|
||||
context->DrawFullscreenTriangle();
|
||||
}
|
||||
|
||||
@@ -61,14 +61,18 @@ PACK_STRUCT(struct ModelsRasterizeData
|
||||
Int3 ChunkCoord;
|
||||
float MaxDistance;
|
||||
Float3 CascadeCoordToPosMul;
|
||||
int ObjectsCount;
|
||||
int32 ObjectsCount;
|
||||
Float3 CascadeCoordToPosAdd;
|
||||
int32 CascadeResolution;
|
||||
float Padding0;
|
||||
int32 CascadeIndex;
|
||||
float CascadeVoxelSize;
|
||||
int32 CascadeMipResolution;
|
||||
int32 CascadeMipFactor;
|
||||
uint32 Objects[GLOBAL_SDF_RASTERIZE_MODEL_MAX_COUNT];
|
||||
uint32 GenerateMipTexResolution;
|
||||
uint32 GenerateMipCoordScale;
|
||||
uint32 GenerateMipTexOffsetX;
|
||||
uint32 GenerateMipMipOffsetX;
|
||||
});
|
||||
|
||||
struct RasterizeModel
|
||||
@@ -125,8 +129,6 @@ uint32 GetHash(const RasterizeChunkKey& key)
|
||||
|
||||
struct CascadeData
|
||||
{
|
||||
GPUTexture* Texture = nullptr;
|
||||
GPUTexture* Mip = nullptr;
|
||||
Vector3 Position;
|
||||
float VoxelSize;
|
||||
BoundingBox Bounds;
|
||||
@@ -163,18 +165,14 @@ struct CascadeData
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
~CascadeData()
|
||||
{
|
||||
RenderTargetPool::Release(Texture);
|
||||
RenderTargetPool::Release(Mip);
|
||||
}
|
||||
};
|
||||
|
||||
class GlobalSignDistanceFieldCustomBuffer : public RenderBuffers::CustomBuffer, public ISceneRenderingListener
|
||||
{
|
||||
public:
|
||||
int32 Resolution = 0;
|
||||
GPUTexture* Texture = nullptr;
|
||||
GPUTexture* TextureMip = nullptr;
|
||||
Array<CascadeData, FixedAllocation<4>> Cascades;
|
||||
HashSet<ScriptingTypeHandle> ObjectTypes;
|
||||
HashSet<GPUTexture*> SDFTextures;
|
||||
@@ -187,6 +185,8 @@ public:
|
||||
e.Item->Deleted.Unbind<GlobalSignDistanceFieldCustomBuffer, &GlobalSignDistanceFieldCustomBuffer::OnSDFTextureDeleted>(this);
|
||||
e.Item->ResidentMipsChanged.Unbind<GlobalSignDistanceFieldCustomBuffer, &GlobalSignDistanceFieldCustomBuffer::OnSDFTextureResidentMipsChanged>(this);
|
||||
}
|
||||
RenderTargetPool::Release(Texture);
|
||||
RenderTargetPool::Release(TextureMip);
|
||||
}
|
||||
|
||||
void OnSDFTextureDeleted(ScriptingObject* object)
|
||||
@@ -300,8 +300,7 @@ bool GlobalSignDistanceFieldPass::setupResources()
|
||||
_csRasterizeModel1 = shader->GetCS("CS_RasterizeModel", 1);
|
||||
_csRasterizeHeightfield = shader->GetCS("CS_RasterizeHeightfield");
|
||||
_csClearChunk = shader->GetCS("CS_ClearChunk");
|
||||
_csGenerateMip0 = shader->GetCS("CS_GenerateMip", 0);
|
||||
_csGenerateMip1 = shader->GetCS("CS_GenerateMip", 1);
|
||||
_csGenerateMip = shader->GetCS("CS_GenerateMip");
|
||||
|
||||
// Init buffer
|
||||
if (!_objectsBuffer)
|
||||
@@ -329,8 +328,7 @@ void GlobalSignDistanceFieldPass::OnShaderReloading(Asset* obj)
|
||||
_csRasterizeModel1 = nullptr;
|
||||
_csRasterizeHeightfield = nullptr;
|
||||
_csClearChunk = nullptr;
|
||||
_csGenerateMip0 = nullptr;
|
||||
_csGenerateMip1 = nullptr;
|
||||
_csGenerateMip = nullptr;
|
||||
_cb0 = nullptr;
|
||||
_cb1 = nullptr;
|
||||
invalidateResources();
|
||||
@@ -351,18 +349,6 @@ void GlobalSignDistanceFieldPass::Dispose()
|
||||
ChunksCache.SetCapacity(0);
|
||||
}
|
||||
|
||||
void GlobalSignDistanceFieldPass::BindingData::BindCascades(GPUContext* context, int32 srvSlot)
|
||||
{
|
||||
for (int32 i = 0; i < 4; i++)
|
||||
context->BindSR(srvSlot + i, Cascades[i] ? Cascades[i]->ViewVolume() : nullptr);
|
||||
}
|
||||
|
||||
void GlobalSignDistanceFieldPass::BindingData::BindCascadeMips(GPUContext* context, int32 srvSlot)
|
||||
{
|
||||
for (int32 i = 0; i < 4; i++)
|
||||
context->BindSR(srvSlot + i, CascadeMips[i] ? CascadeMips[i]->ViewVolume() : nullptr);
|
||||
}
|
||||
|
||||
bool GlobalSignDistanceFieldPass::Get(const RenderBuffers* buffers, BindingData& result)
|
||||
{
|
||||
auto* sdfData = buffers ? buffers->FindCustomBuffer<GlobalSignDistanceFieldCustomBuffer>(TEXT("GlobalSignDistanceField")) : nullptr;
|
||||
@@ -428,14 +414,13 @@ bool GlobalSignDistanceFieldPass::Render(RenderContext& renderContext, GPUContex
|
||||
sdfData.Cascades.Resize(cascadesCount);
|
||||
sdfData.Resolution = resolution;
|
||||
updated = true;
|
||||
auto desc = GPUTextureDescription::New3D(resolution, resolution, resolution, GLOBAL_SDF_FORMAT, GPUTextureFlags::ShaderResource | GPUTextureFlags::UnorderedAccess, 1);
|
||||
for (auto& cascade : sdfData.Cascades)
|
||||
auto desc = GPUTextureDescription::New3D(resolution * cascadesCount, resolution, resolution, GLOBAL_SDF_FORMAT, GPUTextureFlags::ShaderResource | GPUTextureFlags::UnorderedAccess, 1);
|
||||
{
|
||||
GPUTexture*& texture = cascade.Texture;
|
||||
GPUTexture*& texture = sdfData.Texture;
|
||||
if (texture && texture->Width() != desc.Width)
|
||||
{
|
||||
RenderTargetPool::Release(texture);
|
||||
texture = nullptr;
|
||||
sdfData.Texture = nullptr;
|
||||
}
|
||||
if (!texture)
|
||||
{
|
||||
@@ -444,10 +429,11 @@ bool GlobalSignDistanceFieldPass::Render(RenderContext& renderContext, GPUContex
|
||||
return true;
|
||||
}
|
||||
}
|
||||
desc.Width = desc.Height = desc.Depth = resolutionMip;
|
||||
desc.Width = resolutionMip * cascadesCount;
|
||||
desc.Height = desc.Depth = resolutionMip;
|
||||
for (auto& cascade : sdfData.Cascades)
|
||||
{
|
||||
GPUTexture*& texture = cascade.Mip;
|
||||
GPUTexture*& texture = sdfData.TextureMip;
|
||||
if (texture && texture->Width() != desc.Width)
|
||||
{
|
||||
RenderTargetPool::Release(texture);
|
||||
@@ -469,10 +455,12 @@ bool GlobalSignDistanceFieldPass::Render(RenderContext& renderContext, GPUContex
|
||||
{
|
||||
cascade.NonEmptyChunks.Clear();
|
||||
cascade.StaticChunks.Clear();
|
||||
context->ClearUA(cascade.Texture, Float4::One);
|
||||
context->ClearUA(cascade.Mip, Float4::One);
|
||||
}
|
||||
LOG(Info, "Global SDF memory usage: {0} MB", (sdfData.Cascades[0].Texture->GetMemoryUsage() + sdfData.Cascades[0].Mip->GetMemoryUsage()) * ARRAY_COUNT(sdfData.Cascades) / 1024 / 1024);
|
||||
uint64 memoryUsage = sdfData.Texture->GetMemoryUsage();
|
||||
context->ClearUA(sdfData.Texture, Float4::One);
|
||||
memoryUsage += sdfData.TextureMip->GetMemoryUsage();
|
||||
context->ClearUA(sdfData.TextureMip, Float4::One);
|
||||
LOG(Info, "Global SDF memory usage: {0} MB", memoryUsage / 1024 / 1024);
|
||||
}
|
||||
for (SceneRendering* scene : renderContext.List->Scenes)
|
||||
sdfData.ListenSceneRendering(scene);
|
||||
@@ -498,6 +486,8 @@ bool GlobalSignDistanceFieldPass::Render(RenderContext& renderContext, GPUContex
|
||||
bool anyDraw = false;
|
||||
const uint64 cascadeFrequencies[] = { 2, 3, 5, 11 };
|
||||
//const uint64 cascadeFrequencies[] = { 1, 1, 1, 1 };
|
||||
GPUTextureView* textureView = sdfData.Texture->ViewVolume();
|
||||
GPUTextureView* textureMipView = sdfData.TextureMip->ViewVolume();
|
||||
for (int32 cascadeIndex = 0; cascadeIndex < cascadesCount; cascadeIndex++)
|
||||
{
|
||||
// Reduce frequency of the updates
|
||||
@@ -514,8 +504,6 @@ bool GlobalSignDistanceFieldPass::Render(RenderContext& renderContext, GPUContex
|
||||
BoundingBox cascadeBounds(center - cascadeDistance, center + cascadeDistance);
|
||||
// TODO: add scene detail scale factor to PostFx settings (eg. to increase or decrease scene details and quality)
|
||||
const float minObjectRadius = Math::Max(20.0f, cascadeVoxelSize * 0.5f); // Skip too small objects for this cascade
|
||||
GPUTextureView* cascadeView = cascade.Texture->ViewVolume();
|
||||
GPUTextureView* cascadeMipView = cascade.Mip->ViewVolume();
|
||||
|
||||
// Clear cascade before rasterization
|
||||
{
|
||||
@@ -539,6 +527,8 @@ bool GlobalSignDistanceFieldPass::Render(RenderContext& renderContext, GPUContex
|
||||
_objectsBufferCount = 0;
|
||||
_voxelSize = cascadeVoxelSize;
|
||||
_cascadeBounds = cascadeBounds;
|
||||
_cascadeBounds.Minimum += 0.1f; // Adjust to prevent overflowing chunk keys (cascade bounds are used for clamping object bounds)
|
||||
_cascadeBounds.Maximum -= 0.1f; // Adjust to prevent overflowing chunk keys (cascade bounds are used for clamping object bounds)
|
||||
_cascadeIndex = cascadeIndex;
|
||||
_sdfData = &sdfData;
|
||||
{
|
||||
@@ -560,10 +550,6 @@ bool GlobalSignDistanceFieldPass::Render(RenderContext& renderContext, GPUContex
|
||||
{
|
||||
anyDraw = true;
|
||||
context->ResetSR();
|
||||
auto desc = GPUTextureDescription::New3D(resolution, resolution, resolution, GLOBAL_SDF_FORMAT, GPUTextureFlags::ShaderResource | GPUTextureFlags::UnorderedAccess, 1);
|
||||
tmpMip = RenderTargetPool::Get(desc);
|
||||
if (!tmpMip)
|
||||
return true;
|
||||
}
|
||||
ModelsRasterizeData data;
|
||||
data.CascadeCoordToPosMul = (Float3)cascadeBounds.GetSize() / (float)resolution;
|
||||
@@ -571,9 +557,10 @@ bool GlobalSignDistanceFieldPass::Render(RenderContext& renderContext, GPUContex
|
||||
data.MaxDistance = cascadeMaxDistance;
|
||||
data.CascadeResolution = resolution;
|
||||
data.CascadeMipResolution = resolutionMip;
|
||||
data.CascadeIndex = cascadeIndex;
|
||||
data.CascadeMipFactor = GLOBAL_SDF_RASTERIZE_MIP_FACTOR;
|
||||
data.CascadeVoxelSize = cascadeVoxelSize;
|
||||
context->BindUA(0, cascadeView);
|
||||
context->BindUA(0, textureView);
|
||||
context->BindCB(1, _cb1);
|
||||
const int32 chunkDispatchGroups = GLOBAL_SDF_RASTERIZE_CHUNK_SIZE / GLOBAL_SDF_RASTERIZE_GROUP_SIZE;
|
||||
bool anyChunkDispatch = false;
|
||||
@@ -738,25 +725,55 @@ bool GlobalSignDistanceFieldPass::Render(RenderContext& renderContext, GPUContex
|
||||
if (updated || anyChunkDispatch)
|
||||
{
|
||||
PROFILE_GPU_CPU("Generate Mip");
|
||||
context->UpdateCB(_cb1, &data);
|
||||
context->ResetUA();
|
||||
context->BindSR(0, cascadeView);
|
||||
context->BindUA(0, cascadeMipView);
|
||||
const int32 mipDispatchGroups = Math::DivideAndRoundUp(resolutionMip, GLOBAL_SDF_MIP_GROUP_SIZE);
|
||||
static_assert((GLOBAL_SDF_MIP_FLOODS % 2) == 1, "Invalid Global SDF mip flood iterations count.");
|
||||
int32 floodFillIterations = chunks.Count() == 0 ? 1 : GLOBAL_SDF_MIP_FLOODS;
|
||||
context->Dispatch(_csGenerateMip0, mipDispatchGroups, mipDispatchGroups, mipDispatchGroups);
|
||||
context->UnBindSR(0);
|
||||
if (!tmpMip)
|
||||
{
|
||||
// Use temporary texture to flood fill mip
|
||||
auto desc = GPUTextureDescription::New3D(resolutionMip, resolutionMip, resolutionMip, GLOBAL_SDF_FORMAT, GPUTextureFlags::ShaderResource | GPUTextureFlags::UnorderedAccess, 1);
|
||||
tmpMip = RenderTargetPool::Get(desc);
|
||||
if (!tmpMip)
|
||||
return true;
|
||||
}
|
||||
GPUTextureView* tmpMipView = tmpMip->ViewVolume();
|
||||
|
||||
// Tex -> Mip
|
||||
// TODO: use push constants on DX12/Vulkan to provide those 4 uints to the shader
|
||||
data.GenerateMipTexResolution = data.CascadeResolution;
|
||||
data.GenerateMipCoordScale = data.CascadeMipFactor;
|
||||
data.GenerateMipTexOffsetX = data.CascadeIndex * data.CascadeResolution;
|
||||
data.GenerateMipMipOffsetX = data.CascadeIndex * data.CascadeMipResolution;
|
||||
context->UpdateCB(_cb1, &data);
|
||||
context->BindSR(0, textureView);
|
||||
context->BindUA(0, textureMipView);
|
||||
context->Dispatch(_csGenerateMip, mipDispatchGroups, mipDispatchGroups, mipDispatchGroups);
|
||||
|
||||
data.GenerateMipTexResolution = data.CascadeMipResolution;
|
||||
data.GenerateMipCoordScale = 1;
|
||||
for (int32 i = 1; i < floodFillIterations; i++)
|
||||
{
|
||||
context->ResetUA();
|
||||
context->BindSR(0, cascadeMipView);
|
||||
context->BindUA(0, tmpMipView);
|
||||
context->Dispatch(_csGenerateMip1, mipDispatchGroups, mipDispatchGroups, mipDispatchGroups);
|
||||
Swap(tmpMipView, cascadeMipView);
|
||||
if ((i & 1) == 1)
|
||||
{
|
||||
// Mip -> Tmp
|
||||
context->BindSR(0, textureMipView);
|
||||
context->BindUA(0, tmpMipView);
|
||||
data.GenerateMipTexOffsetX = data.CascadeIndex * data.CascadeMipResolution;
|
||||
data.GenerateMipMipOffsetX = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Tmp -> Mip
|
||||
context->BindSR(0, tmpMipView);
|
||||
context->BindUA(0, textureMipView);
|
||||
data.GenerateMipTexOffsetX = 0;
|
||||
data.GenerateMipMipOffsetX = data.CascadeIndex * data.CascadeMipResolution;
|
||||
}
|
||||
context->UpdateCB(_cb1, &data);
|
||||
context->Dispatch(_csGenerateMip, mipDispatchGroups, mipDispatchGroups, mipDispatchGroups);
|
||||
}
|
||||
if (floodFillIterations % 2 == 0)
|
||||
Swap(tmpMipView, cascadeMipView);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -771,26 +788,22 @@ bool GlobalSignDistanceFieldPass::Render(RenderContext& renderContext, GPUContex
|
||||
}
|
||||
|
||||
// Copy results
|
||||
static_assert(ARRAY_COUNT(result.Cascades) == ARRAY_COUNT(sdfData.Cascades), "Invalid cascades count.");
|
||||
static_assert(ARRAY_COUNT(result.CascadeMips) == ARRAY_COUNT(sdfData.Cascades), "Invalid cascades count.");
|
||||
result.Texture = sdfData.Texture;
|
||||
result.TextureMip = sdfData.TextureMip;
|
||||
for (int32 cascadeIndex = 0; cascadeIndex < cascadesCount; cascadeIndex++)
|
||||
{
|
||||
auto& cascade = sdfData.Cascades[cascadeIndex];
|
||||
const float cascadeDistance = distanceExtent * cascadesDistanceScales[cascadeIndex];
|
||||
const float cascadeMaxDistance = cascadeDistance * 2;
|
||||
const float cascadeVoxelSize = cascadeMaxDistance / resolution;
|
||||
const float cascadeVoxelSize = cascadeMaxDistance / (float)resolution;
|
||||
const Vector3 center = cascade.Position;
|
||||
result.Constants.CascadePosDistance[cascadeIndex] = Vector4(center, cascadeDistance);
|
||||
result.Constants.CascadeVoxelSize.Raw[cascadeIndex] = cascadeVoxelSize;
|
||||
result.Cascades[cascadeIndex] = cascade.Texture;
|
||||
result.CascadeMips[cascadeIndex] = cascade.Mip;
|
||||
}
|
||||
for (int32 cascadeIndex = cascadesCount; cascadeIndex < 4; cascadeIndex++)
|
||||
{
|
||||
result.Constants.CascadePosDistance[cascadeIndex] = result.Constants.CascadePosDistance[cascadesCount - 1];
|
||||
result.Constants.CascadeVoxelSize.Raw[cascadeIndex] = result.Constants.CascadeVoxelSize.Raw[cascadesCount - 1];
|
||||
result.Cascades[cascadeIndex] = nullptr;
|
||||
result.CascadeMips[cascadeIndex] = nullptr;
|
||||
}
|
||||
result.Constants.Resolution = (float)resolution;
|
||||
result.Constants.CascadesCount = cascadesCount;
|
||||
@@ -820,8 +833,8 @@ void GlobalSignDistanceFieldPass::RenderDebug(RenderContext& renderContext, GPUC
|
||||
context->UpdateCB(_cb0, &data);
|
||||
context->BindCB(0, _cb0);
|
||||
}
|
||||
bindingData.BindCascades(context, 0);
|
||||
bindingData.BindCascadeMips(context, 4);
|
||||
context->BindSR(0, bindingData.Texture ? bindingData.Texture->ViewVolume() : nullptr);
|
||||
context->BindSR(1, bindingData.TextureMip ? bindingData.TextureMip->ViewVolume() : nullptr);
|
||||
context->SetState(_psDebug);
|
||||
context->SetRenderTarget(output->View());
|
||||
context->SetViewportAndScissors(outputSize.X, outputSize.Y);
|
||||
|
||||
@@ -23,12 +23,9 @@ public:
|
||||
// Binding data for the GPU.
|
||||
struct BindingData
|
||||
{
|
||||
GPUTexture* Cascades[4];
|
||||
GPUTexture* CascadeMips[4];
|
||||
GPUTexture* Texture;
|
||||
GPUTexture* TextureMip;
|
||||
ConstantsData Constants;
|
||||
|
||||
void BindCascades(GPUContext* context, int32 srvSlot);
|
||||
void BindCascadeMips(GPUContext* context, int32 srvSlot);
|
||||
};
|
||||
|
||||
private:
|
||||
@@ -39,8 +36,7 @@ private:
|
||||
GPUShaderProgramCS* _csRasterizeModel1 = nullptr;
|
||||
GPUShaderProgramCS* _csRasterizeHeightfield = nullptr;
|
||||
GPUShaderProgramCS* _csClearChunk = nullptr;
|
||||
GPUShaderProgramCS* _csGenerateMip0 = nullptr;
|
||||
GPUShaderProgramCS* _csGenerateMip1 = nullptr;
|
||||
GPUShaderProgramCS* _csGenerateMip = nullptr;
|
||||
GPUConstantBuffer* _cb0 = nullptr;
|
||||
GPUConstantBuffer* _cb1 = nullptr;
|
||||
|
||||
|
||||
@@ -170,8 +170,7 @@ const Char* ShaderGraphUtilities::GenerateShaderResources(TextWriterUnicode& wri
|
||||
format = TEXT("Texture3D {0} : register(t{1});");
|
||||
break;
|
||||
case MaterialParameterType::GlobalSDF:
|
||||
format = TEXT("Texture3D<float> {0}_Tex[4] : register(t{1});");
|
||||
registers = 4;
|
||||
format = TEXT("Texture3D<float> {0}_Tex : register(t{1});");
|
||||
zeroOffset = false;
|
||||
break;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user