OglPipeline.cs 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833
  1. using OpenTK.Graphics.OpenGL;
  2. using Ryujinx.Graphics.Shader;
  3. using System;
  4. using System.Collections.Generic;
  5. namespace Ryujinx.Graphics.Gal.OpenGL
  6. {
  7. class OglPipeline : IGalPipeline
  8. {
  9. private static Dictionary<GalVertexAttribSize, int> _attribElements =
  10. new Dictionary<GalVertexAttribSize, int>()
  11. {
  12. { GalVertexAttribSize._32_32_32_32, 4 },
  13. { GalVertexAttribSize._32_32_32, 3 },
  14. { GalVertexAttribSize._16_16_16_16, 4 },
  15. { GalVertexAttribSize._32_32, 2 },
  16. { GalVertexAttribSize._16_16_16, 3 },
  17. { GalVertexAttribSize._8_8_8_8, 4 },
  18. { GalVertexAttribSize._16_16, 2 },
  19. { GalVertexAttribSize._32, 1 },
  20. { GalVertexAttribSize._8_8_8, 3 },
  21. { GalVertexAttribSize._8_8, 2 },
  22. { GalVertexAttribSize._16, 1 },
  23. { GalVertexAttribSize._8, 1 },
  24. { GalVertexAttribSize._10_10_10_2, 4 },
  25. { GalVertexAttribSize._11_11_10, 3 }
  26. };
  27. private static Dictionary<GalVertexAttribSize, VertexAttribPointerType> _floatAttribTypes =
  28. new Dictionary<GalVertexAttribSize, VertexAttribPointerType>()
  29. {
  30. { GalVertexAttribSize._32_32_32_32, VertexAttribPointerType.Float },
  31. { GalVertexAttribSize._32_32_32, VertexAttribPointerType.Float },
  32. { GalVertexAttribSize._16_16_16_16, VertexAttribPointerType.HalfFloat },
  33. { GalVertexAttribSize._32_32, VertexAttribPointerType.Float },
  34. { GalVertexAttribSize._16_16_16, VertexAttribPointerType.HalfFloat },
  35. { GalVertexAttribSize._16_16, VertexAttribPointerType.HalfFloat },
  36. { GalVertexAttribSize._32, VertexAttribPointerType.Float },
  37. { GalVertexAttribSize._16, VertexAttribPointerType.HalfFloat }
  38. };
  39. private static Dictionary<GalVertexAttribSize, VertexAttribPointerType> _signedAttribTypes =
  40. new Dictionary<GalVertexAttribSize, VertexAttribPointerType>()
  41. {
  42. { GalVertexAttribSize._32_32_32_32, VertexAttribPointerType.Int },
  43. { GalVertexAttribSize._32_32_32, VertexAttribPointerType.Int },
  44. { GalVertexAttribSize._16_16_16_16, VertexAttribPointerType.Short },
  45. { GalVertexAttribSize._32_32, VertexAttribPointerType.Int },
  46. { GalVertexAttribSize._16_16_16, VertexAttribPointerType.Short },
  47. { GalVertexAttribSize._8_8_8_8, VertexAttribPointerType.Byte },
  48. { GalVertexAttribSize._16_16, VertexAttribPointerType.Short },
  49. { GalVertexAttribSize._32, VertexAttribPointerType.Int },
  50. { GalVertexAttribSize._8_8_8, VertexAttribPointerType.Byte },
  51. { GalVertexAttribSize._8_8, VertexAttribPointerType.Byte },
  52. { GalVertexAttribSize._16, VertexAttribPointerType.Short },
  53. { GalVertexAttribSize._8, VertexAttribPointerType.Byte },
  54. { GalVertexAttribSize._10_10_10_2, VertexAttribPointerType.Int2101010Rev }
  55. };
  56. private static Dictionary<GalVertexAttribSize, VertexAttribPointerType> _unsignedAttribTypes =
  57. new Dictionary<GalVertexAttribSize, VertexAttribPointerType>()
  58. {
  59. { GalVertexAttribSize._32_32_32_32, VertexAttribPointerType.UnsignedInt },
  60. { GalVertexAttribSize._32_32_32, VertexAttribPointerType.UnsignedInt },
  61. { GalVertexAttribSize._16_16_16_16, VertexAttribPointerType.UnsignedShort },
  62. { GalVertexAttribSize._32_32, VertexAttribPointerType.UnsignedInt },
  63. { GalVertexAttribSize._16_16_16, VertexAttribPointerType.UnsignedShort },
  64. { GalVertexAttribSize._8_8_8_8, VertexAttribPointerType.UnsignedByte },
  65. { GalVertexAttribSize._16_16, VertexAttribPointerType.UnsignedShort },
  66. { GalVertexAttribSize._32, VertexAttribPointerType.UnsignedInt },
  67. { GalVertexAttribSize._8_8_8, VertexAttribPointerType.UnsignedByte },
  68. { GalVertexAttribSize._8_8, VertexAttribPointerType.UnsignedByte },
  69. { GalVertexAttribSize._16, VertexAttribPointerType.UnsignedShort },
  70. { GalVertexAttribSize._8, VertexAttribPointerType.UnsignedByte },
  71. { GalVertexAttribSize._10_10_10_2, VertexAttribPointerType.UnsignedInt2101010Rev },
  72. { GalVertexAttribSize._11_11_10, VertexAttribPointerType.UnsignedInt10F11F11FRev }
  73. };
  74. private GalPipelineState _old;
  75. private OglConstBuffer _buffer;
  76. private OglRenderTarget _renderTarget;
  77. private OglRasterizer _rasterizer;
  78. private OglShader _shader;
  79. private int _vaoHandle;
  80. public OglPipeline(
  81. OglConstBuffer buffer,
  82. OglRenderTarget renderTarget,
  83. OglRasterizer rasterizer,
  84. OglShader shader)
  85. {
  86. _buffer = buffer;
  87. _renderTarget = renderTarget;
  88. _rasterizer = rasterizer;
  89. _shader = shader;
  90. // These values match OpenGL's defaults
  91. _old = new GalPipelineState
  92. {
  93. FrontFace = GalFrontFace.Ccw,
  94. CullFaceEnabled = false,
  95. CullFace = GalCullFace.Back,
  96. DepthTestEnabled = false,
  97. DepthWriteEnabled = true,
  98. DepthFunc = GalComparisonOp.Less,
  99. DepthRangeNear = 0,
  100. DepthRangeFar = 1,
  101. StencilTestEnabled = false,
  102. StencilBackFuncFunc = GalComparisonOp.Always,
  103. StencilBackFuncRef = 0,
  104. StencilBackFuncMask = UInt32.MaxValue,
  105. StencilBackOpFail = GalStencilOp.Keep,
  106. StencilBackOpZFail = GalStencilOp.Keep,
  107. StencilBackOpZPass = GalStencilOp.Keep,
  108. StencilBackMask = UInt32.MaxValue,
  109. StencilFrontFuncFunc = GalComparisonOp.Always,
  110. StencilFrontFuncRef = 0,
  111. StencilFrontFuncMask = UInt32.MaxValue,
  112. StencilFrontOpFail = GalStencilOp.Keep,
  113. StencilFrontOpZFail = GalStencilOp.Keep,
  114. StencilFrontOpZPass = GalStencilOp.Keep,
  115. StencilFrontMask = UInt32.MaxValue,
  116. BlendIndependent = false,
  117. PrimitiveRestartEnabled = false,
  118. PrimitiveRestartIndex = 0
  119. };
  120. for (int index = 0; index < GalPipelineState.RenderTargetsCount; index++)
  121. {
  122. _old.Blends[index] = BlendState.Default;
  123. _old.ColorMasks[index] = ColorMaskState.Default;
  124. }
  125. }
  126. public void Bind(GalPipelineState New)
  127. {
  128. BindConstBuffers(New);
  129. BindVertexLayout(New);
  130. if (New.FramebufferSrgb != _old.FramebufferSrgb)
  131. {
  132. Enable(EnableCap.FramebufferSrgb, New.FramebufferSrgb);
  133. _renderTarget.FramebufferSrgb = New.FramebufferSrgb;
  134. }
  135. if (New.FlipX != _old.FlipX || New.FlipY != _old.FlipY || New.Instance != _old.Instance)
  136. {
  137. _shader.SetExtraData(New.FlipX, New.FlipY, New.Instance);
  138. }
  139. if (New.FrontFace != _old.FrontFace)
  140. {
  141. GL.FrontFace(OglEnumConverter.GetFrontFace(New.FrontFace));
  142. }
  143. if (New.CullFaceEnabled != _old.CullFaceEnabled)
  144. {
  145. Enable(EnableCap.CullFace, New.CullFaceEnabled);
  146. }
  147. if (New.CullFaceEnabled)
  148. {
  149. if (New.CullFace != _old.CullFace)
  150. {
  151. GL.CullFace(OglEnumConverter.GetCullFace(New.CullFace));
  152. }
  153. }
  154. if (New.DepthTestEnabled != _old.DepthTestEnabled)
  155. {
  156. Enable(EnableCap.DepthTest, New.DepthTestEnabled);
  157. }
  158. if (New.DepthWriteEnabled != _old.DepthWriteEnabled)
  159. {
  160. GL.DepthMask(New.DepthWriteEnabled);
  161. }
  162. if (New.DepthTestEnabled)
  163. {
  164. if (New.DepthFunc != _old.DepthFunc)
  165. {
  166. GL.DepthFunc(OglEnumConverter.GetDepthFunc(New.DepthFunc));
  167. }
  168. }
  169. if (New.DepthRangeNear != _old.DepthRangeNear ||
  170. New.DepthRangeFar != _old.DepthRangeFar)
  171. {
  172. GL.DepthRange(New.DepthRangeNear, New.DepthRangeFar);
  173. }
  174. if (New.StencilTestEnabled != _old.StencilTestEnabled)
  175. {
  176. Enable(EnableCap.StencilTest, New.StencilTestEnabled);
  177. }
  178. if (New.StencilTwoSideEnabled != _old.StencilTwoSideEnabled)
  179. {
  180. Enable((EnableCap)All.StencilTestTwoSideExt, New.StencilTwoSideEnabled);
  181. }
  182. if (New.StencilTestEnabled)
  183. {
  184. if (New.StencilBackFuncFunc != _old.StencilBackFuncFunc ||
  185. New.StencilBackFuncRef != _old.StencilBackFuncRef ||
  186. New.StencilBackFuncMask != _old.StencilBackFuncMask)
  187. {
  188. GL.StencilFuncSeparate(
  189. StencilFace.Back,
  190. OglEnumConverter.GetStencilFunc(New.StencilBackFuncFunc),
  191. New.StencilBackFuncRef,
  192. New.StencilBackFuncMask);
  193. }
  194. if (New.StencilBackOpFail != _old.StencilBackOpFail ||
  195. New.StencilBackOpZFail != _old.StencilBackOpZFail ||
  196. New.StencilBackOpZPass != _old.StencilBackOpZPass)
  197. {
  198. GL.StencilOpSeparate(
  199. StencilFace.Back,
  200. OglEnumConverter.GetStencilOp(New.StencilBackOpFail),
  201. OglEnumConverter.GetStencilOp(New.StencilBackOpZFail),
  202. OglEnumConverter.GetStencilOp(New.StencilBackOpZPass));
  203. }
  204. if (New.StencilBackMask != _old.StencilBackMask)
  205. {
  206. GL.StencilMaskSeparate(StencilFace.Back, New.StencilBackMask);
  207. }
  208. if (New.StencilFrontFuncFunc != _old.StencilFrontFuncFunc ||
  209. New.StencilFrontFuncRef != _old.StencilFrontFuncRef ||
  210. New.StencilFrontFuncMask != _old.StencilFrontFuncMask)
  211. {
  212. GL.StencilFuncSeparate(
  213. StencilFace.Front,
  214. OglEnumConverter.GetStencilFunc(New.StencilFrontFuncFunc),
  215. New.StencilFrontFuncRef,
  216. New.StencilFrontFuncMask);
  217. }
  218. if (New.StencilFrontOpFail != _old.StencilFrontOpFail ||
  219. New.StencilFrontOpZFail != _old.StencilFrontOpZFail ||
  220. New.StencilFrontOpZPass != _old.StencilFrontOpZPass)
  221. {
  222. GL.StencilOpSeparate(
  223. StencilFace.Front,
  224. OglEnumConverter.GetStencilOp(New.StencilFrontOpFail),
  225. OglEnumConverter.GetStencilOp(New.StencilFrontOpZFail),
  226. OglEnumConverter.GetStencilOp(New.StencilFrontOpZPass));
  227. }
  228. if (New.StencilFrontMask != _old.StencilFrontMask)
  229. {
  230. GL.StencilMaskSeparate(StencilFace.Front, New.StencilFrontMask);
  231. }
  232. }
  233. // Scissor Test
  234. // All scissor test are disabled before drawing final framebuffer to screen so we don't need to handle disabling
  235. // Skip if there are no scissor tests to enable
  236. if (New.ScissorTestCount != 0)
  237. {
  238. int scissorsApplied = 0;
  239. bool applyToAll = false;
  240. for (int index = 0; index < GalPipelineState.RenderTargetsCount; index++)
  241. {
  242. if (New.ScissorTestEnabled[index])
  243. {
  244. // If viewport arrays are unavailable apply first scissor test to all or
  245. // there is only 1 scissor test and it's the first, the scissor test applies to all viewports
  246. if (!OglExtension.Required.ViewportArray || (index == 0 && New.ScissorTestCount == 1))
  247. {
  248. GL.Enable(EnableCap.ScissorTest);
  249. applyToAll = true;
  250. }
  251. else
  252. {
  253. GL.Enable(IndexedEnableCap.ScissorTest, index);
  254. }
  255. if (New.ScissorTestEnabled[index] != _old.ScissorTestEnabled[index] ||
  256. New.ScissorTestX[index] != _old.ScissorTestX[index] ||
  257. New.ScissorTestY[index] != _old.ScissorTestY[index] ||
  258. New.ScissorTestWidth[index] != _old.ScissorTestWidth[index] ||
  259. New.ScissorTestHeight[index] != _old.ScissorTestHeight[index])
  260. {
  261. if (applyToAll)
  262. {
  263. GL.Scissor(New.ScissorTestX[index], New.ScissorTestY[index],
  264. New.ScissorTestWidth[index], New.ScissorTestHeight[index]);
  265. }
  266. else
  267. {
  268. GL.ScissorIndexed(index, New.ScissorTestX[index], New.ScissorTestY[index],
  269. New.ScissorTestWidth[index], New.ScissorTestHeight[index]);
  270. }
  271. }
  272. // If all scissor tests have been applied, or viewport arrays are unavailable we can skip remaining iterations
  273. if (!OglExtension.Required.ViewportArray || ++scissorsApplied == New.ScissorTestCount)
  274. {
  275. break;
  276. }
  277. }
  278. }
  279. }
  280. if (New.BlendIndependent)
  281. {
  282. for (int index = 0; index < GalPipelineState.RenderTargetsCount; index++)
  283. {
  284. SetBlendState(index, New.Blends[index], _old.Blends[index]);
  285. }
  286. }
  287. else
  288. {
  289. if (New.BlendIndependent != _old.BlendIndependent)
  290. {
  291. SetAllBlendState(New.Blends[0]);
  292. }
  293. else
  294. {
  295. SetBlendState(New.Blends[0], _old.Blends[0]);
  296. }
  297. }
  298. if (New.ColorMaskCommon)
  299. {
  300. if (New.ColorMaskCommon != _old.ColorMaskCommon || !New.ColorMasks[0].Equals(_old.ColorMasks[0]))
  301. {
  302. GL.ColorMask(
  303. New.ColorMasks[0].Red,
  304. New.ColorMasks[0].Green,
  305. New.ColorMasks[0].Blue,
  306. New.ColorMasks[0].Alpha);
  307. }
  308. }
  309. else
  310. {
  311. for (int index = 0; index < GalPipelineState.RenderTargetsCount; index++)
  312. {
  313. if (!New.ColorMasks[index].Equals(_old.ColorMasks[index]))
  314. {
  315. GL.ColorMask(
  316. index,
  317. New.ColorMasks[index].Red,
  318. New.ColorMasks[index].Green,
  319. New.ColorMasks[index].Blue,
  320. New.ColorMasks[index].Alpha);
  321. }
  322. }
  323. }
  324. if (New.PrimitiveRestartEnabled != _old.PrimitiveRestartEnabled)
  325. {
  326. Enable(EnableCap.PrimitiveRestart, New.PrimitiveRestartEnabled);
  327. }
  328. if (New.PrimitiveRestartEnabled)
  329. {
  330. if (New.PrimitiveRestartIndex != _old.PrimitiveRestartIndex)
  331. {
  332. GL.PrimitiveRestartIndex(New.PrimitiveRestartIndex);
  333. }
  334. }
  335. _old = New;
  336. }
  337. public void Unbind(GalPipelineState state)
  338. {
  339. if (state.ScissorTestCount > 0)
  340. {
  341. GL.Disable(EnableCap.ScissorTest);
  342. }
  343. }
  344. private void SetAllBlendState(BlendState New)
  345. {
  346. Enable(EnableCap.Blend, New.Enabled);
  347. if (New.Enabled)
  348. {
  349. if (New.SeparateAlpha)
  350. {
  351. GL.BlendEquationSeparate(
  352. OglEnumConverter.GetBlendEquation(New.EquationRgb),
  353. OglEnumConverter.GetBlendEquation(New.EquationAlpha));
  354. GL.BlendFuncSeparate(
  355. (BlendingFactorSrc) OglEnumConverter.GetBlendFactor(New.FuncSrcRgb),
  356. (BlendingFactorDest)OglEnumConverter.GetBlendFactor(New.FuncDstRgb),
  357. (BlendingFactorSrc) OglEnumConverter.GetBlendFactor(New.FuncSrcAlpha),
  358. (BlendingFactorDest)OglEnumConverter.GetBlendFactor(New.FuncDstAlpha));
  359. }
  360. else
  361. {
  362. GL.BlendEquation(OglEnumConverter.GetBlendEquation(New.EquationRgb));
  363. GL.BlendFunc(
  364. OglEnumConverter.GetBlendFactor(New.FuncSrcRgb),
  365. OglEnumConverter.GetBlendFactor(New.FuncDstRgb));
  366. }
  367. }
  368. }
  369. private void SetBlendState(BlendState New, BlendState old)
  370. {
  371. if (New.Enabled != old.Enabled)
  372. {
  373. Enable(EnableCap.Blend, New.Enabled);
  374. }
  375. if (New.Enabled)
  376. {
  377. if (New.SeparateAlpha)
  378. {
  379. if (New.EquationRgb != old.EquationRgb ||
  380. New.EquationAlpha != old.EquationAlpha)
  381. {
  382. GL.BlendEquationSeparate(
  383. OglEnumConverter.GetBlendEquation(New.EquationRgb),
  384. OglEnumConverter.GetBlendEquation(New.EquationAlpha));
  385. }
  386. if (New.FuncSrcRgb != old.FuncSrcRgb ||
  387. New.FuncDstRgb != old.FuncDstRgb ||
  388. New.FuncSrcAlpha != old.FuncSrcAlpha ||
  389. New.FuncDstAlpha != old.FuncDstAlpha)
  390. {
  391. GL.BlendFuncSeparate(
  392. (BlendingFactorSrc) OglEnumConverter.GetBlendFactor(New.FuncSrcRgb),
  393. (BlendingFactorDest)OglEnumConverter.GetBlendFactor(New.FuncDstRgb),
  394. (BlendingFactorSrc) OglEnumConverter.GetBlendFactor(New.FuncSrcAlpha),
  395. (BlendingFactorDest)OglEnumConverter.GetBlendFactor(New.FuncDstAlpha));
  396. }
  397. }
  398. else
  399. {
  400. if (New.EquationRgb != old.EquationRgb)
  401. {
  402. GL.BlendEquation(OglEnumConverter.GetBlendEquation(New.EquationRgb));
  403. }
  404. if (New.FuncSrcRgb != old.FuncSrcRgb ||
  405. New.FuncDstRgb != old.FuncDstRgb)
  406. {
  407. GL.BlendFunc(
  408. OglEnumConverter.GetBlendFactor(New.FuncSrcRgb),
  409. OglEnumConverter.GetBlendFactor(New.FuncDstRgb));
  410. }
  411. }
  412. }
  413. }
  414. private void SetBlendState(int index, BlendState New, BlendState old)
  415. {
  416. if (New.Enabled != old.Enabled)
  417. {
  418. Enable(IndexedEnableCap.Blend, index, New.Enabled);
  419. }
  420. if (New.Enabled)
  421. {
  422. if (New.SeparateAlpha)
  423. {
  424. if (New.EquationRgb != old.EquationRgb ||
  425. New.EquationAlpha != old.EquationAlpha)
  426. {
  427. GL.BlendEquationSeparate(
  428. index,
  429. OglEnumConverter.GetBlendEquation(New.EquationRgb),
  430. OglEnumConverter.GetBlendEquation(New.EquationAlpha));
  431. }
  432. if (New.FuncSrcRgb != old.FuncSrcRgb ||
  433. New.FuncDstRgb != old.FuncDstRgb ||
  434. New.FuncSrcAlpha != old.FuncSrcAlpha ||
  435. New.FuncDstAlpha != old.FuncDstAlpha)
  436. {
  437. GL.BlendFuncSeparate(
  438. index,
  439. (BlendingFactorSrc) OglEnumConverter.GetBlendFactor(New.FuncSrcRgb),
  440. (BlendingFactorDest)OglEnumConverter.GetBlendFactor(New.FuncDstRgb),
  441. (BlendingFactorSrc) OglEnumConverter.GetBlendFactor(New.FuncSrcAlpha),
  442. (BlendingFactorDest)OglEnumConverter.GetBlendFactor(New.FuncDstAlpha));
  443. }
  444. }
  445. else
  446. {
  447. if (New.EquationRgb != old.EquationRgb)
  448. {
  449. GL.BlendEquation(index, OglEnumConverter.GetBlendEquation(New.EquationRgb));
  450. }
  451. if (New.FuncSrcRgb != old.FuncSrcRgb ||
  452. New.FuncDstRgb != old.FuncDstRgb)
  453. {
  454. GL.BlendFunc(
  455. index,
  456. (BlendingFactorSrc) OglEnumConverter.GetBlendFactor(New.FuncSrcRgb),
  457. (BlendingFactorDest)OglEnumConverter.GetBlendFactor(New.FuncDstRgb));
  458. }
  459. }
  460. }
  461. }
  462. private void BindConstBuffers(GalPipelineState New)
  463. {
  464. int freeBinding = OglShader.ReservedCbufCount;
  465. void BindIfNotNull(OglShaderStage stage)
  466. {
  467. if (stage != null)
  468. {
  469. foreach (CBufferDescriptor desc in stage.ConstBufferUsage)
  470. {
  471. long key = New.ConstBufferKeys[(int)stage.Type][desc.Slot];
  472. if (key != 0 && _buffer.TryGetUbo(key, out int uboHandle))
  473. {
  474. GL.BindBufferBase(BufferRangeTarget.UniformBuffer, freeBinding, uboHandle);
  475. }
  476. freeBinding++;
  477. }
  478. }
  479. }
  480. BindIfNotNull(_shader.Current.Vertex);
  481. BindIfNotNull(_shader.Current.TessControl);
  482. BindIfNotNull(_shader.Current.TessEvaluation);
  483. BindIfNotNull(_shader.Current.Geometry);
  484. BindIfNotNull(_shader.Current.Fragment);
  485. }
  486. private void BindVertexLayout(GalPipelineState New)
  487. {
  488. foreach (GalVertexBinding binding in New.VertexBindings)
  489. {
  490. if (!binding.Enabled || !_rasterizer.TryGetVbo(binding.VboKey, out int vboHandle))
  491. {
  492. continue;
  493. }
  494. if (_vaoHandle == 0)
  495. {
  496. _vaoHandle = GL.GenVertexArray();
  497. // Vertex arrays shouldn't be used anywhere else in OpenGL's backend
  498. // if you want to use it, move this line out of the if
  499. GL.BindVertexArray(_vaoHandle);
  500. }
  501. foreach (GalVertexAttrib attrib in binding.Attribs)
  502. {
  503. // Skip uninitialized attributes.
  504. if (attrib.Size == 0)
  505. {
  506. continue;
  507. }
  508. GL.BindBuffer(BufferTarget.ArrayBuffer, vboHandle);
  509. bool unsigned =
  510. attrib.Type == GalVertexAttribType.Unorm ||
  511. attrib.Type == GalVertexAttribType.Uint ||
  512. attrib.Type == GalVertexAttribType.Uscaled;
  513. bool normalize =
  514. attrib.Type == GalVertexAttribType.Snorm ||
  515. attrib.Type == GalVertexAttribType.Unorm;
  516. VertexAttribPointerType type = 0;
  517. if (attrib.Type == GalVertexAttribType.Float)
  518. {
  519. type = GetType(_floatAttribTypes, attrib);
  520. }
  521. else
  522. {
  523. if (unsigned)
  524. {
  525. type = GetType(_unsignedAttribTypes, attrib);
  526. }
  527. else
  528. {
  529. type = GetType(_signedAttribTypes, attrib);
  530. }
  531. }
  532. if (!_attribElements.TryGetValue(attrib.Size, out int size))
  533. {
  534. throw new InvalidOperationException("Invalid attribute size \"" + attrib.Size + "\"!");
  535. }
  536. int offset = attrib.Offset;
  537. if (binding.Stride != 0)
  538. {
  539. GL.EnableVertexAttribArray(attrib.Index);
  540. if (attrib.Type == GalVertexAttribType.Sint ||
  541. attrib.Type == GalVertexAttribType.Uint)
  542. {
  543. IntPtr pointer = new IntPtr(offset);
  544. VertexAttribIntegerType iType = (VertexAttribIntegerType)type;
  545. GL.VertexAttribIPointer(attrib.Index, size, iType, binding.Stride, pointer);
  546. }
  547. else
  548. {
  549. GL.VertexAttribPointer(attrib.Index, size, type, normalize, binding.Stride, offset);
  550. }
  551. }
  552. else
  553. {
  554. GL.DisableVertexAttribArray(attrib.Index);
  555. SetConstAttrib(attrib);
  556. }
  557. if (binding.Instanced && binding.Divisor != 0)
  558. {
  559. GL.VertexAttribDivisor(attrib.Index, 1);
  560. }
  561. else
  562. {
  563. GL.VertexAttribDivisor(attrib.Index, 0);
  564. }
  565. }
  566. }
  567. }
  568. private static VertexAttribPointerType GetType(Dictionary<GalVertexAttribSize, VertexAttribPointerType> dict, GalVertexAttrib attrib)
  569. {
  570. if (!dict.TryGetValue(attrib.Size, out VertexAttribPointerType type))
  571. {
  572. ThrowUnsupportedAttrib(attrib);
  573. }
  574. return type;
  575. }
  576. private static unsafe void SetConstAttrib(GalVertexAttrib attrib)
  577. {
  578. if (attrib.Size == GalVertexAttribSize._10_10_10_2 ||
  579. attrib.Size == GalVertexAttribSize._11_11_10)
  580. {
  581. ThrowUnsupportedAttrib(attrib);
  582. }
  583. fixed (byte* ptr = attrib.Data)
  584. {
  585. if (attrib.Type == GalVertexAttribType.Unorm)
  586. {
  587. switch (attrib.Size)
  588. {
  589. case GalVertexAttribSize._8:
  590. case GalVertexAttribSize._8_8:
  591. case GalVertexAttribSize._8_8_8:
  592. case GalVertexAttribSize._8_8_8_8:
  593. GL.VertexAttrib4N((uint)attrib.Index, ptr);
  594. break;
  595. case GalVertexAttribSize._16:
  596. case GalVertexAttribSize._16_16:
  597. case GalVertexAttribSize._16_16_16:
  598. case GalVertexAttribSize._16_16_16_16:
  599. GL.VertexAttrib4N((uint)attrib.Index, (ushort*)ptr);
  600. break;
  601. case GalVertexAttribSize._32:
  602. case GalVertexAttribSize._32_32:
  603. case GalVertexAttribSize._32_32_32:
  604. case GalVertexAttribSize._32_32_32_32:
  605. GL.VertexAttrib4N((uint)attrib.Index, (uint*)ptr);
  606. break;
  607. }
  608. }
  609. else if (attrib.Type == GalVertexAttribType.Snorm)
  610. {
  611. switch (attrib.Size)
  612. {
  613. case GalVertexAttribSize._8:
  614. case GalVertexAttribSize._8_8:
  615. case GalVertexAttribSize._8_8_8:
  616. case GalVertexAttribSize._8_8_8_8:
  617. GL.VertexAttrib4N((uint)attrib.Index, (sbyte*)ptr);
  618. break;
  619. case GalVertexAttribSize._16:
  620. case GalVertexAttribSize._16_16:
  621. case GalVertexAttribSize._16_16_16:
  622. case GalVertexAttribSize._16_16_16_16:
  623. GL.VertexAttrib4N((uint)attrib.Index, (short*)ptr);
  624. break;
  625. case GalVertexAttribSize._32:
  626. case GalVertexAttribSize._32_32:
  627. case GalVertexAttribSize._32_32_32:
  628. case GalVertexAttribSize._32_32_32_32:
  629. GL.VertexAttrib4N((uint)attrib.Index, (int*)ptr);
  630. break;
  631. }
  632. }
  633. else if (attrib.Type == GalVertexAttribType.Uint)
  634. {
  635. switch (attrib.Size)
  636. {
  637. case GalVertexAttribSize._8:
  638. case GalVertexAttribSize._8_8:
  639. case GalVertexAttribSize._8_8_8:
  640. case GalVertexAttribSize._8_8_8_8:
  641. GL.VertexAttribI4((uint)attrib.Index, ptr);
  642. break;
  643. case GalVertexAttribSize._16:
  644. case GalVertexAttribSize._16_16:
  645. case GalVertexAttribSize._16_16_16:
  646. case GalVertexAttribSize._16_16_16_16:
  647. GL.VertexAttribI4((uint)attrib.Index, (ushort*)ptr);
  648. break;
  649. case GalVertexAttribSize._32:
  650. case GalVertexAttribSize._32_32:
  651. case GalVertexAttribSize._32_32_32:
  652. case GalVertexAttribSize._32_32_32_32:
  653. GL.VertexAttribI4((uint)attrib.Index, (uint*)ptr);
  654. break;
  655. }
  656. }
  657. else if (attrib.Type == GalVertexAttribType.Sint)
  658. {
  659. switch (attrib.Size)
  660. {
  661. case GalVertexAttribSize._8:
  662. case GalVertexAttribSize._8_8:
  663. case GalVertexAttribSize._8_8_8:
  664. case GalVertexAttribSize._8_8_8_8:
  665. GL.VertexAttribI4((uint)attrib.Index, (sbyte*)ptr);
  666. break;
  667. case GalVertexAttribSize._16:
  668. case GalVertexAttribSize._16_16:
  669. case GalVertexAttribSize._16_16_16:
  670. case GalVertexAttribSize._16_16_16_16:
  671. GL.VertexAttribI4((uint)attrib.Index, (short*)ptr);
  672. break;
  673. case GalVertexAttribSize._32:
  674. case GalVertexAttribSize._32_32:
  675. case GalVertexAttribSize._32_32_32:
  676. case GalVertexAttribSize._32_32_32_32:
  677. GL.VertexAttribI4((uint)attrib.Index, (int*)ptr);
  678. break;
  679. }
  680. }
  681. else if (attrib.Type == GalVertexAttribType.Float)
  682. {
  683. switch (attrib.Size)
  684. {
  685. case GalVertexAttribSize._32:
  686. case GalVertexAttribSize._32_32:
  687. case GalVertexAttribSize._32_32_32:
  688. case GalVertexAttribSize._32_32_32_32:
  689. GL.VertexAttrib4(attrib.Index, (float*)ptr);
  690. break;
  691. default: ThrowUnsupportedAttrib(attrib); break;
  692. }
  693. }
  694. }
  695. }
  696. private static void ThrowUnsupportedAttrib(GalVertexAttrib attrib)
  697. {
  698. throw new NotImplementedException("Unsupported size \"" + attrib.Size + "\" on type \"" + attrib.Type + "\"!");
  699. }
  700. private void Enable(EnableCap cap, bool enabled)
  701. {
  702. if (enabled)
  703. {
  704. GL.Enable(cap);
  705. }
  706. else
  707. {
  708. GL.Disable(cap);
  709. }
  710. }
  711. private void Enable(IndexedEnableCap cap, int index, bool enabled)
  712. {
  713. if (enabled)
  714. {
  715. GL.Enable(cap, index);
  716. }
  717. else
  718. {
  719. GL.Disable(cap, index);
  720. }
  721. }
  722. public void ResetDepthMask()
  723. {
  724. _old.DepthWriteEnabled = true;
  725. }
  726. public void ResetColorMask(int index)
  727. {
  728. _old.ColorMasks[index] = ColorMaskState.Default;
  729. }
  730. }
  731. }