|
|
@@ -18,6 +18,7 @@
|
|
|
#include <AnKi/Shaders/Include/GpuSceneTypes.h>
|
|
|
#include <AnKi/Core/GpuMemory/UnifiedGeometryBuffer.h>
|
|
|
#include <AnKi/Core/GpuMemory/GpuSceneBuffer.h>
|
|
|
+#include <AnKi/Core/GpuMemory/GpuVisibleTransientMemoryPool.h>
|
|
|
|
|
|
namespace anki {
|
|
|
|
|
|
@@ -46,6 +47,12 @@ Error RtShadows::initInternal()
|
|
|
|
|
|
ANKI_CHECK(ResourceManager::getSingleton().loadResource("EngineAssets/BlueNoise_Rgba8_64x64.png", m_blueNoiseImage));
|
|
|
|
|
|
+ // Setup build SBT program
|
|
|
+ ANKI_CHECK(loadShaderProgram("ShaderBinaries/RtShadowsSetupSbtBuild.ankiprogbin", m_setupBuildSbtProg, m_setupBuildSbtGrProg));
|
|
|
+
|
|
|
+ // Build SBT program
|
|
|
+ ANKI_CHECK(loadShaderProgram("ShaderBinaries/RtShadowsSbtBuild.ankiprogbin", m_buildSbtProg, m_buildSbtGrProg));
|
|
|
+
|
|
|
// Ray gen program
|
|
|
{
|
|
|
ANKI_CHECK(ResourceManager::getSingleton().loadResource("ShaderBinaries/RtShadowsRayGen.ankiprogbin", m_rayGenProg));
|
|
|
@@ -72,8 +79,6 @@ Error RtShadows::initInternal()
|
|
|
{
|
|
|
ANKI_CHECK(ResourceManager::getSingleton().loadResource("ShaderBinaries/RtShadowsDenoise.ankiprogbin", m_denoiseProg));
|
|
|
ShaderProgramResourceVariantInitInfo variantInitInfo(m_denoiseProg);
|
|
|
- variantInitInfo.addConstant("kOutImageSize",
|
|
|
- UVec2(getRenderer().getInternalResolution().x() / 2, getRenderer().getInternalResolution().y() / 2));
|
|
|
variantInitInfo.addConstant("kMinSampleCount", 8u);
|
|
|
variantInitInfo.addConstant("kMaxSampleCount", 32u);
|
|
|
variantInitInfo.addMutation("BLUR_ORIENTATION", 0);
|
|
|
@@ -90,14 +95,7 @@ Error RtShadows::initInternal()
|
|
|
// SVGF variance program
|
|
|
if(m_useSvgf)
|
|
|
{
|
|
|
- ANKI_CHECK(ResourceManager::getSingleton().loadResource("ShaderBinaries/RtShadowsSvgfVariance.ankiprogbin", m_svgfVarianceProg));
|
|
|
- ShaderProgramResourceVariantInitInfo variantInitInfo(m_svgfVarianceProg);
|
|
|
- variantInitInfo.addConstant("kFramebufferSize",
|
|
|
- UVec2(getRenderer().getInternalResolution().x() / 2, getRenderer().getInternalResolution().y() / 2));
|
|
|
-
|
|
|
- const ShaderProgramResourceVariant* variant;
|
|
|
- m_svgfVarianceProg->getOrCreateVariant(variantInitInfo, variant);
|
|
|
- m_svgfVarianceGrProg.reset(&variant->getProgram());
|
|
|
+ ANKI_CHECK(loadShaderProgram("ShaderBinaries/RtShadowsSvgfVariance.ankiprogbin", m_svgfVarianceProg, m_svgfVarianceGrProg));
|
|
|
}
|
|
|
|
|
|
// SVGF atrous program
|
|
|
@@ -105,8 +103,6 @@ Error RtShadows::initInternal()
|
|
|
{
|
|
|
ANKI_CHECK(ResourceManager::getSingleton().loadResource("ShaderBinaries/RtShadowsSvgfAtrous.ankiprogbin", m_svgfAtrousProg));
|
|
|
ShaderProgramResourceVariantInitInfo variantInitInfo(m_svgfAtrousProg);
|
|
|
- variantInitInfo.addConstant("kFramebufferSize",
|
|
|
- UVec2(getRenderer().getInternalResolution().x() / 2, getRenderer().getInternalResolution().y() / 2));
|
|
|
variantInitInfo.addMutation("LAST_PASS", 0);
|
|
|
|
|
|
const ShaderProgramResourceVariant* variant;
|
|
|
@@ -119,24 +115,12 @@ Error RtShadows::initInternal()
|
|
|
}
|
|
|
|
|
|
// Upscale program
|
|
|
- {
|
|
|
- ANKI_CHECK(ResourceManager::getSingleton().loadResource("ShaderBinaries/RtShadowsUpscale.ankiprogbin", m_upscaleProg));
|
|
|
- ShaderProgramResourceVariantInitInfo variantInitInfo(m_upscaleProg);
|
|
|
- variantInitInfo.addConstant("kOutImageSize", UVec2(getRenderer().getInternalResolution().x(), getRenderer().getInternalResolution().y()));
|
|
|
-
|
|
|
- const ShaderProgramResourceVariant* variant;
|
|
|
- m_upscaleProg->getOrCreateVariant(variantInitInfo, variant);
|
|
|
- m_upscaleGrProg.reset(&variant->getProgram());
|
|
|
- }
|
|
|
-
|
|
|
- // Debug program
|
|
|
- ANKI_CHECK(
|
|
|
- ResourceManager::getSingleton().loadResource("ShaderBinaries/RtShadowsVisualizeRenderTarget.ankiprogbin", m_visualizeRenderTargetsProg));
|
|
|
+ ANKI_CHECK(loadShaderProgram("ShaderBinaries/RtShadowsUpscale.ankiprogbin", m_upscaleProg, m_upscaleGrProg));
|
|
|
|
|
|
// Quarter rez shadow RT
|
|
|
{
|
|
|
TextureInitInfo texinit = getRenderer().create2DRenderTargetInitInfo(
|
|
|
- getRenderer().getInternalResolution().x() / 2, getRenderer().getInternalResolution().y() / 2, Format::kR32G32_Uint,
|
|
|
+ getRenderer().getInternalResolution().x() / 2, getRenderer().getInternalResolution().y() / 2, Format::kR8_Unorm,
|
|
|
TextureUsageBit::kAllSampled | TextureUsageBit::kImageTraceRaysWrite | TextureUsageBit::kImageComputeWrite, "RtShadows History");
|
|
|
m_historyRt = getRenderer().createAndClearRenderTarget(texinit, TextureUsageBit::kSampledFragment);
|
|
|
}
|
|
|
@@ -144,7 +128,7 @@ Error RtShadows::initInternal()
|
|
|
// Temp shadow RT
|
|
|
{
|
|
|
m_intermediateShadowsRtDescr = getRenderer().create2DRenderTargetDescription(
|
|
|
- getRenderer().getInternalResolution().x() / 2, getRenderer().getInternalResolution().y() / 2, Format::kR32G32_Uint, "RtShadows Tmp");
|
|
|
+ getRenderer().getInternalResolution().x() / 2, getRenderer().getInternalResolution().y() / 2, Format::kR8_Unorm, "RtShadows Tmp");
|
|
|
m_intermediateShadowsRtDescr.bake();
|
|
|
}
|
|
|
|
|
|
@@ -170,7 +154,7 @@ Error RtShadows::initInternal()
|
|
|
// Final RT
|
|
|
{
|
|
|
m_upscaledRtDescr = getRenderer().create2DRenderTargetDescription(
|
|
|
- getRenderer().getInternalResolution().x(), getRenderer().getInternalResolution().y(), Format::kR32G32_Uint, "RtShadows Upscaled");
|
|
|
+ getRenderer().getInternalResolution().x(), getRenderer().getInternalResolution().y(), Format::kR8_Unorm, "RtShadows Upscaled");
|
|
|
m_upscaledRtDescr.bake();
|
|
|
}
|
|
|
|
|
|
@@ -184,13 +168,15 @@ void RtShadows::populateRenderGraph(RenderingContext& ctx)
|
|
|
{
|
|
|
ANKI_TRACE_SCOPED_EVENT(RRtShadows);
|
|
|
|
|
|
- RenderGraphDescription& rgraph = ctx.m_renderGraphDescr;
|
|
|
+#define ANKI_DEPTH_DEP \
|
|
|
+ getRenderer().getDepthDownscale().getHiZRt(), TextureUsageBit::kSampledTraceRays | TextureUsageBit::kSampledCompute, kHiZHalfSurface
|
|
|
|
|
|
- buildSbt(ctx);
|
|
|
- const U32 prevRtIdx = getRenderer().getFrameCount() & 1;
|
|
|
+ RenderGraphDescription& rgraph = ctx.m_renderGraphDescr;
|
|
|
|
|
|
// Import RTs
|
|
|
{
|
|
|
+ const U32 prevRtIdx = getRenderer().getFrameCount() & 1;
|
|
|
+
|
|
|
if(!m_rtsImportedOnce) [[unlikely]]
|
|
|
{
|
|
|
m_runCtx.m_historyRt = rgraph.importRenderTarget(m_historyRt.get(), TextureUsageBit::kSampledFragment);
|
|
|
@@ -231,15 +217,79 @@ void RtShadows::populateRenderGraph(RenderingContext& ctx)
|
|
|
m_runCtx.m_upscaledRt = rgraph.newRenderTarget(m_upscaledRtDescr);
|
|
|
}
|
|
|
|
|
|
-#define ANKI_DEPTH_DEP \
|
|
|
- getRenderer().getDepthDownscale().getHiZRt(), TextureUsageBit::kSampledTraceRays | TextureUsageBit::kSampledCompute, kHiZHalfSurface
|
|
|
+ // Setup build SBT dispatch
|
|
|
+ BufferHandle sbtBuildIndirectArgsHandle;
|
|
|
+ BufferOffsetRange sbtBuildIndirectArgsBuffer;
|
|
|
+ {
|
|
|
+ sbtBuildIndirectArgsBuffer = GpuVisibleTransientMemoryPool::getSingleton().allocate(sizeof(DispatchIndirectArgs));
|
|
|
+ sbtBuildIndirectArgsHandle = rgraph.importBuffer(BufferUsageBit::kStorageComputeWrite, sbtBuildIndirectArgsBuffer);
|
|
|
+
|
|
|
+ ComputeRenderPassDescription& rpass = rgraph.newComputeRenderPass("RtShadows setup build SBT");
|
|
|
+
|
|
|
+ rpass.setWork([this, sbtBuildIndirectArgsBuffer](RenderPassWorkContext& rgraphCtx) {
|
|
|
+ CommandBuffer& cmdb = *rgraphCtx.m_commandBuffer;
|
|
|
+
|
|
|
+ cmdb.bindShaderProgram(m_setupBuildSbtGrProg.get());
|
|
|
+
|
|
|
+ cmdb.bindStorageBuffer(0, 0, GpuSceneArrays::RenderableAabbRt::getSingleton().getBufferOffsetRange());
|
|
|
+ cmdb.bindStorageBuffer(0, 1, sbtBuildIndirectArgsBuffer);
|
|
|
|
|
|
- // RT shadows pass
|
|
|
+ cmdb.dispatchCompute(1, 1, 1);
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ // Build the SBT
|
|
|
+ BufferHandle sbtHandle;
|
|
|
+ BufferOffsetRange sbtBuffer;
|
|
|
{
|
|
|
- ComputeRenderPassDescription& rpass = rgraph.newComputeRenderPass("RtShadows");
|
|
|
- rpass.setWork([this](RenderPassWorkContext& rgraphCtx) {
|
|
|
- run(rgraphCtx);
|
|
|
+ // Allocate SBT
|
|
|
+ U8* sbtMem;
|
|
|
+ sbtBuffer = RebarTransientMemoryPool::getSingleton().allocateFrame(
|
|
|
+ (GpuSceneArrays::RenderableAabbRt::getSingleton().getElementCount() + 2) * m_sbtRecordSize, sbtMem);
|
|
|
+ sbtHandle = rgraph.importBuffer(BufferUsageBit::kStorageComputeWrite, sbtBuffer);
|
|
|
+
|
|
|
+ // Write the first 2 entries of the SBT
|
|
|
+ ConstWeakArray<U8> shaderGroupHandles = m_rtLibraryGrProg->getShaderGroupHandles();
|
|
|
+ const U32 shaderHandleSize = GrManager::getSingleton().getDeviceCapabilities().m_shaderGroupHandleSize;
|
|
|
+ memcpy(sbtMem, &shaderGroupHandles[m_rayGenShaderGroupIdx * shaderHandleSize], shaderHandleSize);
|
|
|
+ memcpy(sbtMem + m_sbtRecordSize, &shaderGroupHandles[m_missShaderGroupIdx * shaderHandleSize], shaderHandleSize);
|
|
|
+
|
|
|
+ // Create the pass
|
|
|
+ ComputeRenderPassDescription& rpass = rgraph.newComputeRenderPass("RtShadows build SBT");
|
|
|
+
|
|
|
+ BufferHandle visibilityHandle;
|
|
|
+ BufferOffsetRange visibleRenderableIndicesBuff;
|
|
|
+ getRenderer().getAccelerationStructureBuilder().getVisibilityInfo(visibilityHandle, visibleRenderableIndicesBuff);
|
|
|
+
|
|
|
+ rpass.newBufferDependency(visibilityHandle, BufferUsageBit::kStorageComputeRead);
|
|
|
+ rpass.newBufferDependency(sbtBuildIndirectArgsHandle, BufferUsageBit::kIndirectCompute);
|
|
|
+
|
|
|
+ rpass.setWork([this, sbtBuildIndirectArgsBuffer, sbtBuffer, visibleRenderableIndicesBuff](RenderPassWorkContext& rgraphCtx) {
|
|
|
+ CommandBuffer& cmdb = *rgraphCtx.m_commandBuffer;
|
|
|
+
|
|
|
+ cmdb.bindShaderProgram(m_buildSbtGrProg.get());
|
|
|
+
|
|
|
+ cmdb.bindStorageBuffer(0, 0, GpuSceneArrays::RenderableAabbRt::getSingleton().getBufferOffsetRange());
|
|
|
+ cmdb.bindStorageBuffer(0, 1, &GpuSceneBuffer::getSingleton().getBuffer(), 0, kMaxPtrSize);
|
|
|
+ cmdb.bindStorageBuffer(0, 2, visibleRenderableIndicesBuff);
|
|
|
+ cmdb.bindStorageBuffer(0, 3, &m_rtLibraryGrProg->getShaderGroupHandlesGpuBuffer(), 0, kMaxPtrSize);
|
|
|
+ cmdb.bindStorageBuffer(0, 4, sbtBuffer);
|
|
|
+
|
|
|
+ RtShadowsSbtBuildUniforms unis = {};
|
|
|
+ ANKI_ASSERT(m_sbtRecordSize % 4 == 0);
|
|
|
+ unis.m_sbtRecordDwordSize = m_sbtRecordSize / 4;
|
|
|
+ const U32 shaderHandleSize = GrManager::getSingleton().getDeviceCapabilities().m_shaderGroupHandleSize;
|
|
|
+ ANKI_ASSERT(shaderHandleSize % 4 == 0);
|
|
|
+ unis.m_shaderHandleDwordSize = shaderHandleSize / 4;
|
|
|
+ cmdb.setPushConstants(&unis, sizeof(unis));
|
|
|
+
|
|
|
+ cmdb.dispatchComputeIndirect(sbtBuildIndirectArgsBuffer.m_buffer, sbtBuildIndirectArgsBuffer.m_offset);
|
|
|
});
|
|
|
+ }
|
|
|
+
|
|
|
+ // Ray gen
|
|
|
+ {
|
|
|
+ ComputeRenderPassDescription& rpass = rgraph.newComputeRenderPass("RtShadows");
|
|
|
|
|
|
rpass.newTextureDependency(m_runCtx.m_historyRt, TextureUsageBit::kSampledTraceRays);
|
|
|
rpass.newTextureDependency(m_runCtx.m_intermediateShadowsRts[0], TextureUsageBit::kImageTraceRaysWrite);
|
|
|
@@ -254,16 +304,66 @@ void RtShadows::populateRenderGraph(RenderingContext& ctx)
|
|
|
rpass.newTextureDependency(m_runCtx.m_currentMomentsRt, TextureUsageBit::kImageTraceRaysWrite);
|
|
|
|
|
|
rpass.newBufferDependency(getRenderer().getClusterBinning2().getClustersBufferHandle(), BufferUsageBit::kStorageTraceRaysRead);
|
|
|
- rpass.newBufferDependency(getRenderer().getClusterBinning2().getPackedObjectsBufferHandle(GpuSceneNonRenderableObjectType::kLight),
|
|
|
- BufferUsageBit::kStorageTraceRaysRead);
|
|
|
+
|
|
|
+ rpass.setWork([this, sbtBuffer](RenderPassWorkContext& rgraphCtx) {
|
|
|
+ CommandBuffer& cmdb = *rgraphCtx.m_commandBuffer;
|
|
|
+
|
|
|
+ cmdb.bindShaderProgram(m_rtLibraryGrProg.get());
|
|
|
+
|
|
|
+ // Allocate, set and bind global uniforms
|
|
|
+ {
|
|
|
+ MaterialGlobalUniforms* globalUniforms;
|
|
|
+ const RebarAllocation globalUniformsToken = RebarTransientMemoryPool::getSingleton().allocateFrame(1, globalUniforms);
|
|
|
+
|
|
|
+ memset(globalUniforms, 0, sizeof(*globalUniforms)); // Don't care for now
|
|
|
+
|
|
|
+ cmdb.bindUniformBuffer(U32(MaterialSet::kGlobal), U32(MaterialBinding::kGlobalUniforms), globalUniformsToken);
|
|
|
+ }
|
|
|
+
|
|
|
+ // More globals
|
|
|
+ cmdb.bindAllBindless(U32(MaterialSet::kBindless));
|
|
|
+ cmdb.bindSampler(U32(MaterialSet::kGlobal), U32(MaterialBinding::kTrilinearRepeatSampler),
|
|
|
+ getRenderer().getSamplers().m_trilinearRepeat.get());
|
|
|
+ cmdb.bindStorageBuffer(U32(MaterialSet::kGlobal), U32(MaterialBinding::kGpuScene), &GpuSceneBuffer::getSingleton().getBuffer(), 0,
|
|
|
+ kMaxPtrSize);
|
|
|
+
|
|
|
+#define ANKI_UNIFIED_GEOM_FORMAT(fmt, shaderType) \
|
|
|
+ cmdb.bindReadOnlyTextureBuffer(U32(MaterialSet::kGlobal), U32(MaterialBinding::kUnifiedGeometry_##fmt), \
|
|
|
+ &UnifiedGeometryBuffer::getSingleton().getBuffer(), 0, kMaxPtrSize, Format::k##fmt);
|
|
|
+#include <AnKi/Shaders/Include/UnifiedGeometryTypes.defs.h>
|
|
|
+
|
|
|
+ constexpr U32 kSet = 2;
|
|
|
+
|
|
|
+ cmdb.bindUniformBuffer(kSet, 0, getRenderer().getClusterBinning2().getClusteredShadingUniforms());
|
|
|
+ cmdb.bindStorageBuffer(kSet, 1, getRenderer().getClusterBinning2().getClustersBuffer());
|
|
|
+
|
|
|
+ cmdb.bindSampler(kSet, 2, getRenderer().getSamplers().m_trilinearRepeat.get());
|
|
|
+
|
|
|
+ rgraphCtx.bindImage(kSet, 3, m_runCtx.m_intermediateShadowsRts[0]);
|
|
|
+ rgraphCtx.bindColorTexture(kSet, 4, m_runCtx.m_historyRt);
|
|
|
+ cmdb.bindSampler(kSet, 5, getRenderer().getSamplers().m_trilinearClamp.get());
|
|
|
+ rgraphCtx.bindTexture(kSet, 6, getRenderer().getDepthDownscale().getHiZRt(), kHiZHalfSurface);
|
|
|
+ rgraphCtx.bindColorTexture(kSet, 7, getRenderer().getMotionVectors().getMotionVectorsRt());
|
|
|
+ rgraphCtx.bindColorTexture(kSet, 8, getRenderer().getMotionVectors().getHistoryLengthRt());
|
|
|
+ rgraphCtx.bindColorTexture(kSet, 9, getRenderer().getGBuffer().getColorRt(2));
|
|
|
+ rgraphCtx.bindAccelerationStructure(kSet, 10, getRenderer().getAccelerationStructureBuilder().getAccelerationStructureHandle());
|
|
|
+ rgraphCtx.bindColorTexture(kSet, 11, m_runCtx.m_prevMomentsRt);
|
|
|
+ rgraphCtx.bindImage(kSet, 12, m_runCtx.m_currentMomentsRt);
|
|
|
+ cmdb.bindTexture(kSet, 13, &m_blueNoiseImage->getTextureView());
|
|
|
+
|
|
|
+ cmdb.traceRays(sbtBuffer.m_buffer, sbtBuffer.m_offset, m_sbtRecordSize,
|
|
|
+ GpuSceneArrays::RenderableAabbRt::getSingleton().getElementCount(), 1, getRenderer().getInternalResolution().x() / 2,
|
|
|
+ getRenderer().getInternalResolution().y() / 2, 1);
|
|
|
+ });
|
|
|
}
|
|
|
|
|
|
// Denoise pass horizontal
|
|
|
if(!m_useSvgf)
|
|
|
{
|
|
|
ComputeRenderPassDescription& rpass = rgraph.newComputeRenderPass("RtShadows Denoise Horizontal");
|
|
|
+
|
|
|
rpass.setWork([this, &ctx](RenderPassWorkContext& rgraphCtx) {
|
|
|
- runDenoise(ctx, rgraphCtx);
|
|
|
+ runDenoise(ctx, rgraphCtx, true);
|
|
|
});
|
|
|
|
|
|
rpass.newTextureDependency(m_runCtx.m_intermediateShadowsRts[0], TextureUsageBit::kSampledCompute);
|
|
|
@@ -280,7 +380,7 @@ void RtShadows::populateRenderGraph(RenderingContext& ctx)
|
|
|
{
|
|
|
ComputeRenderPassDescription& rpass = rgraph.newComputeRenderPass("RtShadows Denoise Vertical");
|
|
|
rpass.setWork([this, &ctx](RenderPassWorkContext& rgraphCtx) {
|
|
|
- runDenoise(ctx, rgraphCtx);
|
|
|
+ runDenoise(ctx, rgraphCtx, false);
|
|
|
});
|
|
|
|
|
|
rpass.newTextureDependency(m_runCtx.m_intermediateShadowsRts[1], TextureUsageBit::kSampledCompute);
|
|
|
@@ -296,9 +396,6 @@ void RtShadows::populateRenderGraph(RenderingContext& ctx)
|
|
|
if(m_useSvgf)
|
|
|
{
|
|
|
ComputeRenderPassDescription& rpass = rgraph.newComputeRenderPass("RtShadows SVGF Variance");
|
|
|
- rpass.setWork([this, &ctx](RenderPassWorkContext& rgraphCtx) {
|
|
|
- runSvgfVariance(ctx, rgraphCtx);
|
|
|
- });
|
|
|
|
|
|
rpass.newTextureDependency(m_runCtx.m_intermediateShadowsRts[0], TextureUsageBit::kSampledCompute);
|
|
|
rpass.newTextureDependency(m_runCtx.m_currentMomentsRt, TextureUsageBit::kSampledCompute);
|
|
|
@@ -308,22 +405,38 @@ void RtShadows::populateRenderGraph(RenderingContext& ctx)
|
|
|
|
|
|
rpass.newTextureDependency(m_runCtx.m_intermediateShadowsRts[1], TextureUsageBit::kImageComputeWrite);
|
|
|
rpass.newTextureDependency(m_runCtx.m_varianceRts[1], TextureUsageBit::kImageComputeWrite);
|
|
|
+
|
|
|
+ rpass.setWork([this, &ctx](RenderPassWorkContext& rgraphCtx) {
|
|
|
+ CommandBuffer& cmdb = *rgraphCtx.m_commandBuffer;
|
|
|
+
|
|
|
+ cmdb.bindShaderProgram(m_svgfVarianceGrProg.get());
|
|
|
+
|
|
|
+ cmdb.bindSampler(0, 0, getRenderer().getSamplers().m_trilinearClamp.get());
|
|
|
+
|
|
|
+ rgraphCtx.bindColorTexture(0, 1, m_runCtx.m_intermediateShadowsRts[0]);
|
|
|
+ rgraphCtx.bindColorTexture(0, 2, m_runCtx.m_currentMomentsRt);
|
|
|
+ rgraphCtx.bindColorTexture(0, 3, getRenderer().getMotionVectors().getHistoryLengthRt());
|
|
|
+ rgraphCtx.bindTexture(0, 4, getRenderer().getDepthDownscale().getHiZRt(), kHiZHalfSurface);
|
|
|
+
|
|
|
+ rgraphCtx.bindImage(0, 5, m_runCtx.m_intermediateShadowsRts[1]);
|
|
|
+ rgraphCtx.bindImage(0, 6, m_runCtx.m_varianceRts[1]);
|
|
|
+
|
|
|
+ const Mat4& invProjMat = ctx.m_matrices.m_projectionJitter.getInverse();
|
|
|
+ cmdb.setPushConstants(&invProjMat, sizeof(invProjMat));
|
|
|
+
|
|
|
+ dispatchPPCompute(cmdb, 8, 8, getRenderer().getInternalResolution().x() / 2, getRenderer().getInternalResolution().y() / 2);
|
|
|
+ });
|
|
|
}
|
|
|
|
|
|
// SVGF Atrous
|
|
|
if(m_useSvgf)
|
|
|
{
|
|
|
- m_runCtx.m_atrousPassIdx = 0;
|
|
|
-
|
|
|
for(U32 i = 0; i < m_atrousPassCount; ++i)
|
|
|
{
|
|
|
const Bool lastPass = i == U32(m_atrousPassCount - 1);
|
|
|
const U32 readRtIdx = (i + 1) & 1;
|
|
|
|
|
|
ComputeRenderPassDescription& rpass = rgraph.newComputeRenderPass("RtShadows SVGF Atrous");
|
|
|
- rpass.setWork([this, &ctx](RenderPassWorkContext& rgraphCtx) {
|
|
|
- runSvgfAtrous(ctx, rgraphCtx);
|
|
|
- });
|
|
|
|
|
|
rpass.newTextureDependency(ANKI_DEPTH_DEP);
|
|
|
rpass.newTextureDependency(getRenderer().getGBuffer().getColorRt(2), TextureUsageBit::kSampledCompute);
|
|
|
@@ -340,380 +453,101 @@ void RtShadows::populateRenderGraph(RenderingContext& ctx)
|
|
|
{
|
|
|
rpass.newTextureDependency(m_runCtx.m_historyRt, TextureUsageBit::kImageComputeWrite);
|
|
|
}
|
|
|
+
|
|
|
+ rpass.setWork([this, &ctx, passIdx = i](RenderPassWorkContext& rgraphCtx) {
|
|
|
+ CommandBuffer& cmdb = *rgraphCtx.m_commandBuffer;
|
|
|
+
|
|
|
+ const Bool lastPass = passIdx == m_atrousPassCount - 1;
|
|
|
+ const U32 readRtIdx = (passIdx + 1) & 1;
|
|
|
+
|
|
|
+ if(lastPass)
|
|
|
+ {
|
|
|
+ cmdb.bindShaderProgram(m_svgfAtrousLastPassGrProg.get());
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ cmdb.bindShaderProgram(m_svgfAtrousGrProg.get());
|
|
|
+ }
|
|
|
+
|
|
|
+ cmdb.bindSampler(0, 0, getRenderer().getSamplers().m_nearestNearestClamp.get());
|
|
|
+ cmdb.bindSampler(0, 1, getRenderer().getSamplers().m_trilinearClamp.get());
|
|
|
+
|
|
|
+ rgraphCtx.bindTexture(0, 2, getRenderer().getDepthDownscale().getHiZRt(), kHiZHalfSurface);
|
|
|
+ rgraphCtx.bindColorTexture(0, 3, m_runCtx.m_intermediateShadowsRts[readRtIdx]);
|
|
|
+ rgraphCtx.bindColorTexture(0, 4, m_runCtx.m_varianceRts[readRtIdx]);
|
|
|
+
|
|
|
+ if(!lastPass)
|
|
|
+ {
|
|
|
+ rgraphCtx.bindImage(0, 5, m_runCtx.m_intermediateShadowsRts[!readRtIdx]);
|
|
|
+ rgraphCtx.bindImage(0, 6, m_runCtx.m_varianceRts[!readRtIdx]);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ rgraphCtx.bindImage(0, 5, m_runCtx.m_historyRt);
|
|
|
+ }
|
|
|
+
|
|
|
+ const Mat4& invProjMat = ctx.m_matrices.m_projectionJitter.getInverse();
|
|
|
+ cmdb.setPushConstants(&invProjMat, sizeof(invProjMat));
|
|
|
+
|
|
|
+ dispatchPPCompute(cmdb, 8, 8, getRenderer().getInternalResolution().x() / 2, getRenderer().getInternalResolution().y() / 2);
|
|
|
+ });
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// Upscale
|
|
|
{
|
|
|
ComputeRenderPassDescription& rpass = rgraph.newComputeRenderPass("RtShadows Upscale");
|
|
|
- rpass.setWork([this](RenderPassWorkContext& rgraphCtx) {
|
|
|
- runUpscale(rgraphCtx);
|
|
|
- });
|
|
|
|
|
|
rpass.newTextureDependency(m_runCtx.m_historyRt, TextureUsageBit::kSampledCompute);
|
|
|
rpass.newTextureDependency(getRenderer().getGBuffer().getDepthRt(), TextureUsageBit::kSampledCompute);
|
|
|
rpass.newTextureDependency(ANKI_DEPTH_DEP);
|
|
|
|
|
|
rpass.newTextureDependency(m_runCtx.m_upscaledRt, TextureUsageBit::kImageComputeWrite);
|
|
|
- }
|
|
|
-
|
|
|
- // Find out the lights that will take part in RT pass
|
|
|
- {
|
|
|
- RenderQueue& rqueue = *ctx.m_renderQueue;
|
|
|
- m_runCtx.m_layersWithRejectedHistory.unsetAll();
|
|
|
|
|
|
- if(rqueue.m_directionalLight.hasShadow())
|
|
|
- {
|
|
|
- U32 layerIdx;
|
|
|
- Bool rejectHistory;
|
|
|
- [[maybe_unused]] const Bool layerFound = findShadowLayer(0, layerIdx, rejectHistory);
|
|
|
- ANKI_ASSERT(layerFound && "Directional can't fail");
|
|
|
-
|
|
|
- rqueue.m_directionalLight.m_shadowLayer = U8(layerIdx);
|
|
|
- ANKI_ASSERT(rqueue.m_directionalLight.m_shadowLayer < kMaxRtShadowLayers);
|
|
|
- m_runCtx.m_layersWithRejectedHistory.set(layerIdx, rejectHistory);
|
|
|
- }
|
|
|
-
|
|
|
- for(PointLightQueueElement& light : rqueue.m_pointLights)
|
|
|
- {
|
|
|
- if(!light.hasShadow())
|
|
|
- {
|
|
|
- continue;
|
|
|
- }
|
|
|
-
|
|
|
- U32 layerIdx;
|
|
|
- Bool rejectHistory;
|
|
|
- const Bool layerFound = findShadowLayer(light.m_uuid, layerIdx, rejectHistory);
|
|
|
-
|
|
|
- if(layerFound)
|
|
|
- {
|
|
|
- light.m_shadowLayer = U8(layerIdx);
|
|
|
- ANKI_ASSERT(light.m_shadowLayer < kMaxRtShadowLayers);
|
|
|
- m_runCtx.m_layersWithRejectedHistory.set(layerIdx, rejectHistory);
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- // Disable shadows
|
|
|
- light.m_shadowRenderQueues = {};
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- for(SpotLightQueueElement& light : rqueue.m_spotLights)
|
|
|
- {
|
|
|
- if(!light.hasShadow())
|
|
|
- {
|
|
|
- continue;
|
|
|
- }
|
|
|
-
|
|
|
- U32 layerIdx;
|
|
|
- Bool rejectHistory;
|
|
|
- const Bool layerFound = findShadowLayer(light.m_uuid, layerIdx, rejectHistory);
|
|
|
-
|
|
|
- if(layerFound)
|
|
|
- {
|
|
|
- light.m_shadowLayer = U8(layerIdx);
|
|
|
- ANKI_ASSERT(light.m_shadowLayer < kMaxRtShadowLayers);
|
|
|
- m_runCtx.m_layersWithRejectedHistory.set(layerIdx, rejectHistory);
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- // Disable shadows
|
|
|
- light.m_shadowRenderQueue = nullptr;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-void RtShadows::run(RenderPassWorkContext& rgraphCtx)
|
|
|
-{
|
|
|
- CommandBuffer& cmdb = *rgraphCtx.m_commandBuffer;
|
|
|
-
|
|
|
- cmdb.bindShaderProgram(m_rtLibraryGrProg.get());
|
|
|
-
|
|
|
- // Allocate, set and bind global uniforms
|
|
|
- {
|
|
|
- MaterialGlobalUniforms* globalUniforms;
|
|
|
- const RebarAllocation globalUniformsToken = RebarTransientMemoryPool::getSingleton().allocateFrame(1, globalUniforms);
|
|
|
-
|
|
|
- memset(globalUniforms, 0, sizeof(*globalUniforms)); // Don't care for now
|
|
|
-
|
|
|
- cmdb.bindUniformBuffer(U32(MaterialSet::kGlobal), U32(MaterialBinding::kGlobalUniforms), globalUniformsToken);
|
|
|
- }
|
|
|
-
|
|
|
- // More globals
|
|
|
- cmdb.bindAllBindless(U32(MaterialSet::kBindless));
|
|
|
- cmdb.bindSampler(U32(MaterialSet::kGlobal), U32(MaterialBinding::kTrilinearRepeatSampler), getRenderer().getSamplers().m_trilinearRepeat.get());
|
|
|
- cmdb.bindStorageBuffer(U32(MaterialSet::kGlobal), U32(MaterialBinding::kGpuScene), &GpuSceneBuffer::getSingleton().getBuffer(), 0, kMaxPtrSize);
|
|
|
-
|
|
|
-#define ANKI_UNIFIED_GEOM_FORMAT(fmt, shaderType) \
|
|
|
- cmdb.bindReadOnlyTextureBuffer(U32(MaterialSet::kGlobal), U32(MaterialBinding::kUnifiedGeometry_##fmt), \
|
|
|
- &UnifiedGeometryBuffer::getSingleton().getBuffer(), 0, kMaxPtrSize, Format::k##fmt);
|
|
|
-#include <AnKi/Shaders/Include/UnifiedGeometryTypes.defs.h>
|
|
|
-
|
|
|
- constexpr U32 kSet = 2;
|
|
|
-
|
|
|
- cmdb.bindUniformBuffer(kSet, 0, getRenderer().getClusterBinning2().getClusteredShadingUniforms());
|
|
|
- cmdb.bindStorageBuffer(kSet, 1, getRenderer().getClusterBinning2().getPackedObjectsBuffer(GpuSceneNonRenderableObjectType::kLight));
|
|
|
- cmdb.bindStorageBuffer(kSet, 2, getRenderer().getClusterBinning2().getClustersBuffer());
|
|
|
+ rpass.setWork([this](RenderPassWorkContext& rgraphCtx) {
|
|
|
+ CommandBuffer& cmdb = *rgraphCtx.m_commandBuffer;
|
|
|
|
|
|
- cmdb.bindSampler(kSet, 3, getRenderer().getSamplers().m_trilinearRepeat.get());
|
|
|
+ cmdb.bindShaderProgram(m_upscaleGrProg.get());
|
|
|
|
|
|
- rgraphCtx.bindImage(kSet, 4, m_runCtx.m_intermediateShadowsRts[0]);
|
|
|
+ cmdb.bindSampler(0, 0, getRenderer().getSamplers().m_trilinearClamp.get());
|
|
|
|
|
|
- rgraphCtx.bindColorTexture(kSet, 5, m_runCtx.m_historyRt);
|
|
|
- cmdb.bindSampler(kSet, 6, getRenderer().getSamplers().m_trilinearClamp.get());
|
|
|
- cmdb.bindSampler(kSet, 7, getRenderer().getSamplers().m_nearestNearestClamp.get());
|
|
|
- rgraphCtx.bindTexture(kSet, 8, getRenderer().getDepthDownscale().getHiZRt(), kHiZHalfSurface);
|
|
|
- rgraphCtx.bindColorTexture(kSet, 9, getRenderer().getMotionVectors().getMotionVectorsRt());
|
|
|
- rgraphCtx.bindColorTexture(kSet, 10, getRenderer().getMotionVectors().getHistoryLengthRt());
|
|
|
- rgraphCtx.bindColorTexture(kSet, 11, getRenderer().getGBuffer().getColorRt(2));
|
|
|
- rgraphCtx.bindAccelerationStructure(kSet, 12, getRenderer().getAccelerationStructureBuilder().getAccelerationStructureHandle());
|
|
|
- rgraphCtx.bindColorTexture(kSet, 13, m_runCtx.m_prevMomentsRt);
|
|
|
- rgraphCtx.bindImage(kSet, 14, m_runCtx.m_currentMomentsRt);
|
|
|
- cmdb.bindTexture(kSet, 15, &m_blueNoiseImage->getTextureView());
|
|
|
+ rgraphCtx.bindColorTexture(0, 1, m_runCtx.m_historyRt);
|
|
|
+ rgraphCtx.bindImage(0, 2, m_runCtx.m_upscaledRt);
|
|
|
+ rgraphCtx.bindTexture(0, 3, getRenderer().getDepthDownscale().getHiZRt(), kHiZHalfSurface);
|
|
|
+ rgraphCtx.bindTexture(0, 4, getRenderer().getGBuffer().getDepthRt(), TextureSubresourceInfo(DepthStencilAspectBit::kDepth));
|
|
|
|
|
|
- RtShadowsUniforms unis;
|
|
|
- for(U32 i = 0; i < kMaxRtShadowLayers; ++i)
|
|
|
- {
|
|
|
- unis.historyRejectFactor[i] = F32(m_runCtx.m_layersWithRejectedHistory.get(i));
|
|
|
+ dispatchPPCompute(cmdb, 8, 8, getRenderer().getInternalResolution().x(), getRenderer().getInternalResolution().y());
|
|
|
+ });
|
|
|
}
|
|
|
- cmdb.setPushConstants(&unis, sizeof(unis));
|
|
|
-
|
|
|
- cmdb.traceRays(m_runCtx.m_sbtBuffer.get(), m_runCtx.m_sbtOffset, m_sbtRecordSize, m_runCtx.m_hitGroupCount, 1,
|
|
|
- getRenderer().getInternalResolution().x() / 2, getRenderer().getInternalResolution().y() / 2, 1);
|
|
|
}
|
|
|
|
|
|
-void RtShadows::runDenoise(const RenderingContext& ctx, RenderPassWorkContext& rgraphCtx)
|
|
|
+void RtShadows::runDenoise(const RenderingContext& ctx, RenderPassWorkContext& rgraphCtx, Bool horizontal)
|
|
|
{
|
|
|
CommandBuffer& cmdb = *rgraphCtx.m_commandBuffer;
|
|
|
|
|
|
- cmdb.bindShaderProgram((m_runCtx.m_denoiseOrientation == 0) ? m_grDenoiseHorizontalProg.get() : m_grDenoiseVerticalProg.get());
|
|
|
+ cmdb.bindShaderProgram((horizontal) ? m_grDenoiseHorizontalProg.get() : m_grDenoiseVerticalProg.get());
|
|
|
|
|
|
cmdb.bindSampler(0, 0, getRenderer().getSamplers().m_nearestNearestClamp.get());
|
|
|
- cmdb.bindSampler(0, 1, getRenderer().getSamplers().m_trilinearClamp.get());
|
|
|
- rgraphCtx.bindColorTexture(0, 2, m_runCtx.m_intermediateShadowsRts[m_runCtx.m_denoiseOrientation]);
|
|
|
- rgraphCtx.bindTexture(0, 3, getRenderer().getDepthDownscale().getHiZRt(), kHiZHalfSurface);
|
|
|
- rgraphCtx.bindColorTexture(0, 4, getRenderer().getGBuffer().getColorRt(2));
|
|
|
- rgraphCtx.bindColorTexture(0, 5, m_runCtx.m_currentMomentsRt);
|
|
|
- rgraphCtx.bindColorTexture(0, 6, getRenderer().getMotionVectors().getHistoryLengthRt());
|
|
|
+ rgraphCtx.bindColorTexture(0, 1, m_runCtx.m_intermediateShadowsRts[(horizontal) ? 0 : 1]);
|
|
|
+ rgraphCtx.bindTexture(0, 2, getRenderer().getDepthDownscale().getHiZRt(), kHiZHalfSurface);
|
|
|
+ rgraphCtx.bindColorTexture(0, 3, getRenderer().getGBuffer().getColorRt(2));
|
|
|
+ rgraphCtx.bindColorTexture(0, 4, m_runCtx.m_currentMomentsRt);
|
|
|
+ rgraphCtx.bindColorTexture(0, 5, getRenderer().getMotionVectors().getHistoryLengthRt());
|
|
|
|
|
|
- rgraphCtx.bindImage(0, 7, (m_runCtx.m_denoiseOrientation == 0) ? m_runCtx.m_intermediateShadowsRts[1] : m_runCtx.m_historyRt);
|
|
|
+ rgraphCtx.bindImage(0, 6, (horizontal) ? m_runCtx.m_intermediateShadowsRts[1] : m_runCtx.m_historyRt);
|
|
|
|
|
|
RtShadowsDenoiseUniforms unis;
|
|
|
- unis.invViewProjMat = ctx.m_matrices.m_invertedViewProjectionJitter;
|
|
|
- unis.time = F32(GlobalFrameIndex::getSingleton().m_value);
|
|
|
+ unis.m_invViewProjMat = ctx.m_matrices.m_invertedViewProjectionJitter;
|
|
|
+ unis.m_time = F32(GlobalFrameIndex::getSingleton().m_value % 0xFFFFu);
|
|
|
cmdb.setPushConstants(&unis, sizeof(unis));
|
|
|
|
|
|
dispatchPPCompute(cmdb, 8, 8, getRenderer().getInternalResolution().x() / 2, getRenderer().getInternalResolution().y() / 2);
|
|
|
-
|
|
|
- m_runCtx.m_denoiseOrientation = !m_runCtx.m_denoiseOrientation;
|
|
|
-}
|
|
|
-
|
|
|
-void RtShadows::runSvgfVariance(const RenderingContext& ctx, RenderPassWorkContext& rgraphCtx)
|
|
|
-{
|
|
|
- CommandBuffer& cmdb = *rgraphCtx.m_commandBuffer;
|
|
|
-
|
|
|
- cmdb.bindShaderProgram(m_svgfVarianceGrProg.get());
|
|
|
-
|
|
|
- cmdb.bindSampler(0, 0, getRenderer().getSamplers().m_nearestNearestClamp.get());
|
|
|
- cmdb.bindSampler(0, 1, getRenderer().getSamplers().m_trilinearClamp.get());
|
|
|
-
|
|
|
- rgraphCtx.bindColorTexture(0, 2, m_runCtx.m_intermediateShadowsRts[0]);
|
|
|
- rgraphCtx.bindColorTexture(0, 3, m_runCtx.m_currentMomentsRt);
|
|
|
- rgraphCtx.bindColorTexture(0, 4, getRenderer().getMotionVectors().getHistoryLengthRt());
|
|
|
- rgraphCtx.bindTexture(0, 5, getRenderer().getDepthDownscale().getHiZRt(), kHiZHalfSurface);
|
|
|
-
|
|
|
- rgraphCtx.bindImage(0, 6, m_runCtx.m_intermediateShadowsRts[1]);
|
|
|
- rgraphCtx.bindImage(0, 7, m_runCtx.m_varianceRts[1]);
|
|
|
-
|
|
|
- const Mat4& invProjMat = ctx.m_matrices.m_projectionJitter.getInverse();
|
|
|
- cmdb.setPushConstants(&invProjMat, sizeof(invProjMat));
|
|
|
-
|
|
|
- dispatchPPCompute(cmdb, 8, 8, getRenderer().getInternalResolution().x() / 2, getRenderer().getInternalResolution().y() / 2);
|
|
|
-}
|
|
|
-
|
|
|
-void RtShadows::runSvgfAtrous(const RenderingContext& ctx, RenderPassWorkContext& rgraphCtx)
|
|
|
-{
|
|
|
- CommandBuffer& cmdb = *rgraphCtx.m_commandBuffer;
|
|
|
-
|
|
|
- const Bool lastPass = m_runCtx.m_atrousPassIdx == m_atrousPassCount - 1;
|
|
|
- const U32 readRtIdx = (m_runCtx.m_atrousPassIdx + 1) & 1;
|
|
|
-
|
|
|
- if(lastPass)
|
|
|
- {
|
|
|
- cmdb.bindShaderProgram(m_svgfAtrousLastPassGrProg.get());
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- cmdb.bindShaderProgram(m_svgfAtrousGrProg.get());
|
|
|
- }
|
|
|
-
|
|
|
- cmdb.bindSampler(0, 0, getRenderer().getSamplers().m_nearestNearestClamp.get());
|
|
|
- cmdb.bindSampler(0, 1, getRenderer().getSamplers().m_trilinearClamp.get());
|
|
|
-
|
|
|
- rgraphCtx.bindTexture(0, 2, getRenderer().getDepthDownscale().getHiZRt(), kHiZHalfSurface);
|
|
|
- rgraphCtx.bindColorTexture(0, 3, m_runCtx.m_intermediateShadowsRts[readRtIdx]);
|
|
|
- rgraphCtx.bindColorTexture(0, 4, m_runCtx.m_varianceRts[readRtIdx]);
|
|
|
-
|
|
|
- if(!lastPass)
|
|
|
- {
|
|
|
- rgraphCtx.bindImage(0, 5, m_runCtx.m_intermediateShadowsRts[!readRtIdx]);
|
|
|
- rgraphCtx.bindImage(0, 6, m_runCtx.m_varianceRts[!readRtIdx]);
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- rgraphCtx.bindImage(0, 5, m_runCtx.m_historyRt);
|
|
|
- }
|
|
|
-
|
|
|
- const Mat4& invProjMat = ctx.m_matrices.m_projectionJitter.getInverse();
|
|
|
- cmdb.setPushConstants(&invProjMat, sizeof(invProjMat));
|
|
|
-
|
|
|
- dispatchPPCompute(cmdb, 8, 8, getRenderer().getInternalResolution().x() / 2, getRenderer().getInternalResolution().y() / 2);
|
|
|
-
|
|
|
- ++m_runCtx.m_atrousPassIdx;
|
|
|
-}
|
|
|
-
|
|
|
-void RtShadows::runUpscale(RenderPassWorkContext& rgraphCtx)
|
|
|
-{
|
|
|
- CommandBuffer& cmdb = *rgraphCtx.m_commandBuffer;
|
|
|
-
|
|
|
- cmdb.bindShaderProgram(m_upscaleGrProg.get());
|
|
|
-
|
|
|
- cmdb.bindSampler(0, 0, getRenderer().getSamplers().m_nearestNearestClamp.get());
|
|
|
- cmdb.bindSampler(0, 1, getRenderer().getSamplers().m_trilinearClamp.get());
|
|
|
-
|
|
|
- rgraphCtx.bindColorTexture(0, 2, m_runCtx.m_historyRt);
|
|
|
- rgraphCtx.bindImage(0, 3, m_runCtx.m_upscaledRt);
|
|
|
- rgraphCtx.bindTexture(0, 4, getRenderer().getDepthDownscale().getHiZRt(), kHiZHalfSurface);
|
|
|
- rgraphCtx.bindTexture(0, 5, getRenderer().getGBuffer().getDepthRt(), TextureSubresourceInfo(DepthStencilAspectBit::kDepth));
|
|
|
-
|
|
|
- dispatchPPCompute(cmdb, 8, 8, getRenderer().getInternalResolution().x(), getRenderer().getInternalResolution().y());
|
|
|
-}
|
|
|
-
|
|
|
-void RtShadows::buildSbt(RenderingContext& ctx)
|
|
|
-{
|
|
|
- // Get some things
|
|
|
- ANKI_ASSERT(ctx.m_renderQueue->m_rayTracingQueue);
|
|
|
- ConstWeakArray<RayTracingInstanceQueueElement> instanceElements = ctx.m_renderQueue->m_rayTracingQueue->m_rayTracingInstances;
|
|
|
- const U32 instanceCount = instanceElements.getSize();
|
|
|
- ANKI_ASSERT(instanceCount > 0);
|
|
|
-
|
|
|
- const U32 shaderHandleSize = GrManager::getSingleton().getDeviceCapabilities().m_shaderGroupHandleSize;
|
|
|
-
|
|
|
- const U32 extraSbtRecords = 1 + 1; // Raygen + miss
|
|
|
-
|
|
|
- m_runCtx.m_hitGroupCount = instanceCount;
|
|
|
-
|
|
|
- // Allocate SBT
|
|
|
- U8* sbt;
|
|
|
- const RebarAllocation token =
|
|
|
- RebarTransientMemoryPool::getSingleton().allocateFrame(PtrSize(m_sbtRecordSize) * (instanceCount + extraSbtRecords), sbt);
|
|
|
- [[maybe_unused]] const U8* sbtStart = sbt;
|
|
|
- m_runCtx.m_sbtBuffer.reset(const_cast<Buffer*>(&RebarTransientMemoryPool::getSingleton().getBuffer()));
|
|
|
- m_runCtx.m_sbtOffset = token.getOffset();
|
|
|
-
|
|
|
- // Set the miss and ray gen handles
|
|
|
- ConstWeakArray<U8> shaderGroupHandles = m_rtLibraryGrProg->getShaderGroupHandles();
|
|
|
- memcpy(sbt, &shaderGroupHandles[m_rayGenShaderGroupIdx * shaderHandleSize], shaderHandleSize);
|
|
|
- sbt += m_sbtRecordSize;
|
|
|
- memcpy(sbt, &shaderGroupHandles[m_missShaderGroupIdx * shaderHandleSize], shaderHandleSize);
|
|
|
- sbt += m_sbtRecordSize;
|
|
|
-
|
|
|
- // Init SBT and instances
|
|
|
- ANKI_ASSERT(m_sbtRecordSize >= shaderHandleSize + sizeof(ModelGpuDescriptor));
|
|
|
- for(U32 instanceIdx = 0; instanceIdx < instanceCount; ++instanceIdx)
|
|
|
- {
|
|
|
- const RayTracingInstanceQueueElement& element = instanceElements[instanceIdx];
|
|
|
-
|
|
|
- // Init SBT record
|
|
|
- memcpy(sbt, &shaderGroupHandles[element.m_shaderGroupHandleIndex * shaderHandleSize], shaderHandleSize);
|
|
|
-
|
|
|
- ANKI_ASSERT(shaderHandleSize + sizeof(GpuSceneRenderableVertex) <= m_sbtRecordSize);
|
|
|
- GpuSceneRenderableVertex* shaderRecord = reinterpret_cast<GpuSceneRenderableVertex*>(sbt + shaderHandleSize);
|
|
|
- shaderRecord->m_worldTransformsOffset = element.m_worldTransformsOffset;
|
|
|
- shaderRecord->m_uniformsOffset = element.m_uniformsOffset;
|
|
|
- shaderRecord->m_meshLodOffset = element.m_geometryOffset;
|
|
|
- shaderRecord->m_boneTransformsOrParticleEmitterOffset = 0;
|
|
|
-
|
|
|
- sbt += m_sbtRecordSize;
|
|
|
- }
|
|
|
-
|
|
|
- ANKI_ASSERT(sbtStart + m_sbtRecordSize * (instanceCount + extraSbtRecords) == sbt);
|
|
|
-}
|
|
|
-
|
|
|
-Bool RtShadows::findShadowLayer(U64 lightUuid, U32& layerIdx, Bool& rejectHistoryBuffer)
|
|
|
-{
|
|
|
- const U64 crntFrame = getRenderer().getFrameCount();
|
|
|
- layerIdx = kMaxU32;
|
|
|
- U32 nextBestLayerIdx = kMaxU32;
|
|
|
- U64 nextBestLayerFame = crntFrame;
|
|
|
- rejectHistoryBuffer = false;
|
|
|
-
|
|
|
- for(U32 i = 0; i < m_shadowLayers.getSize(); ++i)
|
|
|
- {
|
|
|
- ShadowLayer& layer = m_shadowLayers[i];
|
|
|
- if(layer.m_lightUuid == lightUuid && layer.m_frameLastUsed == crntFrame - 1)
|
|
|
- {
|
|
|
- // Found it being used last frame
|
|
|
- layerIdx = i;
|
|
|
- layer.m_frameLastUsed = crntFrame;
|
|
|
- layer.m_lightUuid = lightUuid;
|
|
|
- break;
|
|
|
- }
|
|
|
- else if(layer.m_lightUuid == lightUuid || layer.m_frameLastUsed == kMaxU64)
|
|
|
- {
|
|
|
- // Found an empty slot or slot used by the same light
|
|
|
- layerIdx = i;
|
|
|
- layer.m_frameLastUsed = crntFrame;
|
|
|
- layer.m_lightUuid = lightUuid;
|
|
|
- rejectHistoryBuffer = true;
|
|
|
- break;
|
|
|
- }
|
|
|
- else if(layer.m_frameLastUsed < nextBestLayerFame)
|
|
|
- {
|
|
|
- nextBestLayerIdx = i;
|
|
|
- nextBestLayerFame = crntFrame;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- // Not found but there is a good candidate. Use that
|
|
|
- if(layerIdx == kMaxU32 && nextBestLayerIdx != kMaxU32)
|
|
|
- {
|
|
|
- layerIdx = nextBestLayerIdx;
|
|
|
- m_shadowLayers[nextBestLayerIdx].m_frameLastUsed = crntFrame;
|
|
|
- m_shadowLayers[nextBestLayerIdx].m_lightUuid = lightUuid;
|
|
|
- rejectHistoryBuffer = true;
|
|
|
- }
|
|
|
-
|
|
|
- return layerIdx != kMaxU32;
|
|
|
}
|
|
|
|
|
|
void RtShadows::getDebugRenderTarget(CString rtName, Array<RenderTargetHandle, kMaxDebugRenderTargets>& handles,
|
|
|
ShaderProgramPtr& optionalShaderProgram) const
|
|
|
{
|
|
|
- U32 layerGroup = 0;
|
|
|
- if(rtName == "RtShadows")
|
|
|
- {
|
|
|
- layerGroup = 0;
|
|
|
- }
|
|
|
- else if(rtName == "RtShadows1")
|
|
|
- {
|
|
|
- layerGroup = 1;
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- ANKI_ASSERT(rtName == "RtShadows2");
|
|
|
- layerGroup = 2;
|
|
|
- }
|
|
|
-
|
|
|
handles[0] = m_runCtx.m_upscaledRt;
|
|
|
-
|
|
|
- ShaderProgramResourceVariantInitInfo variantInit(m_visualizeRenderTargetsProg);
|
|
|
- variantInit.addMutation("LAYER_GROUP", layerGroup);
|
|
|
-
|
|
|
- const ShaderProgramResourceVariant* variant;
|
|
|
- m_visualizeRenderTargetsProg->getOrCreateVariant(variantInit, variant);
|
|
|
- optionalShaderProgram.reset(&variant->getProgram());
|
|
|
}
|
|
|
|
|
|
} // end namespace anki
|