176 lines
4.8 KiB
C#
176 lines
4.8 KiB
C#
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;
|
|
}
|
|
}
|
|
}
|
|
}
|