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
This commit is contained in:
gdkchan 2018-10-12 22:37:01 -03:00 committed by Ac_K
parent dd3cb33c9f
commit aa1cd849cf
12 changed files with 420 additions and 53 deletions

View file

@ -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