CommandBufferImpl.cpp 6.9 KB

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