diff --git a/Ryujinx.Graphics/Gal/GalPipelineState.cs b/Ryujinx.Graphics/Gal/GalPipelineState.cs index 095d341ea1..c35d226cbf 100644 --- a/Ryujinx.Graphics/Gal/GalPipelineState.cs +++ b/Ryujinx.Graphics/Gal/GalPipelineState.cs @@ -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; diff --git a/Ryujinx.Graphics/Gal/IGalRasterizer.cs b/Ryujinx.Graphics/Gal/IGalRasterizer.cs index 7c8f7dabbf..022db021f0 100644 --- a/Ryujinx.Graphics/Gal/IGalRasterizer.cs +++ b/Ryujinx.Graphics/Gal/IGalRasterizer.cs @@ -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); diff --git a/Ryujinx.Graphics/Gal/OpenGL/OGLPipeline.cs b/Ryujinx.Graphics/Gal/OpenGL/OGLPipeline.cs index 3ce9251ee4..4e2fbc72ca 100644 --- a/Ryujinx.Graphics/Gal/OpenGL/OGLPipeline.cs +++ b/Ryujinx.Graphics/Gal/OpenGL/OGLPipeline.cs @@ -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 AttribElements = + new Dictionary() + { + { 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 AttribTypes = + new Dictionary() + { + { 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 diff --git a/Ryujinx.Graphics/Gal/OpenGL/OGLRasterizer.cs b/Ryujinx.Graphics/Gal/OpenGL/OGLRasterizer.cs index 2c0008d9fa..23138dc0e6 100644 --- a/Ryujinx.Graphics/Gal/OpenGL/OGLRasterizer.cs +++ b/Ryujinx.Graphics/Gal/OpenGL/OGLRasterizer.cs @@ -6,46 +6,6 @@ namespace Ryujinx.Graphics.Gal.OpenGL { public class OGLRasterizer : IGalRasterizer { - private static Dictionary AttribElements = - new Dictionary() - { - { 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 AttribTypes = - new Dictionary() - { - { 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 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); + } } } \ No newline at end of file diff --git a/Ryujinx.Graphics/Gal/OpenGL/OGLRenderer.cs b/Ryujinx.Graphics/Gal/OpenGL/OGLRenderer.cs index 466b782251..db0c4400dd 100644 --- a/Ryujinx.Graphics/Gal/OpenGL/OGLRenderer.cs +++ b/Ryujinx.Graphics/Gal/OpenGL/OGLRenderer.cs @@ -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(); diff --git a/Ryujinx.HLE/Gpu/Engines/NvGpuEngine3d.cs b/Ryujinx.HLE/Gpu/Engines/NvGpuEngine3d.cs index df3da8ecee..be993d4dec 100644 --- a/Ryujinx.HLE/Gpu/Engines/NvGpuEngine3d.cs +++ b/Ryujinx.HLE/Gpu/Engines/NvGpuEngine3d.cs @@ -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(); } }