From 1876b346fea647e8284a66bb6d62c38801035cff Mon Sep 17 00:00:00 2001
From: gdk <gab.dark.100@gmail.com>
Date: Sun, 13 Oct 2019 03:02:07 -0300
Subject: Initial work

---
 Ryujinx.Graphics.OpenGL/Program.cs | 175 +++++++++++++++++++++++++++++++++++++
 1 file changed, 175 insertions(+)
 create mode 100644 Ryujinx.Graphics.OpenGL/Program.cs

(limited to 'Ryujinx.Graphics.OpenGL/Program.cs')

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;
+            }
+        }
+    }
+}
-- 
cgit v1.2.3-70-g09d2