aboutsummaryrefslogtreecommitdiff
path: root/Ryujinx.Graphics/NvGpuEngine3d.cs
diff options
context:
space:
mode:
authorgdkchan <gab.dark.100@gmail.com>2018-10-12 22:37:01 -0300
committerAc_K <Acoustik666@gmail.com>2018-10-13 01:37:01 +0000
commitaa1cd849cfe254dc7c8c9a0783a546a4b9b3c0ab (patch)
treee7d0f9d7399a835818068d7ca034b179cd95b91e /Ryujinx.Graphics/NvGpuEngine3d.cs
parentdd3cb33c9f43412617e2b2b76d9e2a4dec9a2a23 (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.cs83
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