Some improvements to macro stuff
This commit is contained in:
parent
2c59418406
commit
d237bca9a8
5 changed files with 183 additions and 76 deletions
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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
|
||||
}
|
||||
}
|
|
@ -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]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue