Program.cs 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. using OpenTK.Graphics.OpenGL;
  2. using Ryujinx.Common.Logging;
  3. using Ryujinx.Graphics.GAL;
  4. using Ryujinx.Graphics.Shader;
  5. namespace Ryujinx.Graphics.OpenGL
  6. {
  7. class Program : IProgram
  8. {
  9. private const int ShaderStages = 6;
  10. private const int UbStageShift = 5;
  11. private const int SbStageShift = 4;
  12. private const int TexStageShift = 5;
  13. private const int ImgStageShift = 3;
  14. private const int UbsPerStage = 1 << UbStageShift;
  15. private const int SbsPerStage = 1 << SbStageShift;
  16. private const int TexsPerStage = 1 << TexStageShift;
  17. private const int ImgsPerStage = 1 << ImgStageShift;
  18. public int Handle { get; private set; }
  19. public bool IsLinked { get; private set; }
  20. private int[] _ubBindingPoints;
  21. private int[] _sbBindingPoints;
  22. private int[] _textureUnits;
  23. private int[] _imageUnits;
  24. public Program(IShader[] shaders)
  25. {
  26. _ubBindingPoints = new int[UbsPerStage * ShaderStages];
  27. _sbBindingPoints = new int[SbsPerStage * ShaderStages];
  28. _textureUnits = new int[TexsPerStage * ShaderStages];
  29. _imageUnits = new int[ImgsPerStage * ShaderStages];
  30. for (int index = 0; index < _ubBindingPoints.Length; index++)
  31. {
  32. _ubBindingPoints[index] = -1;
  33. }
  34. for (int index = 0; index < _sbBindingPoints.Length; index++)
  35. {
  36. _sbBindingPoints[index] = -1;
  37. }
  38. for (int index = 0; index < _textureUnits.Length; index++)
  39. {
  40. _textureUnits[index] = -1;
  41. }
  42. for (int index = 0; index < _imageUnits.Length; index++)
  43. {
  44. _imageUnits[index] = -1;
  45. }
  46. Handle = GL.CreateProgram();
  47. for (int index = 0; index < shaders.Length; index++)
  48. {
  49. int shaderHandle = ((Shader)shaders[index]).Handle;
  50. GL.AttachShader(Handle, shaderHandle);
  51. }
  52. GL.LinkProgram(Handle);
  53. for (int index = 0; index < shaders.Length; index++)
  54. {
  55. int shaderHandle = ((Shader)shaders[index]).Handle;
  56. GL.DetachShader(Handle, shaderHandle);
  57. }
  58. CheckProgramLink();
  59. Bind();
  60. int extraBlockindex = GL.GetUniformBlockIndex(Handle, "Extra");
  61. if (extraBlockindex >= 0)
  62. {
  63. GL.UniformBlockBinding(Handle, extraBlockindex, 0);
  64. }
  65. int ubBindingPoint = 1;
  66. int sbBindingPoint = 0;
  67. int textureUnit = 0;
  68. int imageUnit = 0;
  69. for (int index = 0; index < shaders.Length; index++)
  70. {
  71. Shader shader = (Shader)shaders[index];
  72. foreach (BufferDescriptor descriptor in shader.Info.CBuffers)
  73. {
  74. int location = GL.GetUniformBlockIndex(Handle, descriptor.Name);
  75. if (location < 0)
  76. {
  77. continue;
  78. }
  79. GL.UniformBlockBinding(Handle, location, ubBindingPoint);
  80. int bpIndex = (int)shader.Stage << UbStageShift | descriptor.Slot;
  81. _ubBindingPoints[bpIndex] = ubBindingPoint;
  82. ubBindingPoint++;
  83. }
  84. foreach (BufferDescriptor descriptor in shader.Info.SBuffers)
  85. {
  86. int location = GL.GetProgramResourceIndex(Handle, ProgramInterface.ShaderStorageBlock, descriptor.Name);
  87. if (location < 0)
  88. {
  89. continue;
  90. }
  91. GL.ShaderStorageBlockBinding(Handle, location, sbBindingPoint);
  92. int bpIndex = (int)shader.Stage << SbStageShift | descriptor.Slot;
  93. _sbBindingPoints[bpIndex] = sbBindingPoint;
  94. sbBindingPoint++;
  95. }
  96. int samplerIndex = 0;
  97. foreach (TextureDescriptor descriptor in shader.Info.Textures)
  98. {
  99. int location = GL.GetUniformLocation(Handle, descriptor.Name);
  100. if (location < 0)
  101. {
  102. continue;
  103. }
  104. GL.Uniform1(location, textureUnit);
  105. int uIndex = (int)shader.Stage << TexStageShift | samplerIndex++;
  106. _textureUnits[uIndex] = textureUnit;
  107. textureUnit++;
  108. }
  109. int imageIndex = 0;
  110. foreach (TextureDescriptor descriptor in shader.Info.Images)
  111. {
  112. int location = GL.GetUniformLocation(Handle, descriptor.Name);
  113. if (location < 0)
  114. {
  115. continue;
  116. }
  117. GL.Uniform1(location, imageUnit);
  118. int uIndex = (int)shader.Stage << ImgStageShift | imageIndex++;
  119. _imageUnits[uIndex] = imageUnit;
  120. imageUnit++;
  121. }
  122. }
  123. }
  124. public void Bind()
  125. {
  126. GL.UseProgram(Handle);
  127. }
  128. public int GetUniformBufferBindingPoint(ShaderStage stage, int index)
  129. {
  130. return _ubBindingPoints[(int)stage << UbStageShift | index];
  131. }
  132. public int GetStorageBufferBindingPoint(ShaderStage stage, int index)
  133. {
  134. return _sbBindingPoints[(int)stage << SbStageShift | index];
  135. }
  136. public int GetTextureUnit(ShaderStage stage, int index)
  137. {
  138. return _textureUnits[(int)stage << TexStageShift | index];
  139. }
  140. public int GetImageUnit(ShaderStage stage, int index)
  141. {
  142. return _imageUnits[(int)stage << ImgStageShift | index];
  143. }
  144. private void CheckProgramLink()
  145. {
  146. GL.GetProgram(Handle, GetProgramParameterName.LinkStatus, out int status);
  147. if (status == 0)
  148. {
  149. // Use GL.GetProgramInfoLog(Handle), it may be too long to print on the log.
  150. Logger.PrintDebug(LogClass.Gpu, "Shader linking failed.");
  151. }
  152. else
  153. {
  154. IsLinked = true;
  155. }
  156. }
  157. public void Dispose()
  158. {
  159. if (Handle != 0)
  160. {
  161. GL.DeleteProgram(Handle);
  162. Handle = 0;
  163. }
  164. }
  165. }
  166. }