CommandBufferImpl.cpp 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334
  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/Gr/gl/CommandBufferImpl.h>
  6. #include <AnKi/Gr/GrManager.h>
  7. #include <AnKi/Gr/gl/GrManagerImpl.h>
  8. #include <AnKi/Gr/gl/GlState.h>
  9. #include <AnKi/Gr/gl/Error.h>
  10. #include <AnKi/Gr/OcclusionQuery.h>
  11. #include <AnKi/Gr/gl/OcclusionQueryImpl.h>
  12. #include <AnKi/Gr/Buffer.h>
  13. #include <AnKi/Gr/gl/BufferImpl.h>
  14. #include <AnKi/Util/Logger.h>
  15. #include <AnKi/Core/Trace.h>
  16. #include <cstring>
  17. namespace anki {
  18. void CommandBufferImpl::init(const CommandBufferInitInfo& init)
  19. {
  20. auto& pool = getManager().getAllocator().getMemoryPool();
  21. m_alloc = CommandBufferAllocator<GlCommand*>(pool.getAllocationCallback(), pool.getAllocationCallbackUserData(), init.m_hints.m_chunkSize, 1.0, 0,
  22. false);
  23. m_flags = init.m_flags;
  24. #if ANKI_EXTRA_CHECKS
  25. m_state.m_secondLevel = !!(init.m_flags & CommandBufferFlag::kSecondLevel);
  26. #endif
  27. if(!!(init.m_flags & CommandBufferFlag::kSecondLevel))
  28. {
  29. // TODO Need to hold a ref
  30. m_state.m_fb = static_cast<const FramebufferImpl*>(init.m_framebuffer.get());
  31. }
  32. }
  33. void CommandBufferImpl::destroy()
  34. {
  35. ANKI_TRACE_SCOPED_EVENT(GL_CMD_BUFFER_DESTROY);
  36. #if ANKI_EXTRA_CHECKS
  37. if(!m_executed && m_firstCommand)
  38. {
  39. ANKI_GL_LOGW("Chain contains commands but never executed. This should only happen on exceptions");
  40. }
  41. #endif
  42. GlCommand* command = m_firstCommand;
  43. while(command != nullptr)
  44. {
  45. GlCommand* next = command->m_nextCommand; // Get next before deleting
  46. m_alloc.deleteInstance(command);
  47. command = next;
  48. }
  49. ANKI_ASSERT(m_alloc.getMemoryPool().getUsersCount() == 1 && "Someone is holding a reference to the command buffer's allocator");
  50. m_alloc = CommandBufferAllocator<U8>();
  51. }
  52. Error CommandBufferImpl::executeAllCommands()
  53. {
  54. ANKI_ASSERT(m_firstCommand != nullptr && "Empty command buffer");
  55. ANKI_ASSERT(m_lastCommand != nullptr && "Empty command buffer");
  56. #if ANKI_EXTRA_CHECKS
  57. m_executed = true;
  58. #endif
  59. Error err = Error::kNone;
  60. GlState& state = static_cast<GrManagerImpl&>(getManager()).getState();
  61. GlCommand* command = m_firstCommand;
  62. while(command != nullptr && !err)
  63. {
  64. err = (*command)(state);
  65. ANKI_CHECK_GL_ERROR();
  66. command = command->m_nextCommand;
  67. }
  68. return err;
  69. }
  70. void CommandBufferImpl::flushDrawcall(CommandBuffer& cmdb)
  71. {
  72. ANKI_ASSERT(!!(m_flags & CommandBufferFlag::GRAPHICS_WORK));
  73. //
  74. // Set default state
  75. //
  76. if(m_state.m_mayContainUnsetState) [[unlikely]]
  77. {
  78. m_state.m_mayContainUnsetState = false;
  79. if(m_state.m_primitiveRestart == 2)
  80. {
  81. cmdb.setPrimitiveRestart(false);
  82. }
  83. if(m_state.m_fillMode == FillMode::COUNT)
  84. {
  85. cmdb.setFillMode(FillMode::SOLID);
  86. }
  87. if(m_state.m_cullMode == static_cast<FaceSelectionBit>(0))
  88. {
  89. cmdb.setCullMode(FaceSelectionBit::BACK);
  90. }
  91. if(m_state.m_polyOffsetFactor == -1.0)
  92. {
  93. cmdb.setPolygonOffset(0.0, 0.0);
  94. }
  95. for(U i = 0; i < 2; ++i)
  96. {
  97. FaceSelectionBit face = (i == 0) ? FaceSelectionBit::FRONT : FaceSelectionBit::BACK;
  98. if(m_state.m_stencilFail[i] == StencilOperation::COUNT)
  99. {
  100. cmdb.setStencilOperations(face, StencilOperation::KEEP, StencilOperation::KEEP, StencilOperation::KEEP);
  101. }
  102. if(m_state.m_stencilCompare[i] == CompareOperation::COUNT)
  103. {
  104. cmdb.setStencilCompareOperation(face, CompareOperation::ALWAYS);
  105. }
  106. if(m_state.m_stencilCompareMask[i] == StateTracker::DUMMY_STENCIL_MASK)
  107. {
  108. cmdb.setStencilCompareMask(face, kMaxU32);
  109. }
  110. if(m_state.m_stencilWriteMask[i] == StateTracker::DUMMY_STENCIL_MASK)
  111. {
  112. cmdb.setStencilWriteMask(face, kMaxU32);
  113. }
  114. if(m_state.m_stencilRef[i] == StateTracker::DUMMY_STENCIL_MASK)
  115. {
  116. cmdb.setStencilReference(face, 0);
  117. }
  118. }
  119. if(m_state.m_depthWrite == 2)
  120. {
  121. cmdb.setDepthWrite(true);
  122. }
  123. if(m_state.m_depthOp == CompareOperation::COUNT)
  124. {
  125. cmdb.setDepthCompareOperation(CompareOperation::LESS);
  126. }
  127. for(U i = 0; i < kMaxColorRenderTargets; ++i)
  128. {
  129. const auto& att = m_state.m_colorAtt[i];
  130. if(att.m_writeMask == StateTracker::INVALID_COLOR_MASK)
  131. {
  132. cmdb.setColorChannelWriteMask(i, ColorBit::ALL);
  133. }
  134. if(att.m_blendSrcFactorRgb == BlendFactor::COUNT)
  135. {
  136. cmdb.setBlendFactors(i, BlendFactor::ONE, BlendFactor::ZERO, BlendFactor::ONE, BlendFactor::ZERO);
  137. }
  138. if(att.m_blendOpRgb == BlendOperation::COUNT)
  139. {
  140. cmdb.setBlendOperation(i, BlendOperation::ADD, BlendOperation::ADD);
  141. }
  142. }
  143. if(!m_state.m_scissorSet)
  144. {
  145. cmdb.setScissor(0, 0, kMaxU32, kMaxU32);
  146. }
  147. }
  148. //
  149. // Fire commands to change some state
  150. //
  151. class StencilCmd final : public GlCommand
  152. {
  153. public:
  154. GLenum m_face;
  155. GLenum m_func;
  156. GLint m_ref;
  157. GLuint m_compareMask;
  158. StencilCmd(GLenum face, GLenum func, GLint ref, GLuint mask)
  159. : m_face(face)
  160. , m_func(func)
  161. , m_ref(ref)
  162. , m_compareMask(mask)
  163. {
  164. }
  165. Error operator()(GlState&)
  166. {
  167. glStencilFuncSeparate(m_face, m_func, m_ref, m_compareMask);
  168. return Error::kNone;
  169. }
  170. };
  171. for(U i = 0; i < 2; ++i)
  172. {
  173. if(m_state.m_glStencilFuncSeparateDirty[i])
  174. {
  175. pushBackNewCommand<StencilCmd>(GL_FRONT + i, convertCompareOperation(m_state.m_stencilCompare[i]), m_state.m_stencilRef[i],
  176. m_state.m_stencilCompareMask[i]);
  177. m_state.m_glStencilFuncSeparateDirty[i] = false;
  178. }
  179. }
  180. class DepthTestCmd final : public GlCommand
  181. {
  182. public:
  183. Bool m_enable;
  184. DepthTestCmd(Bool enable)
  185. : m_enable(enable)
  186. {
  187. }
  188. Error operator()(GlState&)
  189. {
  190. if(m_enable)
  191. {
  192. glEnable(GL_DEPTH_TEST);
  193. }
  194. else
  195. {
  196. glDisable(GL_DEPTH_TEST);
  197. }
  198. return Error::kNone;
  199. }
  200. };
  201. if(m_state.maybeEnableDepthTest())
  202. {
  203. pushBackNewCommand<DepthTestCmd>(m_state.m_depthTestEnabled);
  204. }
  205. class StencilTestCmd final : public GlCommand
  206. {
  207. public:
  208. Bool m_enable;
  209. StencilTestCmd(Bool enable)
  210. : m_enable(enable)
  211. {
  212. }
  213. Error operator()(GlState&)
  214. {
  215. if(m_enable)
  216. {
  217. glEnable(GL_STENCIL_TEST);
  218. }
  219. else
  220. {
  221. glDisable(GL_STENCIL_TEST);
  222. }
  223. return Error::kNone;
  224. }
  225. };
  226. if(m_state.maybeEnableStencilTest())
  227. {
  228. pushBackNewCommand<StencilTestCmd>(m_state.m_stencilTestEnabled);
  229. }
  230. class BlendCmd final : public GlCommand
  231. {
  232. public:
  233. U8 m_enableMask;
  234. U8 m_disableMask;
  235. BlendCmd(U8 enableMask, U8 disableMask)
  236. : m_enableMask(enableMask)
  237. , m_disableMask(disableMask)
  238. {
  239. }
  240. Error operator()(GlState&)
  241. {
  242. for(U i = 0; i < kMaxColorRenderTargets; ++i)
  243. {
  244. if(m_enableMask & (1 << i))
  245. {
  246. glEnablei(GL_BLEND, i);
  247. }
  248. else if(m_disableMask & (1 << i))
  249. {
  250. glDisablei(GL_BLEND, i);
  251. }
  252. }
  253. return Error::kNone;
  254. }
  255. };
  256. U8 blendEnableMask = 0;
  257. U8 blendDisableMask = 0;
  258. for(U i = 0; i < kMaxColorRenderTargets; ++i)
  259. {
  260. if(m_state.maybeEnableBlend(i))
  261. {
  262. if(m_state.m_colorAtt[i].m_enableBlend)
  263. {
  264. blendEnableMask |= 1 << i;
  265. }
  266. else
  267. {
  268. blendDisableMask |= 1 << i;
  269. }
  270. }
  271. }
  272. if(blendEnableMask || blendDisableMask)
  273. {
  274. pushBackNewCommand<BlendCmd>(blendEnableMask, blendDisableMask);
  275. }
  276. }
  277. } // end namespace anki