Move Vertex Assembly into GalPipelineState

This commit is contained in:
ReinUsesLisp 2018-08-01 00:43:42 -03:00
commit c9245100a0
6 changed files with 167 additions and 147 deletions

View file

@ -1,8 +1,28 @@
namespace Ryujinx.Graphics.Gal namespace Ryujinx.Graphics.Gal
{ {
public struct GalVertexBinding
{
//VboKey shouldn't be here, but ARB_vertex_attrib_binding is core since 4.3
public bool Enabled;
public int Stride;
public long VboKey;
public GalVertexAttrib[] Attribs;
}
public struct GalConstBufferBinding
{
public bool Enabled;
public long Key;
}
public struct GalPipelineState public struct GalPipelineState
{ {
public const int ConstBuffersPerStage = 18;
public GalConstBufferBinding[][] ConstBufferKeys;
public GalVertexBinding[] VertexBindings;
public GalFrontFace FrontFace; public GalFrontFace FrontFace;

View file

@ -17,8 +17,6 @@ namespace Ryujinx.Graphics.Gal
void CreateIbo(long Key, int DataSize, IntPtr HostAddress); void CreateIbo(long Key, int DataSize, IntPtr HostAddress);
void SetVertexArray(int Stride, long VboKey, GalVertexAttrib[] Attribs);
void SetIndexArray(int Size, GalIndexFormat Format); void SetIndexArray(int Size, GalIndexFormat Format);
void DrawArrays(int First, int PrimCount, GalPrimitiveType PrimType); void DrawArrays(int First, int PrimCount, GalPrimitiveType PrimType);

View file

@ -1,62 +1,157 @@
using OpenTK.Graphics.OpenGL; using OpenTK.Graphics.OpenGL;
using System; using System;
using System.Collections.Generic;
namespace Ryujinx.Graphics.Gal.OpenGL namespace Ryujinx.Graphics.Gal.OpenGL
{ {
public class OGLPipeline : IGalPipeline public class OGLPipeline : IGalPipeline
{ {
private static Dictionary<GalVertexAttribSize, int> AttribElements =
new Dictionary<GalVertexAttribSize, int>()
{
{ GalVertexAttribSize._32_32_32_32, 4 },
{ GalVertexAttribSize._32_32_32, 3 },
{ GalVertexAttribSize._16_16_16_16, 4 },
{ GalVertexAttribSize._32_32, 2 },
{ GalVertexAttribSize._16_16_16, 3 },
{ GalVertexAttribSize._8_8_8_8, 4 },
{ GalVertexAttribSize._16_16, 2 },
{ GalVertexAttribSize._32, 1 },
{ GalVertexAttribSize._8_8_8, 3 },
{ GalVertexAttribSize._8_8, 2 },
{ GalVertexAttribSize._16, 1 },
{ GalVertexAttribSize._8, 1 },
{ GalVertexAttribSize._10_10_10_2, 4 },
{ GalVertexAttribSize._11_11_10, 3 }
};
private static Dictionary<GalVertexAttribSize, VertexAttribPointerType> AttribTypes =
new Dictionary<GalVertexAttribSize, VertexAttribPointerType>()
{
{ GalVertexAttribSize._32_32_32_32, VertexAttribPointerType.Int },
{ GalVertexAttribSize._32_32_32, VertexAttribPointerType.Int },
{ GalVertexAttribSize._16_16_16_16, VertexAttribPointerType.Short },
{ GalVertexAttribSize._32_32, VertexAttribPointerType.Int },
{ GalVertexAttribSize._16_16_16, VertexAttribPointerType.Short },
{ GalVertexAttribSize._8_8_8_8, VertexAttribPointerType.Byte },
{ GalVertexAttribSize._16_16, VertexAttribPointerType.Short },
{ GalVertexAttribSize._32, VertexAttribPointerType.Int },
{ GalVertexAttribSize._8_8_8, VertexAttribPointerType.Byte },
{ GalVertexAttribSize._8_8, VertexAttribPointerType.Byte },
{ GalVertexAttribSize._16, VertexAttribPointerType.Short },
{ GalVertexAttribSize._8, VertexAttribPointerType.Byte },
{ GalVertexAttribSize._10_10_10_2, VertexAttribPointerType.Int }, //?
{ GalVertexAttribSize._11_11_10, VertexAttribPointerType.Int } //?
};
private GalPipelineState O; private GalPipelineState O;
public OGLPipeline() private OGLRasterizer Rasterizer;
private int VaoHandle;
public OGLPipeline(OGLRasterizer Rasterizer)
{ {
//The following values match OpenGL's defaults this.Rasterizer = Rasterizer;
O = new GalPipelineState();
O.FrontFace = GalFrontFace.CCW; //These values match OpenGL's defaults
O = new GalPipelineState
{
FrontFace = GalFrontFace.CCW,
O.CullFaceEnabled = false; CullFaceEnabled = false,
O.CullFace = GalCullFace.Back; CullFace = GalCullFace.Back,
O.DepthTestEnabled = false; DepthTestEnabled = false,
O.DepthClear = 1f; DepthClear = 1f,
O.DepthFunc = GalComparisonOp.Less; DepthFunc = GalComparisonOp.Less,
O.StencilTestEnabled = false; StencilTestEnabled = false,
O.StencilClear = 0; StencilClear = 0,
O.StencilBackFuncFunc = GalComparisonOp.Always; StencilBackFuncFunc = GalComparisonOp.Always,
O.StencilBackFuncRef = 0; StencilBackFuncRef = 0,
O.StencilBackFuncMask = UInt32.MaxValue; StencilBackFuncMask = UInt32.MaxValue,
O.StencilBackOpFail = GalStencilOp.Keep; StencilBackOpFail = GalStencilOp.Keep,
O.StencilBackOpZFail = GalStencilOp.Keep; StencilBackOpZFail = GalStencilOp.Keep,
O.StencilBackOpZPass = GalStencilOp.Keep; StencilBackOpZPass = GalStencilOp.Keep,
O.StencilBackMask = UInt32.MaxValue; StencilBackMask = UInt32.MaxValue,
O.StencilFrontFuncFunc = GalComparisonOp.Always; StencilFrontFuncFunc = GalComparisonOp.Always,
O.StencilFrontFuncRef = 0; StencilFrontFuncRef = 0,
O.StencilFrontFuncMask = UInt32.MaxValue; StencilFrontFuncMask = UInt32.MaxValue,
O.StencilFrontOpFail = GalStencilOp.Keep; StencilFrontOpFail = GalStencilOp.Keep,
O.StencilFrontOpZFail = GalStencilOp.Keep; StencilFrontOpZFail = GalStencilOp.Keep,
O.StencilFrontOpZPass = GalStencilOp.Keep; StencilFrontOpZPass = GalStencilOp.Keep,
O.StencilFrontMask = UInt32.MaxValue; StencilFrontMask = UInt32.MaxValue,
O.BlendEnabled = false; BlendEnabled = false,
O.BlendSeparateAlpha = false; BlendSeparateAlpha = false,
O.BlendEquationRgb = 0; BlendEquationRgb = 0,
O.BlendFuncSrcRgb = GalBlendFactor.One; BlendFuncSrcRgb = GalBlendFactor.One,
O.BlendFuncDstRgb = GalBlendFactor.Zero; BlendFuncDstRgb = GalBlendFactor.Zero,
O.BlendEquationAlpha = 0; BlendEquationAlpha = 0,
O.BlendFuncSrcAlpha = GalBlendFactor.One; BlendFuncSrcAlpha = GalBlendFactor.One,
O.BlendFuncDstAlpha = GalBlendFactor.Zero; BlendFuncDstAlpha = GalBlendFactor.Zero,
O.PrimitiveRestartEnabled = false; PrimitiveRestartEnabled = false,
O.PrimitiveRestartIndex = 0; PrimitiveRestartIndex = 0
};
} }
public void Bind(ref GalPipelineState S) public void Bind(ref GalPipelineState S)
{ {
// O stands for Other, S from State (current state) //O stands for Older, S for (current) State
foreach (GalVertexBinding Binding in S.VertexBindings)
{
if (!Binding.Enabled || !Rasterizer.TryGetVbo(Binding.VboKey, out int VboHandle))
{
continue;
}
if (VaoHandle == 0)
{
VaoHandle = GL.GenVertexArray();
//Vertex arrays shouldn't be used anywhere else in OpenGL's backend
//if you want to use it, move this line out of the if
GL.BindVertexArray(VaoHandle);
}
foreach (GalVertexAttrib Attrib in Binding.Attribs)
{
GL.EnableVertexAttribArray(Attrib.Index);
GL.BindBuffer(BufferTarget.ArrayBuffer, VboHandle);
bool Unsigned =
Attrib.Type == GalVertexAttribType.Unorm ||
Attrib.Type == GalVertexAttribType.Uint ||
Attrib.Type == GalVertexAttribType.Uscaled;
bool Normalize =
Attrib.Type == GalVertexAttribType.Snorm ||
Attrib.Type == GalVertexAttribType.Unorm;
VertexAttribPointerType Type = 0;
if (Attrib.Type == GalVertexAttribType.Float)
{
Type = VertexAttribPointerType.Float;
}
else
{
Type = AttribTypes[Attrib.Size] + (Unsigned ? 1 : 0);
}
int Size = AttribElements[Attrib.Size];
int Offset = Attrib.Offset;
GL.VertexAttribPointer(Attrib.Index, Size, Type, Normalize, Binding.Stride, Offset);
}
}
//Note: Uncomment SetFrontFace and SetCullFace when flipping issues are solved //Note: Uncomment SetFrontFace and SetCullFace when flipping issues are solved

View file

@ -6,46 +6,6 @@ namespace Ryujinx.Graphics.Gal.OpenGL
{ {
public class OGLRasterizer : IGalRasterizer public class OGLRasterizer : IGalRasterizer
{ {
private static Dictionary<GalVertexAttribSize, int> AttribElements =
new Dictionary<GalVertexAttribSize, int>()
{
{ GalVertexAttribSize._32_32_32_32, 4 },
{ GalVertexAttribSize._32_32_32, 3 },
{ GalVertexAttribSize._16_16_16_16, 4 },
{ GalVertexAttribSize._32_32, 2 },
{ GalVertexAttribSize._16_16_16, 3 },
{ GalVertexAttribSize._8_8_8_8, 4 },
{ GalVertexAttribSize._16_16, 2 },
{ GalVertexAttribSize._32, 1 },
{ GalVertexAttribSize._8_8_8, 3 },
{ GalVertexAttribSize._8_8, 2 },
{ GalVertexAttribSize._16, 1 },
{ GalVertexAttribSize._8, 1 },
{ GalVertexAttribSize._10_10_10_2, 4 },
{ GalVertexAttribSize._11_11_10, 3 }
};
private static Dictionary<GalVertexAttribSize, VertexAttribPointerType> AttribTypes =
new Dictionary<GalVertexAttribSize, VertexAttribPointerType>()
{
{ GalVertexAttribSize._32_32_32_32, VertexAttribPointerType.Int },
{ GalVertexAttribSize._32_32_32, VertexAttribPointerType.Int },
{ GalVertexAttribSize._16_16_16_16, VertexAttribPointerType.Short },
{ GalVertexAttribSize._32_32, VertexAttribPointerType.Int },
{ GalVertexAttribSize._16_16_16, VertexAttribPointerType.Short },
{ GalVertexAttribSize._8_8_8_8, VertexAttribPointerType.Byte },
{ GalVertexAttribSize._16_16, VertexAttribPointerType.Short },
{ GalVertexAttribSize._32, VertexAttribPointerType.Int },
{ GalVertexAttribSize._8_8_8, VertexAttribPointerType.Byte },
{ GalVertexAttribSize._8_8, VertexAttribPointerType.Byte },
{ GalVertexAttribSize._16, VertexAttribPointerType.Short },
{ GalVertexAttribSize._8, VertexAttribPointerType.Byte },
{ GalVertexAttribSize._10_10_10_2, VertexAttribPointerType.Int }, //?
{ GalVertexAttribSize._11_11_10, VertexAttribPointerType.Int } //?
};
private int VaoHandle;
private int[] VertexBuffers; private int[] VertexBuffers;
private OGLCachedResource<int> VboCache; private OGLCachedResource<int> VboCache;
@ -142,65 +102,6 @@ namespace Ryujinx.Graphics.Gal.OpenGL
GL.BufferData(BufferTarget.ElementArrayBuffer, Length, HostAddress, BufferUsageHint.StreamDraw); GL.BufferData(BufferTarget.ElementArrayBuffer, Length, HostAddress, BufferUsageHint.StreamDraw);
} }
public void SetVertexArray(int Stride, long VboKey, GalVertexAttrib[] Attribs)
{
if (!VboCache.TryGetValue(VboKey, out int VboHandle))
{
return;
}
if (VaoHandle == 0)
{
VaoHandle = GL.GenVertexArray();
}
GL.BindVertexArray(VaoHandle);
foreach (GalVertexAttrib Attrib in Attribs)
{
GL.EnableVertexAttribArray(Attrib.Index);
GL.BindBuffer(BufferTarget.ArrayBuffer, VboHandle);
bool Unsigned =
Attrib.Type == GalVertexAttribType.Unorm ||
Attrib.Type == GalVertexAttribType.Uint ||
Attrib.Type == GalVertexAttribType.Uscaled;
bool Normalize =
Attrib.Type == GalVertexAttribType.Snorm ||
Attrib.Type == GalVertexAttribType.Unorm;
VertexAttribPointerType Type = 0;
if (Attrib.Type == GalVertexAttribType.Float)
{
Type = VertexAttribPointerType.Float;
}
else
{
Type = AttribTypes[Attrib.Size] + (Unsigned ? 1 : 0);
}
int Size = AttribElements[Attrib.Size];
int Offset = Attrib.Offset;
if (Attrib.Type == GalVertexAttribType.Sint ||
Attrib.Type == GalVertexAttribType.Uint)
{
IntPtr Pointer = new IntPtr(Offset);
VertexAttribIntegerType IType = (VertexAttribIntegerType)Type;
GL.VertexAttribIPointer(Attrib.Index, Size, IType, Stride, Pointer);
}
else
{
GL.VertexAttribPointer(Attrib.Index, Size, Type, Normalize, Stride, Offset);
}
}
}
public void SetIndexArray(int Size, GalIndexFormat Format) public void SetIndexArray(int Size, GalIndexFormat Format)
{ {
IndexBuffer.Type = OGLEnumConverter.GetDrawElementsType(Format); IndexBuffer.Type = OGLEnumConverter.GetDrawElementsType(Format);
@ -217,8 +118,6 @@ namespace Ryujinx.Graphics.Gal.OpenGL
return; return;
} }
GL.BindVertexArray(VaoHandle);
GL.DrawArrays(OGLEnumConverter.GetPrimitiveType(PrimType), First, PrimCount); GL.DrawArrays(OGLEnumConverter.GetPrimitiveType(PrimType), First, PrimCount);
} }
@ -231,8 +130,6 @@ namespace Ryujinx.Graphics.Gal.OpenGL
PrimitiveType Mode = OGLEnumConverter.GetPrimitiveType(PrimType); PrimitiveType Mode = OGLEnumConverter.GetPrimitiveType(PrimType);
GL.BindVertexArray(VaoHandle);
GL.BindBuffer(BufferTarget.ElementArrayBuffer, IboHandle); GL.BindBuffer(BufferTarget.ElementArrayBuffer, IboHandle);
First <<= IndexBuffer.ElemSizeLog2; First <<= IndexBuffer.ElemSizeLog2;
@ -248,5 +145,10 @@ namespace Ryujinx.Graphics.Gal.OpenGL
GL.DrawElements(Mode, IndexBuffer.Count, IndexBuffer.Type, First); GL.DrawElements(Mode, IndexBuffer.Count, IndexBuffer.Type, First);
} }
} }
public bool TryGetVbo(long VboKey, out int VboHandle)
{
return VboCache.TryGetValue(VboKey, out VboHandle);
}
} }
} }

View file

@ -29,7 +29,7 @@ namespace Ryujinx.Graphics.Gal.OpenGL
Shader = new OGLShader(Buffer as OGLConstBuffer); Shader = new OGLShader(Buffer as OGLConstBuffer);
Pipeline = new OGLPipeline(); Pipeline = new OGLPipeline(Rasterizer as OGLRasterizer);
Texture = new OGLTexture(); Texture = new OGLTexture();

View file

@ -530,6 +530,8 @@ namespace Ryujinx.HLE.Gpu.Engines
((Packed >> 31) & 0x1) != 0)); ((Packed >> 31) & 0x1) != 0));
} }
State.VertexBindings = new GalVertexBinding[32];
for (int Index = 0; Index < 32; Index++) for (int Index = 0; Index < 32; Index++)
{ {
if (Attribs[Index] == null) if (Attribs[Index] == null)
@ -541,14 +543,14 @@ namespace Ryujinx.HLE.Gpu.Engines
bool Enable = (Control & 0x1000) != 0; bool Enable = (Control & 0x1000) != 0;
long VertexPosition = MakeInt64From2xInt32(NvGpuEngine3dReg.VertexArrayNAddress + Index * 4);
long VertexEndPos = MakeInt64From2xInt32(NvGpuEngine3dReg.VertexArrayNEndAddr + Index * 2);
if (!Enable) if (!Enable)
{ {
continue; continue;
} }
long VertexPosition = MakeInt64From2xInt32(NvGpuEngine3dReg.VertexArrayNAddress + Index * 4);
long VertexEndPos = MakeInt64From2xInt32(NvGpuEngine3dReg.VertexArrayNEndAddr + Index * 2);
long VboKey = Vmm.GetPhysicalAddress(VertexPosition); long VboKey = Vmm.GetPhysicalAddress(VertexPosition);
int Stride = Control & 0xfff; int Stride = Control & 0xfff;
@ -564,7 +566,10 @@ namespace Ryujinx.HLE.Gpu.Engines
Gpu.Renderer.Rasterizer.CreateVbo(VboKey, (int)VbSize, DataAddress); Gpu.Renderer.Rasterizer.CreateVbo(VboKey, (int)VbSize, DataAddress);
} }
Gpu.Renderer.Rasterizer.SetVertexArray(Stride, VboKey, Attribs[Index].ToArray()); State.VertexBindings[Index].Enabled = true;
State.VertexBindings[Index].Stride = Stride;
State.VertexBindings[Index].VboKey = VboKey;
State.VertexBindings[Index].Attribs = Attribs[Index].ToArray();
} }
} }