GpuVisibility.cpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399
  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/Utils/GpuVisibility.h>
  6. #include <AnKi/Renderer/Renderer.h>
  7. #include <AnKi/Scene/RenderStateBucket.h>
  8. #include <AnKi/Scene/GpuSceneArray.h>
  9. #include <AnKi/Core/GpuMemory/GpuVisibleTransientMemoryPool.h>
  10. #include <AnKi/Core/GpuMemory/RebarTransientMemoryPool.h>
  11. #include <AnKi/Core/GpuMemory/GpuSceneBuffer.h>
  12. #include <AnKi/Collision/Functions.h>
  13. #include <AnKi/Shaders/Include/GpuVisibilityTypes.h>
  14. #include <AnKi/Core/StatsSet.h>
  15. namespace anki {
  16. static StatCounter g_visibleObjects(StatCategory::kMisc, "Visible objects", StatFlag::kZeroEveryFrame);
  17. static StatCounter g_testedObjects(StatCategory::kMisc, "Visbility tested objects", StatFlag::kZeroEveryFrame);
  18. Error GpuVisibility::init()
  19. {
  20. ANKI_CHECK(ResourceManager::getSingleton().loadResource("ShaderBinaries/GpuVisibility.ankiprogbin", m_prog));
  21. for(U32 i = 0; i < 2; ++i)
  22. {
  23. ShaderProgramResourceVariantInitInfo variantInit(m_prog);
  24. variantInit.addMutation("HZB_TEST", i);
  25. variantInit.addMutation("STATS", ANKI_STATS_ENABLED);
  26. const ShaderProgramResourceVariant* variant;
  27. m_prog->getOrCreateVariant(variantInit, variant);
  28. m_grProgs[i].reset(&variant->getProgram());
  29. }
  30. #if ANKI_STATS_ENABLED
  31. for(GpuReadbackMemoryAllocation& alloc : m_readbackMemory)
  32. {
  33. alloc = GpuReadbackMemoryPool::getSingleton().allocate(sizeof(U32));
  34. }
  35. #endif
  36. return Error::kNone;
  37. }
  38. void GpuVisibility::populateRenderGraph(CString passesName, RenderingTechnique technique, const Mat4& viewProjectionMat, Vec3 lodReferencePoint,
  39. const Array<F32, kMaxLodCount - 1> lodDistances, const RenderTargetHandle* hzbRt,
  40. RenderGraphDescription& rgraph, GpuVisibilityOutput& out)
  41. {
  42. U32 aabbCount = 0;
  43. switch(technique)
  44. {
  45. case RenderingTechnique::kGBuffer:
  46. aabbCount = GpuSceneArrays::RenderableAabbGBuffer::getSingleton().getElementCount();
  47. case RenderingTechnique::kDepth:
  48. aabbCount = GpuSceneArrays::RenderableAabbDepth::getSingleton().getElementCount();
  49. break;
  50. default:
  51. ANKI_ASSERT(0);
  52. }
  53. const U32 bucketCount = RenderStateBucketContainer::getSingleton().getBucketCount(technique);
  54. #if ANKI_STATS_ENABLED
  55. Bool firstCallInTheFrame = false;
  56. if(m_lastFrameIdx != getRenderer().getFrameCount())
  57. {
  58. firstCallInTheFrame = true;
  59. m_lastFrameIdx = getRenderer().getFrameCount();
  60. }
  61. const GpuReadbackMemoryAllocation& readAlloc = m_readbackMemory[(m_lastFrameIdx + 1) % m_readbackMemory.getSize()];
  62. const GpuReadbackMemoryAllocation& writeAlloc = m_readbackMemory[m_lastFrameIdx % m_readbackMemory.getSize()];
  63. Buffer* clearStatsBuffer = &readAlloc.getBuffer();
  64. const PtrSize clearStatsBufferOffset = readAlloc.getOffset();
  65. Buffer* writeStatsBuffer = &writeAlloc.getBuffer();
  66. const PtrSize writeStatsBufferOffset = writeAlloc.getOffset();
  67. if(firstCallInTheFrame)
  68. {
  69. U32 visibleCount;
  70. memcpy(&visibleCount, readAlloc.getMappedMemory(), sizeof(visibleCount));
  71. g_visibleObjects.set(visibleCount);
  72. }
  73. g_testedObjects.increment(aabbCount);
  74. #endif
  75. // Allocate memory for the indirect commands
  76. const GpuVisibleTransientMemoryAllocation indirectArgs =
  77. GpuVisibleTransientMemoryPool::getSingleton().allocate(aabbCount * sizeof(DrawIndexedIndirectArgs));
  78. out.m_drawIndexedIndirectArgsBuffer = indirectArgs.m_buffer;
  79. out.m_drawIndexedIndirectArgsBufferOffset = indirectArgs.m_offset;
  80. out.m_drawIndexedIndirectArgsBufferRange = indirectArgs.m_size;
  81. const GpuVisibleTransientMemoryAllocation instanceRateRenderables =
  82. GpuVisibleTransientMemoryPool::getSingleton().allocate(aabbCount * sizeof(GpuSceneRenderable));
  83. out.m_instanceRateRenderablesBuffer = instanceRateRenderables.m_buffer;
  84. out.m_instanceRateRenderablesBufferOffset = instanceRateRenderables.m_offset;
  85. out.m_instanceRateRenderablesBufferRange = instanceRateRenderables.m_size;
  86. // Allocate and zero the MDI counts
  87. RebarAllocation mdiDrawCounts;
  88. U32* atomics = RebarTransientMemoryPool::getSingleton().allocateFrame<U32>(bucketCount, mdiDrawCounts);
  89. memset(atomics, 0, mdiDrawCounts.m_range);
  90. out.m_mdiDrawCountsBuffer = &RebarTransientMemoryPool::getSingleton().getBuffer();
  91. out.m_mdiDrawCountsBufferOffset = mdiDrawCounts.m_offset;
  92. out.m_mdiDrawCountsBufferRange = mdiDrawCounts.m_range;
  93. // Import buffers
  94. out.m_mdiDrawCountsHandle = rgraph.importBuffer(&RebarTransientMemoryPool::getSingleton().getBuffer(), BufferUsageBit::kNone,
  95. mdiDrawCounts.m_offset, mdiDrawCounts.m_range);
  96. // Create the renderpass
  97. ComputeRenderPassDescription& pass = rgraph.newComputeRenderPass(passesName);
  98. pass.newBufferDependency(getRenderer().getGpuSceneBufferHandle(), BufferUsageBit::kStorageComputeRead);
  99. pass.newBufferDependency(out.m_mdiDrawCountsHandle, BufferUsageBit::kStorageComputeWrite);
  100. if(hzbRt)
  101. {
  102. pass.newTextureDependency(*hzbRt, TextureUsageBit::kSampledCompute);
  103. }
  104. const RenderTargetHandle hzbRtCopy =
  105. (hzbRt) ? *hzbRt : RenderTargetHandle(); // Can't pass to the lambda the hzbRt which is a pointer to who knows what
  106. pass.setWork([this, viewProjectionMat, lodReferencePoint, lodDistances, technique, hzbRtCopy, mdiDrawCountsHandle = out.m_mdiDrawCountsHandle,
  107. instanceRateRenderables, indirectArgs, aabbCount
  108. #if ANKI_STATS_ENABLED
  109. ,
  110. clearStatsBuffer, clearStatsBufferOffset, writeStatsBuffer, writeStatsBufferOffset
  111. #endif
  112. ](RenderPassWorkContext& rpass) {
  113. CommandBuffer& cmdb = *rpass.m_commandBuffer;
  114. cmdb.bindShaderProgram(m_grProgs[hzbRtCopy.isValid()].get());
  115. switch(technique)
  116. {
  117. case RenderingTechnique::kGBuffer:
  118. cmdb.bindStorageBuffer(0, 0, &GpuSceneBuffer::getSingleton().getBuffer(),
  119. GpuSceneArrays::RenderableAabbGBuffer::getSingleton().getGpuSceneOffsetOfArrayBase(),
  120. GpuSceneArrays::RenderableAabbGBuffer::getSingleton().getElementCount()
  121. * GpuSceneArrays::RenderableAabbGBuffer::getSingleton().getElementSize());
  122. break;
  123. case RenderingTechnique::kDepth:
  124. cmdb.bindStorageBuffer(0, 0, &GpuSceneBuffer::getSingleton().getBuffer(),
  125. GpuSceneArrays::RenderableAabbDepth::getSingleton().getGpuSceneOffsetOfArrayBase(),
  126. GpuSceneArrays::RenderableAabbDepth::getSingleton().getElementCount()
  127. * GpuSceneArrays::RenderableAabbDepth::getSingleton().getElementSize());
  128. break;
  129. default:
  130. ANKI_ASSERT(0);
  131. }
  132. cmdb.bindStorageBuffer(
  133. 0, 1, &GpuSceneBuffer::getSingleton().getBuffer(), GpuSceneArrays::Renderable::getSingleton().getGpuSceneOffsetOfArrayBase(),
  134. GpuSceneArrays::Renderable::getSingleton().getElementCount() * GpuSceneArrays::Renderable::getSingleton().getElementSize());
  135. cmdb.bindStorageBuffer(0, 2, &GpuSceneBuffer::getSingleton().getBuffer(), 0, kMaxPtrSize);
  136. cmdb.bindStorageBuffer(0, 3, instanceRateRenderables.m_buffer, instanceRateRenderables.m_offset, instanceRateRenderables.m_size);
  137. cmdb.bindStorageBuffer(0, 4, indirectArgs.m_buffer, indirectArgs.m_offset, indirectArgs.m_size);
  138. U32* offsets = allocateAndBindStorage<U32*>(sizeof(U32) * RenderStateBucketContainer::getSingleton().getBucketCount(technique), cmdb, 0, 5);
  139. U32 bucketCount = 0;
  140. U32 userCount = 0;
  141. RenderStateBucketContainer::getSingleton().iterateBuckets(technique, [&](const RenderStateInfo&, U32 userCount_) {
  142. offsets[bucketCount] = userCount;
  143. userCount += userCount_;
  144. ++bucketCount;
  145. });
  146. ANKI_ASSERT(userCount == RenderStateBucketContainer::getSingleton().getBucketsItemCount(technique));
  147. rpass.bindStorageBuffer(0, 6, mdiDrawCountsHandle);
  148. GpuVisibilityUniforms* unis = allocateAndBindUniforms<GpuVisibilityUniforms*>(sizeof(GpuVisibilityUniforms), cmdb, 0, 7);
  149. Array<Plane, 6> planes;
  150. extractClipPlanes(viewProjectionMat, planes);
  151. for(U32 i = 0; i < 6; ++i)
  152. {
  153. unis->m_clipPlanes[i] = Vec4(planes[i].getNormal().xyz(), planes[i].getOffset());
  154. }
  155. ANKI_ASSERT(kMaxLodCount == 3);
  156. unis->m_maxLodDistances[0] = lodDistances[0];
  157. unis->m_maxLodDistances[1] = lodDistances[1];
  158. unis->m_maxLodDistances[2] = kMaxF32;
  159. unis->m_maxLodDistances[3] = kMaxF32;
  160. unis->m_lodReferencePoint = lodReferencePoint;
  161. unis->m_viewProjectionMat = viewProjectionMat;
  162. if(hzbRtCopy.isValid())
  163. {
  164. rpass.bindColorTexture(0, 8, hzbRtCopy);
  165. cmdb.bindSampler(0, 9, getRenderer().getSamplers().m_nearestNearestClamp.get());
  166. }
  167. #if ANKI_STATS_ENABLED
  168. cmdb.bindStorageBuffer(0, 10, writeStatsBuffer, writeStatsBufferOffset, sizeof(U32));
  169. cmdb.bindStorageBuffer(0, 11, clearStatsBuffer, clearStatsBufferOffset, sizeof(U32));
  170. #endif
  171. dispatchPPCompute(cmdb, 64, 1, aabbCount, 1);
  172. });
  173. }
  174. Error GpuVisibilityNonRenderables::init()
  175. {
  176. ANKI_CHECK(ResourceManager::getSingleton().loadResource("ShaderBinaries/GpuVisibilityNonRenderables.ankiprogbin", m_prog));
  177. for(U32 hzb = 0; hzb < 2; ++hzb)
  178. {
  179. for(GpuSceneNonRenderableObjectType type : EnumIterable<GpuSceneNonRenderableObjectType>())
  180. {
  181. for(U32 cpuFeedback = 0; cpuFeedback < 2; ++cpuFeedback)
  182. {
  183. ShaderProgramResourceVariantInitInfo variantInit(m_prog);
  184. variantInit.addMutation("HZB_TEST", hzb);
  185. variantInit.addMutation("OBJECT_TYPE", U32(type));
  186. variantInit.addMutation("CPU_FEEDBACK", cpuFeedback);
  187. const ShaderProgramResourceVariant* variant;
  188. m_prog->getOrCreateVariant(variantInit, variant);
  189. if(variant)
  190. {
  191. m_grProgs[hzb][type][cpuFeedback].reset(&variant->getProgram());
  192. }
  193. else
  194. {
  195. m_grProgs[hzb][type][cpuFeedback].reset(nullptr);
  196. }
  197. }
  198. }
  199. }
  200. {
  201. CommandBufferInitInfo cmdbInit("TmpClear");
  202. cmdbInit.m_flags |= CommandBufferFlag::kSmallBatch;
  203. CommandBufferPtr cmdb = GrManager::getSingleton().newCommandBuffer(cmdbInit);
  204. for(U32 i = 0; i < kMaxRenderGraphAccelerationStructures; ++i)
  205. {
  206. RendererString name;
  207. name.sprintf("GpuVisibilityNonRenderablesCounters#%u", i);
  208. BufferInitInfo buffInit(name);
  209. buffInit.m_size = 3 * sizeof(U32);
  210. buffInit.m_usage = BufferUsageBit::kStorageComputeWrite | BufferUsageBit::kTransferDestination;
  211. m_counterBuffers[i] = GrManager::getSingleton().newBuffer(buffInit);
  212. cmdb->fillBuffer(m_counterBuffers[i].get(), 0, kMaxPtrSize, 0);
  213. }
  214. cmdb->flush();
  215. GrManager::getSingleton().finish();
  216. }
  217. return Error::kNone;
  218. }
  219. void GpuVisibilityNonRenderables::populateRenderGraph(GpuVisibilityNonRenderablesInput& in, GpuVisibilityNonRenderablesOutput& out)
  220. {
  221. U32 objCount = 0;
  222. switch(in.m_objectType)
  223. {
  224. case GpuSceneNonRenderableObjectType::kLight:
  225. objCount = GpuSceneArrays::Light::getSingleton().getElementCount();
  226. break;
  227. case GpuSceneNonRenderableObjectType::kDecal:
  228. objCount = GpuSceneArrays::Decal::getSingleton().getElementCount();
  229. break;
  230. case GpuSceneNonRenderableObjectType::kFogDensityVolume:
  231. objCount = GpuSceneArrays::FogDensityVolume::getSingleton().getElementCount();
  232. break;
  233. case GpuSceneNonRenderableObjectType::kGlobalIlluminationProbe:
  234. objCount = GpuSceneArrays::GlobalIlluminationProbe::getSingleton().getElementCount();
  235. break;
  236. case GpuSceneNonRenderableObjectType::kReflectionProbe:
  237. objCount = GpuSceneArrays::ReflectionProbe::getSingleton().getElementCount();
  238. break;
  239. default:
  240. ANKI_ASSERT(0);
  241. }
  242. if(objCount == 0)
  243. {
  244. return;
  245. }
  246. if(in.m_cpuFeedbackBuffer.m_buffer)
  247. {
  248. ANKI_ASSERT(in.m_cpuFeedbackBuffer.m_range == sizeof(U32) * (objCount + 1));
  249. }
  250. // Find the counter buffer
  251. U32 counterBufferIdx = kMaxU32;
  252. if(m_lastFrameIdx != getRenderer().getFrameCount())
  253. {
  254. m_lastFrameIdx = getRenderer().getFrameCount();
  255. m_runIdx = 0;
  256. }
  257. counterBufferIdx = m_runIdx++;
  258. // Allocate memory for the result
  259. GpuVisibleTransientMemoryAllocation visibleIndicesAlloc = GpuVisibleTransientMemoryPool::getSingleton().allocate((objCount + 1) * sizeof(U32));
  260. out.m_visiblesBuffer.m_buffer = visibleIndicesAlloc.m_buffer;
  261. out.m_visiblesBuffer.m_offset = visibleIndicesAlloc.m_offset;
  262. out.m_visiblesBuffer.m_range = visibleIndicesAlloc.m_size;
  263. // Import buffers
  264. RenderGraphDescription& rgraph = *in.m_rgraph;
  265. out.m_bufferHandle =
  266. rgraph.importBuffer(out.m_visiblesBuffer.m_buffer, BufferUsageBit::kNone, out.m_visiblesBuffer.m_offset, out.m_visiblesBuffer.m_range);
  267. // Create the renderpass
  268. ComputeRenderPassDescription& pass = rgraph.newComputeRenderPass(in.m_passesName);
  269. pass.newBufferDependency(getRenderer().getGpuSceneBufferHandle(), BufferUsageBit::kStorageComputeRead);
  270. pass.newBufferDependency(out.m_bufferHandle, BufferUsageBit::kStorageComputeWrite);
  271. if(in.m_hzbRt)
  272. {
  273. pass.newTextureDependency(*in.m_hzbRt, TextureUsageBit::kSampledCompute);
  274. }
  275. pass.setWork([this, objType = in.m_objectType, feedbackBuffer = in.m_cpuFeedbackBuffer, viewProjectionMat = in.m_viewProjectionMat,
  276. visibleIndicesBuffHandle = out.m_bufferHandle, counterBufferIdx, objCount](RenderPassWorkContext& rgraph) {
  277. CommandBuffer& cmdb = *rgraph.m_commandBuffer;
  278. const Bool needsFeedback = feedbackBuffer.m_buffer != nullptr;
  279. cmdb.bindShaderProgram(m_grProgs[0][objType][needsFeedback].get());
  280. PtrSize objBufferOffset = 0;
  281. PtrSize objBufferRange = 0;
  282. switch(objType)
  283. {
  284. case GpuSceneNonRenderableObjectType::kLight:
  285. objBufferOffset = GpuSceneArrays::Light::getSingleton().getGpuSceneOffsetOfArrayBase();
  286. objBufferRange = GpuSceneArrays::Light::getSingleton().getElementCount() * GpuSceneArrays::Light::getSingleton().getElementSize();
  287. break;
  288. case GpuSceneNonRenderableObjectType::kDecal:
  289. objBufferOffset = GpuSceneArrays::Decal::getSingleton().getGpuSceneOffsetOfArrayBase();
  290. objBufferRange = GpuSceneArrays::Decal::getSingleton().getElementCount() * GpuSceneArrays::Decal::getSingleton().getElementSize();
  291. break;
  292. case GpuSceneNonRenderableObjectType::kFogDensityVolume:
  293. objBufferOffset = GpuSceneArrays::FogDensityVolume::getSingleton().getGpuSceneOffsetOfArrayBase();
  294. objBufferRange = GpuSceneArrays::FogDensityVolume::getSingleton().getElementCount()
  295. * GpuSceneArrays::FogDensityVolume::getSingleton().getElementSize();
  296. break;
  297. case GpuSceneNonRenderableObjectType::kGlobalIlluminationProbe:
  298. objBufferOffset = GpuSceneArrays::GlobalIlluminationProbe::getSingleton().getGpuSceneOffsetOfArrayBase();
  299. objBufferRange = GpuSceneArrays::GlobalIlluminationProbe::getSingleton().getElementCount()
  300. * GpuSceneArrays::GlobalIlluminationProbe::getSingleton().getElementSize();
  301. break;
  302. case GpuSceneNonRenderableObjectType::kReflectionProbe:
  303. objBufferOffset = GpuSceneArrays::ReflectionProbe::getSingleton().getGpuSceneOffsetOfArrayBase();
  304. objBufferRange =
  305. GpuSceneArrays::ReflectionProbe::getSingleton().getElementCount() * GpuSceneArrays::ReflectionProbe::getSingleton().getElementSize();
  306. break;
  307. default:
  308. ANKI_ASSERT(0);
  309. }
  310. cmdb.bindStorageBuffer(0, 0, &GpuSceneBuffer::getSingleton().getBuffer(), objBufferOffset, objBufferRange);
  311. GpuVisibilityNonRenderableUniforms unis;
  312. Array<Plane, 6> planes;
  313. extractClipPlanes(viewProjectionMat, planes);
  314. for(U32 i = 0; i < 6; ++i)
  315. {
  316. unis.m_clipPlanes[i] = Vec4(planes[i].getNormal().xyz(), planes[i].getOffset());
  317. }
  318. cmdb.setPushConstants(&unis, sizeof(unis));
  319. rgraph.bindStorageBuffer(0, 1, visibleIndicesBuffHandle);
  320. cmdb.bindStorageBuffer(0, 2, m_counterBuffers[counterBufferIdx].get(), 0, kMaxPtrSize);
  321. if(needsFeedback)
  322. {
  323. cmdb.bindStorageBuffer(0, 3, feedbackBuffer.m_buffer, feedbackBuffer.m_offset, feedbackBuffer.m_range);
  324. }
  325. dispatchPPCompute(cmdb, 64, 1, objCount, 1);
  326. });
  327. }
  328. } // end namespace anki