IndirectDiffuseClipmaps.cpp 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568
  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/IndirectDiffuseClipmaps.h>
  6. #include <AnKi/Renderer/Renderer.h>
  7. #include <AnKi/Renderer/GBuffer.h>
  8. #include <AnKi/Renderer/AccelerationStructureBuilder.h>
  9. #include <AnKi/Renderer/Sky.h>
  10. #include <AnKi/Renderer/ShadowMapping.h>
  11. #include <AnKi/Scene/Components/SkyboxComponent.h>
  12. #include <AnKi/Shaders/Include/MaterialTypes.h>
  13. #include <AnKi/Util/Tracer.h>
  14. #include <AnKi/GpuMemory/UnifiedGeometryBuffer.h>
  15. namespace anki {
  16. static void computeClipmapBounds(Vec3 cameraPos, Vec3 lookDir, Clipmap& clipmap)
  17. {
  18. const Vec3 offset = lookDir * kIndirectDiffuseClipmapForwardBias * F32(clipmap.m_index + 1);
  19. cameraPos += offset;
  20. const Vec3 halfSize = clipmap.m_size * 0.5;
  21. const Vec3 probeSize = clipmap.m_size / Vec3(clipmap.m_probeCounts);
  22. const Vec3 roundedPos = (cameraPos / probeSize).round() * probeSize;
  23. clipmap.m_aabbMin = roundedPos - halfSize;
  24. [[maybe_unused]] const Vec3 aabbMax = roundedPos + halfSize;
  25. ANKI_ASSERT(aabbMax - clipmap.m_aabbMin == clipmap.m_size);
  26. }
  27. Error IndirectDiffuseClipmaps::init()
  28. {
  29. ANKI_CHECK(RtMaterialFetchRendererObject::init());
  30. m_appliedGiRtDesc =
  31. getRenderer().create2DRenderTargetDescription(getRenderer().getInternalResolution().x(), getRenderer().getInternalResolution().y(),
  32. getRenderer().getHdrFormat(), "IndirectDiffuseClipmap: Final");
  33. m_appliedGiRtDesc.bake();
  34. m_clipmapInfo[0].m_probeCounts =
  35. UVec3(g_indirectDiffuseClipmapProbesXZCVar, g_indirectDiffuseClipmapProbesYCVar, g_indirectDiffuseClipmapProbesXZCVar);
  36. m_clipmapInfo[1].m_probeCounts = m_clipmapInfo[0].m_probeCounts;
  37. m_clipmapInfo[2].m_probeCounts = m_clipmapInfo[0].m_probeCounts;
  38. m_clipmapInfo[0].m_size = Vec3(g_indirectDiffuseClipmap0XZSizeCVar, g_indirectDiffuseClipmap0YSizeCVar, g_indirectDiffuseClipmap0XZSizeCVar);
  39. m_clipmapInfo[1].m_size = Vec3(g_indirectDiffuseClipmap1XZSizeCVar, g_indirectDiffuseClipmap1YSizeCVar, g_indirectDiffuseClipmap1XZSizeCVar);
  40. m_clipmapInfo[2].m_size = Vec3(g_indirectDiffuseClipmap2XZSizeCVar, g_indirectDiffuseClipmap2YSizeCVar, g_indirectDiffuseClipmap2XZSizeCVar);
  41. U32 probesPerClipmap = 0;
  42. for(U32 i = 0; i < kIndirectDiffuseClipmapCount; ++i)
  43. {
  44. const U32 count = m_clipmapInfo[i].m_probeCounts.x() * m_clipmapInfo[i].m_probeCounts.y() * m_clipmapInfo[i].m_probeCounts.z();
  45. m_clipmapInfo[i].m_probeCountTotal = count;
  46. m_clipmapInfo[i].m_index = i;
  47. if(i == 0)
  48. {
  49. probesPerClipmap = count;
  50. }
  51. else
  52. {
  53. ANKI_ASSERT(probesPerClipmap == count);
  54. }
  55. }
  56. for(U32 i = 0; i < kIndirectDiffuseClipmapCount; ++i)
  57. {
  58. m_probeValidityRtDescs[i] =
  59. getRenderer().create2DRenderTargetDescription(m_clipmapInfo[i].m_probeCounts.x(), m_clipmapInfo[i].m_probeCounts.z(), Format::kR8_Unorm,
  60. generateTempPassName("IndirectDiffuseClipmap: Probe validity #%u", i));
  61. m_probeValidityRtDescs[i].m_depth = m_clipmapInfo[i].m_probeCounts.y();
  62. m_probeValidityRtDescs[i].m_type = TextureType::k3D;
  63. m_probeValidityRtDescs[i].bake();
  64. }
  65. // Create the lighting result texture
  66. const U32 raysPerProbePerFrame = square(g_indirectDiffuseClipmapRadianceOctMapSize / 2);
  67. m_rtResultRtDesc = getRenderer().create2DRenderTargetDescription(probesPerClipmap, raysPerProbePerFrame * kIndirectDiffuseClipmapCount,
  68. Format::kR16G16B16A16_Sfloat, "IndirectDiffuseClipmap: RT result");
  69. m_rtResultRtDesc.bake();
  70. for(U32 clipmap = 0; clipmap < kIndirectDiffuseClipmapCount; ++clipmap)
  71. {
  72. TextureInitInfo volumeInit = getRenderer().create2DRenderTargetInitInfo(
  73. m_clipmapInfo[clipmap].m_probeCounts.x() * (g_indirectDiffuseClipmapRadianceOctMapSize + 2),
  74. m_clipmapInfo[clipmap].m_probeCounts.z() * (g_indirectDiffuseClipmapRadianceOctMapSize + 2), Format::kB10G11R11_Ufloat_Pack32,
  75. TextureUsageBit::kAllShaderResource, generateTempPassName("IndirectDiffuseClipmap: Radiance #%u", clipmap));
  76. volumeInit.m_depth = m_clipmapInfo[clipmap].m_probeCounts.y();
  77. volumeInit.m_type = TextureType::k3D;
  78. m_radianceVolumes[clipmap] = getRenderer().createAndClearRenderTarget(volumeInit, TextureUsageBit::kSrvCompute);
  79. }
  80. for(U32 clipmap = 0; clipmap < kIndirectDiffuseClipmapCount; ++clipmap)
  81. {
  82. TextureInitInfo volumeInit = getRenderer().create2DRenderTargetInitInfo(
  83. m_clipmapInfo[clipmap].m_probeCounts.x() * (g_indirectDiffuseClipmapIrradianceOctMapSize + 2),
  84. m_clipmapInfo[clipmap].m_probeCounts.z() * (g_indirectDiffuseClipmapIrradianceOctMapSize + 2), Format::kB10G11R11_Ufloat_Pack32,
  85. TextureUsageBit::kAllShaderResource, generateTempPassName("IndirectDiffuseClipmap: Irradiance #%u", clipmap));
  86. volumeInit.m_depth = m_clipmapInfo[clipmap].m_probeCounts.y();
  87. volumeInit.m_type = TextureType::k3D;
  88. m_irradianceVolumes[clipmap] = getRenderer().createAndClearRenderTarget(volumeInit, TextureUsageBit::kSrvCompute);
  89. }
  90. for(U32 clipmap = 0; clipmap < kIndirectDiffuseClipmapCount; ++clipmap)
  91. {
  92. TextureInitInfo volumeInit = getRenderer().create2DRenderTargetInitInfo(
  93. m_clipmapInfo[clipmap].m_probeCounts.x() * (g_indirectDiffuseClipmapRadianceOctMapSize + 2),
  94. m_clipmapInfo[clipmap].m_probeCounts.z() * (g_indirectDiffuseClipmapRadianceOctMapSize + 2), Format::kR16G16_Sfloat,
  95. TextureUsageBit::kAllShaderResource, generateTempPassName("IndirectDiffuseClipmap: Dist moments #%u", clipmap));
  96. volumeInit.m_depth = m_clipmapInfo[clipmap].m_probeCounts.y();
  97. volumeInit.m_type = TextureType::k3D;
  98. m_distanceMomentsVolumes[clipmap] = getRenderer().createAndClearRenderTarget(volumeInit, TextureUsageBit::kSrvCompute);
  99. }
  100. const Array<SubMutation, 4> mutation = {{{"GPU_WAVE_SIZE", MutatorValue(GrManager::getSingleton().getDeviceCapabilities().m_maxWaveSize)},
  101. {"RADIANCE_OCTAHEDRON_MAP_SIZE", MutatorValue(g_indirectDiffuseClipmapRadianceOctMapSize)},
  102. {"IRRADIANCE_OCTAHEDRON_MAP_SIZE", MutatorValue(g_indirectDiffuseClipmapIrradianceOctMapSize)},
  103. {"RT_MATERIAL_FETCH_CLIPMAP", 0}}};
  104. ANKI_CHECK(loadShaderProgram("ShaderBinaries/IndirectDiffuseClipmaps.ankiprogbin", mutation, m_prog, m_applyGiGrProg, "Apply"));
  105. ANKI_CHECK(loadShaderProgram("ShaderBinaries/IndirectDiffuseClipmaps.ankiprogbin", mutation, m_prog, m_visProbesGrProg, "VisualizeProbes"));
  106. ANKI_CHECK(loadShaderProgram("ShaderBinaries/IndirectDiffuseClipmaps.ankiprogbin", mutation, m_prog, m_populateCachesGrProg, "PopulateCaches"));
  107. ANKI_CHECK(
  108. loadShaderProgram("ShaderBinaries/IndirectDiffuseClipmaps.ankiprogbin", mutation, m_prog, m_computeIrradianceGrProg, "ComputeIrradiance"));
  109. for(MutatorValue rtMaterialFetchClipmap = 0; rtMaterialFetchClipmap < 2; ++rtMaterialFetchClipmap)
  110. {
  111. ShaderProgramResourcePtr tmpProg;
  112. ANKI_CHECK(ResourceManager::getSingleton().loadResource("ShaderBinaries/IndirectDiffuseClipmaps.ankiprogbin", tmpProg));
  113. ANKI_ASSERT(tmpProg == m_prog);
  114. ShaderProgramResourceVariantInitInfo variantInitInfo(m_prog);
  115. variantInitInfo.requestTechniqueAndTypes(ShaderTypeBit::kRayGen, "RtMaterialFetch");
  116. for(const SubMutation& s : mutation)
  117. {
  118. variantInitInfo.addMutation(s.m_mutatorName, s.m_value);
  119. }
  120. variantInitInfo.addMutation("RT_MATERIAL_FETCH_CLIPMAP", rtMaterialFetchClipmap);
  121. const ShaderProgramResourceVariant* variant;
  122. m_prog->getOrCreateVariant(variantInitInfo, variant);
  123. m_rtLibraryGrProg.reset(&variant->getProgram());
  124. m_rayGenShaderGroupIndices[rtMaterialFetchClipmap] = variant->getShaderGroupHandleIndex();
  125. }
  126. {
  127. ANKI_CHECK(ResourceManager::getSingleton().loadResource("ShaderBinaries/RtMaterialFetchMiss.ankiprogbin", m_missProg));
  128. ShaderProgramResourceVariantInitInfo variantInitInfo(m_missProg);
  129. variantInitInfo.requestTechniqueAndTypes(ShaderTypeBit::kMiss, "RtMaterialFetch");
  130. const ShaderProgramResourceVariant* variant;
  131. m_missProg->getOrCreateVariant(variantInitInfo, variant);
  132. m_missShaderGroupIdx = variant->getShaderGroupHandleIndex();
  133. }
  134. m_sbtRecordSize = getAlignedRoundUp(GrManager::getSingleton().getDeviceCapabilities().m_sbtRecordAlignment,
  135. GrManager::getSingleton().getDeviceCapabilities().m_shaderGroupHandleSize + U32(sizeof(UVec4)));
  136. ANKI_CHECK(ResourceManager::getSingleton().loadResource("EngineAssets/BlueNoise_Rgba8_64x64.png", m_blueNoiseImg));
  137. return Error::kNone;
  138. }
  139. void IndirectDiffuseClipmaps::populateRenderGraph(RenderingContext& ctx)
  140. {
  141. ANKI_TRACE_SCOPED_EVENT(IndirectDiffuse);
  142. for(U32 i = 0; i < kIndirectDiffuseClipmapCount; ++i)
  143. {
  144. m_clipmapInfo[i].m_prevFrameAabbMin = m_clipmapInfo[i].m_aabbMin;
  145. computeClipmapBounds(ctx.m_matrices.m_cameraTransform.getTranslationPart(),
  146. -ctx.m_matrices.m_cameraTransform.getRotationPart().getZAxis().normalize(), m_clipmapInfo[i]);
  147. }
  148. RenderGraphBuilder& rgraph = ctx.m_renderGraphDescr;
  149. const RenderTargetHandle rtResultHandle = rgraph.newRenderTarget(m_rtResultRtDesc);
  150. m_runCtx.m_appliedGiRt = rgraph.newRenderTarget(m_appliedGiRtDesc);
  151. Array<RenderTargetHandle, kIndirectDiffuseClipmapCount> radianceVolumes;
  152. Array<RenderTargetHandle, kIndirectDiffuseClipmapCount> irradianceVolumes;
  153. Array<RenderTargetHandle, kIndirectDiffuseClipmapCount> distanceMomentsVolumes;
  154. for(U32 i = 0; i < kIndirectDiffuseClipmapCount; ++i)
  155. {
  156. if(m_texturesImportedOnce)
  157. {
  158. radianceVolumes[i] = rgraph.importRenderTarget(m_radianceVolumes[i].get());
  159. irradianceVolumes[i] = rgraph.importRenderTarget(m_irradianceVolumes[i].get());
  160. distanceMomentsVolumes[i] = rgraph.importRenderTarget(m_distanceMomentsVolumes[i].get());
  161. }
  162. else
  163. {
  164. radianceVolumes[i] = rgraph.importRenderTarget(m_radianceVolumes[i].get(), TextureUsageBit::kSrvCompute);
  165. irradianceVolumes[i] = rgraph.importRenderTarget(m_irradianceVolumes[i].get(), TextureUsageBit::kSrvCompute);
  166. distanceMomentsVolumes[i] = rgraph.importRenderTarget(m_distanceMomentsVolumes[i].get(), TextureUsageBit::kSrvCompute);
  167. }
  168. }
  169. Array<RenderTargetHandle, kIndirectDiffuseClipmapCount> probeValidityVolumes;
  170. for(U32 i = 0; i < kIndirectDiffuseClipmapCount; ++i)
  171. {
  172. probeValidityVolumes[i] = rgraph.newRenderTarget(m_probeValidityRtDescs[i]);
  173. }
  174. m_runCtx.m_probeValidityRts = probeValidityVolumes;
  175. // SBT build
  176. BufferHandle sbtHandle;
  177. BufferView sbtBuffer;
  178. buildShaderBindingTablePass("IndirectDiffuseClipmaps: Build SBT", m_rtLibraryGrProg.get(), m_rayGenShaderGroupIndices[1], m_missShaderGroupIdx,
  179. m_sbtRecordSize, rgraph, sbtHandle, sbtBuffer);
  180. // Do ray tracing around the probes
  181. {
  182. NonGraphicsRenderPass& pass = rgraph.newNonGraphicsRenderPass("IndirectDiffuseClipmaps: RT");
  183. pass.newTextureDependency(rtResultHandle, TextureUsageBit::kUavCompute);
  184. pass.newBufferDependency(sbtHandle, BufferUsageBit::kShaderBindingTable);
  185. if(getRenderer().getGeneratedSky().isEnabled())
  186. {
  187. pass.newTextureDependency(getRenderer().getGeneratedSky().getEnvironmentMapRt(), TextureUsageBit::kSrvTraceRays);
  188. }
  189. pass.newTextureDependency(getRenderer().getShadowMapping().getShadowmapRt(), TextureUsageBit::kSrvTraceRays);
  190. pass.newAccelerationStructureDependency(getRenderer().getAccelerationStructureBuilder().getAccelerationStructureHandle(),
  191. AccelerationStructureUsageBit::kTraceRaysSrv);
  192. for(U32 clipmap = 0; clipmap < kIndirectDiffuseClipmapCount; ++clipmap)
  193. {
  194. pass.newTextureDependency(irradianceVolumes[clipmap], TextureUsageBit::kSrvCompute);
  195. }
  196. pass.setWork([this, rtResultHandle, &ctx, sbtBuffer, irradianceVolumes, probeValidityVolumes,
  197. distanceMomentsVolumes](RenderPassWorkContext& rgraphCtx) {
  198. CommandBuffer& cmdb = *rgraphCtx.m_commandBuffer;
  199. cmdb.bindShaderProgram(m_rtLibraryGrProg.get());
  200. // More globals
  201. cmdb.bindSampler(ANKI_MATERIAL_REGISTER_TILINEAR_REPEAT_SAMPLER, 0, getRenderer().getSamplers().m_trilinearRepeat.get());
  202. cmdb.bindSrv(ANKI_MATERIAL_REGISTER_GPU_SCENE, 0, GpuSceneBuffer::getSingleton().getBufferView());
  203. cmdb.bindSrv(ANKI_MATERIAL_REGISTER_MESH_LODS, 0, GpuSceneArrays::MeshLod::getSingleton().getBufferView());
  204. cmdb.bindSrv(ANKI_MATERIAL_REGISTER_TRANSFORMS, 0, GpuSceneArrays::Transform::getSingleton().getBufferView());
  205. #define ANKI_UNIFIED_GEOM_FORMAT(fmt, shaderType, reg) \
  206. cmdb.bindSrv( \
  207. reg, 0, \
  208. BufferView(&UnifiedGeometryBuffer::getSingleton().getBuffer(), 0, \
  209. getAlignedRoundDown(getFormatInfo(Format::k##fmt).m_texelSize, UnifiedGeometryBuffer::getSingleton().getBuffer().getSize())), \
  210. Format::k##fmt);
  211. #include <AnKi/Shaders/Include/UnifiedGeometryTypes.def.h>
  212. cmdb.bindConstantBuffer(0, 2, ctx.m_globalRenderingConstantsBuffer);
  213. U32 srv = 0;
  214. rgraphCtx.bindSrv(srv++, 2, getRenderer().getAccelerationStructureBuilder().getAccelerationStructureHandle());
  215. const LightComponent* dirLight = SceneGraph::getSingleton().getDirectionalLight();
  216. const SkyboxComponent* sky = SceneGraph::getSingleton().getSkybox();
  217. const Bool bSkySolidColor =
  218. (!sky || sky->getSkyboxType() == SkyboxType::kSolidColor || (!dirLight && sky->getSkyboxType() == SkyboxType::kGenerated));
  219. if(bSkySolidColor)
  220. {
  221. cmdb.bindSrv(srv++, 2, TextureView(getDummyGpuResources().m_texture2DSrv.get(), TextureSubresourceDesc::all()));
  222. }
  223. else if(sky->getSkyboxType() == SkyboxType::kImage2D)
  224. {
  225. cmdb.bindSrv(srv++, 2, TextureView(&sky->getImageResource().getTexture(), TextureSubresourceDesc::all()));
  226. }
  227. else
  228. {
  229. rgraphCtx.bindSrv(srv++, 2, getRenderer().getGeneratedSky().getEnvironmentMapRt());
  230. }
  231. rgraphCtx.bindSrv(srv++, 2, getRenderer().getShadowMapping().getShadowmapRt());
  232. cmdb.bindSrv(srv++, 2, BufferView(getDummyGpuResources().m_buffer.get(), 0, sizeof(U32)));
  233. cmdb.bindSrv(srv++, 2, BufferView(getDummyGpuResources().m_buffer.get(), 0, sizeof(U32)));
  234. for(U32 clipmap = 0; clipmap < kIndirectDiffuseClipmapCount; ++clipmap)
  235. {
  236. rgraphCtx.bindSrv(srv++, 2, irradianceVolumes[clipmap]);
  237. }
  238. for(U32 clipmap = 0; clipmap < kIndirectDiffuseClipmapCount; ++clipmap)
  239. {
  240. rgraphCtx.bindSrv(srv++, 2, probeValidityVolumes[clipmap]);
  241. }
  242. for(U32 clipmap = 0; clipmap < kIndirectDiffuseClipmapCount; ++clipmap)
  243. {
  244. rgraphCtx.bindSrv(srv++, 2, distanceMomentsVolumes[clipmap]);
  245. }
  246. for(U32 i = 0; i < 3; ++i)
  247. {
  248. cmdb.bindSrv(srv++, 2, TextureView(getDummyGpuResources().m_texture2DSrv.get(), TextureSubresourceDesc::all()));
  249. }
  250. cmdb.bindSampler(0, 2, getRenderer().getSamplers().m_trilinearClamp.get());
  251. cmdb.bindSampler(1, 2, getRenderer().getSamplers().m_trilinearClampShadow.get());
  252. cmdb.bindSampler(2, 2, getRenderer().getSamplers().m_trilinearRepeat.get());
  253. rgraphCtx.bindUav(0, 2, rtResultHandle);
  254. cmdb.bindUav(1, 2, TextureView(getDummyGpuResources().m_texture2DUav.get(), TextureSubresourceDesc::firstSurface()));
  255. ANKI_ASSERT(g_indirectDiffuseClipmapRadianceOctMapSize % 2 == 0);
  256. const U32 raysPerProbePerFrame = square(g_indirectDiffuseClipmapRadianceOctMapSize / 2);
  257. for(U32 clipmap = 0; clipmap < kIndirectDiffuseClipmapCount; ++clipmap)
  258. {
  259. const UVec4 consts(clipmap, g_indirectDiffuseClipmapRadianceOctMapSize, 0, 0);
  260. cmdb.setFastConstants(&consts, sizeof(consts));
  261. const U32 probeCount = m_clipmapInfo[0].m_probeCountTotal;
  262. cmdb.traceRays(sbtBuffer, m_sbtRecordSize, GpuSceneArrays::RenderableBoundingVolumeRt::getSingleton().getElementCount(), 1,
  263. probeCount * raysPerProbePerFrame, 1, 1);
  264. }
  265. });
  266. }
  267. // Populate caches
  268. {
  269. NonGraphicsRenderPass& pass = rgraph.newNonGraphicsRenderPass("IndirectDiffuseClipmaps: Populate caches");
  270. pass.newTextureDependency(rtResultHandle, TextureUsageBit::kSrvCompute);
  271. for(U32 clipmap = 0; clipmap < kIndirectDiffuseClipmapCount; ++clipmap)
  272. {
  273. pass.newTextureDependency(radianceVolumes[clipmap], TextureUsageBit::kUavCompute);
  274. pass.newTextureDependency(probeValidityVolumes[clipmap], TextureUsageBit::kUavCompute);
  275. pass.newTextureDependency(distanceMomentsVolumes[clipmap], TextureUsageBit::kUavCompute);
  276. }
  277. pass.setWork([this, &ctx, rtResultHandle, radianceVolumes, probeValidityVolumes, distanceMomentsVolumes](RenderPassWorkContext& rgraphCtx) {
  278. CommandBuffer& cmdb = *rgraphCtx.m_commandBuffer;
  279. cmdb.bindShaderProgram(m_populateCachesGrProg.get());
  280. rgraphCtx.bindSrv(0, 0, rtResultHandle);
  281. cmdb.bindConstantBuffer(0, 0, ctx.m_globalRenderingConstantsBuffer);
  282. for(U32 clipmap = 0; clipmap < kIndirectDiffuseClipmapCount; ++clipmap)
  283. {
  284. rgraphCtx.bindUav(0, 0, radianceVolumes[clipmap]);
  285. rgraphCtx.bindUav(1, 0, distanceMomentsVolumes[clipmap]);
  286. rgraphCtx.bindUav(2, 0, probeValidityVolumes[clipmap]);
  287. const UVec4 consts(clipmap);
  288. cmdb.setFastConstants(&consts, sizeof(consts));
  289. const U32 raysPerProbePerFrame = square(g_indirectDiffuseClipmapRadianceOctMapSize / 2);
  290. const U32 threadCount = 64;
  291. cmdb.dispatchCompute((raysPerProbePerFrame * m_clipmapInfo[clipmap].m_probeCountTotal + threadCount - 1) / threadCount, 1, 1);
  292. }
  293. });
  294. }
  295. // Compute irradiance
  296. {
  297. NonGraphicsRenderPass& pass = rgraph.newNonGraphicsRenderPass("IndirectDiffuseClipmaps: Irradiance");
  298. for(U32 clipmap = 0; clipmap < kIndirectDiffuseClipmapCount; ++clipmap)
  299. {
  300. pass.newTextureDependency(radianceVolumes[clipmap], TextureUsageBit::kSrvCompute);
  301. pass.newTextureDependency(irradianceVolumes[clipmap], TextureUsageBit::kUavCompute);
  302. }
  303. pass.setWork([this, &ctx, radianceVolumes, irradianceVolumes](RenderPassWorkContext& rgraphCtx) {
  304. CommandBuffer& cmdb = *rgraphCtx.m_commandBuffer;
  305. cmdb.bindShaderProgram(m_computeIrradianceGrProg.get());
  306. cmdb.bindConstantBuffer(0, 0, ctx.m_globalRenderingConstantsBuffer);
  307. cmdb.bindSampler(0, 0, getRenderer().getSamplers().m_trilinearRepeat.get());
  308. for(U32 clipmap = 0; clipmap < kIndirectDiffuseClipmapCount; ++clipmap)
  309. {
  310. rgraphCtx.bindSrv(clipmap, 0, radianceVolumes[clipmap]);
  311. rgraphCtx.bindUav(clipmap, 0, irradianceVolumes[clipmap]);
  312. }
  313. cmdb.dispatchCompute(m_clipmapInfo[0].m_probeCounts[0] * kIndirectDiffuseClipmapCount, m_clipmapInfo[0].m_probeCounts[1],
  314. m_clipmapInfo[0].m_probeCounts[2]);
  315. });
  316. }
  317. // Apply GI
  318. if(0)
  319. {
  320. patchShaderBindingTablePass("IndirectDiffuseClipmaps: Patch SBT", m_rtLibraryGrProg.get(), m_rayGenShaderGroupIndices[0],
  321. m_missShaderGroupIdx, m_sbtRecordSize, rgraph, sbtHandle, sbtBuffer);
  322. NonGraphicsRenderPass& pass = rgraph.newNonGraphicsRenderPass("IndirectDiffuseClipmaps: RTApply");
  323. pass.newBufferDependency(sbtHandle, BufferUsageBit::kShaderBindingTable);
  324. if(getRenderer().getGeneratedSky().isEnabled())
  325. {
  326. pass.newTextureDependency(getRenderer().getGeneratedSky().getEnvironmentMapRt(), TextureUsageBit::kSrvTraceRays);
  327. }
  328. pass.newTextureDependency(getRenderer().getShadowMapping().getShadowmapRt(), TextureUsageBit::kSrvTraceRays);
  329. pass.newAccelerationStructureDependency(getRenderer().getAccelerationStructureBuilder().getAccelerationStructureHandle(),
  330. AccelerationStructureUsageBit::kTraceRaysSrv);
  331. pass.newTextureDependency(getRenderer().getGBuffer().getColorRt(2), TextureUsageBit::kSrvTraceRays);
  332. pass.newTextureDependency(getRenderer().getGBuffer().getDepthRt(), TextureUsageBit::kSrvTraceRays);
  333. for(U32 clipmap = 0; clipmap < kIndirectDiffuseClipmapCount; ++clipmap)
  334. {
  335. pass.newTextureDependency(irradianceVolumes[clipmap], TextureUsageBit::kSrvTraceRays);
  336. pass.newTextureDependency(probeValidityVolumes[clipmap], TextureUsageBit::kSrvTraceRays);
  337. pass.newTextureDependency(distanceMomentsVolumes[clipmap], TextureUsageBit::kSrvTraceRays);
  338. }
  339. pass.newTextureDependency(m_runCtx.m_appliedGiRt, TextureUsageBit::kUavTraceRays);
  340. pass.setWork([this, rtResultHandle, &ctx, sbtBuffer, irradianceVolumes, probeValidityVolumes,
  341. distanceMomentsVolumes](RenderPassWorkContext& rgraphCtx) {
  342. CommandBuffer& cmdb = *rgraphCtx.m_commandBuffer;
  343. cmdb.bindShaderProgram(m_rtLibraryGrProg.get());
  344. // More globals
  345. cmdb.bindSampler(ANKI_MATERIAL_REGISTER_TILINEAR_REPEAT_SAMPLER, 0, getRenderer().getSamplers().m_trilinearRepeat.get());
  346. cmdb.bindSrv(ANKI_MATERIAL_REGISTER_GPU_SCENE, 0, GpuSceneBuffer::getSingleton().getBufferView());
  347. cmdb.bindSrv(ANKI_MATERIAL_REGISTER_MESH_LODS, 0, GpuSceneArrays::MeshLod::getSingleton().getBufferView());
  348. cmdb.bindSrv(ANKI_MATERIAL_REGISTER_TRANSFORMS, 0, GpuSceneArrays::Transform::getSingleton().getBufferView());
  349. #define ANKI_UNIFIED_GEOM_FORMAT(fmt, shaderType, reg) \
  350. cmdb.bindSrv( \
  351. reg, 0, \
  352. BufferView(&UnifiedGeometryBuffer::getSingleton().getBuffer(), 0, \
  353. getAlignedRoundDown(getFormatInfo(Format::k##fmt).m_texelSize, UnifiedGeometryBuffer::getSingleton().getBuffer().getSize())), \
  354. Format::k##fmt);
  355. #include <AnKi/Shaders/Include/UnifiedGeometryTypes.def.h>
  356. cmdb.bindConstantBuffer(0, 2, ctx.m_globalRenderingConstantsBuffer);
  357. U32 srv = 0;
  358. rgraphCtx.bindSrv(srv++, 2, getRenderer().getAccelerationStructureBuilder().getAccelerationStructureHandle());
  359. const LightComponent* dirLight = SceneGraph::getSingleton().getDirectionalLight();
  360. const SkyboxComponent* sky = SceneGraph::getSingleton().getSkybox();
  361. const Bool bSkySolidColor =
  362. (!sky || sky->getSkyboxType() == SkyboxType::kSolidColor || (!dirLight && sky->getSkyboxType() == SkyboxType::kGenerated));
  363. if(bSkySolidColor)
  364. {
  365. cmdb.bindSrv(srv++, 2, TextureView(getDummyGpuResources().m_texture2DSrv.get(), TextureSubresourceDesc::all()));
  366. }
  367. else if(sky->getSkyboxType() == SkyboxType::kImage2D)
  368. {
  369. cmdb.bindSrv(srv++, 2, TextureView(&sky->getImageResource().getTexture(), TextureSubresourceDesc::all()));
  370. }
  371. else
  372. {
  373. rgraphCtx.bindSrv(srv++, 2, getRenderer().getGeneratedSky().getEnvironmentMapRt());
  374. }
  375. rgraphCtx.bindSrv(srv++, 2, getRenderer().getShadowMapping().getShadowmapRt());
  376. cmdb.bindSrv(srv++, 2, BufferView(getDummyGpuResources().m_buffer.get(), 0, sizeof(U32)));
  377. cmdb.bindSrv(srv++, 2, BufferView(getDummyGpuResources().m_buffer.get(), 0, sizeof(U32)));
  378. for(U32 clipmap = 0; clipmap < kIndirectDiffuseClipmapCount; ++clipmap)
  379. {
  380. rgraphCtx.bindSrv(srv++, 2, irradianceVolumes[clipmap]);
  381. }
  382. for(U32 clipmap = 0; clipmap < kIndirectDiffuseClipmapCount; ++clipmap)
  383. {
  384. rgraphCtx.bindSrv(srv++, 2, probeValidityVolumes[clipmap]);
  385. }
  386. for(U32 clipmap = 0; clipmap < kIndirectDiffuseClipmapCount; ++clipmap)
  387. {
  388. rgraphCtx.bindSrv(srv++, 2, distanceMomentsVolumes[clipmap]);
  389. }
  390. rgraphCtx.bindSrv(srv++, 2, getRenderer().getGBuffer().getDepthRt());
  391. cmdb.bindSrv(srv++, 2, TextureView(getDummyGpuResources().m_texture2DSrv.get(), TextureSubresourceDesc::all()));
  392. rgraphCtx.bindSrv(srv++, 2, getRenderer().getGBuffer().getColorRt(2));
  393. cmdb.bindSampler(0, 2, getRenderer().getSamplers().m_trilinearClamp.get());
  394. cmdb.bindSampler(1, 2, getRenderer().getSamplers().m_trilinearClampShadow.get());
  395. cmdb.bindSampler(2, 2, getRenderer().getSamplers().m_trilinearRepeat.get());
  396. rgraphCtx.bindUav(0, 2, m_runCtx.m_appliedGiRt);
  397. cmdb.bindUav(1, 2, TextureView(getDummyGpuResources().m_texture2DUav.get(), TextureSubresourceDesc::firstSurface()));
  398. const Vec3 probeSizes = m_clipmapInfo[0].m_size / Vec3(m_clipmapInfo[0].m_probeCounts);
  399. const F32 rayTMax = max(probeSizes.x(), max(probeSizes.y(), probeSizes.z())) * 10.0f;
  400. const Vec4 consts(rayTMax);
  401. cmdb.setFastConstants(&consts, sizeof(consts));
  402. cmdb.traceRays(sbtBuffer, m_sbtRecordSize, GpuSceneArrays::RenderableBoundingVolumeRt::getSingleton().getElementCount(), 1,
  403. getRenderer().getInternalResolution().x(), getRenderer().getInternalResolution().y(), 1);
  404. });
  405. }
  406. else
  407. {
  408. NonGraphicsRenderPass& pass = rgraph.newNonGraphicsRenderPass("IndirectDiffuseClipmaps composite");
  409. pass.newTextureDependency(getRenderer().getGBuffer().getDepthRt(), TextureUsageBit::kSrvCompute);
  410. pass.newTextureDependency(getRenderer().getGBuffer().getColorRt(2), TextureUsageBit::kSrvCompute);
  411. for(U32 i = 0; i < kIndirectDiffuseClipmapCount; ++i)
  412. {
  413. pass.newTextureDependency(irradianceVolumes[i], TextureUsageBit::kSrvCompute);
  414. pass.newTextureDependency(probeValidityVolumes[i], TextureUsageBit::kSrvCompute);
  415. pass.newTextureDependency(distanceMomentsVolumes[i], TextureUsageBit::kSrvCompute);
  416. }
  417. pass.newTextureDependency(m_runCtx.m_appliedGiRt, TextureUsageBit::kUavCompute);
  418. pass.setWork([this, &ctx, irradianceVolumes, probeValidityVolumes, distanceMomentsVolumes](RenderPassWorkContext& rgraphCtx) {
  419. CommandBuffer& cmdb = *rgraphCtx.m_commandBuffer;
  420. cmdb.bindShaderProgram(m_applyGiGrProg.get());
  421. rgraphCtx.bindSrv(0, 0, getRenderer().getGBuffer().getDepthRt());
  422. rgraphCtx.bindSrv(1, 0, getRenderer().getGBuffer().getColorRt(2));
  423. cmdb.bindSrv(2, 0, TextureView(&m_blueNoiseImg->getTexture(), TextureSubresourceDesc::firstSurface()));
  424. U32 srvReg = 3;
  425. for(U32 i = 0; i < kIndirectDiffuseClipmapCount; ++i)
  426. {
  427. rgraphCtx.bindSrv(srvReg++, 0, irradianceVolumes[i]);
  428. }
  429. for(U32 i = 0; i < kIndirectDiffuseClipmapCount; ++i)
  430. {
  431. rgraphCtx.bindSrv(srvReg++, 0, probeValidityVolumes[i]);
  432. }
  433. for(U32 i = 0; i < kIndirectDiffuseClipmapCount; ++i)
  434. {
  435. rgraphCtx.bindSrv(srvReg++, 0, distanceMomentsVolumes[i]);
  436. }
  437. rgraphCtx.bindUav(0, 0, m_runCtx.m_appliedGiRt);
  438. cmdb.bindConstantBuffer(0, 0, ctx.m_globalRenderingConstantsBuffer);
  439. cmdb.bindSampler(0, 0, getRenderer().getSamplers().m_trilinearRepeat.get());
  440. dispatchPPCompute(cmdb, 8, 8, getRenderer().getInternalResolution().x(), getRenderer().getInternalResolution().y());
  441. });
  442. }
  443. }
  444. void IndirectDiffuseClipmaps::drawDebugProbes(const RenderingContext& ctx, RenderPassWorkContext& rgraphCtx) const
  445. {
  446. CommandBuffer& cmdb = *rgraphCtx.m_commandBuffer;
  447. const U32 clipmap = 0;
  448. cmdb.bindShaderProgram(m_visProbesGrProg.get());
  449. const UVec4 consts(clipmap);
  450. cmdb.setFastConstants(&consts, sizeof(consts));
  451. cmdb.bindConstantBuffer(0, 0, ctx.m_globalRenderingConstantsBuffer);
  452. Texture* visVolume = m_irradianceVolumes[clipmap].get();
  453. cmdb.bindSrv(0, 0, TextureView(visVolume, TextureSubresourceDesc::all()));
  454. rgraphCtx.bindSrv(1, 0, m_runCtx.m_probeValidityRts[clipmap]);
  455. cmdb.bindSampler(0, 0, getRenderer().getSamplers().m_trilinearRepeat.get());
  456. cmdb.draw(PrimitiveTopology::kTriangles, 36, m_clipmapInfo[clipmap].m_probeCountTotal);
  457. }
  458. } // end namespace anki