StateTracker.h 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590
  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. #pragma once
  6. #include <AnKi/Gr/gl/Common.h>
  7. #include <AnKi/Gr/ShaderProgram.h>
  8. #include <AnKi/Gr/Framebuffer.h>
  9. #include <AnKi/Gr/gl/FramebufferImpl.h>
  10. #include <AnKi/Gr/Buffer.h>
  11. #include <AnKi/Gr/gl/BufferImpl.h>
  12. #include <AnKi/Gr/Texture.h>
  13. #include <AnKi/Gr/gl/TextureImpl.h>
  14. #include <AnKi/Gr/Sampler.h>
  15. #include <AnKi/Gr/gl/SamplerImpl.h>
  16. #include <AnKi/Gr/ShaderProgram.h>
  17. #include <AnKi/Gr/gl/ShaderProgramImpl.h>
  18. #include <AnKi/Gr/Framebuffer.h>
  19. #include <AnKi/Gr/gl/FramebufferImpl.h>
  20. #include <AnKi/Gr/Utils/Functions.h>
  21. namespace anki {
  22. /// @addtogroup opengl
  23. /// @{
  24. /// Local state tracker. Used to avoid creating command buffer commands.
  25. class StateTracker
  26. {
  27. public:
  28. /// If it's false then there might be unset state.
  29. Bool m_mayContainUnsetState = true;
  30. #if ANKI_EXTRA_CHECKS
  31. Bool m_secondLevel = false;
  32. #endif
  33. /// @name vert_state
  34. /// @{
  35. class VertexAttribute
  36. {
  37. public:
  38. U32 m_buffBinding = MAX_U32;
  39. Format m_fmt = Format::NONE;
  40. PtrSize m_relativeOffset = MAX_PTR_SIZE;
  41. };
  42. Array<VertexAttribute, MAX_VERTEX_ATTRIBUTES> m_attribs;
  43. Bool setVertexAttribute(U32 location, U32 buffBinding, Format fmt, PtrSize relativeOffset)
  44. {
  45. VertexAttribute& attrib = m_attribs[location];
  46. if(attrib.m_buffBinding != buffBinding || attrib.m_fmt != fmt || attrib.m_relativeOffset != relativeOffset)
  47. {
  48. attrib.m_buffBinding = buffBinding;
  49. attrib.m_fmt = fmt;
  50. attrib.m_relativeOffset = relativeOffset;
  51. return true;
  52. }
  53. return false;
  54. }
  55. class VertexBuffer
  56. {
  57. public:
  58. BufferImpl* m_buff = nullptr;
  59. PtrSize m_offset = 0;
  60. PtrSize m_stride = 0;
  61. VertexStepRate m_stepRate = VertexStepRate::COUNT;
  62. };
  63. Array<VertexBuffer, MAX_VERTEX_ATTRIBUTES> m_vertBuffs;
  64. Bool bindVertexBuffer(U32 binding, BufferPtr buff, PtrSize offset, PtrSize stride, VertexStepRate stepRate)
  65. {
  66. VertexBuffer& b = m_vertBuffs[binding];
  67. b.m_buff = static_cast<BufferImpl*>(buff.get());
  68. b.m_offset = offset;
  69. b.m_stride = stride;
  70. b.m_stepRate = stepRate;
  71. return true;
  72. }
  73. class Index
  74. {
  75. public:
  76. BufferImpl* m_buff = nullptr;
  77. PtrSize m_offset = MAX_PTR_SIZE;
  78. GLenum m_indexType = 0;
  79. } m_idx;
  80. Bool bindIndexBuffer(BufferPtr buff, PtrSize offset, IndexType type)
  81. {
  82. m_idx.m_buff = static_cast<BufferImpl*>(buff.get());
  83. m_idx.m_offset = offset;
  84. m_idx.m_indexType = convertIndexType(type);
  85. return true;
  86. }
  87. /// @}
  88. /// @name input_assembly
  89. /// @{
  90. Bool m_primitiveRestart = 2;
  91. Bool setPrimitiveRestart(Bool enable)
  92. {
  93. if(enable != m_primitiveRestart)
  94. {
  95. m_primitiveRestart = enable;
  96. return true;
  97. }
  98. return false;
  99. }
  100. /// @}
  101. /// @name viewport_state
  102. /// @{
  103. Array<U32, 4> m_viewport = {{MAX_U32, MAX_U32, MAX_U32, MAX_U32}};
  104. Bool setViewport(U32 minx, U32 miny, U32 width, U32 height)
  105. {
  106. ANKI_ASSERT(minx != MAX_U32 && miny != MAX_U32 && width != MAX_U32 && height != MAX_U32);
  107. if(m_viewport[0] != minx || m_viewport[1] != miny || m_viewport[2] != width || m_viewport[3] != height)
  108. {
  109. m_viewport = {{minx, miny, width, height}};
  110. return true;
  111. }
  112. return false;
  113. }
  114. /// @}
  115. /// @name scissor_state
  116. /// @{
  117. Array<GLsizei, 4> m_scissor = {{0, 0, MAX_I32, MAX_I32}};
  118. Bool m_scissorSet = false;
  119. Bool setScissor(GLsizei minx, GLsizei miny, GLsizei width, GLsizei height)
  120. {
  121. if(!m_scissorSet
  122. || (m_scissor[0] != minx || m_scissor[1] != miny || m_scissor[2] != width || m_scissor[3] != height))
  123. {
  124. m_scissor = {{minx, miny, width, height}};
  125. m_scissorSet = true;
  126. return true;
  127. }
  128. return false;
  129. }
  130. /// @}
  131. /// @name rasterizer
  132. /// @{
  133. FillMode m_fillMode = FillMode::COUNT;
  134. Bool setFillMode(FillMode mode)
  135. {
  136. if(m_fillMode != mode)
  137. {
  138. m_fillMode = mode;
  139. return true;
  140. }
  141. return false;
  142. }
  143. FaceSelectionBit m_cullMode = static_cast<FaceSelectionBit>(0);
  144. Bool setCullMode(FaceSelectionBit mode)
  145. {
  146. if(m_cullMode != mode)
  147. {
  148. m_cullMode = mode;
  149. return true;
  150. }
  151. return false;
  152. }
  153. F32 m_polyOffsetFactor = -1.0;
  154. F32 m_polyOffsetUnits = -1.0;
  155. Bool setPolygonOffset(F32 factor, F32 units)
  156. {
  157. if(factor != m_polyOffsetFactor || units != m_polyOffsetUnits)
  158. {
  159. m_polyOffsetFactor = factor;
  160. m_polyOffsetUnits = units;
  161. return true;
  162. }
  163. return false;
  164. }
  165. /// @}
  166. /// @name depth_stencil
  167. /// @{
  168. Bool m_stencilTestEnabled = 2;
  169. Bool maybeEnableStencilTest()
  170. {
  171. Bool enable = !stencilTestDisabled(m_stencilFail[0], m_stencilPassDepthFail[0], m_stencilPassDepthPass[0],
  172. m_stencilCompare[0]);
  173. enable = enable
  174. || !stencilTestDisabled(m_stencilFail[1], m_stencilPassDepthFail[1], m_stencilPassDepthPass[1],
  175. m_stencilCompare[1]);
  176. if(enable != m_stencilTestEnabled)
  177. {
  178. m_stencilTestEnabled = enable;
  179. return true;
  180. }
  181. return false;
  182. }
  183. Array<StencilOperation, 2> m_stencilFail = {{StencilOperation::COUNT, StencilOperation::COUNT}};
  184. Array<StencilOperation, 2> m_stencilPassDepthFail = {{StencilOperation::COUNT, StencilOperation::COUNT}};
  185. Array<StencilOperation, 2> m_stencilPassDepthPass = {{StencilOperation::COUNT, StencilOperation::COUNT}};
  186. Bool setStencilOperations(FaceSelectionBit face, StencilOperation stencilFail,
  187. StencilOperation stencilPassDepthFail, StencilOperation stencilPassDepthPass)
  188. {
  189. Bool changed = false;
  190. if(!!(face & FaceSelectionBit::FRONT)
  191. && (m_stencilFail[0] != stencilFail || m_stencilPassDepthFail[0] != stencilPassDepthFail
  192. || m_stencilPassDepthPass[0] != stencilPassDepthPass))
  193. {
  194. m_stencilFail[0] = stencilFail;
  195. m_stencilPassDepthFail[0] = stencilPassDepthFail;
  196. m_stencilPassDepthPass[0] = stencilPassDepthPass;
  197. changed = true;
  198. }
  199. if(!!(face & FaceSelectionBit::BACK)
  200. && (m_stencilFail[1] != stencilFail || m_stencilPassDepthFail[1] != stencilPassDepthFail
  201. || m_stencilPassDepthPass[1] != stencilPassDepthPass))
  202. {
  203. m_stencilFail[1] = stencilFail;
  204. m_stencilPassDepthFail[1] = stencilPassDepthFail;
  205. m_stencilPassDepthPass[1] = stencilPassDepthPass;
  206. changed = true;
  207. }
  208. return changed;
  209. }
  210. Array<Bool, 2> m_glStencilFuncSeparateDirty = {{false, false}};
  211. Array<CompareOperation, 2> m_stencilCompare = {{CompareOperation::COUNT, CompareOperation::COUNT}};
  212. void setStencilCompareOperation(FaceSelectionBit face, CompareOperation comp)
  213. {
  214. if(!!(face & FaceSelectionBit::FRONT) && m_stencilCompare[0] != comp)
  215. {
  216. m_stencilCompare[0] = comp;
  217. m_glStencilFuncSeparateDirty[0] = true;
  218. }
  219. if(!!(face & FaceSelectionBit::BACK) && m_stencilCompare[1] != comp)
  220. {
  221. m_stencilCompare[1] = comp;
  222. m_glStencilFuncSeparateDirty[1] = true;
  223. }
  224. }
  225. static const U32 DUMMY_STENCIL_MASK = 0x969696;
  226. Array<U32, 2> m_stencilCompareMask = {{DUMMY_STENCIL_MASK, DUMMY_STENCIL_MASK}};
  227. void setStencilCompareMask(FaceSelectionBit face, U32 mask)
  228. {
  229. ANKI_ASSERT(mask != DUMMY_STENCIL_MASK && "Oops");
  230. if(!!(face & FaceSelectionBit::FRONT) && m_stencilCompareMask[0] != mask)
  231. {
  232. m_stencilCompareMask[0] = mask;
  233. m_glStencilFuncSeparateDirty[0] = true;
  234. }
  235. if(!!(face & FaceSelectionBit::BACK) && m_stencilCompareMask[1] != mask)
  236. {
  237. m_stencilCompareMask[1] = mask;
  238. m_glStencilFuncSeparateDirty[1] = true;
  239. }
  240. }
  241. Array<U32, 2> m_stencilWriteMask = {{DUMMY_STENCIL_MASK, DUMMY_STENCIL_MASK}};
  242. Bool setStencilWriteMask(FaceSelectionBit face, U32 mask)
  243. {
  244. ANKI_ASSERT(mask != DUMMY_STENCIL_MASK && "Oops");
  245. Bool changed = false;
  246. if(!!(face & FaceSelectionBit::FRONT) && m_stencilWriteMask[0] != mask)
  247. {
  248. m_stencilWriteMask[0] = mask;
  249. changed = true;
  250. }
  251. if(!!(face & FaceSelectionBit::BACK) && m_stencilWriteMask[1] != mask)
  252. {
  253. m_stencilWriteMask[1] = mask;
  254. changed = true;
  255. }
  256. return changed;
  257. }
  258. Array<U32, 2> m_stencilRef = {{DUMMY_STENCIL_MASK, DUMMY_STENCIL_MASK}};
  259. void setStencilReference(FaceSelectionBit face, U32 mask)
  260. {
  261. ANKI_ASSERT(mask != DUMMY_STENCIL_MASK && "Oops");
  262. if(!!(face & FaceSelectionBit::FRONT) && m_stencilRef[0] != mask)
  263. {
  264. m_stencilRef[0] = mask;
  265. m_glStencilFuncSeparateDirty[0] = true;
  266. }
  267. if(!!(face & FaceSelectionBit::BACK) && m_stencilRef[1] != mask)
  268. {
  269. m_stencilRef[1] = mask;
  270. m_glStencilFuncSeparateDirty[1] = true;
  271. }
  272. }
  273. Bool m_depthTestEnabled = 2; ///< 2 means don't know
  274. Bool maybeEnableDepthTest()
  275. {
  276. ANKI_ASSERT(m_depthWrite <= 1 && m_depthOp != CompareOperation::COUNT);
  277. Bool enable = m_depthWrite || m_depthOp != CompareOperation::ALWAYS;
  278. if(enable != m_depthTestEnabled)
  279. {
  280. m_depthTestEnabled = enable;
  281. return true;
  282. }
  283. return false;
  284. }
  285. Bool m_depthWrite = 2;
  286. Bool setDepthWrite(Bool enable)
  287. {
  288. if(m_depthWrite != enable)
  289. {
  290. m_depthWrite = enable;
  291. return true;
  292. }
  293. return false;
  294. }
  295. CompareOperation m_depthOp = CompareOperation::COUNT;
  296. Bool setDepthCompareOperation(CompareOperation op)
  297. {
  298. if(op != m_depthOp)
  299. {
  300. m_depthOp = op;
  301. return true;
  302. }
  303. return false;
  304. }
  305. /// @}
  306. /// @name color
  307. /// @{
  308. static const ColorBit INVALID_COLOR_MASK = static_cast<ColorBit>(MAX_U8);
  309. class ColorAttachment
  310. {
  311. public:
  312. ColorBit m_writeMask = INVALID_COLOR_MASK;
  313. Bool m_enableBlend = 2;
  314. BlendFactor m_blendSrcFactorRgb = BlendFactor::COUNT;
  315. BlendFactor m_blendDstFactorRgb = BlendFactor::COUNT;
  316. BlendFactor m_blendSrcFactorA = BlendFactor::COUNT;
  317. BlendFactor m_blendDstFactorA = BlendFactor::COUNT;
  318. BlendOperation m_blendOpRgb = BlendOperation::COUNT;
  319. BlendOperation m_blendOpA = BlendOperation::COUNT;
  320. };
  321. Array<ColorAttachment, MAX_COLOR_ATTACHMENTS> m_colorAtt;
  322. Bool setColorChannelWriteMask(U32 attachment, ColorBit mask)
  323. {
  324. if(m_colorAtt[attachment].m_writeMask != mask)
  325. {
  326. m_colorAtt[attachment].m_writeMask = mask;
  327. return true;
  328. }
  329. return false;
  330. }
  331. Bool maybeEnableBlend(U attidx)
  332. {
  333. ColorAttachment& att = m_colorAtt[attidx];
  334. Bool wantBlend = !blendingDisabled(att.m_blendSrcFactorRgb, att.m_blendDstFactorRgb, att.m_blendSrcFactorA,
  335. att.m_blendDstFactorA, att.m_blendOpRgb, att.m_blendOpA);
  336. if(wantBlend != att.m_enableBlend)
  337. {
  338. att.m_enableBlend = wantBlend;
  339. return true;
  340. }
  341. return false;
  342. }
  343. Bool setBlendFactors(U32 attachment, BlendFactor srcRgb, BlendFactor dstRgb, BlendFactor srcA, BlendFactor dstA)
  344. {
  345. auto& att = m_colorAtt[attachment];
  346. if(att.m_blendSrcFactorRgb != srcRgb || att.m_blendDstFactorRgb != dstRgb || att.m_blendSrcFactorA != srcA
  347. || att.m_blendDstFactorA != dstA)
  348. {
  349. att.m_blendSrcFactorRgb = srcRgb;
  350. att.m_blendDstFactorRgb = dstRgb;
  351. att.m_blendSrcFactorA = srcA;
  352. att.m_blendDstFactorA = dstA;
  353. return true;
  354. }
  355. return false;
  356. }
  357. Bool setBlendOperation(U32 attachment, BlendOperation funcRgb, BlendOperation funcA)
  358. {
  359. auto& att = m_colorAtt[attachment];
  360. if(att.m_blendOpRgb != funcRgb || att.m_blendOpA != funcA)
  361. {
  362. att.m_blendOpRgb = funcRgb;
  363. att.m_blendOpA = funcA;
  364. return true;
  365. }
  366. return false;
  367. }
  368. /// @}
  369. /// @name resources
  370. /// @{
  371. class TextureBinding
  372. {
  373. public:
  374. U64 m_texViewUuid = 0;
  375. U64 m_samplerUuid = 0;
  376. };
  377. Array2d<TextureBinding, MAX_DESCRIPTOR_SETS, MAX_TEXTURE_BINDINGS> m_textures;
  378. Bool bindTextureViewAndSampler(U32 set, U32 binding, const TextureViewPtr& texView, const SamplerPtr& sampler)
  379. {
  380. TextureBinding& b = m_textures[set][binding];
  381. Bool dirty;
  382. if(b.m_texViewUuid != texView->getUuid() || b.m_samplerUuid != sampler->getUuid())
  383. {
  384. b.m_texViewUuid = texView->getUuid();
  385. b.m_samplerUuid = sampler->getUuid();
  386. dirty = true;
  387. }
  388. else
  389. {
  390. dirty = false;
  391. }
  392. return dirty;
  393. }
  394. class ShaderBufferBinding
  395. {
  396. public:
  397. BufferImpl* m_buff = nullptr;
  398. PtrSize m_offset;
  399. PtrSize m_range;
  400. };
  401. Array2d<ShaderBufferBinding, MAX_DESCRIPTOR_SETS, MAX_UNIFORM_BUFFER_BINDINGS> m_ubos;
  402. Bool bindUniformBuffer(U32 set, U32 binding, BufferPtr buff, PtrSize offset, PtrSize range)
  403. {
  404. ShaderBufferBinding& b = m_ubos[set][binding];
  405. b.m_buff = static_cast<BufferImpl*>(buff.get());
  406. b.m_offset = offset;
  407. b.m_range = range;
  408. return true;
  409. }
  410. Array2d<ShaderBufferBinding, MAX_DESCRIPTOR_SETS, MAX_STORAGE_BUFFER_BINDINGS> m_ssbos;
  411. Bool bindStorageBuffer(U32 set, U32 binding, BufferPtr buff, PtrSize offset, PtrSize range)
  412. {
  413. ShaderBufferBinding& b = m_ssbos[set][binding];
  414. b.m_buff = static_cast<BufferImpl*>(buff.get());
  415. b.m_offset = offset;
  416. b.m_range = range;
  417. return true;
  418. }
  419. class ImageBinding
  420. {
  421. public:
  422. U64 m_texViewUuid = 0;
  423. };
  424. Array2d<ImageBinding, MAX_DESCRIPTOR_SETS, MAX_IMAGE_BINDINGS> m_images;
  425. Bool bindImage(U32 set, U32 binding, const TextureViewPtr& img)
  426. {
  427. ImageBinding& b = m_images[set][binding];
  428. b.m_texViewUuid = img->getUuid();
  429. return true;
  430. }
  431. ShaderProgramImpl* m_prog = nullptr;
  432. Bool bindShaderProgram(ShaderProgramPtr prog)
  433. {
  434. ShaderProgramImpl* const progimpl = static_cast<ShaderProgramImpl*>(prog.get());
  435. if(progimpl != m_prog)
  436. {
  437. m_prog = progimpl;
  438. return true;
  439. }
  440. return false;
  441. }
  442. /// @}
  443. /// @name other
  444. /// @{
  445. const FramebufferImpl* m_fb = nullptr;
  446. Bool beginRenderPass(const FramebufferPtr& fb)
  447. {
  448. ANKI_ASSERT(!insideRenderPass() && "Already inside a renderpass");
  449. m_fb = static_cast<const FramebufferImpl*>(fb.get());
  450. m_lastSecondLevelCmdb = nullptr;
  451. return true;
  452. }
  453. void endRenderPass()
  454. {
  455. ANKI_ASSERT(insideRenderPass() && "Not inside a renderpass");
  456. if(m_lastSecondLevelCmdb)
  457. {
  458. // Renderpass had 2nd level cmdbs, need to restore the state back to default
  459. ::new(this) StateTracker();
  460. }
  461. else
  462. {
  463. m_fb = nullptr;
  464. }
  465. }
  466. Bool insideRenderPass() const
  467. {
  468. return m_fb != nullptr;
  469. }
  470. CommandBufferImpl* m_lastSecondLevelCmdb = nullptr;
  471. /// @}
  472. /// @name drawcalls
  473. /// @{
  474. void checkIndexedDracall() const
  475. {
  476. ANKI_ASSERT(m_idx.m_indexType != 0 && "Forgot to bind index buffer");
  477. checkDrawcall();
  478. }
  479. void checkNonIndexedDrawcall() const
  480. {
  481. checkDrawcall();
  482. }
  483. void checkDrawcall() const
  484. {
  485. ANKI_ASSERT(m_viewport[1] != MAX_U16 && "Forgot to set the viewport");
  486. ANKI_ASSERT(m_prog && "Forgot to bound a program");
  487. ANKI_ASSERT((insideRenderPass() || m_secondLevel) && "Forgot to begin a render pass");
  488. }
  489. void checkDispatch() const
  490. {
  491. ANKI_ASSERT(m_prog && "Forgot to bound a program");
  492. ANKI_ASSERT(!insideRenderPass() && "Forgot to end the render pass");
  493. }
  494. /// @}
  495. };
  496. /// @}
  497. } // end namespace anki