Improved GPU command lists decoding (#499)

* Better implementation of the DMA pusher, misc fixes

* Remove some debug code

* Correct RGBX8 format

* Add support for linked Texture Sampler Control

* Attempt to fix upside down screen issue
This commit is contained in:
gdkchan 2018-11-17 02:01:31 -02:00 committed by Ac_K
parent b833183ef6
commit d2bb458b51
25 changed files with 616 additions and 395 deletions

View file

@ -7,7 +7,7 @@ using System.Collections.Generic;
namespace Ryujinx.Graphics
{
public class NvGpuEngine3d : INvGpuEngine
class NvGpuEngine3d : INvGpuEngine
{
public int[] Registers { get; private set; }
@ -24,8 +24,6 @@ namespace Ryujinx.Graphics
private ConstBuffer[][] ConstBuffers;
private List<long>[] UploadedKeys;
private int CurrentInstance = 0;
public NvGpuEngine3d(NvGpu Gpu)
@ -59,13 +57,6 @@ namespace Ryujinx.Graphics
ConstBuffers[Index] = new ConstBuffer[18];
}
UploadedKeys = new List<long>[(int)NvGpuBufferType.Count];
for (int i = 0; i < UploadedKeys.Length; i++)
{
UploadedKeys[i] = new List<long>();
}
//Ensure that all components are enabled by default.
//FIXME: Is this correct?
WriteRegister(NvGpuEngine3dReg.ColorMaskN, 0x1111);
@ -81,27 +72,19 @@ namespace Ryujinx.Graphics
}
}
public void CallMethod(NvGpuVmm Vmm, NvGpuPBEntry PBEntry)
public void CallMethod(NvGpuVmm Vmm, GpuMethodCall MethCall)
{
if (Methods.TryGetValue(PBEntry.Method, out NvGpuMethod Method))
if (Methods.TryGetValue(MethCall.Method, out NvGpuMethod Method))
{
Method(Vmm, PBEntry);
Method(Vmm, MethCall);
}
else
{
WriteRegister(PBEntry);
WriteRegister(MethCall);
}
}
public void ResetCache()
{
foreach (List<long> Uploaded in UploadedKeys)
{
Uploaded.Clear();
}
}
private void VertexEndGl(NvGpuVmm Vmm, NvGpuPBEntry PBEntry)
private void VertexEndGl(NvGpuVmm Vmm, GpuMethodCall MethCall)
{
LockCaches();
@ -152,13 +135,11 @@ namespace Ryujinx.Graphics
Gpu.Renderer.Texture.UnlockCache();
}
private void ClearBuffers(NvGpuVmm Vmm, NvGpuPBEntry PBEntry)
private void ClearBuffers(NvGpuVmm Vmm, GpuMethodCall MethCall)
{
int Arg0 = PBEntry.Arguments[0];
int Attachment = (MethCall.Argument >> 6) & 0xf;
int Attachment = (Arg0 >> 6) & 0xf;
GalClearBufferFlags Flags = (GalClearBufferFlags)(Arg0 & 0x3f);
GalClearBufferFlags Flags = (GalClearBufferFlags)(MethCall.Argument & 0x3f);
float Red = ReadRegisterFloat(NvGpuEngine3dReg.ClearNColor + 0);
float Green = ReadRegisterFloat(NvGpuEngine3dReg.ClearNColor + 1);
@ -234,6 +215,15 @@ namespace Ryujinx.Graphics
State.FlipX = GetFlipSign(NvGpuEngine3dReg.ViewportNScaleX);
State.FlipY = GetFlipSign(NvGpuEngine3dReg.ViewportNScaleY);
int ScreenYControl = ReadRegister(NvGpuEngine3dReg.ScreenYControl);
bool NegateY = (ScreenYControl & 1) != 0;
if (NegateY)
{
State.FlipY = -State.FlipY;
}
}
private void SetZeta(NvGpuVmm Vmm)
@ -566,8 +556,11 @@ namespace Ryujinx.Graphics
return;
}
bool LinkedTsc = ReadRegisterBool(NvGpuEngine3dReg.LinkedTsc);
int TicIndex = (TextureHandle >> 0) & 0xfffff;
int TscIndex = (TextureHandle >> 20) & 0xfff;
int TscIndex = LinkedTsc ? TicIndex : (TextureHandle >> 20) & 0xfff;
long TicPosition = MakeInt64From2xInt32(NvGpuEngine3dReg.TexHeaderPoolOffset);
long TscPosition = MakeInt64From2xInt32(NvGpuEngine3dReg.TexSamplerPoolOffset);
@ -618,7 +611,7 @@ namespace Ryujinx.Graphics
long Key = Vmm.GetPhysicalAddress(Cb.Position);
if (QueryKeyUpload(Vmm, Key, Cb.Size, NvGpuBufferType.ConstBuffer))
if (Gpu.ResourceManager.MemoryRegionModified(Vmm, Key, Cb.Size, NvGpuBufferType.ConstBuffer))
{
IntPtr Source = Vmm.GetHostAddress(Cb.Position, Cb.Size);
@ -661,7 +654,7 @@ namespace Ryujinx.Graphics
PrimType == GalPrimitiveType.Quads ||
PrimType == GalPrimitiveType.QuadStrip;
if (!IboCached || QueryKeyUpload(Vmm, IboKey, (uint)IbSize, NvGpuBufferType.Index))
if (!IboCached || Gpu.ResourceManager.MemoryRegionModified(Vmm, IboKey, (uint)IbSize, NvGpuBufferType.Index))
{
if (!UsesLegacyQuads)
{
@ -778,7 +771,7 @@ namespace Ryujinx.Graphics
bool VboCached = Gpu.Renderer.Rasterizer.IsVboCached(VboKey, VbSize);
if (!VboCached || QueryKeyUpload(Vmm, VboKey, VbSize, NvGpuBufferType.Vertex))
if (!VboCached || Gpu.ResourceManager.MemoryRegionModified(Vmm, VboKey, VbSize, NvGpuBufferType.Vertex))
{
IntPtr DataAddress = Vmm.GetHostAddress(VertexPosition, VbSize);
@ -877,9 +870,9 @@ namespace Ryujinx.Graphics
WriteCounterAndTimestamp
}
private void QueryControl(NvGpuVmm Vmm, NvGpuPBEntry PBEntry)
private void QueryControl(NvGpuVmm Vmm, GpuMethodCall MethCall)
{
WriteRegister(PBEntry);
WriteRegister(MethCall);
long Position = MakeInt64From2xInt32(NvGpuEngine3dReg.QueryAddress);
@ -909,29 +902,24 @@ namespace Ryujinx.Graphics
}
}
private void CbData(NvGpuVmm Vmm, NvGpuPBEntry PBEntry)
private void CbData(NvGpuVmm Vmm, GpuMethodCall MethCall)
{
long Position = MakeInt64From2xInt32(NvGpuEngine3dReg.ConstBufferAddress);
int Offset = ReadRegister(NvGpuEngine3dReg.ConstBufferOffset);
foreach (int Arg in PBEntry.Arguments)
{
Vmm.WriteInt32(Position + Offset, Arg);
Vmm.WriteInt32(Position + Offset, MethCall.Argument);
Offset += 4;
}
WriteRegister(NvGpuEngine3dReg.ConstBufferOffset, Offset + 4);
WriteRegister(NvGpuEngine3dReg.ConstBufferOffset, Offset);
UploadedKeys[(int)NvGpuBufferType.ConstBuffer].Clear();
Gpu.ResourceManager.ClearPbCache(NvGpuBufferType.ConstBuffer);
}
private void CbBind(NvGpuVmm Vmm, NvGpuPBEntry PBEntry)
private void CbBind(NvGpuVmm Vmm, GpuMethodCall MethCall)
{
int Stage = (PBEntry.Method - 0x904) >> 3;
int Stage = (MethCall.Method - 0x904) >> 3;
int Index = PBEntry.Arguments[0];
int Index = MethCall.Argument;
bool Enabled = (Index & 1) != 0;
@ -970,14 +958,9 @@ namespace Ryujinx.Graphics
(uint)Registers[(int)Reg + 1];
}
private void WriteRegister(NvGpuPBEntry PBEntry)
private void WriteRegister(GpuMethodCall MethCall)
{
int ArgsCount = PBEntry.Arguments.Count;
if (ArgsCount > 0)
{
Registers[PBEntry.Method] = PBEntry.Arguments[ArgsCount - 1];
}
Registers[MethCall.Method] = MethCall.Argument;
}
private int ReadRegister(NvGpuEngine3dReg Reg)
@ -999,19 +982,5 @@ namespace Ryujinx.Graphics
{
Registers[(int)Reg] = Value;
}
private bool QueryKeyUpload(NvGpuVmm Vmm, long Key, long Size, NvGpuBufferType Type)
{
List<long> Uploaded = UploadedKeys[(int)Type];
if (Uploaded.Contains(Key))
{
return false;
}
Uploaded.Add(Key);
return Vmm.IsRegionModified(Key, Size, Type);
}
}
}