Pipeline.cs 41 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348
  1. using OpenTK.Graphics.OpenGL;
  2. using Ryujinx.Common.Logging;
  3. using Ryujinx.Graphics.GAL;
  4. using Ryujinx.Graphics.OpenGL.Image;
  5. using Ryujinx.Graphics.OpenGL.Queries;
  6. using Ryujinx.Graphics.Shader;
  7. using System;
  8. using System.Runtime.CompilerServices;
  9. using System.Runtime.InteropServices;
  10. namespace Ryujinx.Graphics.OpenGL
  11. {
  12. class Pipeline : IPipeline, IDisposable
  13. {
  14. internal ulong DrawCount { get; private set; }
  15. private Program _program;
  16. private bool _rasterizerDiscard;
  17. private VertexArray _vertexArray;
  18. private Framebuffer _framebuffer;
  19. private IntPtr _indexBaseOffset;
  20. private DrawElementsType _elementsType;
  21. private PrimitiveType _primitiveType;
  22. private int _stencilFrontMask;
  23. private bool _depthMask;
  24. private int _boundDrawFramebuffer;
  25. private int _boundReadFramebuffer;
  26. private struct Vector4<T>
  27. {
  28. public T X;
  29. public T Y;
  30. public T Z;
  31. public T W;
  32. }
  33. private Vector4<int>[] _fpIsBgra = new Vector4<int>[SupportBuffer.FragmentIsBgraCount];
  34. private Vector4<float>[] _renderScale = new Vector4<float>[65];
  35. private TextureBase _unit0Texture;
  36. private FrontFaceDirection _frontFace;
  37. private ClipOrigin _clipOrigin;
  38. private ClipDepthMode _clipDepthMode;
  39. private readonly uint[] _componentMasks;
  40. private uint _scissorEnables;
  41. private bool _tfEnabled;
  42. private TransformFeedbackPrimitiveType _tfTopology;
  43. private BufferHandle _supportBuffer;
  44. private readonly BufferHandle[] _tfbs;
  45. private readonly BufferRange[] _tfbTargets;
  46. private ColorF _blendConstant;
  47. internal Pipeline()
  48. {
  49. _rasterizerDiscard = false;
  50. _clipOrigin = ClipOrigin.LowerLeft;
  51. _clipDepthMode = ClipDepthMode.NegativeOneToOne;
  52. _componentMasks = new uint[Constants.MaxRenderTargets];
  53. for (int index = 0; index < Constants.MaxRenderTargets; index++)
  54. {
  55. _componentMasks[index] = 0xf;
  56. }
  57. var v4Zero = new Vector4<float> { X = 0f, Y = 0f, Z = 0f, W = 0f };
  58. new Span<Vector4<float>>(_renderScale).Fill(v4Zero);
  59. _tfbs = new BufferHandle[Constants.MaxTransformFeedbackBuffers];
  60. _tfbTargets = new BufferRange[Constants.MaxTransformFeedbackBuffers];
  61. }
  62. public void Barrier()
  63. {
  64. GL.MemoryBarrier(MemoryBarrierFlags.AllBarrierBits);
  65. }
  66. public void BeginTransformFeedback(PrimitiveTopology topology)
  67. {
  68. GL.BeginTransformFeedback(_tfTopology = topology.ConvertToTfType());
  69. _tfEnabled = true;
  70. }
  71. public void ClearBuffer(BufferHandle destination, int offset, int size, uint value)
  72. {
  73. Buffer.Clear(destination, offset, size, value);
  74. }
  75. public void ClearRenderTargetColor(int index, uint componentMask, ColorF color)
  76. {
  77. GL.ColorMask(
  78. index,
  79. (componentMask & 1) != 0,
  80. (componentMask & 2) != 0,
  81. (componentMask & 4) != 0,
  82. (componentMask & 8) != 0);
  83. float[] colors = new float[] { color.Red, color.Green, color.Blue, color.Alpha };
  84. GL.ClearBuffer(OpenTK.Graphics.OpenGL.ClearBuffer.Color, index, colors);
  85. RestoreComponentMask(index);
  86. }
  87. public void ClearRenderTargetDepthStencil(float depthValue, bool depthMask, int stencilValue, int stencilMask)
  88. {
  89. bool stencilMaskChanged =
  90. stencilMask != 0 &&
  91. stencilMask != _stencilFrontMask;
  92. bool depthMaskChanged = depthMask && depthMask != _depthMask;
  93. if (stencilMaskChanged)
  94. {
  95. GL.StencilMaskSeparate(StencilFace.Front, stencilMask);
  96. }
  97. if (depthMaskChanged)
  98. {
  99. GL.DepthMask(depthMask);
  100. }
  101. if (depthMask && stencilMask != 0)
  102. {
  103. GL.ClearBuffer(ClearBufferCombined.DepthStencil, 0, depthValue, stencilValue);
  104. }
  105. else if (depthMask)
  106. {
  107. GL.ClearBuffer(OpenTK.Graphics.OpenGL.ClearBuffer.Depth, 0, ref depthValue);
  108. }
  109. else if (stencilMask != 0)
  110. {
  111. GL.ClearBuffer(OpenTK.Graphics.OpenGL.ClearBuffer.Stencil, 0, ref stencilValue);
  112. }
  113. if (stencilMaskChanged)
  114. {
  115. GL.StencilMaskSeparate(StencilFace.Front, _stencilFrontMask);
  116. }
  117. if (depthMaskChanged)
  118. {
  119. GL.DepthMask(_depthMask);
  120. }
  121. }
  122. public void CopyBuffer(BufferHandle source, BufferHandle destination, int srcOffset, int dstOffset, int size)
  123. {
  124. Buffer.Copy(source, destination, srcOffset, dstOffset, size);
  125. }
  126. public void DispatchCompute(int groupsX, int groupsY, int groupsZ)
  127. {
  128. if (!_program.IsLinked)
  129. {
  130. Logger.Debug?.Print(LogClass.Gpu, "Dispatch error, shader not linked.");
  131. return;
  132. }
  133. PrepareForDispatch();
  134. GL.DispatchCompute(groupsX, groupsY, groupsZ);
  135. }
  136. public void Draw(int vertexCount, int instanceCount, int firstVertex, int firstInstance)
  137. {
  138. if (!_program.IsLinked)
  139. {
  140. Logger.Debug?.Print(LogClass.Gpu, "Draw error, shader not linked.");
  141. return;
  142. }
  143. PreDraw();
  144. if (_primitiveType == PrimitiveType.Quads && !HwCapabilities.SupportsQuads)
  145. {
  146. DrawQuadsImpl(vertexCount, instanceCount, firstVertex, firstInstance);
  147. }
  148. else if (_primitiveType == PrimitiveType.QuadStrip && !HwCapabilities.SupportsQuads)
  149. {
  150. DrawQuadStripImpl(vertexCount, instanceCount, firstVertex, firstInstance);
  151. }
  152. else
  153. {
  154. DrawImpl(vertexCount, instanceCount, firstVertex, firstInstance);
  155. }
  156. PostDraw();
  157. }
  158. private void DrawQuadsImpl(
  159. int vertexCount,
  160. int instanceCount,
  161. int firstVertex,
  162. int firstInstance)
  163. {
  164. // TODO: Instanced rendering.
  165. int quadsCount = vertexCount / 4;
  166. int[] firsts = new int[quadsCount];
  167. int[] counts = new int[quadsCount];
  168. for (int quadIndex = 0; quadIndex < quadsCount; quadIndex++)
  169. {
  170. firsts[quadIndex] = firstVertex + quadIndex * 4;
  171. counts[quadIndex] = 4;
  172. }
  173. GL.MultiDrawArrays(
  174. PrimitiveType.TriangleFan,
  175. firsts,
  176. counts,
  177. quadsCount);
  178. }
  179. private void DrawQuadStripImpl(
  180. int vertexCount,
  181. int instanceCount,
  182. int firstVertex,
  183. int firstInstance)
  184. {
  185. int quadsCount = (vertexCount - 2) / 2;
  186. if (firstInstance != 0 || instanceCount != 1)
  187. {
  188. for (int quadIndex = 0; quadIndex < quadsCount; quadIndex++)
  189. {
  190. GL.DrawArraysInstancedBaseInstance(PrimitiveType.TriangleFan, firstVertex + quadIndex * 2, 4, instanceCount, firstInstance);
  191. }
  192. }
  193. else
  194. {
  195. int[] firsts = new int[quadsCount];
  196. int[] counts = new int[quadsCount];
  197. firsts[0] = firstVertex;
  198. counts[0] = 4;
  199. for (int quadIndex = 1; quadIndex < quadsCount; quadIndex++)
  200. {
  201. firsts[quadIndex] = firstVertex + quadIndex * 2;
  202. counts[quadIndex] = 4;
  203. }
  204. GL.MultiDrawArrays(
  205. PrimitiveType.TriangleFan,
  206. firsts,
  207. counts,
  208. quadsCount);
  209. }
  210. }
  211. private void DrawImpl(
  212. int vertexCount,
  213. int instanceCount,
  214. int firstVertex,
  215. int firstInstance)
  216. {
  217. if (firstInstance == 0 && instanceCount == 1)
  218. {
  219. GL.DrawArrays(_primitiveType, firstVertex, vertexCount);
  220. }
  221. else if (firstInstance == 0)
  222. {
  223. GL.DrawArraysInstanced(_primitiveType, firstVertex, vertexCount, instanceCount);
  224. }
  225. else
  226. {
  227. GL.DrawArraysInstancedBaseInstance(
  228. _primitiveType,
  229. firstVertex,
  230. vertexCount,
  231. instanceCount,
  232. firstInstance);
  233. }
  234. }
  235. public void DrawIndexed(
  236. int indexCount,
  237. int instanceCount,
  238. int firstIndex,
  239. int firstVertex,
  240. int firstInstance)
  241. {
  242. if (!_program.IsLinked)
  243. {
  244. Logger.Debug?.Print(LogClass.Gpu, "Draw error, shader not linked.");
  245. return;
  246. }
  247. PreDraw();
  248. int indexElemSize = 1;
  249. switch (_elementsType)
  250. {
  251. case DrawElementsType.UnsignedShort: indexElemSize = 2; break;
  252. case DrawElementsType.UnsignedInt: indexElemSize = 4; break;
  253. }
  254. IntPtr indexBaseOffset = _indexBaseOffset + firstIndex * indexElemSize;
  255. if (_primitiveType == PrimitiveType.Quads && !HwCapabilities.SupportsQuads)
  256. {
  257. DrawQuadsIndexedImpl(
  258. indexCount,
  259. instanceCount,
  260. indexBaseOffset,
  261. indexElemSize,
  262. firstVertex,
  263. firstInstance);
  264. }
  265. else if (_primitiveType == PrimitiveType.QuadStrip && !HwCapabilities.SupportsQuads)
  266. {
  267. DrawQuadStripIndexedImpl(
  268. indexCount,
  269. instanceCount,
  270. indexBaseOffset,
  271. indexElemSize,
  272. firstVertex,
  273. firstInstance);
  274. }
  275. else
  276. {
  277. DrawIndexedImpl(
  278. indexCount,
  279. instanceCount,
  280. indexBaseOffset,
  281. firstVertex,
  282. firstInstance);
  283. }
  284. PostDraw();
  285. }
  286. private void DrawQuadsIndexedImpl(
  287. int indexCount,
  288. int instanceCount,
  289. IntPtr indexBaseOffset,
  290. int indexElemSize,
  291. int firstVertex,
  292. int firstInstance)
  293. {
  294. int quadsCount = indexCount / 4;
  295. if (firstInstance != 0 || instanceCount != 1)
  296. {
  297. if (firstVertex != 0 && firstInstance != 0)
  298. {
  299. for (int quadIndex = 0; quadIndex < quadsCount; quadIndex++)
  300. {
  301. GL.DrawElementsInstancedBaseVertexBaseInstance(
  302. PrimitiveType.TriangleFan,
  303. 4,
  304. _elementsType,
  305. indexBaseOffset + quadIndex * 4 * indexElemSize,
  306. instanceCount,
  307. firstVertex,
  308. firstInstance);
  309. }
  310. }
  311. else if (firstInstance != 0)
  312. {
  313. for (int quadIndex = 0; quadIndex < quadsCount; quadIndex++)
  314. {
  315. GL.DrawElementsInstancedBaseInstance(
  316. PrimitiveType.TriangleFan,
  317. 4,
  318. _elementsType,
  319. indexBaseOffset + quadIndex * 4 * indexElemSize,
  320. instanceCount,
  321. firstInstance);
  322. }
  323. }
  324. else
  325. {
  326. for (int quadIndex = 0; quadIndex < quadsCount; quadIndex++)
  327. {
  328. GL.DrawElementsInstanced(
  329. PrimitiveType.TriangleFan,
  330. 4,
  331. _elementsType,
  332. indexBaseOffset + quadIndex * 4 * indexElemSize,
  333. instanceCount);
  334. }
  335. }
  336. }
  337. else
  338. {
  339. IntPtr[] indices = new IntPtr[quadsCount];
  340. int[] counts = new int[quadsCount];
  341. int[] baseVertices = new int[quadsCount];
  342. for (int quadIndex = 0; quadIndex < quadsCount; quadIndex++)
  343. {
  344. indices[quadIndex] = indexBaseOffset + quadIndex * 4 * indexElemSize;
  345. counts[quadIndex] = 4;
  346. baseVertices[quadIndex] = firstVertex;
  347. }
  348. GL.MultiDrawElementsBaseVertex(
  349. PrimitiveType.TriangleFan,
  350. counts,
  351. _elementsType,
  352. indices,
  353. quadsCount,
  354. baseVertices);
  355. }
  356. }
  357. private void DrawQuadStripIndexedImpl(
  358. int indexCount,
  359. int instanceCount,
  360. IntPtr indexBaseOffset,
  361. int indexElemSize,
  362. int firstVertex,
  363. int firstInstance)
  364. {
  365. // TODO: Instanced rendering.
  366. int quadsCount = (indexCount - 2) / 2;
  367. IntPtr[] indices = new IntPtr[quadsCount];
  368. int[] counts = new int[quadsCount];
  369. int[] baseVertices = new int[quadsCount];
  370. indices[0] = indexBaseOffset;
  371. counts[0] = 4;
  372. baseVertices[0] = firstVertex;
  373. for (int quadIndex = 1; quadIndex < quadsCount; quadIndex++)
  374. {
  375. indices[quadIndex] = indexBaseOffset + quadIndex * 2 * indexElemSize;
  376. counts[quadIndex] = 4;
  377. baseVertices[quadIndex] = firstVertex;
  378. }
  379. GL.MultiDrawElementsBaseVertex(
  380. PrimitiveType.TriangleFan,
  381. counts,
  382. _elementsType,
  383. indices,
  384. quadsCount,
  385. baseVertices);
  386. }
  387. private void DrawIndexedImpl(
  388. int indexCount,
  389. int instanceCount,
  390. IntPtr indexBaseOffset,
  391. int firstVertex,
  392. int firstInstance)
  393. {
  394. if (firstInstance == 0 && firstVertex == 0 && instanceCount == 1)
  395. {
  396. GL.DrawElements(_primitiveType, indexCount, _elementsType, indexBaseOffset);
  397. }
  398. else if (firstInstance == 0 && instanceCount == 1)
  399. {
  400. GL.DrawElementsBaseVertex(
  401. _primitiveType,
  402. indexCount,
  403. _elementsType,
  404. indexBaseOffset,
  405. firstVertex);
  406. }
  407. else if (firstInstance == 0 && firstVertex == 0)
  408. {
  409. GL.DrawElementsInstanced(
  410. _primitiveType,
  411. indexCount,
  412. _elementsType,
  413. indexBaseOffset,
  414. instanceCount);
  415. }
  416. else if (firstInstance == 0)
  417. {
  418. GL.DrawElementsInstancedBaseVertex(
  419. _primitiveType,
  420. indexCount,
  421. _elementsType,
  422. indexBaseOffset,
  423. instanceCount,
  424. firstVertex);
  425. }
  426. else if (firstVertex == 0)
  427. {
  428. GL.DrawElementsInstancedBaseInstance(
  429. _primitiveType,
  430. indexCount,
  431. _elementsType,
  432. indexBaseOffset,
  433. instanceCount,
  434. firstInstance);
  435. }
  436. else
  437. {
  438. GL.DrawElementsInstancedBaseVertexBaseInstance(
  439. _primitiveType,
  440. indexCount,
  441. _elementsType,
  442. indexBaseOffset,
  443. instanceCount,
  444. firstVertex,
  445. firstInstance);
  446. }
  447. }
  448. public void EndTransformFeedback()
  449. {
  450. GL.EndTransformFeedback();
  451. _tfEnabled = false;
  452. }
  453. public void SetAlphaTest(bool enable, float reference, CompareOp op)
  454. {
  455. if (!enable)
  456. {
  457. GL.Disable(EnableCap.AlphaTest);
  458. return;
  459. }
  460. GL.AlphaFunc((AlphaFunction)op.Convert(), reference);
  461. GL.Enable(EnableCap.AlphaTest);
  462. }
  463. public void SetBlendState(int index, BlendDescriptor blend)
  464. {
  465. if (!blend.Enable)
  466. {
  467. GL.Disable(IndexedEnableCap.Blend, index);
  468. return;
  469. }
  470. GL.BlendEquationSeparate(
  471. index,
  472. blend.ColorOp.Convert(),
  473. blend.AlphaOp.Convert());
  474. GL.BlendFuncSeparate(
  475. index,
  476. (BlendingFactorSrc)blend.ColorSrcFactor.Convert(),
  477. (BlendingFactorDest)blend.ColorDstFactor.Convert(),
  478. (BlendingFactorSrc)blend.AlphaSrcFactor.Convert(),
  479. (BlendingFactorDest)blend.AlphaDstFactor.Convert());
  480. static bool IsDualSource(BlendFactor factor)
  481. {
  482. switch (factor)
  483. {
  484. case BlendFactor.Src1Color:
  485. case BlendFactor.Src1ColorGl:
  486. case BlendFactor.Src1Alpha:
  487. case BlendFactor.Src1AlphaGl:
  488. case BlendFactor.OneMinusSrc1Color:
  489. case BlendFactor.OneMinusSrc1ColorGl:
  490. case BlendFactor.OneMinusSrc1Alpha:
  491. case BlendFactor.OneMinusSrc1AlphaGl:
  492. return true;
  493. }
  494. return false;
  495. }
  496. EnsureFramebuffer();
  497. _framebuffer.SetDualSourceBlend(
  498. IsDualSource(blend.ColorSrcFactor) ||
  499. IsDualSource(blend.ColorDstFactor) ||
  500. IsDualSource(blend.AlphaSrcFactor) ||
  501. IsDualSource(blend.AlphaDstFactor));
  502. if (_blendConstant != blend.BlendConstant)
  503. {
  504. _blendConstant = blend.BlendConstant;
  505. GL.BlendColor(
  506. blend.BlendConstant.Red,
  507. blend.BlendConstant.Green,
  508. blend.BlendConstant.Blue,
  509. blend.BlendConstant.Alpha);
  510. }
  511. GL.Enable(IndexedEnableCap.Blend, index);
  512. }
  513. public void SetDepthBias(PolygonModeMask enables, float factor, float units, float clamp)
  514. {
  515. if ((enables & PolygonModeMask.Point) != 0)
  516. {
  517. GL.Enable(EnableCap.PolygonOffsetPoint);
  518. }
  519. else
  520. {
  521. GL.Disable(EnableCap.PolygonOffsetPoint);
  522. }
  523. if ((enables & PolygonModeMask.Line) != 0)
  524. {
  525. GL.Enable(EnableCap.PolygonOffsetLine);
  526. }
  527. else
  528. {
  529. GL.Disable(EnableCap.PolygonOffsetLine);
  530. }
  531. if ((enables & PolygonModeMask.Fill) != 0)
  532. {
  533. GL.Enable(EnableCap.PolygonOffsetFill);
  534. }
  535. else
  536. {
  537. GL.Disable(EnableCap.PolygonOffsetFill);
  538. }
  539. if (enables == 0)
  540. {
  541. return;
  542. }
  543. if (HwCapabilities.SupportsPolygonOffsetClamp)
  544. {
  545. GL.PolygonOffsetClamp(factor, units, clamp);
  546. }
  547. else
  548. {
  549. GL.PolygonOffset(factor, units);
  550. }
  551. }
  552. public void SetDepthClamp(bool clamp)
  553. {
  554. if (!clamp)
  555. {
  556. GL.Disable(EnableCap.DepthClamp);
  557. return;
  558. }
  559. GL.Enable(EnableCap.DepthClamp);
  560. }
  561. public void SetDepthMode(DepthMode mode)
  562. {
  563. ClipDepthMode depthMode = mode.Convert();
  564. if (_clipDepthMode != depthMode)
  565. {
  566. _clipDepthMode = depthMode;
  567. GL.ClipControl(_clipOrigin, depthMode);
  568. }
  569. }
  570. public void SetDepthTest(DepthTestDescriptor depthTest)
  571. {
  572. if (depthTest.TestEnable)
  573. {
  574. GL.Enable(EnableCap.DepthTest);
  575. GL.DepthFunc((DepthFunction)depthTest.Func.Convert());
  576. }
  577. else
  578. {
  579. GL.Disable(EnableCap.DepthTest);
  580. }
  581. GL.DepthMask(depthTest.WriteEnable);
  582. _depthMask = depthTest.WriteEnable;
  583. }
  584. public void SetFaceCulling(bool enable, Face face)
  585. {
  586. if (!enable)
  587. {
  588. GL.Disable(EnableCap.CullFace);
  589. return;
  590. }
  591. GL.CullFace(face.Convert());
  592. GL.Enable(EnableCap.CullFace);
  593. }
  594. public void SetFrontFace(FrontFace frontFace)
  595. {
  596. SetFrontFace(_frontFace = frontFace.Convert());
  597. }
  598. public void SetImage(int binding, ITexture texture, Format imageFormat)
  599. {
  600. if (texture == null)
  601. {
  602. return;
  603. }
  604. TextureBase texBase = (TextureBase)texture;
  605. SizedInternalFormat format = FormatTable.GetImageFormat(imageFormat);
  606. if (format != 0)
  607. {
  608. GL.BindImageTexture(binding, texBase.Handle, 0, true, 0, TextureAccess.ReadWrite, format);
  609. }
  610. }
  611. public void SetIndexBuffer(BufferRange buffer, IndexType type)
  612. {
  613. _elementsType = type.Convert();
  614. _indexBaseOffset = (IntPtr)buffer.Offset;
  615. EnsureVertexArray();
  616. _vertexArray.SetIndexBuffer(buffer.Handle);
  617. }
  618. public void SetLogicOpState(bool enable, LogicalOp op)
  619. {
  620. if (enable)
  621. {
  622. GL.Enable(EnableCap.ColorLogicOp);
  623. GL.LogicOp((LogicOp)op.Convert());
  624. }
  625. else
  626. {
  627. GL.Disable(EnableCap.ColorLogicOp);
  628. }
  629. }
  630. public void SetLineParameters(float width, bool smooth)
  631. {
  632. if (smooth)
  633. {
  634. GL.Enable(EnableCap.LineSmooth);
  635. }
  636. else
  637. {
  638. GL.Disable(EnableCap.LineSmooth);
  639. }
  640. GL.LineWidth(width);
  641. }
  642. public void SetPointParameters(float size, bool isProgramPointSize, bool enablePointSprite, Origin origin)
  643. {
  644. // GL_POINT_SPRITE was deprecated in core profile 3.2+ and causes GL_INVALID_ENUM when set.
  645. // As we don't know if the current context is core or compat, it's safer to keep this code.
  646. if (enablePointSprite)
  647. {
  648. GL.Enable(EnableCap.PointSprite);
  649. }
  650. else
  651. {
  652. GL.Disable(EnableCap.PointSprite);
  653. }
  654. if (isProgramPointSize)
  655. {
  656. GL.Enable(EnableCap.ProgramPointSize);
  657. }
  658. else
  659. {
  660. GL.Disable(EnableCap.ProgramPointSize);
  661. }
  662. GL.PointParameter(origin == Origin.LowerLeft
  663. ? PointSpriteCoordOriginParameter.LowerLeft
  664. : PointSpriteCoordOriginParameter.UpperLeft);
  665. // Games seem to set point size to 0 which generates a GL_INVALID_VALUE
  666. // From the spec, GL_INVALID_VALUE is generated if size is less than or equal to 0.
  667. GL.PointSize(Math.Max(float.Epsilon, size));
  668. }
  669. public void SetPrimitiveRestart(bool enable, int index)
  670. {
  671. if (!enable)
  672. {
  673. GL.Disable(EnableCap.PrimitiveRestart);
  674. return;
  675. }
  676. GL.PrimitiveRestartIndex(index);
  677. GL.Enable(EnableCap.PrimitiveRestart);
  678. }
  679. public void SetPrimitiveTopology(PrimitiveTopology topology)
  680. {
  681. _primitiveType = topology.Convert();
  682. }
  683. public void SetProgram(IProgram program)
  684. {
  685. _program = (Program)program;
  686. if (_tfEnabled)
  687. {
  688. GL.EndTransformFeedback();
  689. _program.Bind();
  690. GL.BeginTransformFeedback(_tfTopology);
  691. }
  692. else
  693. {
  694. _program.Bind();
  695. }
  696. }
  697. public void SetRasterizerDiscard(bool discard)
  698. {
  699. if (discard)
  700. {
  701. GL.Enable(EnableCap.RasterizerDiscard);
  702. }
  703. else
  704. {
  705. GL.Disable(EnableCap.RasterizerDiscard);
  706. }
  707. _rasterizerDiscard = discard;
  708. }
  709. public void SetRenderTargetScale(float scale)
  710. {
  711. _renderScale[0].X = scale;
  712. SetSupportBufferData<Vector4<float>>(SupportBuffer.FragmentRenderScaleOffset, _renderScale, 1); // Just the first element.
  713. }
  714. public void SetRenderTargetColorMasks(ReadOnlySpan<uint> componentMasks)
  715. {
  716. for (int index = 0; index < componentMasks.Length; index++)
  717. {
  718. _componentMasks[index] = componentMasks[index];
  719. RestoreComponentMask(index);
  720. }
  721. }
  722. public void SetRenderTargets(ITexture[] colors, ITexture depthStencil)
  723. {
  724. EnsureFramebuffer();
  725. bool isBgraChanged = false;
  726. for (int index = 0; index < colors.Length; index++)
  727. {
  728. TextureView color = (TextureView)colors[index];
  729. _framebuffer.AttachColor(index, color);
  730. int isBgra = color != null && color.Format.IsBgra8() ? 1 : 0;
  731. if (_fpIsBgra[index].X != isBgra)
  732. {
  733. _fpIsBgra[index].X = isBgra;
  734. isBgraChanged = true;
  735. RestoreComponentMask(index);
  736. }
  737. }
  738. if (isBgraChanged)
  739. {
  740. SetSupportBufferData<Vector4<int>>(SupportBuffer.FragmentIsBgraOffset, _fpIsBgra, SupportBuffer.FragmentIsBgraCount);
  741. }
  742. TextureView depthStencilView = (TextureView)depthStencil;
  743. _framebuffer.AttachDepthStencil(depthStencilView);
  744. _framebuffer.SetDrawBuffers(colors.Length);
  745. }
  746. public void SetSampler(int binding, ISampler sampler)
  747. {
  748. if (sampler == null)
  749. {
  750. return;
  751. }
  752. ((Sampler)sampler).Bind(binding);
  753. }
  754. public void SetScissor(int index, bool enable, int x, int y, int width, int height)
  755. {
  756. uint mask = 1u << index;
  757. if (!enable)
  758. {
  759. if ((_scissorEnables & mask) != 0)
  760. {
  761. _scissorEnables &= ~mask;
  762. GL.Disable(IndexedEnableCap.ScissorTest, index);
  763. }
  764. return;
  765. }
  766. if ((_scissorEnables & mask) == 0)
  767. {
  768. _scissorEnables |= mask;
  769. GL.Enable(IndexedEnableCap.ScissorTest, index);
  770. }
  771. GL.ScissorIndexed(index, x, y, width, height);
  772. }
  773. public void SetStencilTest(StencilTestDescriptor stencilTest)
  774. {
  775. if (!stencilTest.TestEnable)
  776. {
  777. GL.Disable(EnableCap.StencilTest);
  778. return;
  779. }
  780. GL.StencilOpSeparate(
  781. StencilFace.Front,
  782. stencilTest.FrontSFail.Convert(),
  783. stencilTest.FrontDpFail.Convert(),
  784. stencilTest.FrontDpPass.Convert());
  785. GL.StencilFuncSeparate(
  786. StencilFace.Front,
  787. (StencilFunction)stencilTest.FrontFunc.Convert(),
  788. stencilTest.FrontFuncRef,
  789. stencilTest.FrontFuncMask);
  790. GL.StencilMaskSeparate(StencilFace.Front, stencilTest.FrontMask);
  791. GL.StencilOpSeparate(
  792. StencilFace.Back,
  793. stencilTest.BackSFail.Convert(),
  794. stencilTest.BackDpFail.Convert(),
  795. stencilTest.BackDpPass.Convert());
  796. GL.StencilFuncSeparate(
  797. StencilFace.Back,
  798. (StencilFunction)stencilTest.BackFunc.Convert(),
  799. stencilTest.BackFuncRef,
  800. stencilTest.BackFuncMask);
  801. GL.StencilMaskSeparate(StencilFace.Back, stencilTest.BackMask);
  802. GL.Enable(EnableCap.StencilTest);
  803. _stencilFrontMask = stencilTest.FrontMask;
  804. }
  805. public void SetStorageBuffers(int first, ReadOnlySpan<BufferRange> buffers)
  806. {
  807. SetBuffers(first, buffers, isStorage: true);
  808. }
  809. public void SetTexture(int binding, ITexture texture)
  810. {
  811. if (texture == null)
  812. {
  813. return;
  814. }
  815. if (binding == 0)
  816. {
  817. _unit0Texture = (TextureBase)texture;
  818. }
  819. else
  820. {
  821. ((TextureBase)texture).Bind(binding);
  822. }
  823. }
  824. public void SetTransformFeedbackBuffers(ReadOnlySpan<BufferRange> buffers)
  825. {
  826. if (_tfEnabled)
  827. {
  828. GL.EndTransformFeedback();
  829. }
  830. int count = Math.Min(buffers.Length, Constants.MaxTransformFeedbackBuffers);
  831. for (int i = 0; i < count; i++)
  832. {
  833. BufferRange buffer = buffers[i];
  834. _tfbTargets[i] = buffer;
  835. if (buffer.Handle == BufferHandle.Null)
  836. {
  837. GL.BindBufferBase(BufferRangeTarget.TransformFeedbackBuffer, i, 0);
  838. continue;
  839. }
  840. if (_tfbs[i] == BufferHandle.Null)
  841. {
  842. _tfbs[i] = Buffer.Create();
  843. }
  844. Buffer.Resize(_tfbs[i], buffer.Size);
  845. Buffer.Copy(buffer.Handle, _tfbs[i], buffer.Offset, 0, buffer.Size);
  846. GL.BindBufferBase(BufferRangeTarget.TransformFeedbackBuffer, i, _tfbs[i].ToInt32());
  847. }
  848. if (_tfEnabled)
  849. {
  850. GL.BeginTransformFeedback(_tfTopology);
  851. }
  852. }
  853. public void SetUniformBuffers(int first, ReadOnlySpan<BufferRange> buffers)
  854. {
  855. SetBuffers(first, buffers, isStorage: false);
  856. }
  857. public void SetUserClipDistance(int index, bool enableClip)
  858. {
  859. if (!enableClip)
  860. {
  861. GL.Disable(EnableCap.ClipDistance0 + index);
  862. return;
  863. }
  864. GL.Enable(EnableCap.ClipDistance0 + index);
  865. }
  866. public void SetVertexAttribs(ReadOnlySpan<VertexAttribDescriptor> vertexAttribs)
  867. {
  868. EnsureVertexArray();
  869. _vertexArray.SetVertexAttributes(vertexAttribs);
  870. }
  871. public void SetVertexBuffers(ReadOnlySpan<VertexBufferDescriptor> vertexBuffers)
  872. {
  873. EnsureVertexArray();
  874. _vertexArray.SetVertexBuffers(vertexBuffers);
  875. }
  876. public void SetViewports(int first, ReadOnlySpan<Viewport> viewports)
  877. {
  878. float[] viewportArray = new float[viewports.Length * 4];
  879. double[] depthRangeArray = new double[viewports.Length * 2];
  880. for (int index = 0; index < viewports.Length; index++)
  881. {
  882. int viewportElemIndex = index * 4;
  883. Viewport viewport = viewports[index];
  884. viewportArray[viewportElemIndex + 0] = viewport.Region.X;
  885. viewportArray[viewportElemIndex + 1] = viewport.Region.Y + (viewport.Region.Height < 0 ? viewport.Region.Height : 0);
  886. viewportArray[viewportElemIndex + 2] = viewport.Region.Width;
  887. viewportArray[viewportElemIndex + 3] = MathF.Abs(viewport.Region.Height);
  888. if (HwCapabilities.SupportsViewportSwizzle)
  889. {
  890. GL.NV.ViewportSwizzle(
  891. index,
  892. viewport.SwizzleX.Convert(),
  893. viewport.SwizzleY.Convert(),
  894. viewport.SwizzleZ.Convert(),
  895. viewport.SwizzleW.Convert());
  896. }
  897. depthRangeArray[index * 2 + 0] = viewport.DepthNear;
  898. depthRangeArray[index * 2 + 1] = viewport.DepthFar;
  899. }
  900. bool flipY = viewports.Length != 0 && viewports[0].Region.Height < 0;
  901. SetOrigin(flipY ? ClipOrigin.UpperLeft : ClipOrigin.LowerLeft);
  902. GL.ViewportArray(first, viewports.Length, viewportArray);
  903. GL.DepthRangeArray(first, viewports.Length, depthRangeArray);
  904. }
  905. public void TextureBarrier()
  906. {
  907. GL.MemoryBarrier(MemoryBarrierFlags.TextureFetchBarrierBit);
  908. }
  909. public void TextureBarrierTiled()
  910. {
  911. GL.MemoryBarrier(MemoryBarrierFlags.TextureFetchBarrierBit);
  912. }
  913. private void SetBuffers(int first, ReadOnlySpan<BufferRange> buffers, bool isStorage)
  914. {
  915. BufferRangeTarget target = isStorage ? BufferRangeTarget.ShaderStorageBuffer : BufferRangeTarget.UniformBuffer;
  916. for (int index = 0; index < buffers.Length; index++)
  917. {
  918. BufferRange buffer = buffers[index];
  919. if (buffer.Handle == BufferHandle.Null)
  920. {
  921. GL.BindBufferRange(target, first + index, 0, IntPtr.Zero, 0);
  922. continue;
  923. }
  924. GL.BindBufferRange(target, first + index, buffer.Handle.ToInt32(), (IntPtr)buffer.Offset, buffer.Size);
  925. }
  926. }
  927. private void SetOrigin(ClipOrigin origin)
  928. {
  929. if (_clipOrigin != origin)
  930. {
  931. _clipOrigin = origin;
  932. GL.ClipControl(origin, _clipDepthMode);
  933. SetFrontFace(_frontFace);
  934. }
  935. }
  936. private void SetFrontFace(FrontFaceDirection frontFace)
  937. {
  938. // Changing clip origin will also change the front face to compensate
  939. // for the flipped viewport, we flip it again here to compensate as
  940. // this effect is undesirable for us.
  941. if (_clipOrigin == ClipOrigin.UpperLeft)
  942. {
  943. frontFace = frontFace == FrontFaceDirection.Ccw ? FrontFaceDirection.Cw : FrontFaceDirection.Ccw;
  944. }
  945. GL.FrontFace(frontFace);
  946. }
  947. private void EnsureVertexArray()
  948. {
  949. if (_vertexArray == null)
  950. {
  951. _vertexArray = new VertexArray();
  952. _vertexArray.Bind();
  953. }
  954. }
  955. private void EnsureFramebuffer()
  956. {
  957. if (_framebuffer == null)
  958. {
  959. _framebuffer = new Framebuffer();
  960. int boundHandle = _framebuffer.Bind();
  961. _boundDrawFramebuffer = _boundReadFramebuffer = boundHandle;
  962. GL.Enable(EnableCap.FramebufferSrgb);
  963. }
  964. }
  965. internal (int drawHandle, int readHandle) GetBoundFramebuffers()
  966. {
  967. if (BackgroundContextWorker.InBackground)
  968. {
  969. return (0, 0);
  970. }
  971. return (_boundDrawFramebuffer, _boundReadFramebuffer);
  972. }
  973. public void UpdateRenderScale(ShaderStage stage, float[] scales, int textureCount, int imageCount)
  974. {
  975. if (stage != ShaderStage.Compute && stage != ShaderStage.Fragment)
  976. {
  977. return;
  978. }
  979. bool changed = false;
  980. for (int index = 0; index < textureCount + imageCount; index++)
  981. {
  982. if (_renderScale[1 + index].X != scales[index])
  983. {
  984. _renderScale[1 + index].X = scales[index];
  985. changed = true;
  986. }
  987. }
  988. if (changed)
  989. {
  990. SetSupportBufferData<Vector4<float>>(SupportBuffer.FragmentRenderScaleOffset, _renderScale, 1 + textureCount + imageCount);
  991. }
  992. }
  993. private void SetSupportBufferData<T>(int offset, ReadOnlySpan<T> data, int count) where T : unmanaged
  994. {
  995. if (_supportBuffer == BufferHandle.Null)
  996. {
  997. _supportBuffer = Buffer.Create(SupportBuffer.RequiredSize);
  998. GL.BindBufferBase(BufferRangeTarget.UniformBuffer, 0, Unsafe.As<BufferHandle, int>(ref _supportBuffer));
  999. }
  1000. Buffer.SetData(_supportBuffer, offset, MemoryMarshal.Cast<T, byte>(data.Slice(0, count)));
  1001. }
  1002. private void PrepareForDispatch()
  1003. {
  1004. if (_unit0Texture != null)
  1005. {
  1006. _unit0Texture.Bind(0);
  1007. }
  1008. }
  1009. private void PreDraw()
  1010. {
  1011. DrawCount++;
  1012. _vertexArray.Validate();
  1013. if (_unit0Texture != null)
  1014. {
  1015. _unit0Texture.Bind(0);
  1016. }
  1017. }
  1018. private void PostDraw()
  1019. {
  1020. if (_tfEnabled)
  1021. {
  1022. for (int i = 0; i < Constants.MaxTransformFeedbackBuffers; i++)
  1023. {
  1024. if (_tfbTargets[i].Handle != BufferHandle.Null)
  1025. {
  1026. Buffer.Copy(_tfbs[i], _tfbTargets[i].Handle, 0, _tfbTargets[i].Offset, _tfbTargets[i].Size);
  1027. }
  1028. }
  1029. }
  1030. }
  1031. public void RestoreComponentMask(int index)
  1032. {
  1033. // If the bound render target is bgra, swap the red and blue masks.
  1034. uint redMask = _fpIsBgra[index].X == 0 ? 1u : 4u;
  1035. uint blueMask = _fpIsBgra[index].X == 0 ? 4u : 1u;
  1036. GL.ColorMask(
  1037. index,
  1038. (_componentMasks[index] & redMask) != 0,
  1039. (_componentMasks[index] & 2u) != 0,
  1040. (_componentMasks[index] & blueMask) != 0,
  1041. (_componentMasks[index] & 8u) != 0);
  1042. }
  1043. public void RestoreScissor0Enable()
  1044. {
  1045. if ((_scissorEnables & 1u) != 0)
  1046. {
  1047. GL.Enable(IndexedEnableCap.ScissorTest, 0);
  1048. }
  1049. }
  1050. public void RestoreRasterizerDiscard()
  1051. {
  1052. if (_rasterizerDiscard)
  1053. {
  1054. GL.Enable(EnableCap.RasterizerDiscard);
  1055. }
  1056. }
  1057. public bool TryHostConditionalRendering(ICounterEvent value, ulong compare, bool isEqual)
  1058. {
  1059. if (value is CounterQueueEvent)
  1060. {
  1061. // Compare an event and a constant value.
  1062. CounterQueueEvent evt = (CounterQueueEvent)value;
  1063. // Easy host conditional rendering when the check matches what GL can do:
  1064. // - Event is of type samples passed.
  1065. // - Result is not a combination of multiple queries.
  1066. // - Comparing against 0.
  1067. // - Event has not already been flushed.
  1068. if (evt.Disposed)
  1069. {
  1070. // If the event has been flushed, then just use the values on the CPU.
  1071. // The query object may already be repurposed for another draw (eg. begin + end).
  1072. return false;
  1073. }
  1074. if (compare == 0 && evt.Type == QueryTarget.SamplesPassed && evt.ClearCounter)
  1075. {
  1076. GL.BeginConditionalRender(evt.Query, isEqual ? ConditionalRenderType.QueryNoWaitInverted : ConditionalRenderType.QueryNoWait);
  1077. return true;
  1078. }
  1079. }
  1080. // The GPU will flush the queries to CPU and evaluate the condition there instead.
  1081. GL.Flush(); // The thread will be stalled manually flushing the counter, so flush GL commands now.
  1082. return false;
  1083. }
  1084. public bool TryHostConditionalRendering(ICounterEvent value, ICounterEvent compare, bool isEqual)
  1085. {
  1086. GL.Flush(); // The GPU thread will be stalled manually flushing the counter, so flush GL commands now.
  1087. return false; // We don't currently have a way to compare two counters for conditional rendering.
  1088. }
  1089. public void EndHostConditionalRendering()
  1090. {
  1091. GL.EndConditionalRender();
  1092. }
  1093. public void Dispose()
  1094. {
  1095. if (_supportBuffer != BufferHandle.Null)
  1096. {
  1097. Buffer.Delete(_supportBuffer);
  1098. _supportBuffer = BufferHandle.Null;
  1099. }
  1100. for (int i = 0; i < Constants.MaxTransformFeedbackBuffers; i++)
  1101. {
  1102. if (_tfbs[i] != BufferHandle.Null)
  1103. {
  1104. Buffer.Delete(_tfbs[i]);
  1105. _tfbs[i] = BufferHandle.Null;
  1106. }
  1107. }
  1108. _framebuffer?.Dispose();
  1109. _vertexArray?.Dispose();
  1110. }
  1111. }
  1112. }