Ssao.cpp 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295
  1. // Copyright (C) 2009-present, 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/Ssao.h>
  6. #include <AnKi/Renderer/Renderer.h>
  7. #include <AnKi/Renderer/GBuffer.h>
  8. #include <AnKi/Renderer/MotionVectors.h>
  9. #include <AnKi/Renderer/DepthDownscale.h>
  10. #include <AnKi/Renderer/HistoryLength.h>
  11. #include <AnKi/Util/Tracer.h>
  12. namespace anki {
  13. Error Ssao::init()
  14. {
  15. const UVec2 rez = (g_cvarRenderSsaoQuarterRez) ? getRenderer().getInternalResolution() / 2 : getRenderer().getInternalResolution();
  16. const Bool preferCompute = g_cvarRenderPreferCompute;
  17. {
  18. TextureUsageBit usage = TextureUsageBit::kAllSrv;
  19. usage |= (preferCompute) ? TextureUsageBit::kUavCompute : TextureUsageBit::kRtvDsvWrite;
  20. TextureInitInfo texInit = getRenderer().create2DRenderTargetInitInfo(rez.x, rez.y, Format::kR8G8B8A8_Snorm, usage, "Bent normals + SSAO #1");
  21. m_tex[0] = getRenderer().createAndClearRenderTarget(texInit, TextureUsageBit::kAllSrv);
  22. texInit.setName("Bent normals + SSAO #2");
  23. m_tex[1] = getRenderer().createAndClearRenderTarget(texInit, TextureUsageBit::kAllSrv);
  24. }
  25. m_bentNormalsAndSsaoRtDescr = getRenderer().create2DRenderTargetDescription(rez.x, rez.y, Format::kR8G8B8A8_Snorm, "Bent normals + SSAO temp");
  26. m_bentNormalsAndSsaoRtDescr.bake();
  27. const Array<SubMutation, 2> mutation = {{{"SPATIAL_DENOISE_SAMPLE_COUNT", MutatorValue(g_cvarRenderSsaoSpatialDenoiseSampleCout)},
  28. {"DENOISING_QUARTER_RESOLUTION", g_cvarRenderSsaoQuarterRez}}};
  29. ANKI_CHECK(loadShaderProgram("ShaderBinaries/Ssao.ankiprogbin", mutation, m_prog, m_grProg, "Ssao"));
  30. ANKI_CHECK(loadShaderProgram("ShaderBinaries/Ssao.ankiprogbin", mutation, m_prog, m_spatialDenoiseVerticalGrProg, "SsaoSpatialDenoiseVertical"));
  31. ANKI_CHECK(
  32. loadShaderProgram("ShaderBinaries/Ssao.ankiprogbin", mutation, m_prog, m_spatialDenoiseHorizontalGrProg, "SsaoSpatialDenoiseHorizontal"));
  33. ANKI_CHECK(loadShaderProgram("ShaderBinaries/Ssao.ankiprogbin", mutation, m_prog, m_tempralDenoiseGrProg, "SsaoTemporalDenoise"));
  34. ANKI_CHECK(ResourceManager::getSingleton().loadResource("EngineAssets/BlueNoise_Rgba8_64x64.png", m_noiseImage));
  35. return Error::kNone;
  36. }
  37. void Ssao::populateRenderGraph(RenderingContext& ctx)
  38. {
  39. ANKI_TRACE_SCOPED_EVENT(Ssao);
  40. RenderGraphBuilder& rgraph = ctx.m_renderGraphDescr;
  41. const Bool preferCompute = g_cvarRenderPreferCompute;
  42. const U32 readRtIdx = getRenderer().getFrameCount() & 1;
  43. const U32 writeRtIdx = !readRtIdx;
  44. RenderTargetHandle historyRt;
  45. RenderTargetHandle finalRt;
  46. if(m_texImportedOnce) [[likely]]
  47. {
  48. finalRt = rgraph.importRenderTarget(m_tex[writeRtIdx].get());
  49. historyRt = rgraph.importRenderTarget(m_tex[readRtIdx].get());
  50. }
  51. else
  52. {
  53. finalRt = rgraph.importRenderTarget(m_tex[writeRtIdx].get(), TextureUsageBit::kAllSrv);
  54. historyRt = rgraph.importRenderTarget(m_tex[readRtIdx].get(), TextureUsageBit::kAllSrv);
  55. m_texImportedOnce = true;
  56. }
  57. m_runCtx.m_finalRt = finalRt;
  58. const RenderTargetHandle depthRt = (g_cvarRenderSsaoQuarterRez) ? getDepthDownscale().getRt() : getGBuffer().getDepthRt();
  59. const RenderTargetHandle bentNormalsAndSsaoTempRt = rgraph.newRenderTarget(m_bentNormalsAndSsaoRtDescr);
  60. TextureUsageBit readUsage;
  61. TextureUsageBit writeUsage;
  62. if(preferCompute)
  63. {
  64. readUsage = TextureUsageBit::kSrvCompute;
  65. writeUsage = TextureUsageBit::kUavCompute;
  66. }
  67. else
  68. {
  69. readUsage = TextureUsageBit::kSrvPixel;
  70. writeUsage = TextureUsageBit::kRtvDsvWrite;
  71. }
  72. // Main pass
  73. {
  74. RenderPassBase* ppass;
  75. if(preferCompute)
  76. {
  77. NonGraphicsRenderPass& pass = rgraph.newNonGraphicsRenderPass("SSAO");
  78. ppass = &pass;
  79. }
  80. else
  81. {
  82. GraphicsRenderPass& pass = rgraph.newGraphicsRenderPass("SSAO");
  83. pass.setRenderpassInfo({GraphicsRenderPassTargetDesc(finalRt)});
  84. ppass = &pass;
  85. }
  86. ppass->newTextureDependency(getGBuffer().getColorRt(2), readUsage);
  87. ppass->newTextureDependency(getDepthDownscale().getRt(), readUsage);
  88. ppass->newTextureDependency(finalRt, writeUsage);
  89. ppass->setWork([this, &ctx, finalRt](RenderPassWorkContext& rgraphCtx) {
  90. ANKI_TRACE_SCOPED_EVENT(SsaoMain);
  91. CommandBuffer& cmdb = *rgraphCtx.m_commandBuffer;
  92. cmdb.bindShaderProgram(m_grProg.get());
  93. rgraphCtx.bindSrv(0, 0, getGBuffer().getColorRt(2));
  94. rgraphCtx.bindSrv(1, 0, getDepthDownscale().getRt());
  95. cmdb.bindSrv(2, 0, TextureView(&m_noiseImage->getTexture(), TextureSubresourceDesc::all()));
  96. cmdb.bindSampler(0, 0, getRenderer().getSamplers().m_trilinearRepeat.get());
  97. cmdb.bindSampler(1, 0, getRenderer().getSamplers().m_trilinearClamp.get());
  98. const UVec2 rez = getRenderer().getInternalResolution() / 2u;
  99. SsaoConstants& consts = *allocateAndBindConstants<SsaoConstants>(cmdb, 0, 0);
  100. consts.m_radius = g_cvarRenderSsaoRadius;
  101. consts.m_sampleCount = g_cvarRenderSsaoSampleCount;
  102. consts.m_viewportSizef = Vec2(rez);
  103. consts.m_unprojectionParameters = ctx.m_matrices.m_unprojectionParameters;
  104. consts.m_projectionMat00 = ctx.m_matrices.m_projection(0, 0);
  105. consts.m_projectionMat11 = ctx.m_matrices.m_projection(1, 1);
  106. consts.m_projectionMat22 = ctx.m_matrices.m_projection(2, 2);
  107. consts.m_projectionMat23 = ctx.m_matrices.m_projection(2, 3);
  108. consts.m_frameCount = getRenderer().getFrameCount() % kMaxU32;
  109. consts.m_ssaoPower = g_cvarRenderSsaoPower;
  110. consts.m_viewMat = ctx.m_matrices.m_view;
  111. consts.m_viewToWorldMat = ctx.m_matrices.m_cameraTransform;
  112. if(g_cvarRenderPreferCompute)
  113. {
  114. rgraphCtx.bindUav(0, 0, finalRt);
  115. dispatchPPCompute(cmdb, 8, 8, rez.x, rez.y);
  116. }
  117. else
  118. {
  119. cmdb.setViewport(0, 0, rez.x, rez.y);
  120. drawQuad(cmdb);
  121. }
  122. });
  123. }
  124. // Temporal denoise
  125. {
  126. RenderPassBase* ppass;
  127. if(preferCompute)
  128. {
  129. NonGraphicsRenderPass& pass = rgraph.newNonGraphicsRenderPass("SSAO temporal denoise");
  130. ppass = &pass;
  131. }
  132. else
  133. {
  134. GraphicsRenderPass& pass = rgraph.newGraphicsRenderPass("SSAO temporal denoise");
  135. pass.setRenderpassInfo({GraphicsRenderPassTargetDesc(bentNormalsAndSsaoTempRt)});
  136. ppass = &pass;
  137. }
  138. ppass->newTextureDependency(finalRt, readUsage);
  139. ppass->newTextureDependency(historyRt, readUsage);
  140. ppass->newTextureDependency(getMotionVectors().getMotionVectorsRt(), readUsage);
  141. ppass->newTextureDependency(bentNormalsAndSsaoTempRt, writeUsage);
  142. ppass->newTextureDependency(getHistoryLength().getRt(), readUsage);
  143. ppass->setWork([this, bentNormalsAndSsaoTempRt, finalRt, historyRt, &ctx](RenderPassWorkContext& rgraphCtx) {
  144. ANKI_TRACE_SCOPED_EVENT(SsaoTemporalDenoise);
  145. CommandBuffer& cmdb = *rgraphCtx.m_commandBuffer;
  146. cmdb.bindShaderProgram(m_tempralDenoiseGrProg.get());
  147. cmdb.bindSampler(0, 0, getRenderer().getSamplers().m_trilinearClamp.get());
  148. rgraphCtx.bindSrv(0, 0, finalRt);
  149. rgraphCtx.bindSrv(1, 0, historyRt);
  150. rgraphCtx.bindSrv(2, 0, getMotionVectors().getMotionVectorsRt());
  151. rgraphCtx.bindSrv(3, 0, getHistoryLength().getRt());
  152. cmdb.bindConstantBuffer(0, 0, ctx.m_globalRenderingConstantsBuffer);
  153. const UVec2 rez = (g_cvarRenderSsaoQuarterRez) ? getRenderer().getInternalResolution() / 2u : getRenderer().getInternalResolution();
  154. if(g_cvarRenderPreferCompute)
  155. {
  156. rgraphCtx.bindUav(0, 0, bentNormalsAndSsaoTempRt);
  157. dispatchPPCompute(cmdb, 8, 8, rez.x, rez.y);
  158. }
  159. else
  160. {
  161. cmdb.setViewport(0, 0, rez.x, rez.y);
  162. drawQuad(cmdb);
  163. }
  164. });
  165. }
  166. // Spatial denoise vertical
  167. {
  168. RenderPassBase* ppass;
  169. if(preferCompute)
  170. {
  171. NonGraphicsRenderPass& pass = rgraph.newNonGraphicsRenderPass("SSAO spatial denoise vertical");
  172. ppass = &pass;
  173. }
  174. else
  175. {
  176. GraphicsRenderPass& pass = rgraph.newGraphicsRenderPass("SSAO spatial denoise vertical");
  177. pass.setRenderpassInfo({GraphicsRenderPassTargetDesc(historyRt)});
  178. ppass = &pass;
  179. }
  180. ppass->newTextureDependency(bentNormalsAndSsaoTempRt, readUsage);
  181. ppass->newTextureDependency(depthRt, readUsage);
  182. ppass->newTextureDependency(historyRt, writeUsage);
  183. ppass->setWork([this, historyRt, bentNormalsAndSsaoTempRt, depthRt](RenderPassWorkContext& rgraphCtx) {
  184. ANKI_TRACE_SCOPED_EVENT(SsaoSpatialDenoise);
  185. CommandBuffer& cmdb = *rgraphCtx.m_commandBuffer;
  186. cmdb.bindShaderProgram(m_spatialDenoiseVerticalGrProg.get());
  187. cmdb.bindSampler(0, 0, getRenderer().getSamplers().m_trilinearClamp.get());
  188. rgraphCtx.bindSrv(0, 0, bentNormalsAndSsaoTempRt);
  189. rgraphCtx.bindSrv(1, 0, depthRt);
  190. const UVec2 rez = (g_cvarRenderSsaoQuarterRez) ? getRenderer().getInternalResolution() / 2u : getRenderer().getInternalResolution();
  191. if(g_cvarRenderPreferCompute)
  192. {
  193. rgraphCtx.bindUav(0, 0, historyRt);
  194. dispatchPPCompute(cmdb, 8, 8, rez.x, rez.y);
  195. }
  196. else
  197. {
  198. cmdb.setViewport(0, 0, rez.x, rez.y);
  199. drawQuad(cmdb);
  200. }
  201. });
  202. }
  203. // Spatial denoise horizontal
  204. {
  205. RenderPassBase* ppass;
  206. if(preferCompute)
  207. {
  208. NonGraphicsRenderPass& pass = rgraph.newNonGraphicsRenderPass("SSAO spatial denoise horizontal");
  209. ppass = &pass;
  210. }
  211. else
  212. {
  213. GraphicsRenderPass& pass = rgraph.newGraphicsRenderPass("SSAO spatial denoise horizontal");
  214. pass.setRenderpassInfo({GraphicsRenderPassTargetDesc(finalRt)});
  215. ppass = &pass;
  216. }
  217. ppass->newTextureDependency(historyRt, readUsage);
  218. ppass->newTextureDependency(depthRt, readUsage);
  219. ppass->newTextureDependency(finalRt, writeUsage);
  220. ppass->setWork([this, historyRt, finalRt, depthRt](RenderPassWorkContext& rgraphCtx) {
  221. ANKI_TRACE_SCOPED_EVENT(SsaoSpatialDenoise);
  222. CommandBuffer& cmdb = *rgraphCtx.m_commandBuffer;
  223. cmdb.bindShaderProgram(m_spatialDenoiseHorizontalGrProg.get());
  224. cmdb.bindSampler(0, 0, getRenderer().getSamplers().m_trilinearClamp.get());
  225. rgraphCtx.bindSrv(0, 0, historyRt);
  226. rgraphCtx.bindSrv(1, 0, depthRt);
  227. const UVec2 rez = (g_cvarRenderSsaoQuarterRez) ? getRenderer().getInternalResolution() / 2u : getRenderer().getInternalResolution();
  228. if(g_cvarRenderPreferCompute)
  229. {
  230. rgraphCtx.bindUav(0, 0, finalRt);
  231. dispatchPPCompute(cmdb, 8, 8, rez.x, rez.y);
  232. }
  233. else
  234. {
  235. cmdb.setViewport(0, 0, rez.x, rez.y);
  236. drawQuad(cmdb);
  237. }
  238. });
  239. }
  240. }
  241. } // end namespace anki