Merge shader branch, adding support for GLSL decompilation, a macro

interpreter, and a rewrite of the GPU code.
This commit is contained in:
gdkchan 2018-04-08 16:17:35 -03:00
parent 7acd0e0122
commit b9aa3966c0
77 changed files with 5301 additions and 766 deletions

View file

@ -1,5 +1,4 @@
using OpenTK;
using OpenTK.Graphics.OpenGL;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
@ -8,22 +7,15 @@ namespace Ryujinx.Graphics.Gal.OpenGL
{
public class OpenGLRenderer : IGalRenderer
{
private struct VertexBuffer
{
public int VaoHandle;
public int VboHandle;
private OGLBlend Blend;
public int PrimCount;
}
private OGLFrameBuffer FrameBuffer;
private struct Texture
{
public int Handle;
}
private OGLRasterizer Rasterizer;
private List<VertexBuffer> VertexBuffers;
private OGLShader Shader;
private Texture[] Textures;
private OGLTexture Texture;
private ConcurrentQueue<Action> ActionsQueue;
@ -31,9 +23,15 @@ namespace Ryujinx.Graphics.Gal.OpenGL
public OpenGLRenderer()
{
VertexBuffers = new List<VertexBuffer>();
Blend = new OGLBlend();
Textures = new Texture[8];
FrameBuffer = new OGLFrameBuffer();
Rasterizer = new OGLRasterizer();
Shader = new OGLShader();
Texture = new OGLTexture();
ActionsQueue = new ConcurrentQueue<Action>();
}
@ -66,18 +64,6 @@ namespace Ryujinx.Graphics.Gal.OpenGL
public void Render()
{
FbRenderer.Render();
for (int Index = 0; Index < VertexBuffers.Count; Index++)
{
VertexBuffer Vb = VertexBuffers[Index];
if (Vb.VaoHandle != 0 &&
Vb.PrimCount != 0)
{
GL.BindVertexArray(Vb.VaoHandle);
GL.DrawArrays(PrimitiveType.TriangleStrip, 0, Vb.PrimCount);
}
}
}
public void SetWindowSize(int Width, int Height)
@ -106,218 +92,161 @@ namespace Ryujinx.Graphics.Gal.OpenGL
FbRenderer.Set(Fb, Width, Height, Transform, Offs);
}
public void SendVertexBuffer(int Index, byte[] Buffer, int Stride, GalVertexAttrib[] Attribs)
public void SetBlendEnable(bool Enable)
{
if (Index < 0)
if (Enable)
{
throw new ArgumentOutOfRangeException(nameof(Index));
ActionsQueue.Enqueue(() => Blend.Enable());
}
if (Buffer.Length == 0 || Stride == 0)
else
{
return;
ActionsQueue.Enqueue(() => Blend.Disable());
}
EnsureVbInitialized(Index);
VertexBuffer Vb = VertexBuffers[Index];
Vb.PrimCount = Buffer.Length / Stride;
VertexBuffers[Index] = Vb;
IntPtr Length = new IntPtr(Buffer.Length);
GL.BindBuffer(BufferTarget.ArrayBuffer, Vb.VboHandle);
GL.BufferData(BufferTarget.ArrayBuffer, Length, Buffer, BufferUsageHint.StreamDraw);
GL.BindBuffer(BufferTarget.ArrayBuffer, 0);
GL.BindVertexArray(Vb.VaoHandle);
for (int Attr = 0; Attr < 16; Attr++)
{
GL.DisableVertexAttribArray(Attr);
}
foreach (GalVertexAttrib Attrib in Attribs)
{
if (Attrib.Index >= 3) break;
GL.EnableVertexAttribArray(Attrib.Index);
GL.BindBuffer(BufferTarget.ArrayBuffer, Vb.VboHandle);
int Size = 0;
switch (Attrib.Size)
{
case GalVertexAttribSize._8:
case GalVertexAttribSize._16:
case GalVertexAttribSize._32:
Size = 1;
break;
case GalVertexAttribSize._8_8:
case GalVertexAttribSize._16_16:
case GalVertexAttribSize._32_32:
Size = 2;
break;
case GalVertexAttribSize._8_8_8:
case GalVertexAttribSize._11_11_10:
case GalVertexAttribSize._16_16_16:
case GalVertexAttribSize._32_32_32:
Size = 3;
break;
case GalVertexAttribSize._8_8_8_8:
case GalVertexAttribSize._10_10_10_2:
case GalVertexAttribSize._16_16_16_16:
case GalVertexAttribSize._32_32_32_32:
Size = 4;
break;
}
bool Signed =
Attrib.Type == GalVertexAttribType.Snorm ||
Attrib.Type == GalVertexAttribType.Sint ||
Attrib.Type == GalVertexAttribType.Sscaled;
bool Normalize =
Attrib.Type == GalVertexAttribType.Snorm ||
Attrib.Type == GalVertexAttribType.Unorm;
VertexAttribPointerType Type = 0;
switch (Attrib.Type)
{
case GalVertexAttribType.Snorm:
case GalVertexAttribType.Unorm:
case GalVertexAttribType.Sint:
case GalVertexAttribType.Uint:
case GalVertexAttribType.Uscaled:
case GalVertexAttribType.Sscaled:
{
switch (Attrib.Size)
{
case GalVertexAttribSize._8:
case GalVertexAttribSize._8_8:
case GalVertexAttribSize._8_8_8:
case GalVertexAttribSize._8_8_8_8:
{
Type = Signed
? VertexAttribPointerType.Byte
: VertexAttribPointerType.UnsignedByte;
break;
}
case GalVertexAttribSize._16:
case GalVertexAttribSize._16_16:
case GalVertexAttribSize._16_16_16:
case GalVertexAttribSize._16_16_16_16:
{
Type = Signed
? VertexAttribPointerType.Short
: VertexAttribPointerType.UnsignedShort;
break;
}
case GalVertexAttribSize._10_10_10_2:
case GalVertexAttribSize._11_11_10:
case GalVertexAttribSize._32:
case GalVertexAttribSize._32_32:
case GalVertexAttribSize._32_32_32:
case GalVertexAttribSize._32_32_32_32:
{
Type = Signed
? VertexAttribPointerType.Int
: VertexAttribPointerType.UnsignedInt;
break;
}
}
break;
}
case GalVertexAttribType.Float:
{
Type = VertexAttribPointerType.Float;
break;
}
}
GL.VertexAttribPointer(
Attrib.Index,
Size,
Type,
Normalize,
Stride,
Attrib.Offset);
}
GL.BindVertexArray(0);
}
public void SendR8G8B8A8Texture(int Index, byte[] Buffer, int Width, int Height)
public void SetBlend(
GalBlendEquation Equation,
GalBlendFactor FuncSrc,
GalBlendFactor FuncDst)
{
EnsureTexInitialized(Index);
GL.BindTexture(TextureTarget.Texture2D, Textures[Index].Handle);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)TextureWrapMode.Repeat);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)TextureWrapMode.Repeat);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear);
GL.TexImage2D(TextureTarget.Texture2D,
0,
PixelInternalFormat.Rgba,
Width,
Height,
0,
PixelFormat.Rgba,
PixelType.UnsignedByte,
Buffer);
ActionsQueue.Enqueue(() => Blend.Set(Equation, FuncSrc, FuncDst));
}
public void BindTexture(int Index)
public void SetBlendSeparate(
GalBlendEquation EquationRgb,
GalBlendEquation EquationAlpha,
GalBlendFactor FuncSrcRgb,
GalBlendFactor FuncDstRgb,
GalBlendFactor FuncSrcAlpha,
GalBlendFactor FuncDstAlpha)
{
GL.ActiveTexture(TextureUnit.Texture0 + Index);
GL.BindTexture(TextureTarget.Texture2D, Textures[Index].Handle);
ActionsQueue.Enqueue(() =>
{
Blend.SetSeparate(
EquationRgb,
EquationAlpha,
FuncSrcRgb,
FuncDstRgb,
FuncSrcAlpha,
FuncDstAlpha);
});
}
private void EnsureVbInitialized(int VbIndex)
public void SetFb(int FbIndex, int Width, int Height)
{
while (VbIndex >= VertexBuffers.Count)
{
VertexBuffers.Add(new VertexBuffer());
}
VertexBuffer Vb = VertexBuffers[VbIndex];
if (Vb.VaoHandle == 0)
{
Vb.VaoHandle = GL.GenVertexArray();
}
if (Vb.VboHandle == 0)
{
Vb.VboHandle = GL.GenBuffer();
}
VertexBuffers[VbIndex] = Vb;
ActionsQueue.Enqueue(() => FrameBuffer.Set(FbIndex, Width, Height));
}
private void EnsureTexInitialized(int TexIndex)
public void BindFrameBuffer(int FbIndex)
{
Texture Tex = Textures[TexIndex];
ActionsQueue.Enqueue(() => FrameBuffer.Bind(FbIndex));
}
if (Tex.Handle == 0)
public void DrawFrameBuffer(int FbIndex)
{
ActionsQueue.Enqueue(() => FrameBuffer.Draw(FbIndex));
}
public void ClearBuffers(int RtIndex, GalClearBufferFlags Flags)
{
ActionsQueue.Enqueue(() => Rasterizer.ClearBuffers(RtIndex, Flags));
}
public void SetVertexArray(int VbIndex, int Stride, byte[] Buffer, GalVertexAttrib[] Attribs)
{
if ((uint)VbIndex > 31)
{
Tex.Handle = GL.GenTexture();
throw new ArgumentOutOfRangeException(nameof(VbIndex));
}
Textures[TexIndex] = Tex;
ActionsQueue.Enqueue(() => Rasterizer.SetVertexArray(VbIndex, Stride,
Buffer ?? throw new ArgumentNullException(nameof(Buffer)),
Attribs ?? throw new ArgumentNullException(nameof(Attribs))));
}
public void SetIndexArray(byte[] Buffer, GalIndexFormat Format)
{
if (Buffer == null)
{
throw new ArgumentNullException(nameof(Buffer));
}
ActionsQueue.Enqueue(() => Rasterizer.SetIndexArray(Buffer, Format));
}
public void DrawArrays(int VbIndex, GalPrimitiveType PrimType)
{
if ((uint)VbIndex > 31)
{
throw new ArgumentOutOfRangeException(nameof(VbIndex));
}
ActionsQueue.Enqueue(() => Rasterizer.DrawArrays(VbIndex, PrimType));
}
public void DrawElements(int VbIndex, int First, GalPrimitiveType PrimType)
{
if ((uint)VbIndex > 31)
{
throw new ArgumentOutOfRangeException(nameof(VbIndex));
}
ActionsQueue.Enqueue(() => Rasterizer.DrawElements(VbIndex, First, PrimType));
}
public void CreateShader(long Tag, GalShaderType Type, byte[] Data)
{
if (Data == null)
{
throw new ArgumentNullException(nameof(Data));
}
Shader.Create(Tag, Type, Data);
}
public void SetConstBuffer(long Tag, int Cbuf, byte[] Data)
{
if (Data == null)
{
throw new ArgumentNullException(nameof(Data));
}
ActionsQueue.Enqueue(() => Shader.SetConstBuffer(Tag, Cbuf, Data));
}
public void SetUniform1(string UniformName, int Value)
{
if (UniformName == null)
{
throw new ArgumentNullException(nameof(UniformName));
}
ActionsQueue.Enqueue(() => Shader.SetUniform1(UniformName, Value));
}
public IEnumerable<ShaderDeclInfo> GetTextureUsage(long Tag)
{
return Shader.GetTextureUsage(Tag);
}
public void BindShader(long Tag)
{
ActionsQueue.Enqueue(() => Shader.Bind(Tag));
}
public void BindProgram()
{
ActionsQueue.Enqueue(() => Shader.BindProgram());
}
public void SetTexture(int Index, GalTexture Tex)
{
ActionsQueue.Enqueue(() => Texture.Set(Index, Tex));
}
public void SetSampler(int Index, GalTextureSampler Sampler)
{
ActionsQueue.Enqueue(() => Texture.Set(Index, Sampler));
}
}
}