Drawer.cpp 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  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/Drawer.h>
  6. #include <AnKi/Renderer/RenderQueue.h>
  7. #include <AnKi/Resource/ImageResource.h>
  8. #include <AnKi/Renderer/Renderer.h>
  9. #include <AnKi/Util/Tracer.h>
  10. #include <AnKi/Util/Logger.h>
  11. #include <AnKi/Shaders/Include/MaterialTypes.h>
  12. #include <AnKi/Shaders/Include/GpuSceneFunctions.h>
  13. namespace anki {
  14. /// Drawer's context
  15. class RenderableDrawer::Context
  16. {
  17. public:
  18. CommandBufferPtr m_commandBuffer;
  19. Array<const RenderableQueueElement*, kMaxInstanceCount> m_cachedRenderElements;
  20. U32 m_cachedRenderElementCount = 0;
  21. ShaderProgram* m_lastBoundShaderProgram = nullptr;
  22. };
  23. RenderableDrawer::~RenderableDrawer()
  24. {
  25. }
  26. void RenderableDrawer::drawRange(const RenderableDrawerArguments& args, const RenderableQueueElement* begin,
  27. const RenderableQueueElement* end, CommandBufferPtr& cmdb)
  28. {
  29. ANKI_ASSERT(begin && end && begin < end);
  30. // Allocate, set and bind global uniforms
  31. {
  32. RebarGpuMemoryToken globalUniformsToken;
  33. MaterialGlobalUniforms* globalUniforms =
  34. static_cast<MaterialGlobalUniforms*>(RebarStagingGpuMemoryPool::getSingleton().allocateFrame(
  35. sizeof(MaterialGlobalUniforms), globalUniformsToken));
  36. globalUniforms->m_viewProjectionMatrix = args.m_viewProjectionMatrix;
  37. globalUniforms->m_previousViewProjectionMatrix = args.m_previousViewProjectionMatrix;
  38. static_assert(sizeof(globalUniforms->m_viewTransform) == sizeof(args.m_viewMatrix));
  39. memcpy(&globalUniforms->m_viewTransform, &args.m_viewMatrix, sizeof(args.m_viewMatrix));
  40. static_assert(sizeof(globalUniforms->m_cameraTransform) == sizeof(args.m_cameraTransform));
  41. memcpy(&globalUniforms->m_cameraTransform, &args.m_cameraTransform, sizeof(args.m_cameraTransform));
  42. cmdb->bindUniformBuffer(U32(MaterialSet::kGlobal), U32(MaterialBinding::kGlobalUniforms),
  43. RebarStagingGpuMemoryPool::getSingleton().getBuffer(), globalUniformsToken.m_offset,
  44. globalUniformsToken.m_range);
  45. }
  46. // More globals
  47. cmdb->bindAllBindless(U32(MaterialSet::kBindless));
  48. cmdb->bindSampler(U32(MaterialSet::kGlobal), U32(MaterialBinding::kTrilinearRepeatSampler), args.m_sampler);
  49. cmdb->bindStorageBuffer(U32(MaterialSet::kGlobal), U32(MaterialBinding::kGpuScene),
  50. GpuSceneMemoryPool::getSingleton().getBuffer(), 0, kMaxPtrSize);
  51. #define ANKI_UNIFIED_GEOM_FORMAT(fmt, shaderType) \
  52. cmdb->bindReadOnlyTextureBuffer(U32(MaterialSet::kGlobal), U32(MaterialBinding::kUnifiedGeometry_##fmt), \
  53. UnifiedGeometryMemoryPool::getSingleton().getBuffer(), 0, kMaxPtrSize, \
  54. Format::k##fmt);
  55. #include <AnKi/Shaders/Include/UnifiedGeometryTypes.defs.h>
  56. // Misc
  57. cmdb->setVertexAttribute(0, 0, Format::kR32G32B32A32_Uint, 0);
  58. cmdb->bindIndexBuffer(UnifiedGeometryMemoryPool::getSingleton().getBuffer(), 0, IndexType::kU16);
  59. // Set a few things
  60. Context ctx;
  61. ctx.m_commandBuffer = cmdb;
  62. for(; begin != end; ++begin)
  63. {
  64. drawSingle(begin, ctx);
  65. }
  66. // Flush the last drawcall
  67. flushDrawcall(ctx);
  68. }
  69. void RenderableDrawer::flushDrawcall(Context& ctx)
  70. {
  71. CommandBufferPtr cmdb = ctx.m_commandBuffer;
  72. // Instance buffer
  73. RebarGpuMemoryToken token;
  74. GpuSceneRenderablePacked* instances =
  75. static_cast<GpuSceneRenderablePacked*>(RebarStagingGpuMemoryPool::getSingleton().allocateFrame(
  76. sizeof(GpuSceneRenderablePacked) * ctx.m_cachedRenderElementCount, token));
  77. for(U32 i = 0; i < ctx.m_cachedRenderElementCount; ++i)
  78. {
  79. GpuSceneRenderable renderable = {};
  80. renderable.m_worldTransformsOffset = ctx.m_cachedRenderElements[i]->m_worldTransformsOffset;
  81. renderable.m_uniformsOffset = ctx.m_cachedRenderElements[i]->m_uniformsOffset;
  82. renderable.m_geometryOffset = ctx.m_cachedRenderElements[i]->m_geometryOffset;
  83. renderable.m_boneTransformsOffset = ctx.m_cachedRenderElements[i]->m_boneTransformsOffset;
  84. instances[i] = packGpuSceneRenderable(renderable);
  85. }
  86. cmdb->bindVertexBuffer(0, RebarStagingGpuMemoryPool::getSingleton().getBuffer(), token.m_offset,
  87. sizeof(GpuSceneRenderablePacked), VertexStepRate::kInstance);
  88. // Set state
  89. const RenderableQueueElement& firstElement = *ctx.m_cachedRenderElements[0];
  90. if(firstElement.m_program != ctx.m_lastBoundShaderProgram)
  91. {
  92. cmdb->bindShaderProgram(ShaderProgramPtr(firstElement.m_program));
  93. ctx.m_lastBoundShaderProgram = firstElement.m_program;
  94. }
  95. if(firstElement.m_indexed)
  96. {
  97. cmdb->drawElements(firstElement.m_primitiveTopology, firstElement.m_indexCount, ctx.m_cachedRenderElementCount,
  98. firstElement.m_firstIndex);
  99. }
  100. else
  101. {
  102. cmdb->drawArrays(firstElement.m_primitiveTopology, firstElement.m_vertexCount, ctx.m_cachedRenderElementCount,
  103. firstElement.m_firstVertex);
  104. }
  105. // Rendered something, reset the cached transforms
  106. if(ctx.m_cachedRenderElementCount > 1)
  107. {
  108. ANKI_TRACE_INC_COUNTER(RMergedDrawcalls, ctx.m_cachedRenderElementCount - 1);
  109. }
  110. ctx.m_cachedRenderElementCount = 0;
  111. }
  112. void RenderableDrawer::drawSingle(const RenderableQueueElement* renderEl, Context& ctx)
  113. {
  114. if(ctx.m_cachedRenderElementCount == kMaxInstanceCount)
  115. {
  116. flushDrawcall(ctx);
  117. }
  118. const Bool shouldFlush =
  119. ctx.m_cachedRenderElementCount > 0
  120. && !ctx.m_cachedRenderElements[ctx.m_cachedRenderElementCount - 1]->canMergeWith(*renderEl);
  121. if(shouldFlush)
  122. {
  123. flushDrawcall(ctx);
  124. }
  125. // Cache the new one
  126. ctx.m_cachedRenderElements[ctx.m_cachedRenderElementCount] = renderEl;
  127. ++ctx.m_cachedRenderElementCount;
  128. }
  129. } // end namespace anki