Drawer.cpp 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. // Copyright (C) 2009-2022, 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. namespace anki {
  13. /// Drawer's context
  14. class RenderableDrawer::Context
  15. {
  16. public:
  17. RenderQueueDrawContext m_queueCtx;
  18. const RenderableQueueElement* m_renderableElement = nullptr;
  19. Array<RenderableQueueElement, MAX_INSTANCE_COUNT> m_cachedRenderElements;
  20. Array<U8, MAX_INSTANCE_COUNT> m_cachedRenderElementLods;
  21. Array<const void*, MAX_INSTANCE_COUNT> m_userData;
  22. U32 m_cachedRenderElementCount = 0;
  23. U8 m_minLod = 0;
  24. U8 m_maxLod = 0;
  25. };
  26. /// Check if the drawcalls can be merged.
  27. static Bool canMergeRenderableQueueElements(const RenderableQueueElement& a, const RenderableQueueElement& b)
  28. {
  29. return a.m_callback == b.m_callback && a.m_mergeKey != 0 && a.m_mergeKey == b.m_mergeKey;
  30. }
  31. RenderableDrawer::~RenderableDrawer()
  32. {
  33. }
  34. void RenderableDrawer::drawRange(RenderingTechnique technique, const RenderableDrawerArguments& args,
  35. const RenderableQueueElement* begin, const RenderableQueueElement* end,
  36. CommandBufferPtr& cmdb)
  37. {
  38. ANKI_ASSERT(begin && end && begin < end);
  39. // Allocate, set and bind global uniforms
  40. {
  41. StagingGpuMemoryToken globalUniformsToken;
  42. MaterialGlobalUniforms* globalUniforms =
  43. static_cast<MaterialGlobalUniforms*>(m_r->getStagingGpuMemory().allocateFrame(
  44. sizeof(MaterialGlobalUniforms), StagingGpuMemoryType::UNIFORM, globalUniformsToken));
  45. globalUniforms->m_viewProjectionMatrix = args.m_viewProjectionMatrix;
  46. globalUniforms->m_previousViewProjectionMatrix = args.m_previousViewProjectionMatrix;
  47. globalUniforms->m_viewMatrix = args.m_viewMatrix;
  48. globalUniforms->m_cameraTransform = args.m_cameraTransform;
  49. cmdb->bindUniformBuffer(MATERIAL_SET_GLOBAL, MATERIAL_BINDING_GLOBAL_UNIFORMS, globalUniformsToken.m_buffer,
  50. globalUniformsToken.m_offset, globalUniformsToken.m_range);
  51. }
  52. // More globals
  53. cmdb->bindAllBindless(MATERIAL_SET_BINDLESS);
  54. cmdb->bindSampler(MATERIAL_SET_GLOBAL, MATERIAL_BINDING_TRILINEAR_REPEAT_SAMPLER, args.m_sampler);
  55. // Set a few things
  56. Context ctx;
  57. ctx.m_queueCtx.m_viewMatrix = args.m_viewMatrix;
  58. ctx.m_queueCtx.m_viewProjectionMatrix = args.m_viewProjectionMatrix;
  59. ctx.m_queueCtx.m_projectionMatrix = Mat4::getIdentity(); // TODO
  60. ctx.m_queueCtx.m_previousViewProjectionMatrix = args.m_previousViewProjectionMatrix;
  61. ctx.m_queueCtx.m_cameraTransform = args.m_cameraTransform;
  62. ctx.m_queueCtx.m_stagingGpuAllocator = &m_r->getStagingGpuMemory();
  63. ctx.m_queueCtx.m_commandBuffer = cmdb;
  64. ctx.m_queueCtx.m_key = RenderingKey(technique, 0, 1, false, false);
  65. ctx.m_queueCtx.m_debugDraw = false;
  66. ctx.m_queueCtx.m_sampler = args.m_sampler;
  67. ANKI_ASSERT(args.m_minLod < MAX_LOD_COUNT && args.m_maxLod < MAX_LOD_COUNT && args.m_minLod <= args.m_maxLod);
  68. ctx.m_minLod = U8(args.m_minLod);
  69. ctx.m_maxLod = U8(args.m_maxLod);
  70. for(; begin != end; ++begin)
  71. {
  72. ctx.m_renderableElement = begin;
  73. drawSingle(ctx);
  74. }
  75. // Flush the last drawcall
  76. flushDrawcall(ctx);
  77. }
  78. void RenderableDrawer::flushDrawcall(Context& ctx)
  79. {
  80. ctx.m_queueCtx.m_key.setLod(ctx.m_cachedRenderElementLods[0]);
  81. ctx.m_queueCtx.m_key.setInstanceCount(ctx.m_cachedRenderElementCount);
  82. ctx.m_cachedRenderElements[0].m_callback(
  83. ctx.m_queueCtx, ConstWeakArray<void*>(const_cast<void**>(&ctx.m_userData[0]), ctx.m_cachedRenderElementCount));
  84. // Rendered something, reset the cached transforms
  85. if(ctx.m_cachedRenderElementCount > 1)
  86. {
  87. ANKI_TRACE_INC_COUNTER(R_MERGED_DRAWCALLS, ctx.m_cachedRenderElementCount - 1);
  88. }
  89. ctx.m_cachedRenderElementCount = 0;
  90. }
  91. void RenderableDrawer::drawSingle(Context& ctx)
  92. {
  93. if(ctx.m_cachedRenderElementCount == MAX_INSTANCE_COUNT)
  94. {
  95. flushDrawcall(ctx);
  96. }
  97. const RenderableQueueElement& rqel = *ctx.m_renderableElement;
  98. const U8 overridenLod = clamp(rqel.m_lod, ctx.m_minLod, ctx.m_maxLod);
  99. const Bool shouldFlush =
  100. ctx.m_cachedRenderElementCount > 0
  101. && (!canMergeRenderableQueueElements(ctx.m_cachedRenderElements[ctx.m_cachedRenderElementCount - 1], rqel)
  102. || ctx.m_cachedRenderElementLods[ctx.m_cachedRenderElementCount - 1] != overridenLod);
  103. if(shouldFlush)
  104. {
  105. flushDrawcall(ctx);
  106. }
  107. // Cache the new one
  108. ctx.m_cachedRenderElements[ctx.m_cachedRenderElementCount] = rqel;
  109. ctx.m_cachedRenderElementLods[ctx.m_cachedRenderElementCount] = overridenLod;
  110. ctx.m_userData[ctx.m_cachedRenderElementCount] = rqel.m_userData;
  111. ++ctx.m_cachedRenderElementCount;
  112. }
  113. } // end namespace anki