|
@@ -31,11 +31,10 @@ Error IndirectSpecular::init()
|
|
|
|
|
|
|
|
Error IndirectSpecular::initInternal()
|
|
Error IndirectSpecular::initInternal()
|
|
|
{
|
|
{
|
|
|
- const U32 width = m_r->getInternalResolution().x() / 2;
|
|
|
|
|
- const U32 height = m_r->getInternalResolution().y() / 2;
|
|
|
|
|
|
|
+ const UVec2 size = m_r->getInternalResolution() / 2;
|
|
|
const Bool preferCompute = getConfig().getRPreferCompute();
|
|
const Bool preferCompute = getConfig().getRPreferCompute();
|
|
|
|
|
|
|
|
- ANKI_R_LOGV("Initializing indirect specular. Resolution %ux%u", width, height);
|
|
|
|
|
|
|
+ ANKI_R_LOGV("Initializing indirect specular. Resolution %ux%u", size.x(), size.y());
|
|
|
|
|
|
|
|
ANKI_CHECK(getResourceManager().loadResource("EngineAssets/BlueNoise_Rgba8_64x64.png", m_noiseImage));
|
|
ANKI_CHECK(getResourceManager().loadResource("EngineAssets/BlueNoise_Rgba8_64x64.png", m_noiseImage));
|
|
|
|
|
|
|
@@ -44,7 +43,8 @@ Error IndirectSpecular::initInternal()
|
|
|
|
|
|
|
|
usage |= (preferCompute) ? TextureUsageBit::IMAGE_COMPUTE_WRITE : TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE;
|
|
usage |= (preferCompute) ? TextureUsageBit::IMAGE_COMPUTE_WRITE : TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE;
|
|
|
|
|
|
|
|
- TextureInitInfo texInit = m_r->create2DRenderTargetInitInfo(width, height, m_r->getHdrFormat(), usage, "SSR #1");
|
|
|
|
|
|
|
+ TextureInitInfo texInit =
|
|
|
|
|
+ m_r->create2DRenderTargetInitInfo(size.x(), size.y(), m_r->getHdrFormat(), usage, "SSR #1");
|
|
|
m_rts[0] = m_r->createAndClearRenderTarget(texInit, TextureUsageBit::ALL_SAMPLED);
|
|
m_rts[0] = m_r->createAndClearRenderTarget(texInit, TextureUsageBit::ALL_SAMPLED);
|
|
|
texInit.setName("SSR #2");
|
|
texInit.setName("SSR #2");
|
|
|
m_rts[1] = m_r->createAndClearRenderTarget(texInit, TextureUsageBit::ALL_SAMPLED);
|
|
m_rts[1] = m_r->createAndClearRenderTarget(texInit, TextureUsageBit::ALL_SAMPLED);
|
|
@@ -65,6 +65,51 @@ Error IndirectSpecular::initInternal()
|
|
|
m_prog->getOrCreateVariant(variantInit, variant);
|
|
m_prog->getOrCreateVariant(variantInit, variant);
|
|
|
m_grProg = variant->getProgram();
|
|
m_grProg = variant->getProgram();
|
|
|
|
|
|
|
|
|
|
+ // Init VRS SRI generation
|
|
|
|
|
+ const Bool enableVrs = getGrManager().getDeviceCapabilities().m_vrs && getConfig().getRVrs() && !preferCompute;
|
|
|
|
|
+ if(enableVrs)
|
|
|
|
|
+ {
|
|
|
|
|
+ m_vrs.m_sriTexelDimension = getGrManager().getDeviceCapabilities().m_minShadingRateImageTexelSize;
|
|
|
|
|
+ ANKI_ASSERT(m_vrs.m_sriTexelDimension == 8 || m_vrs.m_sriTexelDimension == 16);
|
|
|
|
|
+
|
|
|
|
|
+ const UVec2 rez = (size + m_vrs.m_sriTexelDimension - 1) / m_vrs.m_sriTexelDimension;
|
|
|
|
|
+ m_vrs.m_rtHandle =
|
|
|
|
|
+ m_r->create2DRenderTargetDescription(rez.x(), rez.y(), Format::R8_UINT, "IndirectSpecularVrsSri");
|
|
|
|
|
+ m_vrs.m_rtHandle.bake();
|
|
|
|
|
+
|
|
|
|
|
+ ANKI_CHECK(getResourceManager().loadResource("ShaderBinaries/IndirectSpecularVrsSriGeneration.ankiprogbin",
|
|
|
|
|
+ m_vrs.m_prog));
|
|
|
|
|
+
|
|
|
|
|
+ ShaderProgramResourceVariantInitInfo variantInit(m_vrs.m_prog);
|
|
|
|
|
+ variantInit.addMutation("SRI_TEXEL_DIMENSION", m_vrs.m_sriTexelDimension);
|
|
|
|
|
+
|
|
|
|
|
+ if(m_vrs.m_sriTexelDimension == 16 && getGrManager().getDeviceCapabilities().m_minSubgroupSize >= 32)
|
|
|
|
|
+ {
|
|
|
|
|
+ // Algorithm's workgroup size is 32, GPU's subgroup size is min 32 -> each workgroup has 1 subgroup -> No
|
|
|
|
|
+ // need for shared mem
|
|
|
|
|
+ variantInit.addMutation("SHARED_MEMORY", 0);
|
|
|
|
|
+ }
|
|
|
|
|
+ else if(m_vrs.m_sriTexelDimension == 8 && getGrManager().getDeviceCapabilities().m_minSubgroupSize >= 16)
|
|
|
|
|
+ {
|
|
|
|
|
+ // Algorithm's workgroup size is 16, GPU's subgroup size is min 16 -> each workgroup has 1 subgroup -> No
|
|
|
|
|
+ // need for shared mem
|
|
|
|
|
+ variantInit.addMutation("SHARED_MEMORY", 0);
|
|
|
|
|
+ }
|
|
|
|
|
+ else
|
|
|
|
|
+ {
|
|
|
|
|
+ variantInit.addMutation("SHARED_MEMORY", 1);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ const ShaderProgramResourceVariant* variant;
|
|
|
|
|
+ m_vrs.m_prog->getOrCreateVariant(variantInit, variant);
|
|
|
|
|
+ m_vrs.m_grProg = variant->getProgram();
|
|
|
|
|
+
|
|
|
|
|
+ ANKI_CHECK(getResourceManager().loadResource("ShaderBinaries/VrsSriVisualizeRenderTarget.ankiprogbin",
|
|
|
|
|
+ m_vrs.m_visualizeProg));
|
|
|
|
|
+ m_vrs.m_visualizeProg->getOrCreateVariant(variant);
|
|
|
|
|
+ m_vrs.m_visualizeGrProg = variant->getProgram();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
return Error::NONE;
|
|
return Error::NONE;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -72,6 +117,8 @@ void IndirectSpecular::populateRenderGraph(RenderingContext& ctx)
|
|
|
{
|
|
{
|
|
|
RenderGraphDescription& rgraph = ctx.m_renderGraphDescr;
|
|
RenderGraphDescription& rgraph = ctx.m_renderGraphDescr;
|
|
|
const Bool preferCompute = getConfig().getRPreferCompute();
|
|
const Bool preferCompute = getConfig().getRPreferCompute();
|
|
|
|
|
+ const Bool enableVrs = getGrManager().getDeviceCapabilities().m_vrs && getConfig().getRVrs() && !preferCompute;
|
|
|
|
|
+ const Bool fbDescrHasVrs = m_fbDescr.m_shadingRateAttachmentTexelWidth > 0;
|
|
|
|
|
|
|
|
// Create/import RTs
|
|
// Create/import RTs
|
|
|
const U32 readRtIdx = m_r->getFrameCount() & 1;
|
|
const U32 readRtIdx = m_r->getFrameCount() & 1;
|
|
@@ -88,45 +135,108 @@ void IndirectSpecular::populateRenderGraph(RenderingContext& ctx)
|
|
|
m_rtsImportedOnce = true;
|
|
m_rtsImportedOnce = true;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- // Create pass
|
|
|
|
|
- RenderPassDescriptionBase* ppass;
|
|
|
|
|
- TextureUsageBit readUsage;
|
|
|
|
|
- TextureUsageBit writeUsage;
|
|
|
|
|
- if(preferCompute)
|
|
|
|
|
|
|
+ // Re-bake FB descriptor
|
|
|
|
|
+ if(!preferCompute && enableVrs != fbDescrHasVrs)
|
|
|
{
|
|
{
|
|
|
- ComputeRenderPassDescription& pass = rgraph.newComputeRenderPass("SSR");
|
|
|
|
|
-
|
|
|
|
|
- ppass = &pass;
|
|
|
|
|
- readUsage = TextureUsageBit::SAMPLED_COMPUTE;
|
|
|
|
|
- writeUsage = TextureUsageBit::IMAGE_COMPUTE_WRITE;
|
|
|
|
|
|
|
+ // Re-bake the FB descriptor if the VRS state has changed
|
|
|
|
|
+
|
|
|
|
|
+ if(enableVrs)
|
|
|
|
|
+ {
|
|
|
|
|
+ m_fbDescr.m_shadingRateAttachmentTexelWidth = m_vrs.m_sriTexelDimension;
|
|
|
|
|
+ m_fbDescr.m_shadingRateAttachmentTexelHeight = m_vrs.m_sriTexelDimension;
|
|
|
|
|
+ }
|
|
|
|
|
+ else
|
|
|
|
|
+ {
|
|
|
|
|
+ m_fbDescr.m_shadingRateAttachmentTexelWidth = 0;
|
|
|
|
|
+ m_fbDescr.m_shadingRateAttachmentTexelHeight = 0;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ m_fbDescr.bake();
|
|
|
}
|
|
}
|
|
|
- else
|
|
|
|
|
|
|
+
|
|
|
|
|
+ // VRS SRI
|
|
|
|
|
+ if(enableVrs)
|
|
|
{
|
|
{
|
|
|
- GraphicsRenderPassDescription& pass = rgraph.newGraphicsRenderPass("SSR");
|
|
|
|
|
- pass.setFramebufferInfo(m_fbDescr, {m_runCtx.m_rts[WRITE]});
|
|
|
|
|
|
|
+ m_runCtx.m_sriRt = rgraph.newRenderTarget(m_vrs.m_rtHandle);
|
|
|
|
|
|
|
|
- ppass = &pass;
|
|
|
|
|
- readUsage = TextureUsageBit::SAMPLED_FRAGMENT;
|
|
|
|
|
- writeUsage = TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE;
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ ComputeRenderPassDescription& pass = rgraph.newComputeRenderPass("IndirectSpecular VRS SRI gen");
|
|
|
|
|
|
|
|
- ppass->newDependency(RenderPassDependency(m_runCtx.m_rts[WRITE], writeUsage));
|
|
|
|
|
- ppass->newDependency(RenderPassDependency(m_runCtx.m_rts[READ], readUsage));
|
|
|
|
|
- ppass->newDependency(RenderPassDependency(m_r->getGBuffer().getColorRt(1), readUsage));
|
|
|
|
|
- ppass->newDependency(RenderPassDependency(m_r->getGBuffer().getColorRt(2), readUsage));
|
|
|
|
|
|
|
+ pass.newDependency(RenderPassDependency(m_runCtx.m_sriRt, TextureUsageBit::IMAGE_COMPUTE_WRITE));
|
|
|
|
|
+ pass.newDependency(RenderPassDependency(m_runCtx.m_rts[READ], TextureUsageBit::SAMPLED_COMPUTE));
|
|
|
|
|
|
|
|
- TextureSubresourceInfo hizSubresource;
|
|
|
|
|
- hizSubresource.m_mipmapCount = min(getConfig().getRSsrDepthLod() + 1, m_r->getDepthDownscale().getMipmapCount());
|
|
|
|
|
- ppass->newDependency(RenderPassDependency(m_r->getDepthDownscale().getHiZRt(), readUsage, hizSubresource));
|
|
|
|
|
|
|
+ pass.setWork([this, &ctx](RenderPassWorkContext& rgraphCtx) {
|
|
|
|
|
+ const UVec2 viewport = m_r->getInternalResolution() / 2u;
|
|
|
|
|
+
|
|
|
|
|
+ CommandBufferPtr& cmdb = rgraphCtx.m_commandBuffer;
|
|
|
|
|
+
|
|
|
|
|
+ cmdb->bindShaderProgram(m_vrs.m_grProg);
|
|
|
|
|
+
|
|
|
|
|
+ rgraphCtx.bindColorTexture(0, 0, m_runCtx.m_rts[READ]);
|
|
|
|
|
+ cmdb->bindSampler(0, 1, m_r->getSamplers().m_nearestNearestClamp);
|
|
|
|
|
+ rgraphCtx.bindImage(0, 2, m_runCtx.m_sriRt);
|
|
|
|
|
+
|
|
|
|
|
+ class
|
|
|
|
|
+ {
|
|
|
|
|
+ public:
|
|
|
|
|
+ Vec4 m_v4;
|
|
|
|
|
+ } pc;
|
|
|
|
|
|
|
|
- ppass->newDependency(RenderPassDependency(m_r->getProbeReflections().getReflectionRt(), readUsage));
|
|
|
|
|
|
|
+ pc.m_v4 = Vec4(1.0f / Vec2(viewport), getConfig().getRSsrVrsThreshold(), 0.0f);
|
|
|
|
|
|
|
|
- ppass->newDependency(RenderPassDependency(m_r->getMotionVectors().getMotionVectorsRt(), readUsage));
|
|
|
|
|
- ppass->newDependency(RenderPassDependency(m_r->getMotionVectors().getHistoryLengthRt(), readUsage));
|
|
|
|
|
|
|
+ cmdb->setPushConstants(&pc, sizeof(pc));
|
|
|
|
|
|
|
|
- ppass->setWork([this, &ctx](RenderPassWorkContext& rgraphCtx) {
|
|
|
|
|
- run(ctx, rgraphCtx);
|
|
|
|
|
- });
|
|
|
|
|
|
|
+ dispatchPPCompute(cmdb, m_vrs.m_sriTexelDimension, m_vrs.m_sriTexelDimension, viewport.x(), viewport.y());
|
|
|
|
|
+ });
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // Create pass
|
|
|
|
|
+ {
|
|
|
|
|
+ RenderPassDescriptionBase* ppass;
|
|
|
|
|
+ TextureUsageBit readUsage;
|
|
|
|
|
+ TextureUsageBit writeUsage;
|
|
|
|
|
+ if(preferCompute)
|
|
|
|
|
+ {
|
|
|
|
|
+ ComputeRenderPassDescription& pass = rgraph.newComputeRenderPass("SSR");
|
|
|
|
|
+
|
|
|
|
|
+ ppass = &pass;
|
|
|
|
|
+ readUsage = TextureUsageBit::SAMPLED_COMPUTE;
|
|
|
|
|
+ writeUsage = TextureUsageBit::IMAGE_COMPUTE_WRITE;
|
|
|
|
|
+ }
|
|
|
|
|
+ else
|
|
|
|
|
+ {
|
|
|
|
|
+ GraphicsRenderPassDescription& pass = rgraph.newGraphicsRenderPass("SSR");
|
|
|
|
|
+ pass.setFramebufferInfo(m_fbDescr, {m_runCtx.m_rts[WRITE]}, {},
|
|
|
|
|
+ (enableVrs) ? m_runCtx.m_sriRt : RenderTargetHandle());
|
|
|
|
|
+
|
|
|
|
|
+ ppass = &pass;
|
|
|
|
|
+ readUsage = TextureUsageBit::SAMPLED_FRAGMENT;
|
|
|
|
|
+ writeUsage = TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE;
|
|
|
|
|
+
|
|
|
|
|
+ if(enableVrs)
|
|
|
|
|
+ {
|
|
|
|
|
+ ppass->newDependency(RenderPassDependency(m_runCtx.m_sriRt, TextureUsageBit::FRAMEBUFFER_SHADING_RATE));
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ ppass->newDependency(RenderPassDependency(m_runCtx.m_rts[WRITE], writeUsage));
|
|
|
|
|
+ ppass->newDependency(RenderPassDependency(m_runCtx.m_rts[READ], readUsage));
|
|
|
|
|
+ ppass->newDependency(RenderPassDependency(m_r->getGBuffer().getColorRt(1), readUsage));
|
|
|
|
|
+ ppass->newDependency(RenderPassDependency(m_r->getGBuffer().getColorRt(2), readUsage));
|
|
|
|
|
+
|
|
|
|
|
+ TextureSubresourceInfo hizSubresource;
|
|
|
|
|
+ hizSubresource.m_mipmapCount =
|
|
|
|
|
+ min(getConfig().getRSsrDepthLod() + 1, m_r->getDepthDownscale().getMipmapCount());
|
|
|
|
|
+ ppass->newDependency(RenderPassDependency(m_r->getDepthDownscale().getHiZRt(), readUsage, hizSubresource));
|
|
|
|
|
+
|
|
|
|
|
+ ppass->newDependency(RenderPassDependency(m_r->getProbeReflections().getReflectionRt(), readUsage));
|
|
|
|
|
+
|
|
|
|
|
+ ppass->newDependency(RenderPassDependency(m_r->getMotionVectors().getMotionVectorsRt(), readUsage));
|
|
|
|
|
+ ppass->newDependency(RenderPassDependency(m_r->getMotionVectors().getHistoryLengthRt(), readUsage));
|
|
|
|
|
+
|
|
|
|
|
+ ppass->setWork([this, &ctx](RenderPassWorkContext& rgraphCtx) {
|
|
|
|
|
+ run(ctx, rgraphCtx);
|
|
|
|
|
+ });
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void IndirectSpecular::run(const RenderingContext& ctx, RenderPassWorkContext& rgraphCtx)
|
|
void IndirectSpecular::run(const RenderingContext& ctx, RenderPassWorkContext& rgraphCtx)
|
|
@@ -191,4 +301,19 @@ void IndirectSpecular::run(const RenderingContext& ctx, RenderPassWorkContext& r
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+void IndirectSpecular::getDebugRenderTarget(CString rtName, RenderTargetHandle& handle,
|
|
|
|
|
+ ShaderProgramPtr& optionalShaderProgram) const
|
|
|
|
|
+{
|
|
|
|
|
+ if(rtName == "SSR")
|
|
|
|
|
+ {
|
|
|
|
|
+ handle = m_runCtx.m_rts[WRITE];
|
|
|
|
|
+ }
|
|
|
|
|
+ else
|
|
|
|
|
+ {
|
|
|
|
|
+ ANKI_ASSERT(rtName == "IndirectSpecularVrsSri");
|
|
|
|
|
+ handle = m_runCtx.m_sriRt;
|
|
|
|
|
+ optionalShaderProgram = m_vrs.m_visualizeGrProg;
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
} // end namespace anki
|
|
} // end namespace anki
|