Program.cs 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  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 ubBindingPoint = 0;
  61. int sbBindingPoint = 0;
  62. int textureUnit = 0;
  63. int imageUnit = 0;
  64. for (int index = 0; index < shaders.Length; index++)
  65. {
  66. Shader shader = (Shader)shaders[index];
  67. foreach (BufferDescriptor descriptor in shader.Info.CBuffers)
  68. {
  69. int location = GL.GetUniformBlockIndex(Handle, descriptor.Name);
  70. if (location < 0)
  71. {
  72. continue;
  73. }
  74. GL.UniformBlockBinding(Handle, location, ubBindingPoint);
  75. int bpIndex = (int)shader.Stage << UbStageShift | descriptor.Slot;
  76. _ubBindingPoints[bpIndex] = ubBindingPoint;
  77. ubBindingPoint++;
  78. }
  79. foreach (BufferDescriptor descriptor in shader.Info.SBuffers)
  80. {
  81. int location = GL.GetProgramResourceIndex(Handle, ProgramInterface.ShaderStorageBlock, descriptor.Name);
  82. if (location < 0)
  83. {
  84. continue;
  85. }
  86. GL.ShaderStorageBlockBinding(Handle, location, sbBindingPoint);
  87. int bpIndex = (int)shader.Stage << SbStageShift | descriptor.Slot;
  88. _sbBindingPoints[bpIndex] = sbBindingPoint;
  89. sbBindingPoint++;
  90. }
  91. int samplerIndex = 0;
  92. foreach (TextureDescriptor descriptor in shader.Info.Textures)
  93. {
  94. int location = GL.GetUniformLocation(Handle, descriptor.Name);
  95. if (location < 0)
  96. {
  97. continue;
  98. }
  99. GL.Uniform1(location, textureUnit);
  100. int uIndex = (int)shader.Stage << TexStageShift | samplerIndex++;
  101. _textureUnits[uIndex] = textureUnit;
  102. textureUnit++;
  103. }
  104. int imageIndex = 0;
  105. foreach (TextureDescriptor descriptor in shader.Info.Images)
  106. {
  107. int location = GL.GetUniformLocation(Handle, descriptor.Name);
  108. if (location < 0)
  109. {
  110. continue;
  111. }
  112. GL.Uniform1(location, imageUnit);
  113. int uIndex = (int)shader.Stage << ImgStageShift | imageIndex++;
  114. _imageUnits[uIndex] = imageUnit;
  115. imageUnit++;
  116. }
  117. }
  118. }
  119. public void Bind()
  120. {
  121. GL.UseProgram(Handle);
  122. }
  123. public int GetUniformBufferBindingPoint(ShaderStage stage, int index)
  124. {
  125. return _ubBindingPoints[(int)stage << UbStageShift | index];
  126. }
  127. public int GetStorageBufferBindingPoint(ShaderStage stage, int index)
  128. {
  129. return _sbBindingPoints[(int)stage << SbStageShift | index];
  130. }
  131. public int GetTextureUnit(ShaderStage stage, int index)
  132. {
  133. return _textureUnits[(int)stage << TexStageShift | index];
  134. }
  135. public int GetImageUnit(ShaderStage stage, int index)
  136. {
  137. return _imageUnits[(int)stage << ImgStageShift | index];
  138. }
  139. private void CheckProgramLink()
  140. {
  141. GL.GetProgram(Handle, GetProgramParameterName.LinkStatus, out int status);
  142. if (status == 0)
  143. {
  144. // Use GL.GetProgramInfoLog(Handle), it may be too long to print on the log.
  145. Logger.PrintDebug(LogClass.Gpu, "Shader linking failed.");
  146. }
  147. else
  148. {
  149. IsLinked = true;
  150. }
  151. }
  152. public void Dispose()
  153. {
  154. if (Handle != 0)
  155. {
  156. GL.DeleteProgram(Handle);
  157. Handle = 0;
  158. }
  159. }
  160. }
  161. }