IndirectDiffuseClipmaps.cpp 38 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880
  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/Renderer/HistoryLength.h>
  12. #include <AnKi/Renderer/MotionVectors.h>
  13. #include <AnKi/Scene/Components/SkyboxComponent.h>
  14. #include <AnKi/Shaders/Include/MaterialTypes.h>
  15. #include <AnKi/Util/Tracer.h>
  16. #include <AnKi/GpuMemory/UnifiedGeometryBuffer.h>
  17. namespace anki {
  18. ANKI_SVAR(IdcRays, StatCategory::kRenderer, "IDC ray count", StatFlag::kZeroEveryFrame)
  19. class ProbeRange
  20. {
  21. public:
  22. IVec3 m_begin;
  23. IVec3 m_end;
  24. };
  25. /// Given the clipmap's position of this and the previous frame it splits the clipmap into regions that contain new probes (thus they need a full
  26. /// update) or regions of probes that need a less frequent update.
  27. static void findClipmapInUpdateRanges(Vec3 newClipmapMin, Vec3 oldClipmapMin, Vec3 probeSize, UVec3 probeCountsu,
  28. Array<ProbeRange, 3>& fullUpdateProbeRanges, U32& fullUpdateProbeRangeCount,
  29. ProbeRange& partialUpdateProbeRange)
  30. {
  31. fullUpdateProbeRangeCount = 0;
  32. const IVec3 probeCounts(probeCountsu);
  33. const IVec3 delta = IVec3((newClipmapMin - oldClipmapMin) / probeSize);
  34. const IVec3 absDelta = delta.abs();
  35. if(absDelta.x >= probeCounts.x || absDelta.y >= probeCounts.y || absDelta.z >= probeCounts.z)
  36. {
  37. // No overlap between the old and new clipmap positions, full update
  38. fullUpdateProbeRanges[fullUpdateProbeRangeCount++] = {IVec3(0), probeCounts};
  39. partialUpdateProbeRange = {IVec3(0), IVec3(0)};
  40. }
  41. else
  42. {
  43. IVec3 partialUpdateProbeRangeBegin(0);
  44. IVec3 partialUpdateProbeRangeEnd = probeCounts;
  45. IVec3 fullUpdateProbeRangeBegin(0);
  46. IVec3 fullUpdateProbeRangeEnd(0);
  47. if(delta.x > 0)
  48. {
  49. // New AABB on the right of old
  50. fullUpdateProbeRangeBegin = IVec3(partialUpdateProbeRangeEnd.x - delta.x, partialUpdateProbeRangeBegin.y, partialUpdateProbeRangeBegin.z);
  51. fullUpdateProbeRangeEnd = partialUpdateProbeRangeEnd;
  52. partialUpdateProbeRangeEnd.x -= delta.x;
  53. }
  54. else if(delta.x < 0)
  55. {
  56. // New AABB on the left of old
  57. fullUpdateProbeRangeBegin = partialUpdateProbeRangeBegin;
  58. fullUpdateProbeRangeEnd = IVec3(-delta.x, partialUpdateProbeRangeEnd.y, partialUpdateProbeRangeEnd.z);
  59. partialUpdateProbeRangeBegin.x += -delta.x;
  60. }
  61. if(delta.x != 0)
  62. {
  63. fullUpdateProbeRanges[fullUpdateProbeRangeCount++] = {fullUpdateProbeRangeBegin, fullUpdateProbeRangeEnd};
  64. }
  65. fullUpdateProbeRangeBegin = fullUpdateProbeRangeEnd = IVec3(0);
  66. if(delta.y > 0)
  67. {
  68. // New AABB on the top of old
  69. fullUpdateProbeRangeBegin = IVec3(partialUpdateProbeRangeBegin.x, partialUpdateProbeRangeEnd.y - delta.y, partialUpdateProbeRangeBegin.z);
  70. fullUpdateProbeRangeEnd = partialUpdateProbeRangeEnd;
  71. partialUpdateProbeRangeEnd.y -= delta.y;
  72. }
  73. else if(delta.y < 0)
  74. {
  75. // New AABB at the bottom of old
  76. fullUpdateProbeRangeBegin = partialUpdateProbeRangeBegin;
  77. fullUpdateProbeRangeEnd = IVec3(partialUpdateProbeRangeEnd.x, -delta.y, partialUpdateProbeRangeEnd.z);
  78. partialUpdateProbeRangeBegin.y += -delta.y;
  79. }
  80. if(delta.y != 0)
  81. {
  82. fullUpdateProbeRanges[fullUpdateProbeRangeCount++] = {fullUpdateProbeRangeBegin, fullUpdateProbeRangeEnd};
  83. }
  84. fullUpdateProbeRangeBegin = fullUpdateProbeRangeEnd = IVec3(0);
  85. if(delta.z > 0)
  86. {
  87. // New AABB on the front of old
  88. fullUpdateProbeRangeBegin = IVec3(partialUpdateProbeRangeBegin.x, partialUpdateProbeRangeBegin.y, partialUpdateProbeRangeEnd.z - delta.z);
  89. fullUpdateProbeRangeEnd = partialUpdateProbeRangeEnd;
  90. partialUpdateProbeRangeEnd.z -= delta.z;
  91. }
  92. else if(delta.z < 0)
  93. {
  94. // New AABB on the back of old
  95. fullUpdateProbeRangeBegin = partialUpdateProbeRangeBegin;
  96. fullUpdateProbeRangeEnd = IVec3(partialUpdateProbeRangeEnd.x, partialUpdateProbeRangeEnd.y, -delta.z);
  97. partialUpdateProbeRangeBegin.z += -delta.z;
  98. }
  99. if(delta.z != 0)
  100. {
  101. fullUpdateProbeRanges[fullUpdateProbeRangeCount++] = {fullUpdateProbeRangeBegin, fullUpdateProbeRangeEnd};
  102. }
  103. partialUpdateProbeRange = {partialUpdateProbeRangeBegin, partialUpdateProbeRangeEnd};
  104. // Validation
  105. [[maybe_unused]] I32 totalProbeCount = 0;
  106. for(U32 i = 0; i < fullUpdateProbeRangeCount; ++i)
  107. {
  108. const IVec3 end = fullUpdateProbeRanges[i].m_end;
  109. const IVec3 begin = fullUpdateProbeRanges[i].m_begin;
  110. const IVec3 diff = end - begin;
  111. ANKI_ASSERT(diff.x * diff.y * diff.z > 0);
  112. totalProbeCount += diff.x * diff.y * diff.z;
  113. }
  114. {
  115. const IVec3 end = partialUpdateProbeRange.m_end;
  116. const IVec3 begin = partialUpdateProbeRange.m_begin;
  117. const IVec3 diff = end - begin;
  118. ANKI_ASSERT(diff.x * diff.y * diff.z > 0);
  119. totalProbeCount += diff.x * diff.y * diff.z;
  120. }
  121. ANKI_ASSERT(totalProbeCount == probeCounts.x * probeCounts.y * probeCounts.z);
  122. }
  123. }
  124. static void computeClipmapBounds(Vec3 cameraPos, Vec3 lookDir, U32 clipmapIdx, IndirectDiffuseClipmapConstants& consts)
  125. {
  126. const Vec3 offset = lookDir * kIndirectDiffuseClipmapForwardBias * F32(clipmapIdx + 1);
  127. cameraPos += offset;
  128. const Vec3 halfSize = consts.m_sizes[clipmapIdx].xyz * 0.5f;
  129. const Vec3 probeSize = consts.m_sizes[clipmapIdx].xyz / Vec3(consts.m_probeCounts);
  130. const Vec3 roundedPos = (cameraPos / probeSize).round() * probeSize;
  131. consts.m_aabbMins[clipmapIdx] = (roundedPos - halfSize).xyz0;
  132. [[maybe_unused]] const Vec3 aabbMax = roundedPos + halfSize;
  133. ANKI_ASSERT(aabbMax - consts.m_aabbMins[clipmapIdx].xyz == consts.m_sizes[clipmapIdx].xyz);
  134. }
  135. Error IndirectDiffuseClipmaps::init()
  136. {
  137. ANKI_CHECK(RtMaterialFetchRendererObject::init());
  138. const Bool firstBounceUsesRt = g_cvarRenderIdcFirstBounceRayDistance > 0.0f;
  139. m_lowRezRtDesc = getRenderer().create2DRenderTargetDescription(getRenderer().getInternalResolution().x / 2,
  140. getRenderer().getInternalResolution().y / (!g_cvarRenderIdcApplyHighQuality + 1),
  141. getRenderer().getHdrFormat(), "IndirectDiffuseClipmap: Apply rez");
  142. m_lowRezRtDesc.bake();
  143. m_fullRtDesc = getRenderer().create2DRenderTargetDescription(getRenderer().getInternalResolution().x, getRenderer().getInternalResolution().y,
  144. getRenderer().getHdrFormat(), "IndirectDiffuseClipmap: Full");
  145. m_fullRtDesc.bake();
  146. if(firstBounceUsesRt)
  147. {
  148. for(U32 i = 0; i < 2; ++i)
  149. {
  150. const TextureInitInfo init = getRenderer().create2DRenderTargetInitInfo(
  151. getRenderer().getInternalResolution().x, getRenderer().getInternalResolution().y, Format::kR16G16B16A16_Sfloat,
  152. TextureUsageBit::kAllShaderResource, generateTempPassName("IndirectDiffuseClipmap: Final #%u", i));
  153. m_irradianceRts[i] = getRenderer().createAndClearRenderTarget(init, TextureUsageBit::kSrvCompute);
  154. }
  155. }
  156. m_consts.m_probeCounts = UVec3(g_cvarRenderIdcProbesXZ, g_cvarRenderIdcProbesY, g_cvarRenderIdcProbesXZ);
  157. m_consts.m_totalProbeCount = m_consts.m_probeCounts.x * m_consts.m_probeCounts.y * m_consts.m_probeCounts.z;
  158. m_consts.m_sizes[0] = Vec3(g_cvarRenderIdcClipmap0XZSize, g_cvarRenderIdcClipmap0YSize, g_cvarRenderIdcClipmap0XZSize).xyz0;
  159. m_consts.m_sizes[1] = Vec3(g_cvarRenderIdcClipmap1XZSize, g_cvarRenderIdcClipmap1YSize, g_cvarRenderIdcClipmap1XZSize).xyz0;
  160. m_consts.m_sizes[2] = Vec3(g_cvarRenderIdcClipmap2XZSize, g_cvarRenderIdcClipmap2YSize, g_cvarRenderIdcClipmap2XZSize).xyz0;
  161. for(U32 i = 0; i < kIndirectDiffuseClipmapCount; ++i)
  162. {
  163. TextureInitInfo init = getRenderer().create2DRenderTargetInitInfo(m_consts.m_probeCounts.x, m_consts.m_probeCounts.z, Format::kR8_Unorm,
  164. TextureUsageBit::kUavCompute | TextureUsageBit::kAllSrv,
  165. generateTempPassName("IndirectDiffuseClipmap: Probe validity #%u", i));
  166. init.m_depth = m_consts.m_probeCounts.y;
  167. init.m_type = TextureType::k3D;
  168. m_probeValidityVolumes[i] = getRenderer().createAndClearRenderTarget(init, TextureUsageBit::kSrvCompute);
  169. }
  170. // Create the RT result texture
  171. const U32 texelsPerProbe = square<U32>(g_cvarRenderIdcRadianceOctMapSize);
  172. m_rtResultRtDesc =
  173. getRenderer().create2DRenderTargetDescription(m_consts.m_totalProbeCount, texelsPerProbe * g_cvarRenderIdcRayCountPerTexelOfNewProbe,
  174. Format::kR16G16B16A16_Sfloat, "IndirectDiffuseClipmap: RT result");
  175. m_rtResultRtDesc.bake();
  176. for(U32 clipmap = 0; clipmap < kIndirectDiffuseClipmapCount; ++clipmap)
  177. {
  178. TextureInitInfo volumeInit = getRenderer().create2DRenderTargetInitInfo(
  179. m_consts.m_probeCounts.x * (g_cvarRenderIdcRadianceOctMapSize + 2), m_consts.m_probeCounts.z * (g_cvarRenderIdcRadianceOctMapSize + 2),
  180. Format::kB10G11R11_Ufloat_Pack32, TextureUsageBit::kAllShaderResource,
  181. generateTempPassName("IndirectDiffuseClipmap: Radiance #%u", clipmap));
  182. volumeInit.m_depth = m_consts.m_probeCounts.y;
  183. volumeInit.m_type = TextureType::k3D;
  184. m_radianceVolumes[clipmap] = getRenderer().createAndClearRenderTarget(volumeInit, TextureUsageBit::kSrvCompute);
  185. }
  186. for(U32 clipmap = 0; clipmap < kIndirectDiffuseClipmapCount; ++clipmap)
  187. {
  188. TextureInitInfo volumeInit = getRenderer().create2DRenderTargetInitInfo(
  189. m_consts.m_probeCounts.x * (g_cvarRenderIdcIrradianceOctMapSize + 2),
  190. m_consts.m_probeCounts.z * (g_cvarRenderIdcIrradianceOctMapSize + 2), Format::kB10G11R11_Ufloat_Pack32,
  191. TextureUsageBit::kAllShaderResource, generateTempPassName("IndirectDiffuseClipmap: Irradiance #%u", clipmap));
  192. volumeInit.m_depth = m_consts.m_probeCounts.y;
  193. volumeInit.m_type = TextureType::k3D;
  194. m_irradianceVolumes[clipmap] = getRenderer().createAndClearRenderTarget(volumeInit, TextureUsageBit::kSrvCompute);
  195. }
  196. for(U32 clipmap = 0; clipmap < kIndirectDiffuseClipmapCount; ++clipmap)
  197. {
  198. TextureInitInfo volumeInit = getRenderer().create2DRenderTargetInitInfo(
  199. m_consts.m_probeCounts.x * (g_cvarRenderIdcRadianceOctMapSize + 2), m_consts.m_probeCounts.z * (g_cvarRenderIdcRadianceOctMapSize + 2),
  200. Format::kR16G16_Sfloat, TextureUsageBit::kAllShaderResource, generateTempPassName("IndirectDiffuseClipmap: Dist moments #%u", clipmap));
  201. volumeInit.m_depth = m_consts.m_probeCounts.y;
  202. volumeInit.m_type = TextureType::k3D;
  203. m_distanceMomentsVolumes[clipmap] = getRenderer().createAndClearRenderTarget(volumeInit, TextureUsageBit::kSrvCompute);
  204. }
  205. for(U32 clipmap = 0; clipmap < kIndirectDiffuseClipmapCount; ++clipmap)
  206. {
  207. TextureInitInfo volumeInit = getRenderer().create2DRenderTargetInitInfo(
  208. m_consts.m_probeCounts.x, m_consts.m_probeCounts.z, Format::kB10G11R11_Ufloat_Pack32, TextureUsageBit::kAllShaderResource,
  209. generateTempPassName("IndirectDiffuseClipmap: Avg light #%u", clipmap));
  210. volumeInit.m_depth = m_consts.m_probeCounts.y;
  211. volumeInit.m_type = TextureType::k3D;
  212. m_avgIrradianceVolumes[clipmap] = getRenderer().createAndClearRenderTarget(volumeInit, TextureUsageBit::kSrvCompute);
  213. }
  214. const Array<SubMutation, 6> mutation = {{{"GPU_WAVE_SIZE", MutatorValue(GrManager::getSingleton().getDeviceCapabilities().m_maxWaveSize)},
  215. {"RADIANCE_OCTAHEDRON_MAP_SIZE", MutatorValue(g_cvarRenderIdcRadianceOctMapSize)},
  216. {"IRRADIANCE_OCTAHEDRON_MAP_SIZE", MutatorValue(g_cvarRenderIdcIrradianceOctMapSize)},
  217. {"RT_MATERIAL_FETCH_CLIPMAP", 0},
  218. {"SPATIAL_RECONSTRUCT_TYPE", !g_cvarRenderIdcApplyHighQuality},
  219. {"IRRADIANCE_USE_SH_L2", g_cvarRenderIdcUseSHL2}}};
  220. constexpr CString kProgFname = "ShaderBinaries/IndirectDiffuseClipmaps.ankiprogbin";
  221. ANKI_CHECK(loadShaderProgram(kProgFname, mutation, m_prog, m_applyGiGrProg, "Apply"));
  222. ANKI_CHECK(loadShaderProgram(kProgFname, mutation, m_prog, m_visProbesGrProg, "VisualizeProbes"));
  223. ANKI_CHECK(loadShaderProgram(kProgFname, mutation, m_prog, m_populateCachesGrProg, "PopulateCaches"));
  224. ANKI_CHECK(loadShaderProgram(kProgFname, mutation, m_prog, m_computeIrradianceGrProg, "ComputeIrradiance"));
  225. ANKI_CHECK(loadShaderProgram(kProgFname, mutation, m_prog, m_temporalDenoiseGrProg, "TemporalDenoise"));
  226. ANKI_CHECK(loadShaderProgram(kProgFname, mutation, m_prog, m_spatialReconstructGrProg, "SpatialReconstruct"));
  227. ANKI_CHECK(loadShaderProgram(kProgFname, mutation, m_prog, m_bilateralDenoiseGrProg, "BilateralDenoise"));
  228. ANKI_CHECK(loadShaderProgram(kProgFname, mutation, m_prog, m_rtMaterialFetchInlineRtGrProg, "RtMaterialFetchInlineRt"));
  229. ANKI_CHECK(loadShaderProgram(kProgFname, mutation, m_prog, m_applyGiUsingInlineRtGrProg, "ApplyInlineRt"));
  230. for(MutatorValue rtMaterialFetchClipmap = 0; rtMaterialFetchClipmap < 2; ++rtMaterialFetchClipmap)
  231. {
  232. ShaderProgramResourcePtr tmpProg;
  233. ANKI_CHECK(ResourceManager::getSingleton().loadResource(kProgFname, tmpProg));
  234. ANKI_ASSERT(tmpProg == m_prog);
  235. ShaderProgramResourceVariantInitInfo variantInitInfo(m_prog);
  236. variantInitInfo.requestTechniqueAndTypes(ShaderTypeBit::kRayGen, "RtMaterialFetch");
  237. for(const SubMutation& s : mutation)
  238. {
  239. variantInitInfo.addMutation(s.m_mutatorName, s.m_value);
  240. }
  241. variantInitInfo.addMutation("RT_MATERIAL_FETCH_CLIPMAP", rtMaterialFetchClipmap);
  242. const ShaderProgramResourceVariant* variant;
  243. m_prog->getOrCreateVariant(variantInitInfo, variant);
  244. m_rtLibraryGrProg.reset(&variant->getProgram());
  245. m_rayGenShaderGroupIndices[rtMaterialFetchClipmap] = variant->getShaderGroupHandleIndex();
  246. }
  247. {
  248. ANKI_CHECK(ResourceManager::getSingleton().loadResource("ShaderBinaries/RtMaterialFetchMiss.ankiprogbin", m_missProg));
  249. ShaderProgramResourceVariantInitInfo variantInitInfo(m_missProg);
  250. variantInitInfo.requestTechniqueAndTypes(ShaderTypeBit::kMiss, "RtMaterialFetch");
  251. const ShaderProgramResourceVariant* variant;
  252. m_missProg->getOrCreateVariant(variantInitInfo, variant);
  253. m_missShaderGroupIdx = variant->getShaderGroupHandleIndex();
  254. }
  255. m_sbtRecordSize = getAlignedRoundUp(GrManager::getSingleton().getDeviceCapabilities().m_sbtRecordAlignment,
  256. GrManager::getSingleton().getDeviceCapabilities().m_shaderGroupHandleSize + U32(sizeof(UVec4)));
  257. ANKI_CHECK(ResourceManager::getSingleton().loadResource("EngineAssets/BlueNoise_Rgba8_64x64.png", m_blueNoiseImg));
  258. for(U32 i = 0; i < kIndirectDiffuseClipmapCount; ++i)
  259. {
  260. m_consts.m_textures[i].m_radianceTexture = m_radianceVolumes[i]->getOrCreateBindlessTextureIndex(TextureSubresourceDesc::all());
  261. m_consts.m_textures[i].m_irradianceTexture = m_irradianceVolumes[i]->getOrCreateBindlessTextureIndex(TextureSubresourceDesc::all());
  262. m_consts.m_textures[i].m_distanceMomentsTexture = m_distanceMomentsVolumes[i]->getOrCreateBindlessTextureIndex(TextureSubresourceDesc::all());
  263. m_consts.m_textures[i].m_probeValidityTexture = m_probeValidityVolumes[i]->getOrCreateBindlessTextureIndex(TextureSubresourceDesc::all());
  264. m_consts.m_textures[i].m_averageIrradianceTexture = m_avgIrradianceVolumes[i]->getOrCreateBindlessTextureIndex(TextureSubresourceDesc::all());
  265. m_consts.m_textures[i].m_distanceMomentsOctMapSize = (m_distanceMomentsVolumes[i]->getWidth() / m_consts.m_probeCounts.x) - 2;
  266. m_consts.m_textures[i].m_irradianceOctMapSize = (m_irradianceVolumes[i]->getWidth() / m_consts.m_probeCounts.x) - 2;
  267. m_consts.m_textures[i].m_radianceOctMapSize = (m_radianceVolumes[i]->getWidth() / m_consts.m_probeCounts.x) - 2;
  268. m_consts.m_previousFrameAabbMins[i] = 100000.0f * m_consts.m_sizes[i] / Vec4(Vec3(m_consts.m_probeCounts), 1.0f);
  269. m_consts.m_aabbMins[i] = m_consts.m_previousFrameAabbMins[i];
  270. }
  271. return Error::kNone;
  272. }
  273. void IndirectDiffuseClipmaps::populateRenderGraph(RenderingContext& ctx)
  274. {
  275. ANKI_TRACE_SCOPED_EVENT(IndirectDiffuse);
  276. const Bool firstBounceUsesRt = g_cvarRenderIdcFirstBounceRayDistance > 0.0f;
  277. for(U32 i = 0; i < kIndirectDiffuseClipmapCount; ++i)
  278. {
  279. m_consts.m_previousFrameAabbMins[i] = m_consts.m_aabbMins[i];
  280. computeClipmapBounds(ctx.m_matrices.m_cameraTransform.getTranslationPart(),
  281. -ctx.m_matrices.m_cameraTransform.getRotationPart().getZAxis().normalize(), i, m_consts);
  282. }
  283. RenderGraphBuilder& rgraph = ctx.m_renderGraphDescr;
  284. const RenderTargetHandle rtResultHandle = rgraph.newRenderTarget(m_rtResultRtDesc);
  285. const RenderTargetHandle lowRezRt = rgraph.newRenderTarget(m_lowRezRtDesc);
  286. const RenderTargetHandle fullRtTmp = rgraph.newRenderTarget(m_fullRtDesc);
  287. Array<RenderTargetHandle, 2> fullRts;
  288. if(firstBounceUsesRt)
  289. {
  290. for(U32 i = 0; i < 2; ++i)
  291. {
  292. if(m_texturesImportedOnce) [[likely]]
  293. {
  294. fullRts[i] = rgraph.importRenderTarget(m_irradianceRts[i].get());
  295. }
  296. else
  297. {
  298. fullRts[i] = rgraph.importRenderTarget(m_irradianceRts[i].get(), TextureUsageBit::kSrvCompute);
  299. }
  300. }
  301. }
  302. Array<RenderTargetHandle, kIndirectDiffuseClipmapCount>& radianceVolumes = m_runCtx.m_handles.m_radianceVolumes;
  303. Array<RenderTargetHandle, kIndirectDiffuseClipmapCount>& irradianceVolumes = m_runCtx.m_handles.m_irradianceVolumes;
  304. Array<RenderTargetHandle, kIndirectDiffuseClipmapCount>& distanceMomentsVolumes = m_runCtx.m_handles.m_distanceMomentsVolumes;
  305. Array<RenderTargetHandle, kIndirectDiffuseClipmapCount>& probeValidityVolumes = m_runCtx.m_handles.m_probeValidityVolumes;
  306. Array<RenderTargetHandle, kIndirectDiffuseClipmapCount>& avgIrradianceVolumes = m_runCtx.m_handles.m_avgIrradianceVolumes;
  307. for(U32 i = 0; i < kIndirectDiffuseClipmapCount; ++i)
  308. {
  309. if(m_texturesImportedOnce) [[likely]]
  310. {
  311. radianceVolumes[i] = rgraph.importRenderTarget(m_radianceVolumes[i].get());
  312. irradianceVolumes[i] = rgraph.importRenderTarget(m_irradianceVolumes[i].get());
  313. distanceMomentsVolumes[i] = rgraph.importRenderTarget(m_distanceMomentsVolumes[i].get());
  314. probeValidityVolumes[i] = rgraph.importRenderTarget(m_probeValidityVolumes[i].get());
  315. avgIrradianceVolumes[i] = rgraph.importRenderTarget(m_avgIrradianceVolumes[i].get());
  316. }
  317. else
  318. {
  319. radianceVolumes[i] = rgraph.importRenderTarget(m_radianceVolumes[i].get(), TextureUsageBit::kSrvCompute);
  320. irradianceVolumes[i] = rgraph.importRenderTarget(m_irradianceVolumes[i].get(), TextureUsageBit::kSrvCompute);
  321. distanceMomentsVolumes[i] = rgraph.importRenderTarget(m_distanceMomentsVolumes[i].get(), TextureUsageBit::kSrvCompute);
  322. probeValidityVolumes[i] = rgraph.importRenderTarget(m_probeValidityVolumes[i].get(), TextureUsageBit::kSrvCompute);
  323. avgIrradianceVolumes[i] = rgraph.importRenderTarget(m_avgIrradianceVolumes[i].get(), TextureUsageBit::kSrvCompute);
  324. }
  325. }
  326. m_texturesImportedOnce = true;
  327. // SBT build
  328. BufferHandle sbtHandle;
  329. BufferView sbtBuffer;
  330. if(!g_cvarRenderIdcInlineRt)
  331. {
  332. buildShaderBindingTablePass("IndirectDiffuseClipmaps: Build SBT", m_rtLibraryGrProg.get(), m_rayGenShaderGroupIndices[1],
  333. m_missShaderGroupIdx, m_sbtRecordSize, rgraph, sbtHandle, sbtBuffer);
  334. }
  335. for(U32 clipmap = 0; clipmap < kIndirectDiffuseClipmapCount; ++clipmap)
  336. {
  337. // Compute probe ranges and ray budgets and stuff
  338. Array<ProbeRange, 3> fullUpdateRanges;
  339. U32 fullUpdateRangeCount = 0;
  340. ProbeRange partialUpdateRange;
  341. const Vec3 probeSize = m_consts.m_sizes[clipmap].xyz / Vec3(m_consts.m_probeCounts);
  342. findClipmapInUpdateRanges(m_consts.m_aabbMins[clipmap].xyz, m_consts.m_previousFrameAabbMins[clipmap].xyz, probeSize,
  343. UVec3(m_consts.m_probeCounts), fullUpdateRanges, fullUpdateRangeCount, partialUpdateRange);
  344. U32 fullUpdateRayCount = 0;
  345. for(U32 i = 0; i < fullUpdateRangeCount; ++i)
  346. {
  347. const UVec3 counts = UVec3(fullUpdateRanges[i].m_end - fullUpdateRanges[i].m_begin);
  348. const U32 count = counts.x * counts.y * counts.z;
  349. fullUpdateRayCount += square<U32>(g_cvarRenderIdcRadianceOctMapSize) * g_cvarRenderIdcRayCountPerTexelOfNewProbe * count;
  350. }
  351. const U32 remainingRayCount = (g_cvarRenderIdcProbeRayBudget / kIndirectDiffuseClipmapCount > fullUpdateRayCount)
  352. ? g_cvarRenderIdcProbeRayBudget / kIndirectDiffuseClipmapCount - fullUpdateRayCount
  353. : 0;
  354. const UVec3 partialUpdateProbeCounts = UVec3(partialUpdateRange.m_end - partialUpdateRange.m_begin);
  355. U32 partialUpdateProbeCount = remainingRayCount / square<U32>(g_cvarRenderIdcRadianceOctMapSize);
  356. partialUpdateProbeCount = min(partialUpdateProbeCount, partialUpdateProbeCounts.x * partialUpdateProbeCounts.y * partialUpdateProbeCounts.z);
  357. g_svarIdcRays.increment(fullUpdateRayCount + partialUpdateProbeCount * square<U32>(g_cvarRenderIdcRadianceOctMapSize));
  358. struct ClipmapRegion
  359. {
  360. UVec3 m_probesBegin;
  361. U32 m_partialUpdate;
  362. UVec3 m_probeCounts;
  363. U32 m_probeCount;
  364. };
  365. struct ProbeUpdateConsts
  366. {
  367. U32 m_clipmapIdx;
  368. U32 m_radianceOctMapSize; // Have it here as well as well as a mutator. Can't use the mutator cause it will create may raygen variants
  369. U32 m_rayCountPerTexel; // Ray count per oct map texel
  370. U32 m_maxProbesToUpdate;
  371. ClipmapRegion m_clipmapRegion;
  372. };
  373. // Do ray tracing around the probes
  374. {
  375. NonGraphicsRenderPass& pass = rgraph.newNonGraphicsRenderPass(generateTempPassName("IndirectDiffuseClipmaps: RT (clipmap %u)", clipmap));
  376. pass.newTextureDependency(rtResultHandle, (g_cvarRenderIdcInlineRt) ? TextureUsageBit::kUavCompute : TextureUsageBit::kUavDispatchRays);
  377. if(!g_cvarRenderIdcInlineRt)
  378. {
  379. pass.newBufferDependency(sbtHandle, BufferUsageBit::kShaderBindingTable);
  380. }
  381. setRgenSpace2Dependencies(pass, g_cvarRenderIdcInlineRt);
  382. for(U32 clipmap = 0; clipmap < kIndirectDiffuseClipmapCount; ++clipmap)
  383. {
  384. pass.newTextureDependency(irradianceVolumes[clipmap], TextureUsageBit::kSrvCompute);
  385. }
  386. pass.setWork([this, rtResultHandle, &ctx, sbtBuffer, fullUpdateRangeCount, clipmap, fullUpdateRanges, partialUpdateRange,
  387. partialUpdateProbeCount](RenderPassWorkContext& rgraphCtx) {
  388. CommandBuffer& cmdb = *rgraphCtx.m_commandBuffer;
  389. cmdb.bindShaderProgram((g_cvarRenderIdcInlineRt) ? m_rtMaterialFetchInlineRtGrProg.get() : m_rtLibraryGrProg.get());
  390. // More globals
  391. cmdb.bindSampler(ANKI_MATERIAL_REGISTER_TILINEAR_REPEAT_SAMPLER, 0, getRenderer().getSamplers().m_trilinearRepeat.get());
  392. cmdb.bindSrv(ANKI_MATERIAL_REGISTER_GPU_SCENE, 0, GpuSceneBuffer::getSingleton().getBufferView());
  393. cmdb.bindSrv(ANKI_MATERIAL_REGISTER_MESH_LODS, 0, GpuSceneArrays::MeshLod::getSingleton().getBufferView());
  394. cmdb.bindSrv(ANKI_MATERIAL_REGISTER_TRANSFORMS, 0, GpuSceneArrays::Transform::getSingleton().getBufferView());
  395. cmdb.bindSrv(ANKI_MATERIAL_REGISTER_UNIFIED_GEOMETRY, 0, UnifiedGeometryBuffer::getSingleton().getBufferView());
  396. #define ANKI_UNIFIED_GEOM_FORMAT(fmt, shaderType, reg) \
  397. cmdb.bindSrv( \
  398. reg, 0, \
  399. BufferView(&UnifiedGeometryBuffer::getSingleton().getBuffer(), 0, \
  400. getAlignedRoundDown(getFormatInfo(Format::k##fmt).m_texelSize, UnifiedGeometryBuffer::getSingleton().getBuffer().getSize())), \
  401. Format::k##fmt);
  402. #include <AnKi/Shaders/Include/UnifiedGeometryTypes.def.h>
  403. bindRgenSpace2Resources(ctx, rgraphCtx);
  404. rgraphCtx.bindUav(0, 2, rtResultHandle);
  405. ProbeUpdateConsts consts;
  406. consts.m_clipmapIdx = clipmap;
  407. consts.m_radianceOctMapSize = g_cvarRenderIdcRadianceOctMapSize;
  408. // Do full updates
  409. for(U32 i = 0; i < fullUpdateRangeCount; ++i)
  410. {
  411. cmdb.pushDebugMarker("Full update", Vec3(0.0f, 1.0f, 1.0f));
  412. consts.m_rayCountPerTexel = g_cvarRenderIdcRayCountPerTexelOfNewProbe;
  413. consts.m_clipmapRegion.m_probesBegin = UVec3(fullUpdateRanges[i].m_begin);
  414. consts.m_clipmapRegion.m_probeCounts = UVec3(fullUpdateRanges[i].m_end - fullUpdateRanges[i].m_begin);
  415. consts.m_clipmapRegion.m_probeCount =
  416. consts.m_clipmapRegion.m_probeCounts.x * consts.m_clipmapRegion.m_probeCounts.y * consts.m_clipmapRegion.m_probeCounts.z;
  417. consts.m_maxProbesToUpdate = consts.m_clipmapRegion.m_probeCount;
  418. consts.m_clipmapRegion.m_partialUpdate = 0;
  419. cmdb.setFastConstants(&consts, sizeof(consts));
  420. const U32 threadCount =
  421. consts.m_clipmapRegion.m_probeCount * square<U32>(g_cvarRenderIdcRadianceOctMapSize) * consts.m_rayCountPerTexel;
  422. if(g_cvarRenderIdcInlineRt)
  423. {
  424. cmdb.dispatchCompute((threadCount + 64 - 1) / 64, 1, 1);
  425. }
  426. else
  427. {
  428. cmdb.dispatchRays(sbtBuffer, m_sbtRecordSize, GpuSceneArrays::RenderableBoundingVolumeRt::getSingleton().getElementCount(), 1,
  429. threadCount, 1, 1);
  430. }
  431. cmdb.popDebugMarker();
  432. }
  433. // Do partial updates
  434. if(partialUpdateProbeCount)
  435. {
  436. cmdb.pushDebugMarker("Partial update", Vec3(0.0f, 1.0f, 1.0f));
  437. consts.m_rayCountPerTexel = 1;
  438. consts.m_clipmapRegion.m_probesBegin = UVec3(partialUpdateRange.m_begin);
  439. consts.m_clipmapRegion.m_probeCounts = UVec3(partialUpdateRange.m_end - partialUpdateRange.m_begin);
  440. consts.m_clipmapRegion.m_probeCount =
  441. consts.m_clipmapRegion.m_probeCounts.x * consts.m_clipmapRegion.m_probeCounts.y * consts.m_clipmapRegion.m_probeCounts.z;
  442. consts.m_maxProbesToUpdate = partialUpdateProbeCount;
  443. consts.m_clipmapRegion.m_partialUpdate = 1;
  444. cmdb.setFastConstants(&consts, sizeof(consts));
  445. const U32 threadCount = partialUpdateProbeCount * square<U32>(g_cvarRenderIdcRadianceOctMapSize);
  446. if(g_cvarRenderIdcInlineRt)
  447. {
  448. cmdb.dispatchCompute((threadCount + 64 - 1) / 64, 1, 1);
  449. }
  450. else
  451. {
  452. cmdb.dispatchRays(sbtBuffer, m_sbtRecordSize, GpuSceneArrays::RenderableBoundingVolumeRt::getSingleton().getElementCount(), 1,
  453. threadCount, 1, 1);
  454. }
  455. cmdb.popDebugMarker();
  456. }
  457. });
  458. }
  459. // Populate caches
  460. {
  461. NonGraphicsRenderPass& pass =
  462. rgraph.newNonGraphicsRenderPass(generateTempPassName("IndirectDiffuseClipmaps: Populate caches (clipmap %u)", clipmap));
  463. pass.newTextureDependency(rtResultHandle, TextureUsageBit::kSrvCompute);
  464. pass.newTextureDependency(radianceVolumes[clipmap], TextureUsageBit::kUavCompute);
  465. pass.newTextureDependency(probeValidityVolumes[clipmap], TextureUsageBit::kUavCompute);
  466. pass.newTextureDependency(distanceMomentsVolumes[clipmap], TextureUsageBit::kUavCompute);
  467. pass.setWork([this, &ctx, rtResultHandle, radianceVolumes, probeValidityVolumes, distanceMomentsVolumes, clipmap, fullUpdateRanges,
  468. partialUpdateRange, partialUpdateProbeCount, fullUpdateRangeCount](RenderPassWorkContext& rgraphCtx) {
  469. CommandBuffer& cmdb = *rgraphCtx.m_commandBuffer;
  470. cmdb.bindShaderProgram(m_populateCachesGrProg.get());
  471. rgraphCtx.bindSrv(0, 0, rtResultHandle);
  472. cmdb.bindConstantBuffer(0, 0, ctx.m_globalRenderingConstantsBuffer);
  473. rgraphCtx.bindUav(0, 0, radianceVolumes[clipmap]);
  474. rgraphCtx.bindUav(1, 0, distanceMomentsVolumes[clipmap]);
  475. rgraphCtx.bindUav(2, 0, probeValidityVolumes[clipmap]);
  476. ProbeUpdateConsts consts;
  477. consts.m_clipmapIdx = clipmap;
  478. consts.m_radianceOctMapSize = g_cvarRenderIdcRadianceOctMapSize;
  479. // Do full updates
  480. const U32 numthreads = 64;
  481. for(U32 i = 0; i < fullUpdateRangeCount; ++i)
  482. {
  483. cmdb.pushDebugMarker("Full update", Vec3(0.0f, 1.0f, 1.0f));
  484. consts.m_rayCountPerTexel = g_cvarRenderIdcRayCountPerTexelOfNewProbe;
  485. consts.m_clipmapRegion.m_probesBegin = UVec3(fullUpdateRanges[i].m_begin);
  486. consts.m_clipmapRegion.m_probeCounts = UVec3(fullUpdateRanges[i].m_end - fullUpdateRanges[i].m_begin);
  487. consts.m_clipmapRegion.m_probeCount =
  488. consts.m_clipmapRegion.m_probeCounts.x * consts.m_clipmapRegion.m_probeCounts.y * consts.m_clipmapRegion.m_probeCounts.z;
  489. consts.m_maxProbesToUpdate = consts.m_clipmapRegion.m_probeCount;
  490. consts.m_clipmapRegion.m_partialUpdate = 0;
  491. cmdb.setFastConstants(&consts, sizeof(consts));
  492. U32 threadCount = consts.m_clipmapRegion.m_probeCount * square<U32>(g_cvarRenderIdcRadianceOctMapSize);
  493. threadCount = (threadCount + numthreads - 1) / numthreads;
  494. cmdb.dispatchCompute(threadCount, 1, 1);
  495. cmdb.popDebugMarker();
  496. }
  497. // Do partial updates
  498. if(partialUpdateProbeCount)
  499. {
  500. cmdb.pushDebugMarker("Partial update", Vec3(0.0f, 1.0f, 1.0f));
  501. consts.m_rayCountPerTexel = 1;
  502. consts.m_clipmapRegion.m_probesBegin = UVec3(partialUpdateRange.m_begin);
  503. consts.m_clipmapRegion.m_probeCounts = UVec3(partialUpdateRange.m_end - partialUpdateRange.m_begin);
  504. consts.m_clipmapRegion.m_probeCount =
  505. consts.m_clipmapRegion.m_probeCounts.x * consts.m_clipmapRegion.m_probeCounts.y * consts.m_clipmapRegion.m_probeCounts.z;
  506. consts.m_maxProbesToUpdate = partialUpdateProbeCount;
  507. consts.m_clipmapRegion.m_partialUpdate = 1;
  508. cmdb.setFastConstants(&consts, sizeof(consts));
  509. U32 threadCount = consts.m_maxProbesToUpdate * square<U32>(g_cvarRenderIdcRadianceOctMapSize);
  510. threadCount = (threadCount + numthreads - 1) / numthreads;
  511. cmdb.dispatchCompute(threadCount, 1, 1);
  512. cmdb.popDebugMarker();
  513. }
  514. });
  515. }
  516. }
  517. // Compute irradiance
  518. {
  519. NonGraphicsRenderPass& pass = rgraph.newNonGraphicsRenderPass("IndirectDiffuseClipmaps: Irradiance");
  520. for(U32 clipmap = 0; clipmap < kIndirectDiffuseClipmapCount; ++clipmap)
  521. {
  522. pass.newTextureDependency(radianceVolumes[clipmap], TextureUsageBit::kSrvCompute);
  523. pass.newTextureDependency(irradianceVolumes[clipmap], TextureUsageBit::kUavCompute);
  524. pass.newTextureDependency(avgIrradianceVolumes[clipmap], TextureUsageBit::kUavCompute);
  525. }
  526. pass.setWork([this, &ctx, radianceVolumes, irradianceVolumes, avgIrradianceVolumes](RenderPassWorkContext& rgraphCtx) {
  527. CommandBuffer& cmdb = *rgraphCtx.m_commandBuffer;
  528. cmdb.bindShaderProgram(m_computeIrradianceGrProg.get());
  529. cmdb.bindConstantBuffer(0, 0, ctx.m_globalRenderingConstantsBuffer);
  530. U32 uav = 0;
  531. for(U32 clipmap = 0; clipmap < kIndirectDiffuseClipmapCount; ++clipmap)
  532. {
  533. rgraphCtx.bindSrv(clipmap, 0, radianceVolumes[clipmap]);
  534. rgraphCtx.bindUav(uav++, 0, irradianceVolumes[clipmap]);
  535. }
  536. for(U32 clipmap = 0; clipmap < kIndirectDiffuseClipmapCount; ++clipmap)
  537. {
  538. rgraphCtx.bindUav(uav++, 0, avgIrradianceVolumes[clipmap]);
  539. }
  540. cmdb.dispatchCompute(m_consts.m_probeCounts[0] * kIndirectDiffuseClipmapCount, m_consts.m_probeCounts[1], m_consts.m_probeCounts[2]);
  541. });
  542. }
  543. // Apply GI
  544. if(firstBounceUsesRt)
  545. {
  546. if(!g_cvarRenderIdcInlineRt)
  547. {
  548. patchShaderBindingTablePass("IndirectDiffuseClipmaps: Patch SBT", m_rtLibraryGrProg.get(), m_rayGenShaderGroupIndices[0],
  549. m_missShaderGroupIdx, m_sbtRecordSize, rgraph, sbtHandle, sbtBuffer);
  550. }
  551. NonGraphicsRenderPass& pass = rgraph.newNonGraphicsRenderPass("IndirectDiffuseClipmaps: RTApply");
  552. if(!g_cvarRenderIdcInlineRt)
  553. {
  554. pass.newBufferDependency(sbtHandle, BufferUsageBit::kShaderBindingTable);
  555. }
  556. for(U32 clipmap = 0; clipmap < kIndirectDiffuseClipmapCount; ++clipmap)
  557. {
  558. pass.newTextureDependency(irradianceVolumes[clipmap], TextureUsageBit::kSrvDispatchRays);
  559. pass.newTextureDependency(probeValidityVolumes[clipmap], TextureUsageBit::kSrvDispatchRays);
  560. pass.newTextureDependency(distanceMomentsVolumes[clipmap], TextureUsageBit::kSrvDispatchRays);
  561. }
  562. pass.newTextureDependency(lowRezRt, TextureUsageBit::kUavDispatchRays);
  563. setRgenSpace2Dependencies(pass);
  564. pass.setWork([this, &ctx, sbtBuffer, lowRezRt](RenderPassWorkContext& rgraphCtx) {
  565. CommandBuffer& cmdb = *rgraphCtx.m_commandBuffer;
  566. // More globals
  567. cmdb.bindSampler(ANKI_MATERIAL_REGISTER_TILINEAR_REPEAT_SAMPLER, 0, getRenderer().getSamplers().m_trilinearRepeat.get());
  568. cmdb.bindSrv(ANKI_MATERIAL_REGISTER_GPU_SCENE, 0, GpuSceneBuffer::getSingleton().getBufferView());
  569. cmdb.bindSrv(ANKI_MATERIAL_REGISTER_MESH_LODS, 0, GpuSceneArrays::MeshLod::getSingleton().getBufferView());
  570. cmdb.bindSrv(ANKI_MATERIAL_REGISTER_TRANSFORMS, 0, GpuSceneArrays::Transform::getSingleton().getBufferView());
  571. cmdb.bindSrv(ANKI_MATERIAL_REGISTER_UNIFIED_GEOMETRY, 0, UnifiedGeometryBuffer::getSingleton().getBufferView());
  572. #define ANKI_UNIFIED_GEOM_FORMAT(fmt, shaderType, reg) \
  573. cmdb.bindSrv( \
  574. reg, 0, \
  575. BufferView(&UnifiedGeometryBuffer::getSingleton().getBuffer(), 0, \
  576. getAlignedRoundDown(getFormatInfo(Format::k##fmt).m_texelSize, UnifiedGeometryBuffer::getSingleton().getBuffer().getSize())), \
  577. Format::k##fmt);
  578. #include <AnKi/Shaders/Include/UnifiedGeometryTypes.def.h>
  579. bindRgenSpace2Resources(ctx, rgraphCtx);
  580. rgraphCtx.bindUav(0, 2, lowRezRt);
  581. const Array<Vec4, 3> consts = {Vec4(g_cvarRenderIdcFirstBounceRayDistance), {}, {}};
  582. cmdb.setFastConstants(&consts, sizeof(consts));
  583. const U32 width = getRenderer().getInternalResolution().x / 2;
  584. const U32 height = getRenderer().getInternalResolution().y / (!g_cvarRenderIdcApplyHighQuality + 1);
  585. if(g_cvarRenderIdcInlineRt)
  586. {
  587. cmdb.bindShaderProgram(m_applyGiUsingInlineRtGrProg.get());
  588. dispatchPPCompute(cmdb, 8, 8, width, height);
  589. }
  590. else
  591. {
  592. cmdb.bindShaderProgram(m_rtLibraryGrProg.get());
  593. cmdb.dispatchRays(sbtBuffer, m_sbtRecordSize, GpuSceneArrays::RenderableBoundingVolumeRt::getSingleton().getElementCount(), 1, width,
  594. height, 1);
  595. }
  596. g_svarIdcRays.increment(width * height);
  597. });
  598. }
  599. else
  600. {
  601. NonGraphicsRenderPass& pass = rgraph.newNonGraphicsRenderPass("IndirectDiffuseClipmaps: Apply irradiance");
  602. pass.newTextureDependency(getGBuffer().getDepthRt(), TextureUsageBit::kSrvCompute);
  603. pass.newTextureDependency(getGBuffer().getColorRt(2), TextureUsageBit::kSrvCompute);
  604. for(U32 i = 0; i < kIndirectDiffuseClipmapCount; ++i)
  605. {
  606. pass.newTextureDependency(irradianceVolumes[i], TextureUsageBit::kSrvCompute);
  607. pass.newTextureDependency(probeValidityVolumes[i], TextureUsageBit::kSrvCompute);
  608. pass.newTextureDependency(distanceMomentsVolumes[i], TextureUsageBit::kSrvCompute);
  609. pass.newTextureDependency(avgIrradianceVolumes[i], TextureUsageBit::kSrvCompute);
  610. }
  611. pass.newTextureDependency(lowRezRt, TextureUsageBit::kUavCompute);
  612. pass.setWork([this, &ctx, lowRezRt](RenderPassWorkContext& rgraphCtx) {
  613. CommandBuffer& cmdb = *rgraphCtx.m_commandBuffer;
  614. cmdb.bindShaderProgram(m_applyGiGrProg.get());
  615. rgraphCtx.bindSrv(0, 0, getGBuffer().getDepthRt());
  616. rgraphCtx.bindSrv(1, 0, getGBuffer().getColorRt(2));
  617. cmdb.bindSrv(2, 0, TextureView(&m_blueNoiseImg->getTexture(), TextureSubresourceDesc::firstSurface()));
  618. rgraphCtx.bindUav(0, 0, lowRezRt);
  619. cmdb.bindConstantBuffer(0, 0, ctx.m_globalRenderingConstantsBuffer);
  620. cmdb.bindSampler(0, 0, getRenderer().getSamplers().m_trilinearRepeat.get());
  621. dispatchPPCompute(cmdb, 8, 8, getRenderer().getInternalResolution().x / 2,
  622. getRenderer().getInternalResolution().y / (!g_cvarRenderIdcApplyHighQuality + 1));
  623. });
  624. }
  625. // Spatial reconstruct
  626. {
  627. NonGraphicsRenderPass& pass = rgraph.newNonGraphicsRenderPass("IndirectDiffuseClipmaps: Spatial reconstruct");
  628. pass.newTextureDependency(getGBuffer().getDepthRt(), TextureUsageBit::kSrvCompute);
  629. pass.newTextureDependency(lowRezRt, TextureUsageBit::kSrvCompute);
  630. pass.newTextureDependency(fullRtTmp, TextureUsageBit::kUavCompute);
  631. pass.setWork([this, lowRezRt, fullRtTmp](RenderPassWorkContext& rgraphCtx) {
  632. CommandBuffer& cmdb = *rgraphCtx.m_commandBuffer;
  633. cmdb.bindShaderProgram(m_spatialReconstructGrProg.get());
  634. rgraphCtx.bindSrv(0, 0, lowRezRt);
  635. rgraphCtx.bindSrv(1, 0, getGBuffer().getDepthRt());
  636. rgraphCtx.bindUav(0, 0, fullRtTmp);
  637. dispatchPPCompute(cmdb, 8, 8, getRenderer().getInternalResolution().x / 2,
  638. getRenderer().getInternalResolution().y / (!g_cvarRenderIdcApplyHighQuality + 1));
  639. });
  640. }
  641. if(!firstBounceUsesRt)
  642. {
  643. m_runCtx.m_handles.m_appliedIrradiance = fullRtTmp;
  644. return;
  645. }
  646. const RenderTargetHandle historyRt = fullRts[0];
  647. const RenderTargetHandle outRt = fullRts[1];
  648. // Temporal denoise
  649. {
  650. NonGraphicsRenderPass& pass = rgraph.newNonGraphicsRenderPass("IndirectDiffuseClipmaps: Temporal denoise");
  651. pass.newTextureDependency(fullRtTmp, TextureUsageBit::kSrvCompute);
  652. pass.newTextureDependency(historyRt, TextureUsageBit::kSrvCompute);
  653. pass.newTextureDependency(getHistoryLength().getRt(), TextureUsageBit::kSrvCompute);
  654. pass.newTextureDependency(getMotionVectors().getMotionVectorsRt(), TextureUsageBit::kSrvCompute);
  655. pass.newTextureDependency(outRt, TextureUsageBit::kUavCompute);
  656. pass.setWork([this, &ctx, fullRtTmp, historyRt, outRt](RenderPassWorkContext& rgraphCtx) {
  657. CommandBuffer& cmdb = *rgraphCtx.m_commandBuffer;
  658. cmdb.bindShaderProgram(m_temporalDenoiseGrProg.get());
  659. rgraphCtx.bindSrv(0, 0, getHistoryLength().getRt());
  660. rgraphCtx.bindSrv(1, 0, getMotionVectors().getMotionVectorsRt());
  661. rgraphCtx.bindSrv(2, 0, historyRt);
  662. rgraphCtx.bindSrv(3, 0, fullRtTmp);
  663. rgraphCtx.bindUav(0, 0, outRt);
  664. cmdb.bindSampler(0, 0, getRenderer().getSamplers().m_trilinearClamp.get());
  665. cmdb.bindConstantBuffer(0, 0, ctx.m_globalRenderingConstantsBuffer);
  666. dispatchPPCompute(cmdb, 8, 8, getRenderer().getInternalResolution().x, getRenderer().getInternalResolution().y);
  667. });
  668. }
  669. // Bilateral denoise
  670. {
  671. NonGraphicsRenderPass& pass = rgraph.newNonGraphicsRenderPass("IndirectDiffuseClipmaps: Bilateral denoise");
  672. pass.newTextureDependency(getGBuffer().getDepthRt(), TextureUsageBit::kSrvCompute);
  673. pass.newTextureDependency(outRt, TextureUsageBit::kSrvCompute);
  674. pass.newTextureDependency(historyRt, TextureUsageBit::kUavCompute);
  675. pass.setWork([this, outRt, historyRt](RenderPassWorkContext& rgraphCtx) {
  676. CommandBuffer& cmdb = *rgraphCtx.m_commandBuffer;
  677. cmdb.bindShaderProgram(m_bilateralDenoiseGrProg.get());
  678. rgraphCtx.bindSrv(0, 0, outRt);
  679. rgraphCtx.bindSrv(1, 0, getGBuffer().getDepthRt());
  680. rgraphCtx.bindUav(0, 0, historyRt);
  681. dispatchPPCompute(cmdb, 8, 8, getRenderer().getInternalResolution().x, getRenderer().getInternalResolution().y);
  682. });
  683. }
  684. m_runCtx.m_handles.m_appliedIrradiance = historyRt;
  685. }
  686. void IndirectDiffuseClipmaps::drawDebugProbes(const RenderingContext& ctx, RenderPassWorkContext& rgraphCtx) const
  687. {
  688. CommandBuffer& cmdb = *rgraphCtx.m_commandBuffer;
  689. const U32 clipmap = 0;
  690. cmdb.bindShaderProgram(m_visProbesGrProg.get());
  691. const UVec4 consts(clipmap);
  692. cmdb.setFastConstants(&consts, sizeof(consts));
  693. cmdb.bindConstantBuffer(0, 0, ctx.m_globalRenderingConstantsBuffer);
  694. const RenderTargetHandle visVolume = m_runCtx.m_handles.m_radianceVolumes[clipmap];
  695. rgraphCtx.bindSrv(0, 0, visVolume);
  696. rgraphCtx.bindSrv(1, 0, m_runCtx.m_handles.m_probeValidityVolumes[clipmap]);
  697. cmdb.bindSampler(0, 0, getRenderer().getSamplers().m_trilinearRepeat.get());
  698. cmdb.draw(PrimitiveTopology::kTriangles, 36, m_consts.m_totalProbeCount);
  699. }
  700. } // end namespace anki