diff --git a/Ryujinx.Graphics/Gal/OpenGL/OGLShader.cs b/Ryujinx.Graphics/Gal/OpenGL/OGLShader.cs index b2c94f4e23..0b0d997661 100644 --- a/Ryujinx.Graphics/Gal/OpenGL/OGLShader.cs +++ b/Ryujinx.Graphics/Gal/OpenGL/OGLShader.cs @@ -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) diff --git a/Ryujinx.Graphics/Gpu/MacroInterpreter.cs b/Ryujinx.Graphics/Gpu/MacroInterpreter.cs index 476d1a122c..caaf2e2e66 100644 --- a/Ryujinx.Graphics/Gpu/MacroInterpreter.cs +++ b/Ryujinx.Graphics/Gpu/MacroInterpreter.cs @@ -6,6 +6,7 @@ namespace Ryujinx.Graphics.Gpu { class MacroInterpreter { + private NvGpuFifo PFifo; private INvGpuEngine Engine; public Queue 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(); + Fifo = new Queue(); 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; } diff --git a/Ryujinx.Graphics/Gpu/NvGpuEngine3d.cs b/Ryujinx.Graphics/Gpu/NvGpuEngine3d.cs index dd24d74e5a..1a56d172ea 100644 --- a/Ryujinx.Graphics/Gpu/NvGpuEngine3d.cs +++ b/Ryujinx.Graphics/Gpu/NvGpuEngine3d.cs @@ -11,57 +11,156 @@ namespace Ryujinx.Graphics.Gpu private Dictionary 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() + Methods = new Dictionary(); + + 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; + } } } \ No newline at end of file diff --git a/Ryujinx.Graphics/Gpu/NvGpuEngine3dReg.cs b/Ryujinx.Graphics/Gpu/NvGpuEngine3dReg.cs index b029f406f8..6e87e365eb 100644 --- a/Ryujinx.Graphics/Gpu/NvGpuEngine3dReg.cs +++ b/Ryujinx.Graphics/Gpu/NvGpuEngine3dReg.cs @@ -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 } } \ No newline at end of file diff --git a/Ryujinx.Graphics/Gpu/NvGpuFifo.cs b/Ryujinx.Graphics/Gpu/NvGpuFifo.cs index 53b2cf95e8..0de7365d66 100644 --- a/Ryujinx.Graphics/Gpu/NvGpuFifo.cs +++ b/Ryujinx.Graphics/Gpu/NvGpuFifo.cs @@ -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]); } } }