StateTracker.h 14 KB

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