Drawer.cpp 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  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/Drawer.h>
  6. #include <AnKi/Resource/ImageResource.h>
  7. #include <AnKi/Renderer/Renderer.h>
  8. #include <AnKi/Util/Tracer.h>
  9. #include <AnKi/Util/Logger.h>
  10. #include <AnKi/Shaders/Include/MaterialTypes.h>
  11. #include <AnKi/Shaders/Include/GpuSceneFunctions.h>
  12. #include <AnKi/Core/GpuMemory/UnifiedGeometryBuffer.h>
  13. #include <AnKi/Core/GpuMemory/RebarTransientMemoryPool.h>
  14. #include <AnKi/Core/GpuMemory/GpuSceneBuffer.h>
  15. #include <AnKi/Core/StatsSet.h>
  16. #include <AnKi/Scene/RenderStateBucket.h>
  17. namespace anki {
  18. static StatCounter g_executedDrawcallsStatVar(StatCategory::kRenderer, "Drawcalls executed", StatFlag::kZeroEveryFrame);
  19. static StatCounter g_maxDrawcallsStatVar(StatCategory::kRenderer, "Drawcalls possible", StatFlag::kZeroEveryFrame);
  20. RenderableDrawer::~RenderableDrawer()
  21. {
  22. }
  23. Error RenderableDrawer::init()
  24. {
  25. #if ANKI_STATS_ENABLED
  26. constexpr Array<MutatorValue, 3> kColorAttachmentCounts = {0, 1, 4};
  27. U32 count = 0;
  28. for(MutatorValue attachmentCount : kColorAttachmentCounts)
  29. {
  30. ANKI_CHECK(loadShaderProgram("ShaderBinaries/DrawerStats.ankiprogbin", Array<SubMutation, 1>{{{"COLOR_ATTACHMENT_COUNT", attachmentCount}}},
  31. m_stats.m_statsProg, m_stats.m_updateStatsGrProgs[count]));
  32. ++count;
  33. }
  34. #endif
  35. return Error::kNone;
  36. }
  37. void RenderableDrawer::setState(const RenderableDrawerArguments& args, CommandBuffer& cmdb)
  38. {
  39. // Allocate, set and bind global uniforms
  40. {
  41. MaterialGlobalConstants* globalUniforms;
  42. const RebarAllocation globalUniformsToken = RebarTransientMemoryPool::getSingleton().allocateFrame(1, globalUniforms);
  43. globalUniforms->m_viewProjectionMatrix = args.m_viewProjectionMatrix;
  44. globalUniforms->m_previousViewProjectionMatrix = args.m_previousViewProjectionMatrix;
  45. static_assert(sizeof(globalUniforms->m_viewTransform) == sizeof(args.m_viewMatrix));
  46. memcpy(&globalUniforms->m_viewTransform, &args.m_viewMatrix, sizeof(args.m_viewMatrix));
  47. static_assert(sizeof(globalUniforms->m_cameraTransform) == sizeof(args.m_cameraTransform));
  48. memcpy(&globalUniforms->m_cameraTransform, &args.m_cameraTransform, sizeof(args.m_cameraTransform));
  49. cmdb.bindConstantBuffer(U32(MaterialSet::kGlobal), U32(MaterialBinding::kGlobalConstants), globalUniformsToken);
  50. }
  51. // More globals
  52. cmdb.bindAllBindless(U32(MaterialSet::kBindless));
  53. cmdb.bindSampler(U32(MaterialSet::kGlobal), U32(MaterialBinding::kTrilinearRepeatSampler), args.m_sampler);
  54. cmdb.bindUavBuffer(U32(MaterialSet::kGlobal), U32(MaterialBinding::kGpuScene), &GpuSceneBuffer::getSingleton().getBuffer(), 0, kMaxPtrSize);
  55. #define ANKI_UNIFIED_GEOM_FORMAT(fmt, shaderType) \
  56. cmdb.bindReadOnlyTextureBuffer(U32(MaterialSet::kGlobal), U32(MaterialBinding::kUnifiedGeometry_##fmt), \
  57. &UnifiedGeometryBuffer::getSingleton().getBuffer(), 0, kMaxPtrSize, Format::k##fmt);
  58. #include <AnKi/Shaders/Include/UnifiedGeometryTypes.defs.h>
  59. // Misc
  60. cmdb.setVertexAttribute(0, 0, Format::kR32G32B32A32_Uint, 0);
  61. cmdb.bindIndexBuffer(&UnifiedGeometryBuffer::getSingleton().getBuffer(), 0, IndexType::kU16);
  62. }
  63. void RenderableDrawer::drawMdi(const RenderableDrawerArguments& args, CommandBuffer& cmdb)
  64. {
  65. #if ANKI_STATS_ENABLED
  66. U32 variant = 0;
  67. switch(args.m_renderingTechinuqe)
  68. {
  69. case RenderingTechnique::kGBuffer:
  70. variant = 2;
  71. break;
  72. case RenderingTechnique::kForward:
  73. variant = 1;
  74. break;
  75. case RenderingTechnique::kDepth:
  76. variant = 0;
  77. break;
  78. default:
  79. ANKI_ASSERT(0);
  80. }
  81. {
  82. LockGuard lock(m_stats.m_mtx);
  83. if(m_stats.m_frameIdx != getRenderer().getFrameCount())
  84. {
  85. m_stats.m_frameIdx = getRenderer().getFrameCount();
  86. // Get previous stats
  87. U32 prevFrameCount;
  88. PtrSize dataRead;
  89. getRenderer().getReadbackManager().readMostRecentData(m_stats.m_readback, &prevFrameCount, sizeof(prevFrameCount), dataRead);
  90. if(dataRead > 0) [[likely]]
  91. {
  92. g_executedDrawcallsStatVar.set(prevFrameCount);
  93. }
  94. // Get place to write new stats
  95. getRenderer().getReadbackManager().allocateData(m_stats.m_readback, sizeof(U32), m_stats.m_statsBuffer, m_stats.m_statsBufferOffset);
  96. // Allocate another atomic to count the passes. Do that because the calls to drawMdi might not be in the same order as they run on the GPU
  97. U32* counter;
  98. m_stats.m_passCountBuffer = RebarTransientMemoryPool::getSingleton().allocateFrame(sizeof(U32), counter);
  99. *counter = 0;
  100. }
  101. U32* counter;
  102. BufferOffsetRange threadCountBuff = RebarTransientMemoryPool::getSingleton().allocateFrame(sizeof(U32), counter);
  103. *counter = 0;
  104. cmdb.pushDebugMarker("Draw stats", Vec3(0.0f, 1.0f, 0.0f));
  105. cmdb.bindShaderProgram(m_stats.m_updateStatsGrProgs[variant].get());
  106. cmdb.bindUavBuffer(0, 0, m_stats.m_statsBuffer, m_stats.m_statsBufferOffset, sizeof(U32));
  107. cmdb.bindUavBuffer(0, 1, threadCountBuff);
  108. cmdb.bindUavBuffer(0, 2, args.m_mdiDrawCountsBuffer);
  109. cmdb.bindUavBuffer(0, 3, m_stats.m_passCountBuffer);
  110. cmdb.draw(PrimitiveTopology::kTriangles, 6);
  111. cmdb.popDebugMarker();
  112. }
  113. #endif
  114. setState(args, cmdb);
  115. cmdb.bindVertexBuffer(0, args.m_instanceRateRenderablesBuffer.m_buffer, args.m_instanceRateRenderablesBuffer.m_offset,
  116. sizeof(GpuSceneRenderableVertex), VertexStepRate::kInstance);
  117. U32 allUserCount = 0;
  118. U32 bucketCount = 0;
  119. RenderStateBucketContainer::getSingleton().iterateBuckets(args.m_renderingTechinuqe, [&](const RenderStateInfo& state, U32 userCount) {
  120. if(userCount == 0)
  121. {
  122. ++bucketCount;
  123. return;
  124. }
  125. ShaderProgramPtr prog = state.m_program;
  126. cmdb.bindShaderProgram(prog.get());
  127. const U32 maxDrawCount = userCount;
  128. if(state.m_indexedDrawcall)
  129. {
  130. cmdb.drawIndexedIndirectCount(state.m_primitiveTopology, args.m_drawIndexedIndirectArgsBuffer.m_buffer,
  131. args.m_drawIndexedIndirectArgsBuffer.m_offset + sizeof(DrawIndexedIndirectArgs) * allUserCount,
  132. sizeof(DrawIndexedIndirectArgs), args.m_mdiDrawCountsBuffer.m_buffer,
  133. args.m_mdiDrawCountsBuffer.m_offset + sizeof(U32) * bucketCount, maxDrawCount);
  134. }
  135. else
  136. {
  137. // Yes, the DrawIndexedIndirectArgs is intentional
  138. cmdb.drawIndirectCount(state.m_primitiveTopology, args.m_drawIndexedIndirectArgsBuffer.m_buffer,
  139. args.m_drawIndexedIndirectArgsBuffer.m_offset + sizeof(DrawIndexedIndirectArgs) * allUserCount,
  140. sizeof(DrawIndexedIndirectArgs), args.m_mdiDrawCountsBuffer.m_buffer,
  141. args.m_mdiDrawCountsBuffer.m_offset + sizeof(U32) * bucketCount, maxDrawCount);
  142. }
  143. ++bucketCount;
  144. allUserCount += userCount;
  145. });
  146. ANKI_ASSERT(bucketCount == RenderStateBucketContainer::getSingleton().getBucketCount(args.m_renderingTechinuqe));
  147. g_maxDrawcallsStatVar.increment(allUserCount);
  148. }
  149. } // end namespace anki