diff --git a/Ryujinx.Graphics.Gpu/ClassId.cs b/Ryujinx.Graphics.Gpu/ClassId.cs
index 3cde0ac0..be4ebe4b 100644
--- a/Ryujinx.Graphics.Gpu/ClassId.cs
+++ b/Ryujinx.Graphics.Gpu/ClassId.cs
@@ -1,5 +1,8 @@
namespace Ryujinx.Graphics.Gpu
{
+ ///
+ /// GPU engine class ID.
+ ///
enum ClassId
{
Engine2D = 0x902d,
diff --git a/Ryujinx.Graphics.Gpu/Constants.cs b/Ryujinx.Graphics.Gpu/Constants.cs
index 501933fb..ff5b9f94 100644
--- a/Ryujinx.Graphics.Gpu/Constants.cs
+++ b/Ryujinx.Graphics.Gpu/Constants.cs
@@ -1,14 +1,48 @@
namespace Ryujinx.Graphics.Gpu
{
+ ///
+ /// Common Maxwell GPU constants.
+ ///
static class Constants
{
+ ///
+ /// Maximum number of compute uniform buffers.
+ ///
public const int TotalCpUniformBuffers = 8;
+
+ ///
+ /// Maximum number of compute storage buffers (this is a API limitation).
+ ///
public const int TotalCpStorageBuffers = 16;
+
+ ///
+ /// Maximum number of graphics uniform buffers.
+ ///
public const int TotalGpUniformBuffers = 18;
+
+ ///
+ /// Maximum number of graphics storage buffers (this is a API limitation).
+ ///
public const int TotalGpStorageBuffers = 16;
- public const int TotalRenderTargets = 8;
- public const int TotalShaderStages = 5;
- public const int TotalVertexBuffers = 16;
- public const int TotalViewports = 8;
+
+ ///
+ /// Maximum number of render target color buffers.
+ ///
+ public const int TotalRenderTargets = 8;
+
+ ///
+ /// Number of shader stages.
+ ///
+ public const int TotalShaderStages = 5;
+
+ ///
+ /// Maximum number of vertex buffers.
+ ///
+ public const int TotalVertexBuffers = 16;
+
+ ///
+ /// Maximum number of viewports.
+ ///
+ public const int TotalViewports = 8;
}
}
\ No newline at end of file
diff --git a/Ryujinx.Graphics.Gpu/DmaPusher.cs b/Ryujinx.Graphics.Gpu/DmaPusher.cs
index ae9cc868..d90bbd73 100644
--- a/Ryujinx.Graphics.Gpu/DmaPusher.cs
+++ b/Ryujinx.Graphics.Gpu/DmaPusher.cs
@@ -3,6 +3,9 @@ using System.Threading;
namespace Ryujinx.Graphics.Gpu
{
+ ///
+ /// GPU DMA pusher, used to push commands to the GPU.
+ ///
public class DmaPusher
{
private ConcurrentQueue _ibBuffer;
@@ -10,6 +13,9 @@ namespace Ryujinx.Graphics.Gpu
private ulong _dmaPut;
private ulong _dmaGet;
+ ///
+ /// Internal GPFIFO state.
+ ///
private struct DmaState
{
public int Method;
@@ -34,6 +40,10 @@ namespace Ryujinx.Graphics.Gpu
private AutoResetEvent _event;
+ ///
+ /// Creates a new instance of the GPU DMA pusher.
+ ///
+ /// GPU context that the pusher belongs to
internal DmaPusher(GpuContext context)
{
_context = context;
@@ -45,6 +55,10 @@ namespace Ryujinx.Graphics.Gpu
_event = new AutoResetEvent(false);
}
+ ///
+ /// Pushes a GPFIFO entry.
+ ///
+ /// GPFIFO entry
public void Push(ulong entry)
{
_ibBuffer.Enqueue(entry);
@@ -52,16 +66,27 @@ namespace Ryujinx.Graphics.Gpu
_event.Set();
}
+ ///
+ /// Waits until commands are pushed to the FIFO.
+ ///
+ /// True if commands were received, false if wait timed out
public bool WaitForCommands()
{
return _event.WaitOne(8);
}
+ ///
+ /// Processes commands pushed to the FIFO.
+ ///
public void DispatchCalls()
{
while (Step());
}
+ ///
+ /// Processes a single command on the FIFO.
+ ///
+ ///
private bool Step()
{
if (_dmaGet != _dmaPut)
@@ -162,6 +187,10 @@ namespace Ryujinx.Graphics.Gpu
return true;
}
+ ///
+ /// Sets current non-immediate method call state.
+ ///
+ /// Compressed method word
private void SetNonImmediateState(int word)
{
_state.Method = (word >> 0) & 0x1fff;
@@ -169,6 +198,10 @@ namespace Ryujinx.Graphics.Gpu
_state.MethodCount = (word >> 16) & 0x1fff;
}
+ ///
+ /// Forwards the method call to GPU engines.
+ ///
+ /// Call argument
private void CallMethod(int argument)
{
_context.Fifo.CallMethod(new MethodParams(
diff --git a/Ryujinx.Graphics.Gpu/GpuContext.cs b/Ryujinx.Graphics.Gpu/GpuContext.cs
index bb172c9e..d68dd2c0 100644
--- a/Ryujinx.Graphics.Gpu/GpuContext.cs
+++ b/Ryujinx.Graphics.Gpu/GpuContext.cs
@@ -5,30 +5,68 @@ using System;
namespace Ryujinx.Graphics.Gpu
{
+ ///
+ /// GPU emulation context.
+ ///
public class GpuContext
{
+ ///
+ /// Host renderer.
+ ///
public IRenderer Renderer { get; }
+ ///
+ /// Physical memory access (it actually accesses the process memory, not actual physical memory).
+ ///
internal PhysicalMemory PhysicalMemory { get; private set; }
+ ///
+ /// GPU memory manager.
+ ///
public MemoryManager MemoryManager { get; }
+ ///
+ /// GPU memory accessor.
+ ///
internal MemoryAccessor MemoryAccessor { get; }
+ ///
+ /// GPU engine methods processing.
+ ///
internal Methods Methods { get; }
+ ///
+ /// GPU commands FIFO.
+ ///
internal NvGpuFifo Fifo { get; }
+ ///
+ /// DMA pusher.
+ ///
public DmaPusher DmaPusher { get; }
+ ///
+ /// Presentation window.
+ ///
public Window Window { get; }
+ ///
+ /// Internal sequence number, used to avoid needless resource data updates
+ /// in the middle of a command buffer before synchronizations.
+ ///
internal int SequenceNumber { get; private set; }
private readonly Lazy _caps;
+ ///
+ /// Host hardware capabilities.
+ ///
internal Capabilities Capabilities => _caps.Value;
+ ///
+ /// Creates a new instance of the GPU emulation context.
+ ///
+ /// Host renderer
public GpuContext(IRenderer renderer)
{
Renderer = renderer;
@@ -48,11 +86,20 @@ namespace Ryujinx.Graphics.Gpu
_caps = new Lazy(Renderer.GetCapabilities);
}
+ ///
+ /// Advances internal sequence number.
+ /// This forces the update of any modified GPU resource.
+ ///
internal void AdvanceSequence()
{
SequenceNumber++;
}
+ ///
+ /// Sets the process memory manager, after the application process is initialized.
+ /// This is required for any GPU memory access.
+ ///
+ /// CPU memory manager
public void SetVmm(ARMeilleure.Memory.MemoryManager cpuMemory)
{
PhysicalMemory = new PhysicalMemory(cpuMemory);
diff --git a/Ryujinx.Graphics.Gpu/GraphicsConfig.cs b/Ryujinx.Graphics.Gpu/GraphicsConfig.cs
index c5eaa0b3..468d3a34 100644
--- a/Ryujinx.Graphics.Gpu/GraphicsConfig.cs
+++ b/Ryujinx.Graphics.Gpu/GraphicsConfig.cs
@@ -1,12 +1,21 @@
namespace Ryujinx.Graphics.Gpu
{
+ ///
+ /// General GPU and graphics configuration.
+ ///
public static class GraphicsConfig
{
+ ///
+ /// Base directory used to write shader code dumps.
+ /// Set to null to disable code dumping.
+ ///
public static string ShadersDumpPath;
+ ///
+ /// Fast GPU time calculates the internal GPU time ticks as if the GPU was capable of
+ /// processing commands almost instantly, instead of using the host timer.
+ /// This can avoid lower resolution on some games when GPU performance is poor.
+ ///
public static bool FastGpuTime = true;
-
- public static bool DisableTUpdate;
- public static bool DisableBUpdate;
}
}
\ No newline at end of file
diff --git a/Ryujinx.Graphics.Gpu/MacroInterpreter.cs b/Ryujinx.Graphics.Gpu/MacroInterpreter.cs
index e424b8ff..cfc3815b 100644
--- a/Ryujinx.Graphics.Gpu/MacroInterpreter.cs
+++ b/Ryujinx.Graphics.Gpu/MacroInterpreter.cs
@@ -5,6 +5,9 @@ using System.Collections.Generic;
namespace Ryujinx.Graphics.Gpu
{
+ ///
+ /// Macro code interpreter.
+ ///
class MacroInterpreter
{
private enum AssignmentOperation
@@ -42,10 +45,6 @@ namespace Ryujinx.Graphics.Gpu
BitwiseNotAnd = 12
}
- private GpuContext _context;
-
- private NvGpuFifo _pFifo;
-
public Queue Fifo { get; private set; }
private int[] _gprs;
@@ -61,16 +60,23 @@ namespace Ryujinx.Graphics.Gpu
private int _pc;
- public MacroInterpreter(GpuContext context, NvGpuFifo pFifo)
+ ///
+ /// Creates a new instance of the macro code interpreter.
+ ///
+ public MacroInterpreter()
{
- _context = context;
- _pFifo = pFifo;
-
Fifo = new Queue();
_gprs = new int[8];
}
+ ///
+ /// Executes a macro program until it exits.
+ ///
+ /// Code of the program to execute
+ /// Start position to execute
+ /// Optional argument passed to the program, 0 if not used
+ /// Current GPU state
public void Execute(int[] mme, int position, int param, GpuState state)
{
Reset();
@@ -88,6 +94,10 @@ namespace Ryujinx.Graphics.Gpu
Step(mme, state);
}
+ ///
+ /// Resets the internal interpreter state.
+ /// Call each time you run a new program.
+ ///
private void Reset()
{
for (int index = 0; index < _gprs.Length; index++)
@@ -101,6 +111,12 @@ namespace Ryujinx.Graphics.Gpu
_carry = false;
}
+ ///
+ /// Executes a single instruction of the program.
+ ///
+ /// Program code to execute
+ /// Current GPU state
+ /// True to continue execution, false if the program exited
private bool Step(int[] mme, GpuState state)
{
int baseAddr = _pc - 1;
@@ -226,12 +242,21 @@ namespace Ryujinx.Graphics.Gpu
return !exit;
}
+ ///
+ /// Fetches a single operation code from the program code.
+ ///
+ /// Program code
private void FetchOpCode(int[] mme)
{
_opCode = _pipeOp;
_pipeOp = mme[_pc++];
}
+ ///
+ /// Gets the result of the current Arithmetic and Logic unit operation.
+ ///
+ /// Current GPU state
+ /// Operation result
private int GetAluResult(GpuState state)
{
AluOperation op = (AluOperation)(_opCode & 7);
@@ -303,6 +328,13 @@ namespace Ryujinx.Graphics.Gpu
throw new ArgumentException(nameof(_opCode));
}
+ ///
+ /// Gets the result of a Arithmetic and Logic operation using registers.
+ ///
+ /// Arithmetic and Logic unit operation with registers
+ /// First operand value
+ /// Second operand value
+ /// Operation result
private int GetAluResult(AluRegOperation aluOp, int a, int b)
{
switch (aluOp)
@@ -353,43 +385,70 @@ namespace Ryujinx.Graphics.Gpu
throw new ArgumentOutOfRangeException(nameof(aluOp));
}
+ ///
+ /// Extracts a 32-bits signed integer constant from the current operation code.
+ ///
+ ///
private int GetImm()
{
// Note: The immediate is signed, the sign-extension is intended here.
return _opCode >> 14;
}
+ ///
+ /// Sets the current method address, for method calls.
+ ///
+ /// Packed address and increment value
private void SetMethAddr(int value)
{
_methAddr = (value >> 0) & 0xfff;
_methIncr = (value >> 12) & 0x3f;
}
+ ///
+ /// Sets the destination register value.
+ ///
+ /// Value to set (usually the operation result)
private void SetDstGpr(int value)
{
_gprs[(_opCode >> 8) & 7] = value;
}
+ ///
+ /// Gets first operand value from the respective register.
+ ///
+ /// Operand value
private int GetGprA()
{
return GetGprValue((_opCode >> 11) & 7);
}
+ ///
+ /// Gets second operand value from the respective register.
+ ///
+ /// Operand value
private int GetGprB()
{
return GetGprValue((_opCode >> 14) & 7);
}
+ ///
+ /// Gets the value from a register, or 0 if the R0 register is specified.
+ ///
+ /// Index of the register
+ /// Register value
private int GetGprValue(int index)
{
return index != 0 ? _gprs[index] : 0;
}
+ ///
+ /// Fetches a call argument from the call argument FIFO.
+ ///
+ /// The call argument, or 0 if the FIFO is empty
private int FetchParam()
{
- int value;
-
- if (!Fifo.TryDequeue(out value))
+ if (!Fifo.TryDequeue(out int value))
{
Logger.PrintWarning(LogClass.Gpu, "Macro attempted to fetch an inexistent argument.");
@@ -399,11 +458,22 @@ namespace Ryujinx.Graphics.Gpu
return value;
}
+ ///
+ /// Reads data from a GPU register.
+ ///
+ /// Current GPU state
+ /// Register offset to read
+ /// GPU register value
private int Read(GpuState state, int reg)
{
return state.Read(reg);
}
+ ///
+ /// Performs a GPU method call.
+ ///
+ /// Current GPU state
+ /// Call argument
private void Send(GpuState state, int value)
{
MethodParams meth = new MethodParams(_methAddr, value);
diff --git a/Ryujinx.Graphics.Gpu/MethodParams.cs b/Ryujinx.Graphics.Gpu/MethodParams.cs
index fea4eb30..dd60f77c 100644
--- a/Ryujinx.Graphics.Gpu/MethodParams.cs
+++ b/Ryujinx.Graphics.Gpu/MethodParams.cs
@@ -1,14 +1,42 @@
namespace Ryujinx.Graphics
{
+ ///
+ /// Method call parameters.
+ ///
struct MethodParams
{
- public int Method { get; private set; }
- public int Argument { get; private set; }
- public int SubChannel { get; private set; }
- public int MethodCount { get; private set; }
+ ///
+ /// Method offset.
+ ///
+ public int Method { get; }
+ ///
+ /// Method call argument.
+ ///
+ public int Argument { get; }
+
+ ///
+ /// Sub-channel where the call should be sent.
+ ///
+ public int SubChannel { get; }
+
+ ///
+ /// For multiple calls to the same method, this is the remaining calls count.
+ ///
+ public int MethodCount { get; }
+
+ ///
+ /// Indicates if the current call is the last one from a batch of calls to the same method.
+ ///
public bool IsLastCall => MethodCount <= 1;
+ ///
+ /// Constructs the method call parameters structure.
+ ///
+ /// Method offset
+ /// Method call argument
+ /// Optional sub-channel where the method should be sent (not required for macro calls)
+ /// Optional remaining calls count (not required for macro calls)
public MethodParams(
int method,
int argument,
diff --git a/Ryujinx.Graphics.Gpu/NvGpuFifo.cs b/Ryujinx.Graphics.Gpu/NvGpuFifo.cs
index 6e02f391..6f51527f 100644
--- a/Ryujinx.Graphics.Gpu/NvGpuFifo.cs
+++ b/Ryujinx.Graphics.Gpu/NvGpuFifo.cs
@@ -2,6 +2,9 @@ using Ryujinx.Graphics.Gpu.State;
namespace Ryujinx.Graphics.Gpu
{
+ ///
+ /// GPU commands FIFO.
+ ///
class NvGpuFifo
{
private const int MacrosCount = 0x80;
@@ -13,25 +16,36 @@ namespace Ryujinx.Graphics.Gpu
private GpuContext _context;
+ ///
+ /// Cached GPU macro program.
+ ///
private struct CachedMacro
{
- public int Position { get; private set; }
+ public int Position { get; }
private bool _executionPending;
private int _argument;
private MacroInterpreter _interpreter;
- public CachedMacro(GpuContext context, NvGpuFifo fifo, int position)
+ ///
+ /// Creates a new instance of the GPU cached macro program.
+ ///
+ /// Macro code start position
+ public CachedMacro(int position)
{
Position = position;
_executionPending = false;
_argument = 0;
- _interpreter = new MacroInterpreter(context, fifo);
+ _interpreter = new MacroInterpreter();
}
+ ///
+ /// Sets the first argument for the macro call.
+ ///
+ /// First argument
public void StartExecution(int argument)
{
_argument = argument;
@@ -39,6 +53,11 @@ namespace Ryujinx.Graphics.Gpu
_executionPending = true;
}
+ ///
+ /// Starts executing the macro program code.
+ ///
+ /// Program code
+ /// Current GPU state
public void Execute(int[] mme, GpuState state)
{
if (_executionPending)
@@ -49,6 +68,10 @@ namespace Ryujinx.Graphics.Gpu
}
}
+ ///
+ /// Pushes a argument to the macro call argument FIFO.
+ ///
+ /// Argument to be pushed
public void PushArgument(int argument)
{
_interpreter?.Fifo.Enqueue(argument);
@@ -62,11 +85,24 @@ namespace Ryujinx.Graphics.Gpu
private int[] _mme;
+ ///
+ /// GPU sub-channel information.
+ ///
private class SubChannel
{
+ ///
+ /// Sub-channel GPU state.
+ ///
public GpuState State { get; }
+
+ ///
+ /// Engine bound to the sub-channel.
+ ///
public ClassId Class { get; set; }
+ ///
+ /// Creates a new instance of the GPU sub-channel.
+ ///
public SubChannel()
{
State = new GpuState();
@@ -75,6 +111,10 @@ namespace Ryujinx.Graphics.Gpu
private SubChannel[] _subChannels;
+ ///
+ /// Creates a new instance of the GPU commands FIFO.
+ ///
+ /// GPU emulation context
public NvGpuFifo(GpuContext context)
{
_context = context;
@@ -93,6 +133,10 @@ namespace Ryujinx.Graphics.Gpu
}
}
+ ///
+ /// Calls a GPU method.
+ ///
+ /// GPU method call parameters
public void CallMethod(MethodParams meth)
{
if ((NvGpuFifoMeth)meth.Method == NvGpuFifoMeth.BindChannel)
@@ -137,7 +181,7 @@ namespace Ryujinx.Graphics.Gpu
{
int position = meth.Argument;
- _macros[_currMacroBindIndex++] = new CachedMacro(_context, this, position);
+ _macros[_currMacroBindIndex++] = new CachedMacro(position);
break;
}
diff --git a/Ryujinx.Graphics.Gpu/NvGpuFifoMeth.cs b/Ryujinx.Graphics.Gpu/NvGpuFifoMeth.cs
index 09aaa6c3..89023407 100644
--- a/Ryujinx.Graphics.Gpu/NvGpuFifoMeth.cs
+++ b/Ryujinx.Graphics.Gpu/NvGpuFifoMeth.cs
@@ -1,5 +1,8 @@
namespace Ryujinx.Graphics.Gpu
{
+ ///
+ /// GPU commands FIFO processor commands.
+ ///
enum NvGpuFifoMeth
{
BindChannel = 0,
diff --git a/Ryujinx.Graphics.Gpu/Window.cs b/Ryujinx.Graphics.Gpu/Window.cs
index d5494aa4..29c36248 100644
--- a/Ryujinx.Graphics.Gpu/Window.cs
+++ b/Ryujinx.Graphics.Gpu/Window.cs
@@ -7,17 +7,45 @@ namespace Ryujinx.Graphics.Gpu
{
using Texture = Image.Texture;
+ ///
+ /// GPU image presentation window.
+ ///
public class Window
{
private readonly GpuContext _context;
+ ///
+ /// Texture presented on the window.
+ ///
private struct PresentationTexture
{
- public TextureInfo Info { get; }
- public ImageCrop Crop { get; }
- public Action