CommandBufferImpl.cpp 6.9 KB

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