diff options
| author | gdkchan <gab.dark.100@gmail.com> | 2018-10-12 22:37:01 -0300 |
|---|---|---|
| committer | Ac_K <Acoustik666@gmail.com> | 2018-10-13 01:37:01 +0000 |
| commit | aa1cd849cfe254dc7c8c9a0783a546a4b9b3c0ab (patch) | |
| tree | e7d0f9d7399a835818068d7ca034b179cd95b91e /Ryujinx.Graphics/NvGpuEngine3d.cs | |
| parent | dd3cb33c9f43412617e2b2b76d9e2a4dec9a2a23 (diff) | |
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
Diffstat (limited to 'Ryujinx.Graphics/NvGpuEngine3d.cs')
| -rw-r--r-- | Ryujinx.Graphics/NvGpuEngine3d.cs | 83 |
1 files changed, 76 insertions, 7 deletions
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<GalVertexAttrib>[] Attribs = new List<GalVertexAttrib>[32]; @@ -613,10 +652,19 @@ namespace Ryujinx.Graphics Attribs[ArrayIndex] = new List<GalVertexAttrib>(); } + 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 |
