aboutsummaryrefslogtreecommitdiff
path: root/Ryujinx.Graphics.OpenGL/Program.cs
diff options
context:
space:
mode:
authorgdk <gab.dark.100@gmail.com>2019-10-13 03:02:07 -0300
committerThog <thog@protonmail.com>2020-01-09 02:13:00 +0100
commit1876b346fea647e8284a66bb6d62c38801035cff (patch)
tree6eeff094298cda84d1613dc5ec0691e51d7b35f1 /Ryujinx.Graphics.OpenGL/Program.cs
parentf617fb542a0e3d36012d77a4b5acbde7b08902f2 (diff)
Initial work
Diffstat (limited to 'Ryujinx.Graphics.OpenGL/Program.cs')
-rw-r--r--Ryujinx.Graphics.OpenGL/Program.cs175
1 files changed, 175 insertions, 0 deletions
diff --git a/Ryujinx.Graphics.OpenGL/Program.cs b/Ryujinx.Graphics.OpenGL/Program.cs
new file mode 100644
index 00000000..1f95b449
--- /dev/null
+++ b/Ryujinx.Graphics.OpenGL/Program.cs
@@ -0,0 +1,175 @@
+using Ryujinx.Graphics.GAL;
+using Ryujinx.Graphics.Shader;
+using OpenTK.Graphics.OpenGL;
+
+namespace Ryujinx.Graphics.OpenGL
+{
+ class Program : IProgram
+ {
+ private const int StageShift = 5;
+ private const int SbStageShift = 4;
+
+ public int Handle { get; private set; }
+
+ public bool IsLinked { get; private set; }
+
+ private int[] _ubBindingPoints;
+ private int[] _sbBindingPoints;
+ private int[] _textureUnits;
+
+ public Program(IShader[] shaders)
+ {
+ _ubBindingPoints = new int[32 * 6];
+ _sbBindingPoints = new int[16 * 6];
+ _textureUnits = new int[32 * 6];
+
+ for (int index = 0; index < _ubBindingPoints.Length; index++)
+ {
+ _ubBindingPoints[index] = -1;
+ }
+
+ for (int index = 0; index < _sbBindingPoints.Length; index++)
+ {
+ _sbBindingPoints[index] = -1;
+ }
+
+ for (int index = 0; index < _textureUnits.Length; index++)
+ {
+ _textureUnits[index] = -1;
+ }
+
+ Handle = GL.CreateProgram();
+
+ for (int index = 0; index < shaders.Length; index++)
+ {
+ int shaderHandle = ((Shader)shaders[index]).Handle;
+
+ GL.AttachShader(Handle, shaderHandle);
+ }
+
+ GL.LinkProgram(Handle);
+
+ CheckProgramLink();
+
+ Bind();
+
+ int extraBlockindex = GL.GetUniformBlockIndex(Handle, "Extra");
+
+ if (extraBlockindex >= 0)
+ {
+ GL.UniformBlockBinding(Handle, extraBlockindex, 0);
+ }
+
+ int ubBindingPoint = 1;
+ int sbBindingPoint = 0;
+ int textureUnit = 0;
+
+ for (int index = 0; index < shaders.Length; index++)
+ {
+ Shader shader = (Shader)shaders[index];
+
+ foreach (BufferDescriptor descriptor in shader.Info.CBuffers)
+ {
+ int location = GL.GetUniformBlockIndex(Handle, descriptor.Name);
+
+ if (location < 0)
+ {
+ continue;
+ }
+
+ GL.UniformBlockBinding(Handle, location, ubBindingPoint);
+
+ int bpIndex = (int)shader.Stage << StageShift | descriptor.Slot;
+
+ _ubBindingPoints[bpIndex] = ubBindingPoint;
+
+ ubBindingPoint++;
+ }
+
+ foreach (BufferDescriptor descriptor in shader.Info.SBuffers)
+ {
+ int location = GL.GetProgramResourceIndex(Handle, ProgramInterface.ShaderStorageBlock, descriptor.Name);
+
+ if (location < 0)
+ {
+ continue;
+ }
+
+ GL.ShaderStorageBlockBinding(Handle, location, sbBindingPoint);
+
+ int bpIndex = (int)shader.Stage << SbStageShift | descriptor.Slot;
+
+ _sbBindingPoints[bpIndex] = sbBindingPoint;
+
+ sbBindingPoint++;
+ }
+
+ int samplerIndex = 0;
+
+ foreach (TextureDescriptor descriptor in shader.Info.Textures)
+ {
+ int location = GL.GetUniformLocation(Handle, descriptor.Name);
+
+ if (location < 0)
+ {
+ continue;
+ }
+
+ GL.Uniform1(location, textureUnit);
+
+ int uIndex = (int)shader.Stage << StageShift | samplerIndex++;
+
+ _textureUnits[uIndex] = textureUnit;
+
+ textureUnit++;
+ }
+ }
+ }
+
+ public void Bind()
+ {
+ GL.UseProgram(Handle);
+ }
+
+ public int GetUniformBufferBindingPoint(ShaderStage stage, int index)
+ {
+ return _ubBindingPoints[(int)stage << StageShift | index];
+ }
+
+ public int GetStorageBufferBindingPoint(ShaderStage stage, int index)
+ {
+ return _sbBindingPoints[(int)stage << SbStageShift | index];
+ }
+
+ public int GetTextureUnit(ShaderStage stage, int index)
+ {
+ return _textureUnits[(int)stage << StageShift | index];
+ }
+
+ private void CheckProgramLink()
+ {
+ int status = 0;
+
+ GL.GetProgram(Handle, GetProgramParameterName.LinkStatus, out status);
+
+ if (status == 0)
+ {
+ // throw new System.Exception(GL.GetProgramInfoLog(Handle));
+ }
+ else
+ {
+ IsLinked = true;
+ }
+ }
+
+ public void Dispose()
+ {
+ if (Handle != 0)
+ {
+ GL.DeleteProgram(Handle);
+
+ Handle = 0;
+ }
+ }
+ }
+}