DepthDownscale.cpp 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  1. // Copyright (C) 2009-2021, Panagiotis Christopoulos Charitos and contributors.
  2. // All rights reserved.
  3. // Code licensed under the BSD License.
  4. // http://www.anki3d.org/LICENSE
  5. #include <AnKi/Renderer/DepthDownscale.h>
  6. #include <AnKi/Renderer/Renderer.h>
  7. #include <AnKi/Renderer/GBuffer.h>
  8. #if ANKI_COMPILER_GCC_COMPATIBLE
  9. # pragma GCC diagnostic push
  10. # pragma GCC diagnostic ignored "-Wunused-function"
  11. # pragma GCC diagnostic ignored "-Wignored-qualifiers"
  12. #endif
  13. #define A_CPU
  14. #include <ThirdParty/FidelityFX/ffx_a.h>
  15. #include <ThirdParty/FidelityFX/ffx_spd.h>
  16. #if ANKI_COMPILER_GCC_COMPATIBLE
  17. # pragma GCC diagnostic pop
  18. #endif
  19. namespace anki {
  20. DepthDownscale::~DepthDownscale()
  21. {
  22. if(m_clientBufferAddr)
  23. {
  24. m_clientBuffer->unmap();
  25. }
  26. }
  27. Error DepthDownscale::initInternal(const ConfigSet&)
  28. {
  29. const U32 width = m_r->getInternalResolution().x() >> 1;
  30. const U32 height = m_r->getInternalResolution().y() >> 1;
  31. m_mipCount = computeMaxMipmapCount2d(width, height, HIERARCHICAL_Z_MIN_HEIGHT);
  32. m_lastMipSize.x() = width >> (m_mipCount - 1);
  33. m_lastMipSize.y() = height >> (m_mipCount - 1);
  34. ANKI_R_LOGI("Initializing HiZ. Mip count %u, last mip size %ux%u", m_mipCount, m_lastMipSize.x(),
  35. m_lastMipSize.y());
  36. const Bool supportsReductionSampler = getGrManager().getDeviceCapabilities().m_samplingFilterMinMax;
  37. // Create RT descr
  38. {
  39. TextureInitInfo texInit = m_r->create2DRenderTargetInitInfo(
  40. width, height, Format::R32_SFLOAT, TextureUsageBit::ALL_SAMPLED | TextureUsageBit::IMAGE_COMPUTE_WRITE,
  41. "HiZ");
  42. texInit.m_mipmapCount = U8(m_mipCount);
  43. texInit.m_initialUsage = TextureUsageBit::SAMPLED_FRAGMENT;
  44. m_hizTex = m_r->createAndClearRenderTarget(texInit);
  45. }
  46. // Progs
  47. {
  48. ANKI_CHECK(getResourceManager().loadResource("Shaders/DepthDownscale.ankiprog", m_prog));
  49. ShaderProgramResourceVariantInitInfo variantInitInfo(m_prog);
  50. variantInitInfo.addMutation("SAMPLE_RESOLVE_TYPE", 2);
  51. variantInitInfo.addMutation("WAVE_OPERATIONS", 0);
  52. variantInitInfo.addMutation("REDUCTION_SAMPLER", supportsReductionSampler);
  53. const ShaderProgramResourceVariant* variant;
  54. m_prog->getOrCreateVariant(variantInitInfo, variant);
  55. m_grProg = variant->getProgram();
  56. }
  57. // Reduction sampler
  58. if(supportsReductionSampler)
  59. {
  60. SamplerInitInfo sinit("HiZReduction");
  61. sinit.m_addressing = SamplingAddressing::CLAMP;
  62. sinit.m_mipmapFilter = SamplingFilter::MAX;
  63. sinit.m_minMagFilter = SamplingFilter::MAX;
  64. m_reductionSampler = getGrManager().newSampler(sinit);
  65. }
  66. // Counter buffer
  67. {
  68. BufferInitInfo buffInit("HiZCounterBuffer");
  69. buffInit.m_size = sizeof(U32);
  70. buffInit.m_usage = BufferUsageBit::STORAGE_COMPUTE_WRITE | BufferUsageBit::TRANSFER_DESTINATION;
  71. m_counterBuffer = getGrManager().newBuffer(buffInit);
  72. }
  73. // Copy to buffer
  74. {
  75. // Create buffer
  76. BufferInitInfo buffInit("HiZ Client");
  77. buffInit.m_mapAccess = BufferMapAccessBit::READ;
  78. buffInit.m_size = PtrSize(m_lastMipSize.y()) * PtrSize(m_lastMipSize.x()) * sizeof(F32);
  79. buffInit.m_usage = BufferUsageBit::STORAGE_COMPUTE_WRITE;
  80. m_clientBuffer = getGrManager().newBuffer(buffInit);
  81. m_clientBufferAddr = m_clientBuffer->map(0, buffInit.m_size, BufferMapAccessBit::READ);
  82. // Fill the buffer with 1.0f
  83. for(U32 i = 0; i < m_lastMipSize.x() * m_lastMipSize.y(); ++i)
  84. {
  85. static_cast<F32*>(m_clientBufferAddr)[i] = 1.0f;
  86. }
  87. }
  88. return Error::NONE;
  89. }
  90. Error DepthDownscale::init(const ConfigSet& cfg)
  91. {
  92. ANKI_R_LOGI("Initializing depth downscale passes");
  93. const Error err = initInternal(cfg);
  94. if(err)
  95. {
  96. ANKI_R_LOGE("Failed to initialize depth downscale passes");
  97. }
  98. return err;
  99. }
  100. void DepthDownscale::importRenderTargets(RenderingContext& ctx)
  101. {
  102. RenderGraphDescription& rgraph = ctx.m_renderGraphDescr;
  103. // Import RT
  104. if(m_hizTexImportedOnce)
  105. {
  106. m_runCtx.m_hizRt = rgraph.importRenderTarget(m_hizTex);
  107. }
  108. else
  109. {
  110. m_runCtx.m_hizRt = rgraph.importRenderTarget(m_hizTex, TextureUsageBit::SAMPLED_FRAGMENT);
  111. m_hizTexImportedOnce = true;
  112. }
  113. }
  114. void DepthDownscale::populateRenderGraph(RenderingContext& ctx)
  115. {
  116. RenderGraphDescription& rgraph = ctx.m_renderGraphDescr;
  117. ComputeRenderPassDescription& pass = rgraph.newComputeRenderPass("HiZ");
  118. pass.newDependency(RenderPassDependency(m_r->getGBuffer().getDepthRt(), TextureUsageBit::SAMPLED_COMPUTE,
  119. TextureSubresourceInfo(DepthStencilAspectBit::DEPTH)));
  120. for(U32 mip = 0; mip < m_mipCount; ++mip)
  121. {
  122. TextureSubresourceInfo subresource;
  123. subresource.m_firstMipmap = mip;
  124. pass.newDependency(RenderPassDependency(m_runCtx.m_hizRt, TextureUsageBit::IMAGE_COMPUTE_WRITE, subresource));
  125. }
  126. pass.setWork([this](RenderPassWorkContext& rgraphCtx) {
  127. CommandBufferPtr& cmdb = rgraphCtx.m_commandBuffer;
  128. // Zero the counter buffer before everything else
  129. if(ANKI_UNLIKELY(!m_counterBufferZeroed))
  130. {
  131. m_counterBufferZeroed = true;
  132. cmdb->fillBuffer(m_counterBuffer, 0, MAX_PTR_SIZE, 0);
  133. cmdb->setBufferBarrier(m_counterBuffer, BufferUsageBit::TRANSFER_DESTINATION,
  134. BufferUsageBit::STORAGE_COMPUTE_WRITE, 0, MAX_PTR_SIZE);
  135. }
  136. cmdb->bindShaderProgram(m_grProg);
  137. varAU2(dispatchThreadGroupCountXY);
  138. varAU2(workGroupOffset); // needed if Left and Top are not 0,0
  139. varAU2(numWorkGroupsAndMips);
  140. varAU4(rectInfo) = initAU4(0, 0, m_r->getInternalResolution().x(), m_r->getInternalResolution().y());
  141. SpdSetup(dispatchThreadGroupCountXY, workGroupOffset, numWorkGroupsAndMips, rectInfo);
  142. SpdSetup(dispatchThreadGroupCountXY, workGroupOffset, numWorkGroupsAndMips, rectInfo, m_mipCount);
  143. class PC
  144. {
  145. public:
  146. U32 m_workgroupCount;
  147. U32 m_mipmapCount;
  148. Vec2 m_srcTexSizeOverOne;
  149. U32 m_lastMipWidth;
  150. U32 m_padding[3u];
  151. } pc;
  152. pc.m_workgroupCount = numWorkGroupsAndMips[0];
  153. pc.m_mipmapCount = numWorkGroupsAndMips[1];
  154. pc.m_srcTexSizeOverOne = 1.0f / Vec2(m_r->getInternalResolution());
  155. pc.m_lastMipWidth = m_lastMipSize.x();
  156. cmdb->setPushConstants(&pc, sizeof(pc));
  157. constexpr U32 maxMipsSpdCanProduce = 12;
  158. for(U32 mip = 0; mip < maxMipsSpdCanProduce; ++mip)
  159. {
  160. TextureSubresourceInfo subresource;
  161. if(mip < m_mipCount)
  162. {
  163. subresource.m_firstMipmap = mip;
  164. }
  165. else
  166. {
  167. subresource.m_firstMipmap = 0;
  168. }
  169. rgraphCtx.bindImage(0, 0, m_runCtx.m_hizRt, subresource, mip);
  170. }
  171. if(m_mipCount >= 5)
  172. {
  173. TextureSubresourceInfo subresource;
  174. subresource.m_firstMipmap = 4;
  175. rgraphCtx.bindImage(0, 1, m_runCtx.m_hizRt, subresource);
  176. }
  177. else
  178. {
  179. // Bind something random
  180. TextureSubresourceInfo subresource;
  181. subresource.m_firstMipmap = 0;
  182. rgraphCtx.bindImage(0, 1, m_runCtx.m_hizRt, subresource);
  183. }
  184. cmdb->bindStorageBuffer(0, 2, m_counterBuffer, 0, MAX_PTR_SIZE);
  185. cmdb->bindStorageBuffer(0, 3, m_clientBuffer, 0, MAX_PTR_SIZE);
  186. cmdb->bindSampler(0, 4, (doesSamplerReduction()) ? m_reductionSampler : m_r->getSamplers().m_trilinearClamp);
  187. rgraphCtx.bindTexture(0, 5, m_r->getGBuffer().getDepthRt(),
  188. TextureSubresourceInfo(DepthStencilAspectBit::DEPTH));
  189. cmdb->dispatchCompute(dispatchThreadGroupCountXY[0], dispatchThreadGroupCountXY[1], 1);
  190. });
  191. }
  192. } // end namespace anki