Move Vertex Assembly into GalPipelineState

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

View file

@ -1,8 +1,28 @@
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 const int ConstBuffersPerStage = 18;
public GalConstBufferBinding[][] ConstBufferKeys;
public GalVertexBinding[] VertexBindings;
public GalFrontFace FrontFace;

View file

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

View file

@ -1,62 +1,157 @@
using OpenTK.Graphics.OpenGL;
using System;
using System.Collections.Generic;
namespace Ryujinx.Graphics.Gal.OpenGL
{
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;
public OGLPipeline()
private OGLRasterizer Rasterizer;
private int VaoHandle;
public OGLPipeline(OGLRasterizer Rasterizer)
{
//The following values match OpenGL's defaults
O = new GalPipelineState();
this.Rasterizer = Rasterizer;
O.FrontFace = GalFrontFace.CCW;
//These values match OpenGL's defaults
O = new GalPipelineState
{
FrontFace = GalFrontFace.CCW,
O.CullFaceEnabled = false;
O.CullFace = GalCullFace.Back;
CullFaceEnabled = false,
CullFace = GalCullFace.Back,
O.DepthTestEnabled = false;
O.DepthClear = 1f;
O.DepthFunc = GalComparisonOp.Less;
DepthTestEnabled = false,
DepthClear = 1f,
DepthFunc = GalComparisonOp.Less,
O.StencilTestEnabled = false;
O.StencilClear = 0;
StencilTestEnabled = false,
StencilClear = 0,
O.StencilBackFuncFunc = GalComparisonOp.Always;
O.StencilBackFuncRef = 0;
O.StencilBackFuncMask = UInt32.MaxValue;
O.StencilBackOpFail = GalStencilOp.Keep;
O.StencilBackOpZFail = GalStencilOp.Keep;
O.StencilBackOpZPass = GalStencilOp.Keep;
O.StencilBackMask = UInt32.MaxValue;
StencilBackFuncFunc = GalComparisonOp.Always,
StencilBackFuncRef = 0,
StencilBackFuncMask = UInt32.MaxValue,
StencilBackOpFail = GalStencilOp.Keep,
StencilBackOpZFail = GalStencilOp.Keep,
StencilBackOpZPass = GalStencilOp.Keep,
StencilBackMask = UInt32.MaxValue,
O.StencilFrontFuncFunc = GalComparisonOp.Always;
O.StencilFrontFuncRef = 0;
O.StencilFrontFuncMask = UInt32.MaxValue;
O.StencilFrontOpFail = GalStencilOp.Keep;
O.StencilFrontOpZFail = GalStencilOp.Keep;
O.StencilFrontOpZPass = GalStencilOp.Keep;
O.StencilFrontMask = UInt32.MaxValue;
StencilFrontFuncFunc = GalComparisonOp.Always,
StencilFrontFuncRef = 0,
StencilFrontFuncMask = UInt32.MaxValue,
StencilFrontOpFail = GalStencilOp.Keep,
StencilFrontOpZFail = GalStencilOp.Keep,
StencilFrontOpZPass = GalStencilOp.Keep,
StencilFrontMask = UInt32.MaxValue,
O.BlendEnabled = false;
O.BlendSeparateAlpha = false;
BlendEnabled = false,
BlendSeparateAlpha = false,
O.BlendEquationRgb = 0;
O.BlendFuncSrcRgb = GalBlendFactor.One;
O.BlendFuncDstRgb = GalBlendFactor.Zero;
O.BlendEquationAlpha = 0;
O.BlendFuncSrcAlpha = GalBlendFactor.One;
O.BlendFuncDstAlpha = GalBlendFactor.Zero;
BlendEquationRgb = 0,
BlendFuncSrcRgb = GalBlendFactor.One,
BlendFuncDstRgb = GalBlendFactor.Zero,
BlendEquationAlpha = 0,
BlendFuncSrcAlpha = GalBlendFactor.One,
BlendFuncDstAlpha = GalBlendFactor.Zero,
O.PrimitiveRestartEnabled = false;
O.PrimitiveRestartIndex = 0;
PrimitiveRestartEnabled = false,
PrimitiveRestartIndex = 0
};
}
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

View file

@ -6,46 +6,6 @@ namespace Ryujinx.Graphics.Gal.OpenGL
{
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 OGLCachedResource<int> VboCache;
@ -142,65 +102,6 @@ namespace Ryujinx.Graphics.Gal.OpenGL
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)
{
IndexBuffer.Type = OGLEnumConverter.GetDrawElementsType(Format);
@ -217,8 +118,6 @@ namespace Ryujinx.Graphics.Gal.OpenGL
return;
}
GL.BindVertexArray(VaoHandle);
GL.DrawArrays(OGLEnumConverter.GetPrimitiveType(PrimType), First, PrimCount);
}
@ -231,8 +130,6 @@ namespace Ryujinx.Graphics.Gal.OpenGL
PrimitiveType Mode = OGLEnumConverter.GetPrimitiveType(PrimType);
GL.BindVertexArray(VaoHandle);
GL.BindBuffer(BufferTarget.ElementArrayBuffer, IboHandle);
First <<= IndexBuffer.ElemSizeLog2;
@ -248,5 +145,10 @@ namespace Ryujinx.Graphics.Gal.OpenGL
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);
Pipeline = new OGLPipeline();
Pipeline = new OGLPipeline(Rasterizer as OGLRasterizer);
Texture = new OGLTexture();

View file

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