GraphicsStateTracker.h 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615
  1. // Copyright (C) 2009-present, 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/BackendCommon/Common.h>
  7. #include <AnKi/Gr/ShaderProgram.h>
  8. namespace anki {
  9. /// @addtogroup graphics
  10. /// @{
  11. /// This is the way the command buffer sets the graphics state.
  12. class GraphicsStateTracker
  13. {
  14. friend class GraphicsPipelineFactory;
  15. public:
  16. void bindVertexBuffer(U32 binding, VertexStepRate stepRate
  17. #if ANKI_GR_BACKEND_VULKAN
  18. ,
  19. U32 stride
  20. #endif
  21. )
  22. {
  23. auto& vertState = m_staticState.m_vert;
  24. if(!vertState.m_bindingsSetMask.get(binding) || vertState.m_bindings[binding].m_stepRate != stepRate
  25. #if ANKI_GR_BACKEND_VULKAN
  26. || vertState.m_bindings[binding].m_stride != stride
  27. #endif
  28. )
  29. {
  30. vertState.m_bindingsSetMask.set(binding);
  31. #if ANKI_GR_BACKEND_VULKAN
  32. vertState.m_bindings[binding].m_stride = stride;
  33. #endif
  34. vertState.m_bindings[binding].m_stepRate = stepRate;
  35. m_hashes.m_vert = 0;
  36. }
  37. }
  38. void setVertexAttribute(VertexAttributeSemantic attribute, U32 buffBinding, Format fmt, U32 relativeOffset)
  39. {
  40. auto& attr = m_staticState.m_vert.m_attribs[attribute];
  41. if(!m_staticState.m_vert.m_attribsSetMask.get(attribute) || attr.m_fmt != fmt || attr.m_binding != buffBinding
  42. || attr.m_relativeOffset != relativeOffset)
  43. {
  44. attr.m_fmt = fmt;
  45. attr.m_binding = buffBinding;
  46. attr.m_relativeOffset = relativeOffset;
  47. m_staticState.m_vert.m_attribsSetMask.set(attribute);
  48. m_hashes.m_vert = 0;
  49. }
  50. }
  51. void setFillMode(FillMode mode)
  52. {
  53. ANKI_ASSERT(mode < FillMode::kCount);
  54. if(m_staticState.m_rast.m_fillMode != mode)
  55. {
  56. m_staticState.m_rast.m_fillMode = mode;
  57. m_hashes.m_rast = 0;
  58. }
  59. }
  60. void setCullMode(FaceSelectionBit mode)
  61. {
  62. if(m_staticState.m_rast.m_cullMode != mode)
  63. {
  64. m_staticState.m_rast.m_cullMode = mode;
  65. m_hashes.m_rast = 0;
  66. }
  67. }
  68. void setStencilOperations(FaceSelectionBit face, StencilOperation stencilFail, StencilOperation stencilPassDepthFail,
  69. StencilOperation stencilPassDepthPass)
  70. {
  71. ANKI_ASSERT(face != FaceSelectionBit::kNone);
  72. auto& front = m_staticState.m_stencil.m_face[0];
  73. if(!!(face & FaceSelectionBit::kFront)
  74. && (front.m_fail != stencilFail || front.m_stencilPassDepthFail != stencilPassDepthFail
  75. || front.m_stencilPassDepthPass != stencilPassDepthPass))
  76. {
  77. front.m_fail = stencilFail;
  78. front.m_stencilPassDepthFail = stencilPassDepthFail;
  79. front.m_stencilPassDepthPass = stencilPassDepthPass;
  80. m_hashes.m_depthStencil = 0;
  81. }
  82. auto& back = m_staticState.m_stencil.m_face[1];
  83. if(!!(face & FaceSelectionBit::kBack)
  84. && (back.m_fail != stencilFail || back.m_stencilPassDepthFail != stencilPassDepthFail
  85. || back.m_stencilPassDepthPass != stencilPassDepthPass))
  86. {
  87. back.m_fail = stencilFail;
  88. back.m_stencilPassDepthFail = stencilPassDepthFail;
  89. back.m_stencilPassDepthPass = stencilPassDepthPass;
  90. m_hashes.m_depthStencil = 0;
  91. }
  92. }
  93. void setStencilCompareOperation(FaceSelectionBit face, CompareOperation comp)
  94. {
  95. ANKI_ASSERT(face != FaceSelectionBit::kNone);
  96. if(!!(face & FaceSelectionBit::kFront) && m_staticState.m_stencil.m_face[0].m_compare != comp)
  97. {
  98. m_staticState.m_stencil.m_face[0].m_compare = comp;
  99. m_hashes.m_depthStencil = 0;
  100. }
  101. if(!!(face & FaceSelectionBit::kBack) && m_staticState.m_stencil.m_face[1].m_compare != comp)
  102. {
  103. m_staticState.m_stencil.m_face[1].m_compare = comp;
  104. m_hashes.m_depthStencil = 0;
  105. }
  106. }
  107. void setStencilCompareMask(FaceSelectionBit face, U32 mask)
  108. {
  109. ANKI_ASSERT(face != FaceSelectionBit::kNone);
  110. #if ANKI_GR_BACKEND_VULKAN
  111. if(!!(face & FaceSelectionBit::kFront) && m_dynState.m_stencilFaces[0].m_compareMask != mask)
  112. {
  113. m_dynState.m_stencilFaces[0].m_compareMask = mask;
  114. m_dynState.m_stencilCompareMaskDirty = true;
  115. }
  116. if(!!(face & FaceSelectionBit::kBack) && m_dynState.m_stencilFaces[1].m_compareMask != mask)
  117. {
  118. m_dynState.m_stencilFaces[1].m_compareMask = mask;
  119. m_dynState.m_stencilCompareMaskDirty = true;
  120. }
  121. #else
  122. if(!!(face & FaceSelectionBit::kFront) && m_staticState.m_stencil.m_face[0].m_compareMask != mask)
  123. {
  124. m_staticState.m_stencil.m_face[0].m_compareMask = mask;
  125. m_hashes.m_depthStencil = 0;
  126. }
  127. if(!!(face & FaceSelectionBit::kBack) && m_staticState.m_stencil.m_face[1].m_compareMask != mask)
  128. {
  129. m_staticState.m_stencil.m_face[1].m_compareMask = mask;
  130. m_hashes.m_depthStencil = 0;
  131. }
  132. #endif
  133. }
  134. void setStencilWriteMask(FaceSelectionBit face, U32 mask)
  135. {
  136. ANKI_ASSERT(face != FaceSelectionBit::kNone);
  137. #if ANKI_GR_BACKEND_VULKAN
  138. if(!!(face & FaceSelectionBit::kFront) && m_dynState.m_stencilFaces[0].m_writeMask != mask)
  139. {
  140. m_dynState.m_stencilFaces[0].m_writeMask = mask;
  141. m_dynState.m_stencilWriteMaskDirty = true;
  142. }
  143. if(!!(face & FaceSelectionBit::kBack) && m_dynState.m_stencilFaces[1].m_writeMask != mask)
  144. {
  145. m_dynState.m_stencilFaces[1].m_writeMask = mask;
  146. m_dynState.m_stencilWriteMaskDirty = true;
  147. }
  148. #else
  149. if(!!(face & FaceSelectionBit::kFront) && m_staticState.m_stencil.m_face[0].m_writeMask != mask)
  150. {
  151. m_staticState.m_stencil.m_face[0].m_writeMask = mask;
  152. m_hashes.m_depthStencil = 0;
  153. }
  154. if(!!(face & FaceSelectionBit::kBack) && m_staticState.m_stencil.m_face[1].m_writeMask != mask)
  155. {
  156. m_staticState.m_stencil.m_face[1].m_writeMask = mask;
  157. m_hashes.m_depthStencil = 0;
  158. }
  159. #endif
  160. }
  161. void setStencilReference(FaceSelectionBit face, U32 ref)
  162. {
  163. ANKI_ASSERT(face != FaceSelectionBit::kNone);
  164. ANKI_ASSERT((ANKI_GR_BACKEND_VULKAN || face == FaceSelectionBit::kFrontAndBack) && "D3D only supports a single value for both sides");
  165. if(!!(face & FaceSelectionBit::kFront) && m_dynState.m_stencilFaces[0].m_ref != ref)
  166. {
  167. m_dynState.m_stencilFaces[0].m_ref = ref;
  168. m_dynState.m_stencilRefDirty = true;
  169. }
  170. if(!!(face & FaceSelectionBit::kBack) && m_dynState.m_stencilFaces[1].m_ref != ref)
  171. {
  172. m_dynState.m_stencilFaces[1].m_ref = ref;
  173. m_dynState.m_stencilRefDirty = true;
  174. }
  175. }
  176. void setDepthWrite(Bool enable)
  177. {
  178. if(m_staticState.m_depth.m_writeEnabled != enable)
  179. {
  180. m_staticState.m_depth.m_writeEnabled = enable;
  181. m_hashes.m_depthStencil = 0;
  182. }
  183. }
  184. void setDepthCompareOperation(CompareOperation op)
  185. {
  186. ANKI_ASSERT(op < CompareOperation::kCount);
  187. if(m_staticState.m_depth.m_compare != op)
  188. {
  189. m_staticState.m_depth.m_compare = op;
  190. m_hashes.m_depthStencil = 0;
  191. }
  192. }
  193. void setPolygonOffset(F32 factor, F32 units)
  194. {
  195. #if ANKI_GR_BACKEND_VULKAN
  196. if(m_dynState.m_depthBiasConstantFactor != factor || m_dynState.m_depthBiasSlopeFactor != units)
  197. {
  198. m_dynState.m_depthBiasConstantFactor = factor;
  199. m_dynState.m_depthBiasSlopeFactor = units;
  200. m_dynState.m_depthBiasClamp = 0.0f;
  201. m_dynState.m_depthBiasDirty = true;
  202. m_staticState.m_rast.m_depthBiasEnabled = factor != 0.0f || units != 0.0f;
  203. }
  204. #else
  205. if(m_staticState.m_rast.m_depthBias != factor || m_staticState.m_rast.m_slopeScaledDepthBias != units)
  206. {
  207. m_staticState.m_rast.m_depthBias = factor;
  208. m_staticState.m_rast.m_slopeScaledDepthBias = units;
  209. m_staticState.m_rast.m_depthBiasClamp = 0.0f;
  210. m_hashes.m_rast = 0;
  211. }
  212. #endif
  213. }
  214. void setAlphaToCoverage(Bool enable)
  215. {
  216. if(m_staticState.m_blend.m_alphaToCoverage != enable)
  217. {
  218. m_staticState.m_blend.m_alphaToCoverage = enable;
  219. m_hashes.m_blend = 0;
  220. }
  221. }
  222. void setBlendFactors(U32 attachment, BlendFactor srcRgb, BlendFactor dstRgb, BlendFactor srcA, BlendFactor dstA)
  223. {
  224. auto& rt = m_staticState.m_blend.m_colorRts[attachment];
  225. if(rt.m_srcRgb != srcRgb || rt.m_srcA != srcA || rt.m_dstRgb != dstRgb || rt.m_dstA != dstA)
  226. {
  227. rt.m_srcRgb = srcRgb;
  228. rt.m_srcA = srcA;
  229. rt.m_dstRgb = dstRgb;
  230. rt.m_dstA = dstA;
  231. m_hashes.m_blend = 0;
  232. }
  233. }
  234. void setBlendOperation(U32 attachment, BlendOperation funcRgb, BlendOperation funcA)
  235. {
  236. auto& rt = m_staticState.m_blend.m_colorRts[attachment];
  237. if(rt.m_funcRgb != funcRgb || rt.m_funcA != funcA)
  238. {
  239. rt.m_funcRgb = funcRgb;
  240. rt.m_funcA = funcA;
  241. m_hashes.m_blend = 0;
  242. }
  243. }
  244. void beginRenderPass(ConstWeakArray<Format> colorFormats, Format depthStencilFormat, UVec2 rtsSize)
  245. {
  246. m_staticState.m_misc.m_colorRtFormats.fill(Format::kNone);
  247. m_staticState.m_misc.m_colorRtMask.unsetAll();
  248. for(U8 i = 0; i < colorFormats.getSize(); ++i)
  249. {
  250. ANKI_ASSERT(colorFormats[i] != Format::kNone);
  251. m_staticState.m_misc.m_colorRtFormats[i] = colorFormats[i];
  252. m_staticState.m_misc.m_colorRtMask.set(i);
  253. }
  254. m_staticState.m_misc.m_depthStencilFormat = depthStencilFormat;
  255. m_hashes.m_misc = 0; // Always mark it dirty because calling beginRenderPass is a rare occurance and we want to avoid extra checks
  256. if(m_rtsSize != rtsSize)
  257. {
  258. m_rtsSize = rtsSize;
  259. // Re-set the viewport and scissor because they depend on the size of the render targets
  260. m_dynState.m_scissorDirty = true;
  261. m_dynState.m_viewportDirty = true;
  262. }
  263. }
  264. void bindShaderProgram(ShaderProgram* prog)
  265. {
  266. ANKI_ASSERT(prog);
  267. if(prog != m_staticState.m_shaderProg)
  268. {
  269. const ShaderReflection& refl = prog->getReflection();
  270. if(m_staticState.m_vert.m_activeAttribs != refl.m_vertex.m_vertexAttributeMask)
  271. {
  272. m_staticState.m_vert.m_activeAttribs = refl.m_vertex.m_vertexAttributeMask;
  273. m_hashes.m_vert = 0;
  274. }
  275. #if ANKI_GR_BACKEND_VULKAN
  276. if(!!(prog->getShaderTypes() & ShaderTypeBit::kVertex) && refl.m_vertex.m_vertexAttributeMask.getSetBitCount())
  277. {
  278. if(m_staticState.m_shaderProg)
  279. {
  280. const Bool semanticsChanged = m_staticState.m_shaderProg->getReflection().m_vertex.m_vkVertexAttributeLocations
  281. != refl.m_vertex.m_vkVertexAttributeLocations;
  282. if(semanticsChanged)
  283. {
  284. m_hashes.m_vert = 0;
  285. }
  286. }
  287. for(VertexAttributeSemantic s : EnumIterable<VertexAttributeSemantic>())
  288. {
  289. m_staticState.m_vert.m_attribs[s].m_semanticToVertexAttributeLocation = refl.m_vertex.m_vkVertexAttributeLocations[s];
  290. }
  291. }
  292. #endif
  293. if(m_staticState.m_misc.m_colorRtMask != refl.m_pixel.m_colorRenderTargetWritemask)
  294. {
  295. m_staticState.m_misc.m_colorRtMask = refl.m_pixel.m_colorRenderTargetWritemask;
  296. m_hashes.m_misc = 0;
  297. }
  298. m_staticState.m_shaderProg = prog;
  299. m_hashes.m_shaderProg = 0;
  300. }
  301. }
  302. void setPrimitiveTopology(PrimitiveTopology topology)
  303. {
  304. if(m_staticState.m_ia.m_topology != topology)
  305. {
  306. m_staticState.m_ia.m_topology = topology;
  307. m_hashes.m_ia = 0;
  308. #if ANKI_GR_BACKEND_DIRECT3D
  309. m_dynState.m_topologyDirty = true;
  310. #endif
  311. }
  312. }
  313. void setViewport(U32 minx, U32 miny, U32 width, U32 height)
  314. {
  315. if(m_dynState.m_viewport[0] != minx || m_dynState.m_viewport[1] != miny || m_dynState.m_viewport[2] != width
  316. || m_dynState.m_viewport[3] != height)
  317. {
  318. m_dynState.m_viewport[0] = minx;
  319. m_dynState.m_viewport[1] = miny;
  320. m_dynState.m_viewport[2] = width;
  321. m_dynState.m_viewport[3] = height;
  322. m_dynState.m_viewportDirty = true;
  323. // Scissor needs to be re-adjusted if it's in its default size
  324. m_dynState.m_scissorDirty = true;
  325. }
  326. }
  327. void setScissor(U32 minx, U32 miny, U32 width, U32 height)
  328. {
  329. if(m_dynState.m_scissor[0] != minx || m_dynState.m_scissor[1] != miny || m_dynState.m_scissor[2] != width
  330. || m_dynState.m_scissor[3] != height)
  331. {
  332. m_dynState.m_scissor[0] = minx;
  333. m_dynState.m_scissor[1] = miny;
  334. m_dynState.m_scissor[2] = width;
  335. m_dynState.m_scissor[3] = height;
  336. m_dynState.m_scissorDirty = true;
  337. }
  338. }
  339. void setLineWidth(F32 width)
  340. {
  341. #if ANKI_GR_BACKEND_VULKAN
  342. if(m_dynState.m_lineWidth != width)
  343. {
  344. m_dynState.m_lineWidth = width;
  345. m_dynState.m_lineWidthDirty = true;
  346. }
  347. #else
  348. ANKI_ASSERT(width == 1.0f && "DX only accepts 1.0 line width");
  349. #endif
  350. }
  351. #if ANKI_GR_BACKEND_VULKAN
  352. void setEnablePipelineStatistics(Bool enable)
  353. {
  354. m_staticState.m_misc.m_pipelineStatisticsEnabled = enable;
  355. }
  356. #endif
  357. void setPrimitiveRestart(Bool enable)
  358. {
  359. if(m_staticState.m_ia.m_primitiveRestartEnabled != enable)
  360. {
  361. m_staticState.m_ia.m_primitiveRestartEnabled = enable;
  362. m_hashes.m_ia = 0;
  363. }
  364. }
  365. void setColorChannelWriteMask(U32 attachment, ColorBit mask)
  366. {
  367. if(m_staticState.m_blend.m_colorRts[attachment].m_channelWriteMask != mask)
  368. {
  369. m_staticState.m_blend.m_colorRts[attachment].m_channelWriteMask = mask;
  370. m_hashes.m_blend = 0;
  371. }
  372. }
  373. ShaderProgram& getShaderProgram()
  374. {
  375. ANKI_ASSERT(m_staticState.m_shaderProg);
  376. return *m_staticState.m_shaderProg;
  377. }
  378. private:
  379. ANKI_BEGIN_PACKED_STRUCT
  380. class StaticState
  381. {
  382. public:
  383. class Vertex
  384. {
  385. public:
  386. class Binding
  387. {
  388. public:
  389. #if ANKI_GR_BACKEND_VULKAN
  390. U32 m_stride;
  391. #endif
  392. VertexStepRate m_stepRate;
  393. Binding()
  394. {
  395. // No init for opt
  396. }
  397. };
  398. class Attribute
  399. {
  400. public:
  401. U32 m_relativeOffset;
  402. Format m_fmt;
  403. U32 m_binding;
  404. #if ANKI_GR_BACKEND_VULKAN
  405. U8 m_semanticToVertexAttributeLocation;
  406. #endif
  407. Attribute()
  408. {
  409. // No init for opt
  410. }
  411. };
  412. Array<Binding, U32(VertexAttributeSemantic::kCount)> m_bindings;
  413. Array<Attribute, U32(VertexAttributeSemantic::kCount)> m_attribs;
  414. BitSet<U32(VertexAttributeSemantic::kCount)> m_activeAttribs = false;
  415. BitSet<U32(VertexAttributeSemantic::kCount)> m_bindingsSetMask = false;
  416. BitSet<U32(VertexAttributeSemantic::kCount)> m_attribsSetMask = false;
  417. } m_vert;
  418. class InputAssembler
  419. {
  420. public:
  421. PrimitiveTopology m_topology = PrimitiveTopology::kTriangles;
  422. Bool m_primitiveRestartEnabled = false;
  423. } m_ia;
  424. class Rast
  425. {
  426. public:
  427. FillMode m_fillMode = FillMode::kSolid;
  428. FaceSelectionBit m_cullMode = FaceSelectionBit::kBack;
  429. #if ANKI_GR_BACKEND_VULKAN
  430. Bool m_depthBiasEnabled = false;
  431. #else
  432. F32 m_depthBias = 0.0f;
  433. F32 m_depthBiasClamp = 0.0f;
  434. F32 m_slopeScaledDepthBias = 0.0f;
  435. #endif
  436. } m_rast;
  437. class
  438. {
  439. public:
  440. class StencilFace
  441. {
  442. public:
  443. StencilOperation m_fail = StencilOperation::kKeep;
  444. StencilOperation m_stencilPassDepthFail = StencilOperation::kKeep;
  445. StencilOperation m_stencilPassDepthPass = StencilOperation::kKeep;
  446. CompareOperation m_compare = CompareOperation::kAlways;
  447. #if ANKI_GR_BACKEND_DIRECT3D
  448. U32 m_compareMask = 0x5A5A5A5A; ///< Use a stupid number to initialize.
  449. U32 m_writeMask = 0x5A5A5A5A; ///< Use a stupid number to initialize.
  450. #endif
  451. };
  452. Array<StencilFace, 2> m_face;
  453. } m_stencil;
  454. class
  455. {
  456. public:
  457. CompareOperation m_compare = CompareOperation::kLess;
  458. Bool m_writeEnabled = true;
  459. } m_depth;
  460. class
  461. {
  462. public:
  463. class Rt
  464. {
  465. public:
  466. ColorBit m_channelWriteMask = ColorBit::kAll;
  467. BlendFactor m_srcRgb = BlendFactor::kOne;
  468. BlendFactor m_dstRgb = BlendFactor::kZero;
  469. BlendFactor m_srcA = BlendFactor::kOne;
  470. BlendFactor m_dstA = BlendFactor::kZero;
  471. BlendOperation m_funcRgb = BlendOperation::kAdd;
  472. BlendOperation m_funcA = BlendOperation::kAdd;
  473. };
  474. Array<Rt, kMaxColorRenderTargets> m_colorRts;
  475. Bool m_alphaToCoverage = false;
  476. } m_blend;
  477. class Misc
  478. {
  479. public:
  480. Array<Format, kMaxColorRenderTargets> m_colorRtFormats = {};
  481. Format m_depthStencilFormat = Format::kNone;
  482. BitSet<kMaxColorRenderTargets> m_colorRtMask = {false};
  483. #if ANKI_GR_BACKEND_VULKAN
  484. Bool m_pipelineStatisticsEnabled = false;
  485. #endif
  486. } m_misc;
  487. ShaderProgram* m_shaderProg = nullptr;
  488. } m_staticState;
  489. ANKI_END_PACKED_STRUCT
  490. class DynamicState
  491. {
  492. public:
  493. class StencilFace
  494. {
  495. public:
  496. #if ANKI_GR_BACKEND_VULKAN
  497. U32 m_compareMask = 0x5A5A5A5A; ///< Use a stupid number to initialize.
  498. U32 m_writeMask = 0x5A5A5A5A; ///< Use a stupid number to initialize.
  499. #endif
  500. U32 m_ref = 0x5A5A5A5A; ///< Use a stupid number to initialize.
  501. };
  502. Array<StencilFace, 2> m_stencilFaces;
  503. Array<U32, 4> m_viewport = {};
  504. Array<U32, 4> m_scissor = {0, 0, kMaxU32, kMaxU32};
  505. #if ANKI_GR_BACKEND_VULKAN
  506. F32 m_depthBiasConstantFactor = 0.0f;
  507. F32 m_depthBiasClamp = 0.0f;
  508. F32 m_depthBiasSlopeFactor = 0.0f;
  509. F32 m_lineWidth = 1.0f;
  510. #endif
  511. #if ANKI_GR_BACKEND_VULKAN
  512. Bool m_stencilCompareMaskDirty : 1 = true;
  513. Bool m_stencilWriteMaskDirty : 1 = true;
  514. Bool m_depthBiasDirty : 1 = true;
  515. Bool m_lineWidthDirty : 1 = true;
  516. #else
  517. Bool m_topologyDirty : 1 = true;
  518. #endif
  519. Bool m_stencilRefDirty : 1 = true;
  520. Bool m_viewportDirty : 1 = true;
  521. Bool m_scissorDirty : 1 = true;
  522. } m_dynState;
  523. class Hashes
  524. {
  525. public:
  526. U64 m_vert = 0;
  527. U64 m_rast = 0;
  528. U64 m_ia = 0;
  529. U64 m_depthStencil = 0;
  530. U64 m_blend = 0;
  531. U64 m_misc = 0;
  532. U64 m_shaderProg = 0;
  533. } m_hashes;
  534. U64 m_globalHash = 0;
  535. UVec2 m_rtsSize = UVec2(0u);
  536. Bool updateHashes();
  537. };
  538. /// @}
  539. } // end namespace anki