Add XML documentation to Ryujinx.Graphics.Gpu.Engine
This commit is contained in:
parent
d1c0a64e6a
commit
4a4e2f7c72
12 changed files with 305 additions and 1 deletions
|
@ -10,6 +10,11 @@ namespace Ryujinx.Graphics.Gpu.Engine
|
||||||
{
|
{
|
||||||
partial class Methods
|
partial class Methods
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Dispatches compute work.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="state">Current GPU state</param>
|
||||||
|
/// <param name="argument">Method call argument</param>
|
||||||
public void Dispatch(GpuState state, int argument)
|
public void Dispatch(GpuState state, int argument)
|
||||||
{
|
{
|
||||||
uint dispatchParamsAddress = (uint)state.Get<int>(MethodOffset.DispatchParamsAddress);
|
uint dispatchParamsAddress = (uint)state.Get<int>(MethodOffset.DispatchParamsAddress);
|
||||||
|
|
|
@ -4,22 +4,36 @@ using System.Runtime.InteropServices;
|
||||||
|
|
||||||
namespace Ryujinx.Graphics.Gpu.Engine
|
namespace Ryujinx.Graphics.Gpu.Engine
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Compute uniform buffer parameters.
|
||||||
|
/// </summary>
|
||||||
struct UniformBufferParams
|
struct UniformBufferParams
|
||||||
{
|
{
|
||||||
public int AddressLow;
|
public int AddressLow;
|
||||||
public int AddressHighAndSize;
|
public int AddressHighAndSize;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Packs the split address to a 64-bits integer.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>Uniform buffer GPU virtual address</returns>
|
||||||
public ulong PackAddress()
|
public ulong PackAddress()
|
||||||
{
|
{
|
||||||
return (uint)AddressLow | ((ulong)(AddressHighAndSize & 0xff) << 32);
|
return (uint)AddressLow | ((ulong)(AddressHighAndSize & 0xff) << 32);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Unpacks the uniform buffer size in bytes.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>Uniform buffer size in bytes</returns>
|
||||||
public ulong UnpackSize()
|
public ulong UnpackSize()
|
||||||
{
|
{
|
||||||
return (ulong)((AddressHighAndSize >> 15) & 0x1ffff);
|
return (ulong)((AddressHighAndSize >> 15) & 0x1ffff);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Compute dispatch parameters.
|
||||||
|
/// </summary>
|
||||||
struct ComputeParams
|
struct ComputeParams
|
||||||
{
|
{
|
||||||
public int Unknown0;
|
public int Unknown0;
|
||||||
|
@ -61,6 +75,9 @@ namespace Ryujinx.Graphics.Gpu.Engine
|
||||||
private UniformBufferParams _uniformBuffer6;
|
private UniformBufferParams _uniformBuffer6;
|
||||||
private UniformBufferParams _uniformBuffer7;
|
private UniformBufferParams _uniformBuffer7;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Uniform buffer parameters.
|
||||||
|
/// </summary>
|
||||||
public Span<UniformBufferParams> UniformBuffers
|
public Span<UniformBufferParams> UniformBuffers
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
|
@ -89,36 +106,65 @@ namespace Ryujinx.Graphics.Gpu.Engine
|
||||||
public int Unknown62;
|
public int Unknown62;
|
||||||
public int Unknown63;
|
public int Unknown63;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Unpacks the work group X size.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>Work group X size</returns>
|
||||||
public int UnpackGridSizeX()
|
public int UnpackGridSizeX()
|
||||||
{
|
{
|
||||||
return GridSizeX & 0x7fffffff;
|
return GridSizeX & 0x7fffffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Unpacks the work group Y size.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>Work group Y size</returns>
|
||||||
public int UnpackGridSizeY()
|
public int UnpackGridSizeY()
|
||||||
{
|
{
|
||||||
return GridSizeYZ & 0xffff;
|
return GridSizeYZ & 0xffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Unpacks the work group Z size.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>Work group Z size</returns>
|
||||||
public int UnpackGridSizeZ()
|
public int UnpackGridSizeZ()
|
||||||
{
|
{
|
||||||
return (GridSizeYZ >> 16) & 0xffff;
|
return (GridSizeYZ >> 16) & 0xffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Unpacks the local group X size.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>Local group X size</returns>
|
||||||
public int UnpackBlockSizeX()
|
public int UnpackBlockSizeX()
|
||||||
{
|
{
|
||||||
return (BlockSizeX >> 16) & 0xffff;
|
return (BlockSizeX >> 16) & 0xffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Unpacks the local group Y size.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>Local group Y size</returns>
|
||||||
public int UnpackBlockSizeY()
|
public int UnpackBlockSizeY()
|
||||||
{
|
{
|
||||||
return BlockSizeYZ & 0xffff;
|
return BlockSizeYZ & 0xffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Unpacks the local group Z size.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>Local group Z size</returns>
|
||||||
public int UnpackBlockSizeZ()
|
public int UnpackBlockSizeZ()
|
||||||
{
|
{
|
||||||
return (BlockSizeYZ >> 16) & 0xffff;
|
return (BlockSizeYZ >> 16) & 0xffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Unpacks the uniform buffers enable mask.
|
||||||
|
/// Each bit set on the mask indicates that the respective buffer index is enabled.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>Uniform buffers enable mask</returns>
|
||||||
public uint UnpackUniformBuffersEnableMask()
|
public uint UnpackUniformBuffersEnableMask()
|
||||||
{
|
{
|
||||||
return (uint)UniformBuffersConfig & 0xff;
|
return (uint)UniformBuffersConfig & 0xff;
|
||||||
|
|
|
@ -19,6 +19,11 @@ namespace Ryujinx.Graphics.Gpu.Engine
|
||||||
|
|
||||||
private int[] _buffer;
|
private int[] _buffer;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Launches Inline-to-Memory engine DMA copy.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="state">Current GPU state</param>
|
||||||
|
/// <param name="argument">Method call argument</param>
|
||||||
public void LaunchDma(GpuState state, int argument)
|
public void LaunchDma(GpuState state, int argument)
|
||||||
{
|
{
|
||||||
_params = state.Get<Inline2MemoryParams>(MethodOffset.I2mParams);
|
_params = state.Get<Inline2MemoryParams>(MethodOffset.I2mParams);
|
||||||
|
@ -42,6 +47,11 @@ namespace Ryujinx.Graphics.Gpu.Engine
|
||||||
_finished = false;
|
_finished = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Pushes a word of data to the Inline-to-Memory engine.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="state">Current GPU state</param>
|
||||||
|
/// <param name="argument">Method call argument</param>
|
||||||
public void LoadInlineData(GpuState state, int argument)
|
public void LoadInlineData(GpuState state, int argument)
|
||||||
{
|
{
|
||||||
if (!_finished)
|
if (!_finished)
|
||||||
|
@ -55,6 +65,9 @@ namespace Ryujinx.Graphics.Gpu.Engine
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Performs actual copy of the inline data after the transfer is finished.
|
||||||
|
/// </summary>
|
||||||
private void FinishTransfer()
|
private void FinishTransfer()
|
||||||
{
|
{
|
||||||
Span<byte> data = MemoryMarshal.Cast<int, byte>(_buffer).Slice(0, _size);
|
Span<byte> data = MemoryMarshal.Cast<int, byte>(_buffer).Slice(0, _size);
|
||||||
|
|
|
@ -5,6 +5,12 @@ namespace Ryujinx.Graphics.Gpu.Engine
|
||||||
{
|
{
|
||||||
partial class Methods
|
partial class Methods
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Clears the current color and depth-stencil buffers.
|
||||||
|
/// Which buffers should be cleared is also specified on the argument.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="state">Current GPU state</param>
|
||||||
|
/// <param name="argument">Method call argument</param>
|
||||||
private void Clear(GpuState state, int argument)
|
private void Clear(GpuState state, int argument)
|
||||||
{
|
{
|
||||||
UpdateRenderTargetState(state, useControl: false);
|
UpdateRenderTargetState(state, useControl: false);
|
||||||
|
|
|
@ -6,6 +6,11 @@ namespace Ryujinx.Graphics.Gpu.Engine
|
||||||
{
|
{
|
||||||
partial class Methods
|
partial class Methods
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Performs a buffer to buffer, or buffer to texture copy.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="state">Current GPU state</param>
|
||||||
|
/// <param name="argument">Method call argument</param>
|
||||||
private void CopyBuffer(GpuState state, int argument)
|
private void CopyBuffer(GpuState state, int argument)
|
||||||
{
|
{
|
||||||
var cbp = state.Get<CopyBufferParams>(MethodOffset.CopyBufferParams);
|
var cbp = state.Get<CopyBufferParams>(MethodOffset.CopyBufferParams);
|
||||||
|
|
|
@ -7,6 +7,11 @@ namespace Ryujinx.Graphics.Gpu.Engine
|
||||||
|
|
||||||
partial class Methods
|
partial class Methods
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Performs a texture to texture copy.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="state">Current GPU state</param>
|
||||||
|
/// <param name="argument">Method call argument</param>
|
||||||
private void CopyTexture(GpuState state, int argument)
|
private void CopyTexture(GpuState state, int argument)
|
||||||
{
|
{
|
||||||
var dstCopyTexture = state.Get<CopyTexture>(MethodOffset.CopyDstTexture);
|
var dstCopyTexture = state.Get<CopyTexture>(MethodOffset.CopyDstTexture);
|
||||||
|
|
|
@ -22,8 +22,17 @@ namespace Ryujinx.Graphics.Gpu.Engine
|
||||||
|
|
||||||
private int _instanceIndex;
|
private int _instanceIndex;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Primitive type of the current draw.
|
||||||
|
/// </summary>
|
||||||
public PrimitiveType PrimitiveType { get; private set; }
|
public PrimitiveType PrimitiveType { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Finishes draw call.
|
||||||
|
/// This draws geometry on the bound buffers based on the current GPU state.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="state">Current GPU state</param>
|
||||||
|
/// <param name="argument">Method call argument</param>
|
||||||
private void DrawEnd(GpuState state, int argument)
|
private void DrawEnd(GpuState state, int argument)
|
||||||
{
|
{
|
||||||
if (_instancedDrawPending)
|
if (_instancedDrawPending)
|
||||||
|
@ -86,6 +95,12 @@ namespace Ryujinx.Graphics.Gpu.Engine
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Starts draw.
|
||||||
|
/// This sets primitive type and instanced draw parameters.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="state">Current GPU state</param>
|
||||||
|
/// <param name="argument">Method call argument</param>
|
||||||
private void DrawBegin(GpuState state, int argument)
|
private void DrawBegin(GpuState state, int argument)
|
||||||
{
|
{
|
||||||
if ((argument & (1 << 26)) != 0)
|
if ((argument & (1 << 26)) != 0)
|
||||||
|
@ -106,11 +121,24 @@ namespace Ryujinx.Graphics.Gpu.Engine
|
||||||
PrimitiveType = type;
|
PrimitiveType = type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sets the index buffer count.
|
||||||
|
/// This also sets internal state that indicates that the next draw is a indexed draw.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="state">Current GPU state</param>
|
||||||
|
/// <param name="argument">Method call argument</param>
|
||||||
private void SetIndexBufferCount(GpuState state, int argument)
|
private void SetIndexBufferCount(GpuState state, int argument)
|
||||||
{
|
{
|
||||||
_drawIndexed = true;
|
_drawIndexed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Perform any deferred draws.
|
||||||
|
/// This is used for instanced draws.
|
||||||
|
/// Since each instance is a separate draw, we defer the draw and accumulate the instance count.
|
||||||
|
/// Once we detect the last instanced draw, then we perform the host instanced draw,
|
||||||
|
/// with the accumulated instance count.
|
||||||
|
/// </summary>
|
||||||
public void PerformDeferredDraws()
|
public void PerformDeferredDraws()
|
||||||
{
|
{
|
||||||
// Perform any pending instanced draw.
|
// Perform any pending instanced draw.
|
||||||
|
|
|
@ -10,6 +10,11 @@ namespace Ryujinx.Graphics.Gpu.Engine
|
||||||
{
|
{
|
||||||
private ulong _runningCounter;
|
private ulong _runningCounter;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Writes a GPU counter to guest memory.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="state">Current GPU state</param>
|
||||||
|
/// <param name="argument">Method call argument</param>
|
||||||
private void Report(GpuState state, int argument)
|
private void Report(GpuState state, int argument)
|
||||||
{
|
{
|
||||||
ReportMode mode = (ReportMode)(argument & 3);
|
ReportMode mode = (ReportMode)(argument & 3);
|
||||||
|
@ -23,6 +28,10 @@ namespace Ryujinx.Graphics.Gpu.Engine
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Writes a GPU semaphore value to guest memory.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="state">Current GPU state</param>
|
||||||
private void ReportSemaphore(GpuState state)
|
private void ReportSemaphore(GpuState state)
|
||||||
{
|
{
|
||||||
var rs = state.Get<ReportState>(MethodOffset.ReportState);
|
var rs = state.Get<ReportState>(MethodOffset.ReportState);
|
||||||
|
@ -32,12 +41,21 @@ namespace Ryujinx.Graphics.Gpu.Engine
|
||||||
_context.AdvanceSequence();
|
_context.AdvanceSequence();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Packed GPU counter data (including GPU timestamp) in memory.
|
||||||
|
/// </summary>
|
||||||
private struct CounterData
|
private struct CounterData
|
||||||
{
|
{
|
||||||
public ulong Counter;
|
public ulong Counter;
|
||||||
public ulong Timestamp;
|
public ulong Timestamp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Writes a GPU counter to guest memory.
|
||||||
|
/// This also writes the current timestamp value.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="state">Current GPU state</param>
|
||||||
|
/// <param name="type">Counter to be written to memory</param>
|
||||||
private void ReportCounter(GpuState state, ReportCounterType type)
|
private void ReportCounter(GpuState state, ReportCounterType type)
|
||||||
{
|
{
|
||||||
CounterData counterData = new CounterData();
|
CounterData counterData = new CounterData();
|
||||||
|
@ -83,6 +101,12 @@ namespace Ryujinx.Graphics.Gpu.Engine
|
||||||
_context.MemoryAccessor.Write(rs.Address.Pack(), data);
|
_context.MemoryAccessor.Write(rs.Address.Pack(), data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Converts a nanoseconds timestamp value to Maxwell time ticks.
|
||||||
|
/// The frequency is approximately 1.63Hz.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="nanoseconds">Timestamp in nanoseconds</param>
|
||||||
|
/// <returns>Maxwell ticks</returns>
|
||||||
private static ulong ConvertNanosecondsToTicks(ulong nanoseconds)
|
private static ulong ConvertNanosecondsToTicks(ulong nanoseconds)
|
||||||
{
|
{
|
||||||
// We need to divide first to avoid overflows.
|
// We need to divide first to avoid overflows.
|
||||||
|
|
|
@ -5,6 +5,11 @@ namespace Ryujinx.Graphics.Gpu.Engine
|
||||||
{
|
{
|
||||||
partial class Methods
|
partial class Methods
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Resets the value of a internal GPU counter back to zero.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="state">Current GPU state</param>
|
||||||
|
/// <param name="argument">Method call argument</param>
|
||||||
private void ResetCounter(GpuState state, int argument)
|
private void ResetCounter(GpuState state, int argument)
|
||||||
{
|
{
|
||||||
ResetCounterType type = (ResetCounterType)argument;
|
ResetCounterType type = (ResetCounterType)argument;
|
||||||
|
|
|
@ -4,31 +4,62 @@ namespace Ryujinx.Graphics.Gpu.Engine
|
||||||
{
|
{
|
||||||
partial class Methods
|
partial class Methods
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Binds a uniform buffer for the vertex shader stage.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="state">Current GPU state</param>
|
||||||
|
/// <param name="argument">Method call argument</param>
|
||||||
private void UniformBufferBindVertex(GpuState state, int argument)
|
private void UniformBufferBindVertex(GpuState state, int argument)
|
||||||
{
|
{
|
||||||
UniformBufferBind(state, argument, ShaderType.Vertex);
|
UniformBufferBind(state, argument, ShaderType.Vertex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Binds a uniform buffer for the tessellation control shader stage.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="state">Current GPU state</param>
|
||||||
|
/// <param name="argument">Method call argument</param>
|
||||||
private void UniformBufferBindTessControl(GpuState state, int argument)
|
private void UniformBufferBindTessControl(GpuState state, int argument)
|
||||||
{
|
{
|
||||||
UniformBufferBind(state, argument, ShaderType.TessellationControl);
|
UniformBufferBind(state, argument, ShaderType.TessellationControl);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Binds a uniform buffer for the tessellation evaluation shader stage.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="state">Current GPU state</param>
|
||||||
|
/// <param name="argument">Method call argument</param>
|
||||||
private void UniformBufferBindTessEvaluation(GpuState state, int argument)
|
private void UniformBufferBindTessEvaluation(GpuState state, int argument)
|
||||||
{
|
{
|
||||||
UniformBufferBind(state, argument, ShaderType.TessellationEvaluation);
|
UniformBufferBind(state, argument, ShaderType.TessellationEvaluation);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Binds a uniform buffer for the geometry shader stage.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="state">Current GPU state</param>
|
||||||
|
/// <param name="argument">Method call argument</param>
|
||||||
private void UniformBufferBindGeometry(GpuState state, int argument)
|
private void UniformBufferBindGeometry(GpuState state, int argument)
|
||||||
{
|
{
|
||||||
UniformBufferBind(state, argument, ShaderType.Geometry);
|
UniformBufferBind(state, argument, ShaderType.Geometry);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Binds a uniform buffer for the fragment shader stage.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="state">Current GPU state</param>
|
||||||
|
/// <param name="argument">Method call argument</param>
|
||||||
private void UniformBufferBindFragment(GpuState state, int argument)
|
private void UniformBufferBindFragment(GpuState state, int argument)
|
||||||
{
|
{
|
||||||
UniformBufferBind(state, argument, ShaderType.Fragment);
|
UniformBufferBind(state, argument, ShaderType.Fragment);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///Binds a uniform buffer for the specified shader stage.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="state">Current GPU state</param>
|
||||||
|
/// <param name="argument">Method call argument</param>
|
||||||
|
/// <param name="type">Shader stage that will access the uniform buffer</param>
|
||||||
private void UniformBufferBind(GpuState state, int argument, ShaderType type)
|
private void UniformBufferBind(GpuState state, int argument, ShaderType type)
|
||||||
{
|
{
|
||||||
bool enable = (argument & 1) != 0;
|
bool enable = (argument & 1) != 0;
|
||||||
|
|
|
@ -4,6 +4,11 @@ namespace Ryujinx.Graphics.Gpu.Engine
|
||||||
{
|
{
|
||||||
partial class Methods
|
partial class Methods
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Updates the uniform buffer data with inline data.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="state">Current GPU state</param>
|
||||||
|
/// <param name="argument">New uniform buffer data word</param>
|
||||||
private void UniformBufferUpdate(GpuState state, int argument)
|
private void UniformBufferUpdate(GpuState state, int argument)
|
||||||
{
|
{
|
||||||
var uniformBuffer = state.Get<UniformBufferState>(MethodOffset.UniformBufferState);
|
var uniformBuffer = state.Get<UniformBufferState>(MethodOffset.UniformBufferState);
|
||||||
|
|
|
@ -12,6 +12,9 @@ namespace Ryujinx.Graphics.Gpu.Engine
|
||||||
{
|
{
|
||||||
using Texture = Image.Texture;
|
using Texture = Image.Texture;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// GPU method implementations.
|
||||||
|
/// </summary>
|
||||||
partial class Methods
|
partial class Methods
|
||||||
{
|
{
|
||||||
private readonly GpuContext _context;
|
private readonly GpuContext _context;
|
||||||
|
@ -20,12 +23,23 @@ namespace Ryujinx.Graphics.Gpu.Engine
|
||||||
|
|
||||||
private readonly ShaderProgramInfo[] _currentProgramInfo;
|
private readonly ShaderProgramInfo[] _currentProgramInfo;
|
||||||
|
|
||||||
public BufferManager BufferManager { get; }
|
/// <summary>
|
||||||
|
/// GPU buffer manager.
|
||||||
|
/// </summary>
|
||||||
|
public BufferManager BufferManager { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// GPU texture manager.
|
||||||
|
/// </summary>
|
||||||
public TextureManager TextureManager { get; }
|
public TextureManager TextureManager { get; }
|
||||||
|
|
||||||
private bool _isAnyVbInstanced;
|
private bool _isAnyVbInstanced;
|
||||||
private bool _vsUsesInstanceId;
|
private bool _vsUsesInstanceId;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new instance of the GPU methods class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="context">GPU context</param>
|
||||||
public Methods(GpuContext context)
|
public Methods(GpuContext context)
|
||||||
{
|
{
|
||||||
_context = context;
|
_context = context;
|
||||||
|
@ -38,6 +52,10 @@ namespace Ryujinx.Graphics.Gpu.Engine
|
||||||
TextureManager = new TextureManager(context);
|
TextureManager = new TextureManager(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Register callback for GPU method calls that triggers an action on the GPU.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="state">GPU state where the triggers will be registered</param>
|
||||||
public void RegisterCallbacks(GpuState state)
|
public void RegisterCallbacks(GpuState state)
|
||||||
{
|
{
|
||||||
state.RegisterCallback(MethodOffset.LaunchDma, LaunchDma);
|
state.RegisterCallback(MethodOffset.LaunchDma, LaunchDma);
|
||||||
|
@ -72,6 +90,10 @@ namespace Ryujinx.Graphics.Gpu.Engine
|
||||||
state.RegisterCallback(MethodOffset.UniformBufferBindFragment, UniformBufferBindFragment);
|
state.RegisterCallback(MethodOffset.UniformBufferBindFragment, UniformBufferBindFragment);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Updates host state based on the current guest GPU state.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="state">Guest GPU state</param>
|
||||||
private void UpdateState(GpuState state)
|
private void UpdateState(GpuState state)
|
||||||
{
|
{
|
||||||
// Shaders must be the first one to be updated if modified, because
|
// Shaders must be the first one to be updated if modified, because
|
||||||
|
@ -175,6 +197,10 @@ namespace Ryujinx.Graphics.Gpu.Engine
|
||||||
CommitBindings();
|
CommitBindings();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Ensures that the bindings are visible to the host GPU.
|
||||||
|
/// This actually performs the binding using the host graphics API.
|
||||||
|
/// </summary>
|
||||||
private void CommitBindings()
|
private void CommitBindings()
|
||||||
{
|
{
|
||||||
UpdateStorageBuffers();
|
UpdateStorageBuffers();
|
||||||
|
@ -183,6 +209,9 @@ namespace Ryujinx.Graphics.Gpu.Engine
|
||||||
TextureManager.CommitGraphicsBindings();
|
TextureManager.CommitGraphicsBindings();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Updates storage buffer bindings.
|
||||||
|
/// </summary>
|
||||||
private void UpdateStorageBuffers()
|
private void UpdateStorageBuffers()
|
||||||
{
|
{
|
||||||
for (int stage = 0; stage < _currentProgramInfo.Length; stage++)
|
for (int stage = 0; stage < _currentProgramInfo.Length; stage++)
|
||||||
|
@ -213,6 +242,11 @@ namespace Ryujinx.Graphics.Gpu.Engine
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Updates render targets (color and depth-stencil buffers) based on current render target state.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="state">Current GPU state</param>
|
||||||
|
/// <param name="useControl">Use draw buffers information from render target control register</param>
|
||||||
private void UpdateRenderTargetState(GpuState state, bool useControl)
|
private void UpdateRenderTargetState(GpuState state, bool useControl)
|
||||||
{
|
{
|
||||||
var rtControl = state.Get<RtControl>(MethodOffset.RtControl);
|
var rtControl = state.Get<RtControl>(MethodOffset.RtControl);
|
||||||
|
@ -267,12 +301,21 @@ namespace Ryujinx.Graphics.Gpu.Engine
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Checks if a render target color buffer is used.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="colorState">Color buffer information</param>
|
||||||
|
/// <returns>True if the specified buffer is enabled/used, false otherwise</returns>
|
||||||
private static bool IsRtEnabled(RtColorState colorState)
|
private static bool IsRtEnabled(RtColorState colorState)
|
||||||
{
|
{
|
||||||
// Colors are disabled by writing 0 to the format.
|
// Colors are disabled by writing 0 to the format.
|
||||||
return colorState.Format != 0 && colorState.WidthOrStride != 0;
|
return colorState.Format != 0 && colorState.WidthOrStride != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Updates host depth test state based on current GPU state.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="state">Current GPU state</param>
|
||||||
private void UpdateDepthTestState(GpuState state)
|
private void UpdateDepthTestState(GpuState state)
|
||||||
{
|
{
|
||||||
_context.Renderer.Pipeline.SetDepthTest(new DepthTestDescriptor(
|
_context.Renderer.Pipeline.SetDepthTest(new DepthTestDescriptor(
|
||||||
|
@ -281,6 +324,10 @@ namespace Ryujinx.Graphics.Gpu.Engine
|
||||||
state.Get<CompareOp>(MethodOffset.DepthTestFunc)));
|
state.Get<CompareOp>(MethodOffset.DepthTestFunc)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Updates host viewport transform and clipping state based on current GPU state.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="state">Current GPU state</param>
|
||||||
private void UpdateViewportTransform(GpuState state)
|
private void UpdateViewportTransform(GpuState state)
|
||||||
{
|
{
|
||||||
DepthMode depthMode = state.Get<DepthMode>(MethodOffset.DepthMode);
|
DepthMode depthMode = state.Get<DepthMode>(MethodOffset.DepthMode);
|
||||||
|
@ -343,6 +390,10 @@ namespace Ryujinx.Graphics.Gpu.Engine
|
||||||
_context.Renderer.Pipeline.SetViewports(0, viewports);
|
_context.Renderer.Pipeline.SetViewports(0, viewports);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Updates host depth bias (also called polygon offset) state based on current GPU state.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="state">Current GPU state</param>
|
||||||
private void UpdateDepthBiasState(GpuState state)
|
private void UpdateDepthBiasState(GpuState state)
|
||||||
{
|
{
|
||||||
var depthBias = state.Get<DepthBiasState>(MethodOffset.DepthBiasState);
|
var depthBias = state.Get<DepthBiasState>(MethodOffset.DepthBiasState);
|
||||||
|
@ -360,6 +411,10 @@ namespace Ryujinx.Graphics.Gpu.Engine
|
||||||
_context.Renderer.Pipeline.SetDepthBias(enables, factor, units, clamp);
|
_context.Renderer.Pipeline.SetDepthBias(enables, factor, units, clamp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Updates host stencil test state based on current GPU state.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="state">Current GPU state</param>
|
||||||
private void UpdateStencilTestState(GpuState state)
|
private void UpdateStencilTestState(GpuState state)
|
||||||
{
|
{
|
||||||
var backMasks = state.Get<StencilBackMasks> (MethodOffset.StencilBackMasks);
|
var backMasks = state.Get<StencilBackMasks> (MethodOffset.StencilBackMasks);
|
||||||
|
@ -413,6 +468,10 @@ namespace Ryujinx.Graphics.Gpu.Engine
|
||||||
backMask));
|
backMask));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Updates current sampler pool address and size based on guest GPU state.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="state">Current GPU state</param>
|
||||||
private void UpdateSamplerPoolState(GpuState state)
|
private void UpdateSamplerPoolState(GpuState state)
|
||||||
{
|
{
|
||||||
var texturePool = state.Get<PoolState>(MethodOffset.TexturePoolState);
|
var texturePool = state.Get<PoolState>(MethodOffset.TexturePoolState);
|
||||||
|
@ -427,6 +486,10 @@ namespace Ryujinx.Graphics.Gpu.Engine
|
||||||
TextureManager.SetGraphicsSamplerPool(samplerPool.Address.Pack(), maximumId, samplerIndex);
|
TextureManager.SetGraphicsSamplerPool(samplerPool.Address.Pack(), maximumId, samplerIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Updates current texture pool address and size based on guest GPU state.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="state">Current GPU state</param>
|
||||||
private void UpdateTexturePoolState(GpuState state)
|
private void UpdateTexturePoolState(GpuState state)
|
||||||
{
|
{
|
||||||
var texturePool = state.Get<PoolState>(MethodOffset.TexturePoolState);
|
var texturePool = state.Get<PoolState>(MethodOffset.TexturePoolState);
|
||||||
|
@ -436,6 +499,10 @@ namespace Ryujinx.Graphics.Gpu.Engine
|
||||||
TextureManager.SetGraphicsTextureBufferIndex(state.Get<int>(MethodOffset.TextureBufferIndex));
|
TextureManager.SetGraphicsTextureBufferIndex(state.Get<int>(MethodOffset.TextureBufferIndex));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Updates host vertex attributes based on guest GPU state.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="state">Current GPU state</param>
|
||||||
private void UpdateVertexAttribState(GpuState state)
|
private void UpdateVertexAttribState(GpuState state)
|
||||||
{
|
{
|
||||||
VertexAttribDescriptor[] vertexAttribs = new VertexAttribDescriptor[16];
|
VertexAttribDescriptor[] vertexAttribs = new VertexAttribDescriptor[16];
|
||||||
|
@ -460,6 +527,10 @@ namespace Ryujinx.Graphics.Gpu.Engine
|
||||||
_context.Renderer.Pipeline.SetVertexAttribs(vertexAttribs);
|
_context.Renderer.Pipeline.SetVertexAttribs(vertexAttribs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Updates host primitive restart based on guest GPU state.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="state">Current GPU state</param>
|
||||||
private void UpdatePrimitiveRestartState(GpuState state)
|
private void UpdatePrimitiveRestartState(GpuState state)
|
||||||
{
|
{
|
||||||
PrimitiveRestartState primitiveRestart = state.Get<PrimitiveRestartState>(MethodOffset.PrimitiveRestartState);
|
PrimitiveRestartState primitiveRestart = state.Get<PrimitiveRestartState>(MethodOffset.PrimitiveRestartState);
|
||||||
|
@ -469,6 +540,10 @@ namespace Ryujinx.Graphics.Gpu.Engine
|
||||||
primitiveRestart.Index);
|
primitiveRestart.Index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Updates host index buffer binding based on guest GPU state.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="state">Current GPU state</param>
|
||||||
private void UpdateIndexBufferState(GpuState state)
|
private void UpdateIndexBufferState(GpuState state)
|
||||||
{
|
{
|
||||||
var indexBuffer = state.Get<IndexBufferState>(MethodOffset.IndexBufferState);
|
var indexBuffer = state.Get<IndexBufferState>(MethodOffset.IndexBufferState);
|
||||||
|
@ -500,6 +575,10 @@ namespace Ryujinx.Graphics.Gpu.Engine
|
||||||
UpdateVertexBufferState(state);
|
UpdateVertexBufferState(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Updates host vertex buffer bindings based on guest GPU state.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="state">Current GPU state</param>
|
||||||
private void UpdateVertexBufferState(GpuState state)
|
private void UpdateVertexBufferState(GpuState state)
|
||||||
{
|
{
|
||||||
_isAnyVbInstanced = false;
|
_isAnyVbInstanced = false;
|
||||||
|
@ -550,6 +629,10 @@ namespace Ryujinx.Graphics.Gpu.Engine
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Updates host face culling and orientation based on guest GPU state.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="state">Current GPU state</param>
|
||||||
private void UpdateFaceState(GpuState state)
|
private void UpdateFaceState(GpuState state)
|
||||||
{
|
{
|
||||||
var face = state.Get<FaceState>(MethodOffset.FaceState);
|
var face = state.Get<FaceState>(MethodOffset.FaceState);
|
||||||
|
@ -559,6 +642,11 @@ namespace Ryujinx.Graphics.Gpu.Engine
|
||||||
_context.Renderer.Pipeline.SetFrontFace(face.FrontFace);
|
_context.Renderer.Pipeline.SetFrontFace(face.FrontFace);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Updates host render target color masks, based on guest GPU state.
|
||||||
|
/// This defines with color channels are written to each color buffer.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="state">Current GPU state</param>
|
||||||
private void UpdateRtColorMask(GpuState state)
|
private void UpdateRtColorMask(GpuState state)
|
||||||
{
|
{
|
||||||
bool rtColorMaskShared = state.Get<Boolean32>(MethodOffset.RtColorMaskShared);
|
bool rtColorMaskShared = state.Get<Boolean32>(MethodOffset.RtColorMaskShared);
|
||||||
|
@ -582,6 +670,10 @@ namespace Ryujinx.Graphics.Gpu.Engine
|
||||||
_context.Renderer.Pipeline.SetRenderTargetColorMasks(componentMasks);
|
_context.Renderer.Pipeline.SetRenderTargetColorMasks(componentMasks);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Updates host render target color buffer blending state, based on guest state.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="state">Current GPU state</param>
|
||||||
private void UpdateBlendState(GpuState state)
|
private void UpdateBlendState(GpuState state)
|
||||||
{
|
{
|
||||||
bool blendIndependent = state.Get<Boolean32>(MethodOffset.BlendIndependent);
|
bool blendIndependent = state.Get<Boolean32>(MethodOffset.BlendIndependent);
|
||||||
|
@ -623,6 +715,9 @@ namespace Ryujinx.Graphics.Gpu.Engine
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Storage buffer address and size information.
|
||||||
|
/// </summary>
|
||||||
private struct SbDescriptor
|
private struct SbDescriptor
|
||||||
{
|
{
|
||||||
public uint AddressLow;
|
public uint AddressLow;
|
||||||
|
@ -636,6 +731,10 @@ namespace Ryujinx.Graphics.Gpu.Engine
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Updates host shaders based on the guest GPU state.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="state">Current GPU state</param>
|
||||||
private void UpdateShaderState(GpuState state)
|
private void UpdateShaderState(GpuState state)
|
||||||
{
|
{
|
||||||
ShaderAddresses addresses = new ShaderAddresses();
|
ShaderAddresses addresses = new ShaderAddresses();
|
||||||
|
@ -726,6 +825,11 @@ namespace Ryujinx.Graphics.Gpu.Engine
|
||||||
_context.Renderer.Pipeline.SetProgram(gs.HostProgram);
|
_context.Renderer.Pipeline.SetProgram(gs.HostProgram);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets viewport transform enable.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="state">Current GPU state</param>
|
||||||
|
/// <returns>Viewport transform enable</returns>
|
||||||
public bool GetViewportTransformEnable(GpuState state)
|
public bool GetViewportTransformEnable(GpuState state)
|
||||||
{
|
{
|
||||||
// FIXME: We should read ViewportTransformEnable, but it seems that some games writes 0 there?
|
// FIXME: We should read ViewportTransformEnable, but it seems that some games writes 0 there?
|
||||||
|
@ -734,6 +838,11 @@ namespace Ryujinx.Graphics.Gpu.Engine
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets texture target from a sampler type.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="type">Sampler type</param>
|
||||||
|
/// <returns>Texture target value</returns>
|
||||||
private static Target GetTarget(SamplerType type)
|
private static Target GetTarget(SamplerType type)
|
||||||
{
|
{
|
||||||
type &= ~(SamplerType.Indexed | SamplerType.Shadow);
|
type &= ~(SamplerType.Indexed | SamplerType.Shadow);
|
||||||
|
@ -776,16 +885,38 @@ namespace Ryujinx.Graphics.Gpu.Engine
|
||||||
return Target.Texture2D;
|
return Target.Texture2D;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Issues a texture barrier.
|
||||||
|
/// This waits until previous texture writes from the GPU to finish, before
|
||||||
|
/// performing new operations with said textures.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="state">Current GPU state</param>
|
||||||
|
/// <param name="argument">Method call argument</param>
|
||||||
private void TextureBarrier(GpuState state, int argument)
|
private void TextureBarrier(GpuState state, int argument)
|
||||||
{
|
{
|
||||||
_context.Renderer.Pipeline.TextureBarrier();
|
_context.Renderer.Pipeline.TextureBarrier();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Invalidates all modified textures on the cache.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="state">Current GPU state</param>
|
||||||
|
/// <param name="argument">Method call argument</param>
|
||||||
private void InvalidateTextures(GpuState state, int argument)
|
private void InvalidateTextures(GpuState state, int argument)
|
||||||
{
|
{
|
||||||
TextureManager.Flush();
|
TextureManager.Flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Issues a texture barrier.
|
||||||
|
/// This waits until previous texture writes from the GPU to finish, before
|
||||||
|
/// performing new operations with said textures.
|
||||||
|
/// This performs a per-tile wait, it is only valid if both the previous write
|
||||||
|
/// and current access has the same access patterns.
|
||||||
|
/// This may be faster than the regular barrier on tile-based rasterizers.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="state"></param>
|
||||||
|
/// <param name="argument"></param>
|
||||||
private void TextureBarrierTiled(GpuState state, int argument)
|
private void TextureBarrierTiled(GpuState state, int argument)
|
||||||
{
|
{
|
||||||
_context.Renderer.Pipeline.TextureBarrierTiled();
|
_context.Renderer.Pipeline.TextureBarrierTiled();
|
||||||
|
|
Loading…
Reference in a new issue