PackVisibleClusteredObjects.cpp 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. // Copyright (C) 2009-2023, 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/PackVisibleClusteredObjects.h>
  6. #include <AnKi/Renderer/Renderer.h>
  7. #include <AnKi/Renderer/RenderQueue.h>
  8. #include <AnKi/Resource/ResourceManager.h>
  9. #include <AnKi/Shaders/Include/GpuSceneTypes.h>
  10. #include <AnKi/Shaders/Include/MiscRendererTypes.h>
  11. namespace anki {
  12. PackVisibleClusteredObjects::PackVisibleClusteredObjects(Renderer* r)
  13. : RendererObject(r)
  14. {
  15. }
  16. PackVisibleClusteredObjects::~PackVisibleClusteredObjects()
  17. {
  18. }
  19. Error PackVisibleClusteredObjects::init()
  20. {
  21. ANKI_CHECK(m_r->getExternalSubsystems().m_resourceManager->loadResource(
  22. "ShaderBinaries/PackVisibleClusteredObjects.ankiprogbin", m_packProg));
  23. U32 maxWaveSize = m_r->getExternalSubsystems().m_grManager->getDeviceCapabilities().m_maxSubgroupSize;
  24. if(maxWaveSize == 16 || maxWaveSize == 32)
  25. {
  26. m_threadGroupSize = maxWaveSize;
  27. }
  28. else
  29. {
  30. m_threadGroupSize = 64;
  31. }
  32. for(ClusteredObjectType type = ClusteredObjectType::kFirst; type < ClusteredObjectType::kCount; ++type)
  33. {
  34. const ShaderProgramResourceVariant* variant;
  35. ShaderProgramResourceVariantInitInfo variantInit(m_packProg);
  36. variantInit.addMutation("OBJECT_TYPE", U32(type));
  37. variantInit.addMutation("THREAD_GROUP_SIZE", m_threadGroupSize);
  38. m_packProg->getOrCreateVariant(variantInit, variant);
  39. m_grProgs[type] = variant->getProgram();
  40. }
  41. U32 offset = 0;
  42. for(ClusteredObjectType type = ClusteredObjectType::kFirst; type < ClusteredObjectType::kCount; ++type)
  43. {
  44. alignRoundUp(getExternalSubsystems().m_grManager->getDeviceCapabilities().m_storageBufferBindOffsetAlignment,
  45. offset);
  46. m_structureBufferOffsets[type] = offset;
  47. offset += kMaxVisibleClusteredObjects[type] * kClusteredObjectSizes[type];
  48. }
  49. BufferInitInfo buffInit("ClusterObjects");
  50. buffInit.m_size = offset;
  51. buffInit.m_usage = BufferUsageBit::kAllCompute | BufferUsageBit::kAllGraphics;
  52. m_allClustererObjects = m_r->getExternalSubsystems().m_grManager->newBuffer(buffInit);
  53. return Error::kNone;
  54. }
  55. template<typename TClustererType, ClusteredObjectType kType, typename TRenderQueueElement>
  56. void PackVisibleClusteredObjects::dispatchType(WeakArray<TRenderQueueElement> array, const RenderQueue& rqueue,
  57. CommandBufferPtr& cmdb)
  58. {
  59. if(array.getSize() == 0)
  60. {
  61. return;
  62. }
  63. RebarGpuMemoryToken token;
  64. U32* indices = allocateStorage<U32*>(array.getSize() * sizeof(U32), token);
  65. RebarGpuMemoryToken extrasToken;
  66. PointLightExtra* plightExtras = nullptr;
  67. SpotLightExtra* slightExtras = nullptr;
  68. if constexpr(std::is_same_v<TClustererType, PointLight>)
  69. {
  70. plightExtras = allocateStorage<PointLightExtra*>(array.getSize() * sizeof(PointLightExtra), extrasToken);
  71. }
  72. else if constexpr(std::is_same_v<TClustererType, SpotLight>)
  73. {
  74. slightExtras = allocateStorage<SpotLightExtra*>(array.getSize() * sizeof(SpotLightExtra), extrasToken);
  75. }
  76. // Write ReBAR
  77. for(const auto& el : array)
  78. {
  79. *indices = el.m_index;
  80. ++indices;
  81. if constexpr(std::is_same_v<TClustererType, PointLight>)
  82. {
  83. if(el.m_shadowRenderQueues[0] == nullptr)
  84. {
  85. plightExtras->m_shadowAtlasTileScale = -1.0f;
  86. plightExtras->m_shadowLayer = kMaxU32;
  87. }
  88. else
  89. {
  90. plightExtras->m_shadowLayer = el.m_shadowLayer;
  91. plightExtras->m_shadowAtlasTileScale = el.m_shadowAtlasTileSize;
  92. for(U32 f = 0; f < 6; ++f)
  93. {
  94. plightExtras->m_shadowAtlasTileOffsets[f] = Vec4(el.m_shadowAtlasTileOffsets[f], 0.0f, 0.0f);
  95. }
  96. }
  97. ++plightExtras;
  98. }
  99. else if constexpr(std::is_same_v<TClustererType, SpotLight>)
  100. {
  101. slightExtras->m_shadowLayer = el.m_shadowLayer;
  102. slightExtras->m_textureMatrix = el.m_textureMatrix;
  103. ++slightExtras;
  104. }
  105. }
  106. cmdb->bindStorageBuffer(0, 0, GpuSceneMemoryPool::getSingleton().getBuffer(),
  107. rqueue.m_clustererObjectsArrayOffsets[kType], rqueue.m_clustererObjectsArrayRanges[kType]);
  108. cmdb->bindStorageBuffer(0, 1, m_allClustererObjects, m_structureBufferOffsets[kType],
  109. array.getSize() * sizeof(TClustererType));
  110. cmdb->bindStorageBuffer(0, 2, RebarStagingGpuMemoryPool::getSingleton().getBuffer(), token.m_offset, token.m_range);
  111. if constexpr(std::is_same_v<TClustererType, PointLight> || std::is_same_v<TClustererType, SpotLight>)
  112. {
  113. cmdb->bindStorageBuffer(0, 3, RebarStagingGpuMemoryPool::getSingleton().getBuffer(), extrasToken.m_offset,
  114. extrasToken.m_range);
  115. }
  116. cmdb->bindShaderProgram(m_grProgs[kType]);
  117. const UVec4 pc(array.getSize());
  118. cmdb->setPushConstants(&pc, sizeof(pc));
  119. dispatchPPCompute(cmdb, m_threadGroupSize, 1, 1, array.getSize(), 1, 1);
  120. }
  121. void PackVisibleClusteredObjects::populateRenderGraph(RenderingContext& ctx)
  122. {
  123. RenderGraphDescription& rgraph = ctx.m_renderGraphDescr;
  124. ComputeRenderPassDescription& pass = rgraph.newComputeRenderPass("PackClusterObjects");
  125. pass.newBufferDependency(m_r->getGpuSceneBufferHandle(), BufferUsageBit::kStorageComputeRead);
  126. m_allClustererObjectsHandle = rgraph.importBuffer(m_allClustererObjects, BufferUsageBit::kNone);
  127. pass.newBufferDependency(m_allClustererObjectsHandle, BufferUsageBit::kStorageComputeWrite);
  128. pass.setWork([&ctx, this](RenderPassWorkContext& rgraphCtx) {
  129. const RenderQueue& rqueue = *ctx.m_renderQueue;
  130. CommandBufferPtr& cmdb = rgraphCtx.m_commandBuffer;
  131. dispatchType<PointLight, ClusteredObjectType::kPointLight>(rqueue.m_pointLights, rqueue, cmdb);
  132. dispatchType<SpotLight, ClusteredObjectType::kSpotLight>(rqueue.m_spotLights, rqueue, cmdb);
  133. dispatchType<Decal, ClusteredObjectType::kDecal>(rqueue.m_decals, rqueue, cmdb);
  134. dispatchType<FogDensityVolume, ClusteredObjectType::kFogDensityVolume>(rqueue.m_fogDensityVolumes, rqueue,
  135. cmdb);
  136. dispatchType<ReflectionProbe, ClusteredObjectType::kReflectionProbe>(rqueue.m_reflectionProbes, rqueue, cmdb);
  137. dispatchType<GlobalIlluminationProbe, ClusteredObjectType::kGlobalIlluminationProbe>(rqueue.m_giProbes, rqueue,
  138. cmdb);
  139. });
  140. }
  141. } // end namespace anki