diff options
author | gdk <gab.dark.100@gmail.com> | 2019-10-13 03:02:07 -0300 |
---|---|---|
committer | Thog <thog@protonmail.com> | 2020-01-09 02:13:00 +0100 |
commit | 1876b346fea647e8284a66bb6d62c38801035cff (patch) | |
tree | 6eeff094298cda84d1613dc5ec0691e51d7b35f1 /Ryujinx.Graphics.OpenGL/Program.cs | |
parent | f617fb542a0e3d36012d77a4b5acbde7b08902f2 (diff) |
Initial work
Diffstat (limited to 'Ryujinx.Graphics.OpenGL/Program.cs')
-rw-r--r-- | Ryujinx.Graphics.OpenGL/Program.cs | 175 |
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; + } + } + } +} |