From aa1cd849cfe254dc7c8c9a0783a546a4b9b3c0ab Mon Sep 17 00:00:00 2001 From: gdkchan Date: Fri, 12 Oct 2018 22:37:01 -0300 Subject: Quads, QuadStrip, const attributes and half-float attributes support (#447) * Quads, QuadStrip and const attributes support * Add support for half float attributes and fix texture pitch alignment * Throw when an unsupported float type is used as const attribute aswell --- Ryujinx.Graphics/NvGpuEngine3d.cs | 83 +++++++++++++++++++++++++++++++++++---- 1 file changed, 76 insertions(+), 7 deletions(-) (limited to 'Ryujinx.Graphics/NvGpuEngine3d.cs') diff --git a/Ryujinx.Graphics/NvGpuEngine3d.cs b/Ryujinx.Graphics/NvGpuEngine3d.cs index 22c09377..3dd7746d 100644 --- a/Ryujinx.Graphics/NvGpuEngine3d.cs +++ b/Ryujinx.Graphics/NvGpuEngine3d.cs @@ -433,7 +433,7 @@ namespace Ryujinx.Graphics private void SetRenderTargets() { - //Commercial games do not seem to + //Commercial games do not seem to //bool SeparateFragData = ReadRegisterBool(NvGpuEngine3dReg.RTSeparateFragData); uint Control = (uint)(ReadRegister(NvGpuEngine3dReg.RTControl)); @@ -568,12 +568,15 @@ namespace Ryujinx.Graphics private void UploadVertexArrays(NvGpuVmm Vmm, GalPipelineState State) { - long IndexPosition = MakeInt64From2xInt32(NvGpuEngine3dReg.IndexArrayAddress); + long IbPosition = MakeInt64From2xInt32(NvGpuEngine3dReg.IndexArrayAddress); - long IboKey = Vmm.GetPhysicalAddress(IndexPosition); + long IboKey = Vmm.GetPhysicalAddress(IbPosition); int IndexEntryFmt = ReadRegister(NvGpuEngine3dReg.IndexArrayFormat); int IndexCount = ReadRegister(NvGpuEngine3dReg.IndexBatchCount); + int PrimCtrl = ReadRegister(NvGpuEngine3dReg.VertexBeginGl); + + GalPrimitiveType PrimType = (GalPrimitiveType)(PrimCtrl & 0xffff); GalIndexFormat IndexFormat = (GalIndexFormat)IndexEntryFmt; @@ -590,14 +593,50 @@ namespace Ryujinx.Graphics bool IboCached = Gpu.Renderer.Rasterizer.IsIboCached(IboKey, (uint)IbSize); + bool UsesLegacyQuads = + PrimType == GalPrimitiveType.Quads || + PrimType == GalPrimitiveType.QuadStrip; + if (!IboCached || QueryKeyUpload(Vmm, IboKey, (uint)IbSize, NvGpuBufferType.Index)) { - IntPtr DataAddress = Vmm.GetHostAddress(IndexPosition, IbSize); + if (!UsesLegacyQuads) + { + IntPtr DataAddress = Vmm.GetHostAddress(IbPosition, IbSize); - Gpu.Renderer.Rasterizer.CreateIbo(IboKey, IbSize, DataAddress); + Gpu.Renderer.Rasterizer.CreateIbo(IboKey, IbSize, DataAddress); + } + else + { + byte[] Buffer = Vmm.ReadBytes(IbPosition, IbSize); + + if (PrimType == GalPrimitiveType.Quads) + { + Buffer = QuadHelper.ConvertIbQuadsToTris(Buffer, IndexEntrySize, IndexCount); + } + else /* if (PrimType == GalPrimitiveType.QuadStrip) */ + { + Buffer = QuadHelper.ConvertIbQuadStripToTris(Buffer, IndexEntrySize, IndexCount); + } + + Gpu.Renderer.Rasterizer.CreateIbo(IboKey, IbSize, Buffer); + } } - Gpu.Renderer.Rasterizer.SetIndexArray(IbSize, IndexFormat); + if (!UsesLegacyQuads) + { + Gpu.Renderer.Rasterizer.SetIndexArray(IbSize, IndexFormat); + } + else + { + if (PrimType == GalPrimitiveType.Quads) + { + Gpu.Renderer.Rasterizer.SetIndexArray(QuadHelper.ConvertIbSizeQuadsToTris(IbSize), IndexFormat); + } + else /* if (PrimType == GalPrimitiveType.QuadStrip) */ + { + Gpu.Renderer.Rasterizer.SetIndexArray(QuadHelper.ConvertIbSizeQuadStripToTris(IbSize), IndexFormat); + } + } } List[] Attribs = new List[32]; @@ -613,10 +652,19 @@ namespace Ryujinx.Graphics Attribs[ArrayIndex] = new List(); } + long VertexPosition = MakeInt64From2xInt32(NvGpuEngine3dReg.VertexArrayNAddress + ArrayIndex * 4); + + int Offset = (Packed >> 7) & 0x3fff; + + //Note: 16 is the maximum size of an attribute, + //having a component size of 32-bits with 4 elements (a vec4). + IntPtr Pointer = Vmm.GetHostAddress(VertexPosition + Offset, 16); + Attribs[ArrayIndex].Add(new GalVertexAttrib( Attr, ((Packed >> 6) & 0x1) != 0, - (Packed >> 7) & 0x3fff, + Offset, + Pointer, (GalVertexAttribSize)((Packed >> 21) & 0x3f), (GalVertexAttribType)((Packed >> 27) & 0x7), ((Packed >> 31) & 0x1) != 0)); @@ -722,6 +770,27 @@ namespace Ryujinx.Graphics long IboKey = Vmm.GetPhysicalAddress(IndexPosition); + //Quad primitive types were deprecated on OpenGL 3.x, + //they are converted to a triangles index buffer on IB creation, + //so we should use the triangles type here too. + if (PrimType == GalPrimitiveType.Quads || + PrimType == GalPrimitiveType.QuadStrip) + { + PrimType = GalPrimitiveType.Triangles; + + //Note: We assume that index first points to the first + //vertex of a quad, if it points to the middle of a + //quad (First % 4 != 0 for Quads) then it will not work properly. + if (PrimType == GalPrimitiveType.Quads) + { + IndexFirst = QuadHelper.ConvertIbSizeQuadsToTris(IndexFirst); + } + else /* if (PrimType == GalPrimitiveType.QuadStrip) */ + { + IndexFirst = QuadHelper.ConvertIbSizeQuadStripToTris(IndexFirst); + } + } + Gpu.Renderer.Rasterizer.DrawElements(IboKey, IndexFirst, VertexBase, PrimType); } else -- cgit v1.2.3