Some improvements to macro stuff

This commit is contained in:
gdkchan 2018-03-28 16:40:51 -03:00
parent 85e0ed9876
commit 0a0cc69a7b
5 changed files with 183 additions and 76 deletions

View file

@ -72,21 +72,12 @@ namespace Ryujinx.Graphics.Gal.OpenGL
Stages.Add(Tag, Stage);
CompileAndCheck(Stage.Handle, Glsl);
}
}
}
public void SetConstBuffer(int Cbuf, byte[] Data)
{
if (Cbuf != 3) return;
Console.WriteLine("cb: " + Cbuf);
foreach (byte b in Data)
{
Console.Write(b.ToString("x2") + " ");
}
Console.WriteLine();
}
public void Bind(long Tag)

View file

@ -6,6 +6,7 @@ namespace Ryujinx.Graphics.Gpu
{
class MacroInterpreter
{
private NvGpuFifo PFifo;
private INvGpuEngine Engine;
public Queue<int> Fifo { get; private set; }
@ -19,11 +20,12 @@ namespace Ryujinx.Graphics.Gpu
private long Pc;
public MacroInterpreter(INvGpuEngine Engine)
public MacroInterpreter(NvGpuFifo PFifo, INvGpuEngine Engine)
{
this.PFifo = PFifo;
this.Engine = Engine;
Fifo = new Queue<int>();
Fifo = new Queue<int>();
Gprs = new int[8];
}
@ -60,7 +62,7 @@ namespace Ryujinx.Graphics.Gpu
Pc += 4;
int Op = (OpCode >> 0) & 7;
int Op = OpCode & 7;
if (Op < 7)
{
@ -107,8 +109,14 @@ namespace Ryujinx.Graphics.Gpu
if (Taken)
{
//Execute one more instruction due to delay slot.
bool KeepExecuting = Step(Memory);
bool KeepExecuting = true;
//When bit 5 is set, branches executes as if delay slots didn't exist.
if ((OpCode & 0x20) == 0)
{
//Execute one more instruction due to delay slot.
KeepExecuting = Step(Memory);
}
Pc = BaseAddr + (GetImm(OpCode) << 2);
@ -166,7 +174,7 @@ namespace Ryujinx.Graphics.Gpu
//Bitfield move.
case 2:
{
Src = (Src >> BfSrcBit) & BfMask;
Src = (int)((uint)Src >> BfSrcBit) & BfMask;
Dst &= ~(BfMask << BfDstBit);
@ -174,11 +182,11 @@ namespace Ryujinx.Graphics.Gpu
return Dst;
}
//Bitfield extract with left shift by immediate.
case 3:
{
Src = (Src >> Dst) & BfMask;
Src = (int)((uint)Src >> Dst) & BfMask;
return Src << BfDstBit;
}
@ -186,7 +194,7 @@ namespace Ryujinx.Graphics.Gpu
//Bitfield extract with left shift by register.
case 4:
{
Src = (Src >> BfSrcBit) & BfMask;
Src = (int)((uint)Src >> BfSrcBit) & BfMask;
return Src << Dst;
}
@ -204,9 +212,9 @@ namespace Ryujinx.Graphics.Gpu
throw new ArgumentException(nameof(OpCode));
}
private int GetAluResult(int SubOp, int A, int B)
private int GetAluResult(int AluOp, int A, int B)
{
switch (SubOp)
switch (AluOp)
{
//Add.
case 0: return A + B;
@ -254,7 +262,7 @@ namespace Ryujinx.Graphics.Gpu
case 12: return ~(A & B);
}
throw new ArgumentOutOfRangeException(nameof(SubOp));
throw new ArgumentOutOfRangeException(nameof(AluOp));
}
private int GetImm(int OpCode)
@ -291,7 +299,17 @@ namespace Ryujinx.Graphics.Gpu
private int FetchParam()
{
Fifo.TryDequeue(out int Value);
int Value;
//If we don't have any parameters in the FIFO,
//keep running the PFIFO engine until it writes the parameters.
while (!Fifo.TryDequeue(out Value))
{
if (!PFifo.Step())
{
return 0;
}
}
return Value;
}

View file

@ -11,57 +11,156 @@ namespace Ryujinx.Graphics.Gpu
private Dictionary<int, NvGpuMethod> Methods;
private struct ConstBuffer
{
public bool Enabled;
public long Position;
public int Size;
}
private ConstBuffer[] Cbs;
public NvGpuEngine3d(NsGpu Gpu)
{
this.Gpu = Gpu;
Registers = new int[0xe00];
Methods = new Dictionary<int, NvGpuMethod>()
Methods = new Dictionary<int, NvGpuMethod>();
void AddMethod(int Meth, int Count, int Stride, NvGpuMethod Method)
{
{ 0x6c3, QueryControl }
};
while (Count-- > 0)
{
Methods.Add(Meth, Method);
Meth += Stride;
}
}
AddMethod(0x585, 1, 1, VertexEndGl);
AddMethod(0x6c3, 1, 1, QueryControl);
AddMethod(0x8e4, 16, 1, CbData);
AddMethod(0x904, 1, 1, CbBind);
Cbs = new ConstBuffer[18];
}
public void CallMethod(AMemory Memory, NsGpuPBEntry PBEntry)
{
if (Methods.TryGetValue(PBEntry.Method, out NvGpuMethod Methd))
if (Methods.TryGetValue(PBEntry.Method, out NvGpuMethod Method))
{
Methd(Memory, PBEntry);
Method(Memory, PBEntry);
}
else
{
WriteRegister(PBEntry);
}
}
if (PBEntry.Arguments.Count == 1)
{
Registers[PBEntry.Method] = PBEntry.Arguments[0];
}
private void VertexEndGl(AMemory Memory, NsGpuPBEntry PBEntry)
{
int TexCbuf = ReadRegister(NvGpuEngine3dReg.TextureCbIndex);
int TexHandle = ReadCb(Memory, TexCbuf, 0x20);
}
private void QueryControl(AMemory Memory, NsGpuPBEntry PBEntry)
{
long Position = MakeAddress(NvGpuEngine3dReg.QueryAddr);
int Seq = Registers[(int)NvGpuEngine3dReg.QuerySequence];
int Ctrl = Registers[(int)NvGpuEngine3dReg.QueryControl];
int Mode = Ctrl & 3;
if (Mode == 0)
if (TryGetCpuAddr(NvGpuEngine3dReg.QueryAddr, out long Position))
{
//Write.
Position = Gpu.MemoryMgr.GetCpuAddr(Position);
int Seq = Registers[(int)NvGpuEngine3dReg.QuerySequence];
int Ctrl = Registers[(int)NvGpuEngine3dReg.QueryControl];
if (Position != -1)
int Mode = Ctrl & 3;
if (Mode == 0)
{
//Write.
Memory.WriteInt32(Position, Seq);
}
}
WriteRegister(PBEntry);
}
private long MakeAddress(NvGpuEngine3dReg Reg)
private void CbData(AMemory Memory, NsGpuPBEntry PBEntry)
{
if (TryGetCpuAddr(NvGpuEngine3dReg.CbAddress, out long Position))
{
int Offset = ReadRegister(NvGpuEngine3dReg.CbOffset);
foreach (int Arg in PBEntry.Arguments)
{
Memory.WriteInt32(Position + Offset, Arg);
Offset += 4;
}
WriteRegister(NvGpuEngine3dReg.CbOffset, Offset);
}
}
private void CbBind(AMemory Memory, NsGpuPBEntry PBEntry)
{
int Index = PBEntry.Arguments[0];
bool Enabled = (Index & 1) != 0;
Index = (Index >> 4) & 0x1f;
if (TryGetCpuAddr(NvGpuEngine3dReg.CbAddress, out long Position))
{
Cbs[Index].Position = Position;
}
Cbs[Index].Enabled = Enabled;
Cbs[Index].Size = ReadRegister(NvGpuEngine3dReg.CbSize);
}
private int ReadCb(AMemory Memory, int Cbuf, int Offset)
{
long Position = Cbs[Cbuf].Position;
int Value = Memory.ReadInt32(Position + Offset);
return Value;
}
private bool TryGetCpuAddr(NvGpuEngine3dReg Reg, out long Position)
{
Position = MakeInt64From2xInt32(Reg);
Position = Gpu.GetCpuAddr(Position);
return Position != -1;
}
private long MakeInt64From2xInt32(NvGpuEngine3dReg Reg)
{
return
(long)Registers[(int)Reg + 0] << 32 |
(uint)Registers[(int)Reg + 1];
}
private void WriteRegister(NsGpuPBEntry PBEntry)
{
int ArgsCount = PBEntry.Arguments.Count;
if (ArgsCount > 0)
{
Registers[PBEntry.Method] = PBEntry.Arguments[ArgsCount - 1];
}
}
private int ReadRegister(NvGpuEngine3dReg Reg)
{
return Registers[(int)Reg];
}
private void WriteRegister(NvGpuEngine3dReg Reg, int Value)
{
Registers[(int)Reg] = Value;
}
}
}

View file

@ -2,8 +2,12 @@ namespace Ryujinx.Graphics.Gpu
{
enum NvGpuEngine3dReg
{
QueryAddr = 0x6c0,
QuerySequence = 0x6c2,
QueryControl = 0x6c3
QueryAddr = 0x6c0,
QuerySequence = 0x6c2,
QueryControl = 0x6c3,
CbSize = 0x8e0,
CbAddress = 0x8e1,
CbOffset = 0x8e3,
TextureCbIndex = 0x982
}
}

View file

@ -11,7 +11,7 @@ namespace Ryujinx.Graphics.Gpu
private NsGpu Gpu;
private ConcurrentQueue<(AMemory, NsGpuPBEntry[])> BufferQueue;
private ConcurrentQueue<(AMemory, NsGpuPBEntry)> BufferQueue;
private NvGpuEngine[] SubChannels;
@ -21,11 +21,11 @@ namespace Ryujinx.Graphics.Gpu
private MacroInterpreter Interpreter;
public CachedMacro(INvGpuEngine Engine, long Position)
public CachedMacro(NvGpuFifo PFifo, INvGpuEngine Engine, long Position)
{
this.Position = Position;
Interpreter = new MacroInterpreter(Engine);
Interpreter = new MacroInterpreter(PFifo, Engine);
}
public void PushParam(int Param)
@ -39,50 +39,45 @@ namespace Ryujinx.Graphics.Gpu
}
}
private long CurrentMacroPosition;
private int CurrentMacroBindIndex;
private long CurrMacroPosition;
private int CurrMacroBindIndex;
private CachedMacro[] Macros;
private Queue<(int, int)> MacroQueue;
public NvGpuFifo(NsGpu Gpu)
{
this.Gpu = Gpu;
BufferQueue = new ConcurrentQueue<(AMemory, NsGpuPBEntry[])>();
BufferQueue = new ConcurrentQueue<(AMemory, NsGpuPBEntry)>();
SubChannels = new NvGpuEngine[8];
Macros = new CachedMacro[MacrosCount];
MacroQueue = new Queue<(int, int)>();
}
public void PushBuffer(AMemory Memory, NsGpuPBEntry[] Buffer)
{
BufferQueue.Enqueue((Memory, Buffer));
foreach (NsGpuPBEntry PBEntry in Buffer)
{
BufferQueue.Enqueue((Memory, PBEntry));
}
}
public void DispatchCalls()
{
while (BufferQueue.TryDequeue(out (AMemory Memory, NsGpuPBEntry[] Buffer) Tuple))
{
foreach (NsGpuPBEntry PBEntry in Tuple.Buffer)
{
CallMethod(Tuple.Memory, PBEntry);
}
ExecuteMacros(Tuple.Memory);
}
while (Step());
}
private void ExecuteMacros(AMemory Memory)
public bool Step()
{
while (MacroQueue.TryDequeue(out (int Index, int Param) Tuple))
if (BufferQueue.TryDequeue(out (AMemory Memory, NsGpuPBEntry PBEntry) Tuple))
{
Macros[Tuple.Index].Execute(Memory, Tuple.Param);
CallMethod(Tuple.Memory, Tuple.PBEntry);
return true;
}
return false;
}
private void CallMethod(AMemory Memory, NsGpuPBEntry PBEntry)
@ -102,20 +97,20 @@ namespace Ryujinx.Graphics.Gpu
case NvGpuFifoMeth.SetMacroUploadAddress:
{
CurrentMacroPosition = (long)((ulong)PBEntry.Arguments[0] << 2);
CurrMacroPosition = (long)((ulong)PBEntry.Arguments[0] << 2);
break;
}
case NvGpuFifoMeth.SendMacroCodeData:
{
long Position = Gpu.GetCpuAddr(CurrentMacroPosition);
long Position = Gpu.GetCpuAddr(CurrMacroPosition);
foreach (int Arg in PBEntry.Arguments)
{
Memory.WriteInt32(Position, Arg);
CurrentMacroPosition += 4;
CurrMacroPosition += 4;
Position += 4;
}
@ -124,7 +119,7 @@ namespace Ryujinx.Graphics.Gpu
case NvGpuFifoMeth.SetMacroBindingIndex:
{
CurrentMacroBindIndex = PBEntry.Arguments[0];
CurrMacroBindIndex = PBEntry.Arguments[0];
break;
}
@ -135,7 +130,7 @@ namespace Ryujinx.Graphics.Gpu
Position = Gpu.GetCpuAddr(Position);
Macros[CurrentMacroBindIndex] = new CachedMacro(Gpu.Engine3d, Position);
Macros[CurrMacroBindIndex] = new CachedMacro(this, Gpu.Engine3d, Position);
break;
}
@ -169,7 +164,7 @@ namespace Ryujinx.Graphics.Gpu
}
else
{
MacroQueue.Enqueue((MacroIndex, PBEntry.Arguments[0]));
Macros[MacroIndex].Execute(Memory, PBEntry.Arguments[0]);
}
}
}