aboutsummaryrefslogtreecommitdiff
path: root/Ryujinx.Graphics.Gpu
diff options
context:
space:
mode:
authorgdkchan <gab.dark.100@gmail.com>2020-07-15 00:01:10 -0300
committerGitHub <noreply@github.com>2020-07-15 13:01:10 +1000
commit788ca6a411762035a6a7a88100c4b582b47ee82d (patch)
treed48bfb91aecaead2906ec2d390357546f8c0611f /Ryujinx.Graphics.Gpu
parent16dafe63166d065f40b57a9b7cf8017a6ba0b1ef (diff)
Initial transform feedback support (#1370)
* Initial transform feedback support * Some nits and fixes * Update ReportCounterType and Write method * Can't change shader or TFB bindings while TFB is active * Fix geometry shader input names with new naming
Diffstat (limited to 'Ryujinx.Graphics.Gpu')
-rw-r--r--Ryujinx.Graphics.Gpu/Constants.cs5
-rw-r--r--Ryujinx.Graphics.Gpu/Engine/MethodReport.cs10
-rw-r--r--Ryujinx.Graphics.Gpu/Engine/Methods.cs44
-rw-r--r--Ryujinx.Graphics.Gpu/Memory/BufferManager.cs50
-rw-r--r--Ryujinx.Graphics.Gpu/Memory/MemoryAccessor.cs4
-rw-r--r--Ryujinx.Graphics.Gpu/Shader/ShaderCache.cs36
-rw-r--r--Ryujinx.Graphics.Gpu/State/GpuState.cs19
-rw-r--r--Ryujinx.Graphics.Gpu/State/GpuStateTable.cs54
-rw-r--r--Ryujinx.Graphics.Gpu/State/MethodOffset.cs6
-rw-r--r--Ryujinx.Graphics.Gpu/State/ReportCounterType.cs11
-rw-r--r--Ryujinx.Graphics.Gpu/State/TfBufferState.cs18
-rw-r--r--Ryujinx.Graphics.Gpu/State/TfState.cs15
12 files changed, 223 insertions, 49 deletions
diff --git a/Ryujinx.Graphics.Gpu/Constants.cs b/Ryujinx.Graphics.Gpu/Constants.cs
index ac6b6139..231152f5 100644
--- a/Ryujinx.Graphics.Gpu/Constants.cs
+++ b/Ryujinx.Graphics.Gpu/Constants.cs
@@ -36,6 +36,11 @@ namespace Ryujinx.Graphics.Gpu
public const int TotalGpStorageBuffers = 16;
/// <summary>
+ /// Maximum number of transform feedback buffers.
+ /// </summary>
+ public const int TotalTransformFeedbackBuffers = 4;
+
+ /// <summary>
/// Maximum number of render target color buffers.
/// </summary>
public const int TotalRenderTargets = 8;
diff --git a/Ryujinx.Graphics.Gpu/Engine/MethodReport.cs b/Ryujinx.Graphics.Gpu/Engine/MethodReport.cs
index 224a4da1..fcea4389 100644
--- a/Ryujinx.Graphics.Gpu/Engine/MethodReport.cs
+++ b/Ryujinx.Graphics.Gpu/Engine/MethodReport.cs
@@ -61,8 +61,6 @@ namespace Ryujinx.Graphics.Gpu.Engine
/// <param name="type">Counter to be written to memory</param>
private void ReportCounter(GpuState state, ReportCounterType type)
{
- CounterData counterData = new CounterData();
-
var rs = state.Get<SemaphoreState>(MethodOffset.ReportState);
ulong gpuVa = rs.Address.Pack();
@@ -80,16 +78,14 @@ namespace Ryujinx.Graphics.Gpu.Engine
EventHandler<ulong> resultHandler = (object evt, ulong result) =>
{
+ CounterData counterData = new CounterData();
+
counterData.Counter = result;
counterData.Timestamp = ticks;
- Span<CounterData> counterDataSpan = MemoryMarshal.CreateSpan(ref counterData, 1);
-
- Span<byte> data = MemoryMarshal.Cast<CounterData, byte>(counterDataSpan);
-
if (counter?.Invalid != true)
{
- _context.MemoryAccessor.Write(gpuVa, data);
+ _context.MemoryAccessor.Write(gpuVa, counterData);
}
};
diff --git a/Ryujinx.Graphics.Gpu/Engine/Methods.cs b/Ryujinx.Graphics.Gpu/Engine/Methods.cs
index d5b11c2c..093f9048 100644
--- a/Ryujinx.Graphics.Gpu/Engine/Methods.cs
+++ b/Ryujinx.Graphics.Gpu/Engine/Methods.cs
@@ -40,6 +40,8 @@ namespace Ryujinx.Graphics.Gpu.Engine
private bool _forceShaderUpdate;
+ private bool _prevTfEnable;
+
/// <summary>
/// Creates a new instance of the GPU methods class.
/// </summary>
@@ -124,6 +126,14 @@ namespace Ryujinx.Graphics.Gpu.Engine
/// <param name="state">Guest GPU state</param>
private void UpdateState(GpuState state)
{
+ bool tfEnable = state.Get<Boolean32>(MethodOffset.TfEnable);
+
+ if (!tfEnable && _prevTfEnable)
+ {
+ _context.Renderer.Pipeline.EndTransformFeedback();
+ _prevTfEnable = false;
+ }
+
// Shaders must be the first one to be updated if modified, because
// some of the other state depends on information from the currently
// bound shaders.
@@ -134,6 +144,11 @@ namespace Ryujinx.Graphics.Gpu.Engine
UpdateShaderState(state);
}
+ if (state.QueryModified(MethodOffset.TfBufferState))
+ {
+ UpdateTfBufferState(state);
+ }
+
if (state.QueryModified(MethodOffset.ClipDistanceEnable))
{
UpdateUserClipState(state);
@@ -258,6 +273,12 @@ namespace Ryujinx.Graphics.Gpu.Engine
}
CommitBindings();
+
+ if (tfEnable && !_prevTfEnable)
+ {
+ _context.Renderer.Pipeline.BeginTransformFeedback(PrimitiveType.Convert());
+ _prevTfEnable = true;
+ }
}
/// <summary>
@@ -318,7 +339,7 @@ namespace Ryujinx.Graphics.Gpu.Engine
/// </summary>
/// <param name="state">Current GPU state</param>
/// <param name="useControl">Use draw buffers information from render target control register</param>
- /// <param name="singleUse">If this is not -1, it indicates that only the given indexed target will be used.</param>
+ /// <param name="singleUse">If this is not -1, it indicates that only the given indexed target will be used.</param>
private void UpdateRenderTargetState(GpuState state, bool useControl, int singleUse = -1)
{
var rtControl = state.Get<RtControl>(MethodOffset.RtControl);
@@ -1004,6 +1025,27 @@ namespace Ryujinx.Graphics.Gpu.Engine
}
/// <summary>
+ /// Updates transform feedback buffer state based on the guest GPU state.
+ /// </summary>
+ /// <param name="state">Current GPU state</param>
+ private void UpdateTfBufferState(GpuState state)
+ {
+ for (int index = 0; index < Constants.TotalTransformFeedbackBuffers; index++)
+ {
+ TfBufferState tfb = state.Get<TfBufferState>(MethodOffset.TfBufferState, index);
+
+ if (!tfb.Enable)
+ {
+ BufferManager.SetTransformFeedbackBuffer(index, 0, 0);
+
+ continue;
+ }
+
+ BufferManager.SetTransformFeedbackBuffer(index, tfb.Address.Pack(), (uint)tfb.Size);
+ }
+ }
+
+ /// <summary>
/// Updates user-defined clipping based on the guest GPU state.
/// </summary>
/// <param name="state">Current GPU state</param>
diff --git a/Ryujinx.Graphics.Gpu/Memory/BufferManager.cs b/Ryujinx.Graphics.Gpu/Memory/BufferManager.cs
index 533b0576..9712f58f 100644
--- a/Ryujinx.Graphics.Gpu/Memory/BufferManager.cs
+++ b/Ryujinx.Graphics.Gpu/Memory/BufferManager.cs
@@ -24,8 +24,8 @@ namespace Ryujinx.Graphics.Gpu.Memory
private Buffer[] _bufferOverlaps;
private IndexBuffer _indexBuffer;
-
private VertexBuffer[] _vertexBuffers;
+ private BufferBounds[] _transformFeedbackBuffers;
private class BuffersPerStage
{
@@ -56,6 +56,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
private bool _indexBufferDirty;
private bool _vertexBuffersDirty;
private uint _vertexBuffersEnableMask;
+ private bool _transformFeedbackBuffersDirty;
private bool _rebind;
@@ -73,6 +74,8 @@ namespace Ryujinx.Graphics.Gpu.Memory
_vertexBuffers = new VertexBuffer[Constants.TotalVertexBuffers];
+ _transformFeedbackBuffers = new BufferBounds[Constants.TotalTransformFeedbackBuffers];
+
_cpStorageBuffers = new BuffersPerStage(Constants.TotalCpStorageBuffers);
_cpUniformBuffers = new BuffersPerStage(Constants.TotalCpUniformBuffers);
@@ -144,6 +147,16 @@ namespace Ryujinx.Graphics.Gpu.Memory
}
}
+ public void SetTransformFeedbackBuffer(int index, ulong gpuVa, ulong size)
+ {
+ ulong address = TranslateAndCreateBuffer(gpuVa, size);
+
+ _transformFeedbackBuffers[index].Address = address;
+ _transformFeedbackBuffers[index].Size = size;
+
+ _transformFeedbackBuffersDirty = true;
+ }
+
/// <summary>
/// Sets a storage buffer on the compute pipeline.
/// Storage buffers can be read and written to on shaders.
@@ -522,6 +535,41 @@ namespace Ryujinx.Graphics.Gpu.Memory
}
}
+ if (_transformFeedbackBuffersDirty)
+ {
+ _transformFeedbackBuffersDirty = false;
+
+ for (int index = 0; index < Constants.TotalTransformFeedbackBuffers; index++)
+ {
+ BufferBounds tfb = _transformFeedbackBuffers[index];
+
+ if (tfb.Address == 0)
+ {
+ _context.Renderer.Pipeline.SetTransformFeedbackBuffer(index, new BufferRange(BufferHandle.Null, 0, 0));
+
+ continue;
+ }
+
+ BufferRange buffer = GetBufferRange(tfb.Address, tfb.Size);
+
+ _context.Renderer.Pipeline.SetTransformFeedbackBuffer(index, buffer);
+ }
+ }
+ else
+ {
+ for (int index = 0; index < Constants.TotalTransformFeedbackBuffers; index++)
+ {
+ BufferBounds tfb = _transformFeedbackBuffers[index];
+
+ if (tfb.Address == 0)
+ {
+ continue;
+ }
+
+ SynchronizeBufferRange(tfb.Address, tfb.Size);
+ }
+ }
+
if (_gpStorageBuffersDirty || _rebind)
{
_gpStorageBuffersDirty = false;
diff --git a/Ryujinx.Graphics.Gpu/Memory/MemoryAccessor.cs b/Ryujinx.Graphics.Gpu/Memory/MemoryAccessor.cs
index 5cc8ec24..2c53f699 100644
--- a/Ryujinx.Graphics.Gpu/Memory/MemoryAccessor.cs
+++ b/Ryujinx.Graphics.Gpu/Memory/MemoryAccessor.cs
@@ -63,11 +63,11 @@ namespace Ryujinx.Graphics.Gpu.Memory
/// </summary>
/// <param name="gpuVa">GPU virtual address to write the value into</param>
/// <param name="value">The value to be written</param>
- public void Write(ulong gpuVa, int value)
+ public void Write<T>(ulong gpuVa, T value) where T : unmanaged
{
ulong processVa = _context.MemoryManager.Translate(gpuVa);
- _context.PhysicalMemory.Write(processVa, BitConverter.GetBytes(value));
+ _context.PhysicalMemory.Write(processVa, MemoryMarshal.Cast<T, byte>(MemoryMarshal.CreateSpan(ref value, 1)));
}
/// <summary>
diff --git a/Ryujinx.Graphics.Gpu/Shader/ShaderCache.cs b/Ryujinx.Graphics.Gpu/Shader/ShaderCache.cs
index 8a1abe32..d16f1057 100644
--- a/Ryujinx.Graphics.Gpu/Shader/ShaderCache.cs
+++ b/Ryujinx.Graphics.Gpu/Shader/ShaderCache.cs
@@ -82,7 +82,7 @@ namespace Ryujinx.Graphics.Gpu.Shader
shader.HostShader = _context.Renderer.CompileShader(shader.Program);
- IProgram hostProgram = _context.Renderer.CreateProgram(new IShader[] { shader.HostShader });
+ IProgram hostProgram = _context.Renderer.CreateProgram(new IShader[] { shader.HostShader }, null);
ShaderBundle cpShader = new ShaderBundle(hostProgram, shader);
@@ -150,6 +150,8 @@ namespace Ryujinx.Graphics.Gpu.Shader
continue;
}
+ var tfd = GetTransformFeedbackDescriptors(state);
+
IShader hostShader = _context.Renderer.CompileShader(program);
shaders[stage].HostShader = hostShader;
@@ -157,7 +159,7 @@ namespace Ryujinx.Graphics.Gpu.Shader
hostShaders.Add(hostShader);
}
- IProgram hostProgram = _context.Renderer.CreateProgram(hostShaders.ToArray());
+ IProgram hostProgram = _context.Renderer.CreateProgram(hostShaders.ToArray(), GetTransformFeedbackDescriptors(state));
ShaderBundle gpShaders = new ShaderBundle(hostProgram, shaders);
@@ -174,6 +176,36 @@ namespace Ryujinx.Graphics.Gpu.Shader
}
/// <summary>
+ /// Gets transform feedback state from the current GPU state.
+ /// </summary>
+ /// <param name="state">Current GPU state</param>
+ /// <returns>Four transform feedback descriptors for the enabled TFBs, or null if TFB is disabled</returns>
+ private TransformFeedbackDescriptor[] GetTransformFeedbackDescriptors(GpuState state)
+ {
+ bool tfEnable = state.Get<Boolean32>(MethodOffset.TfEnable);
+
+ if (!tfEnable)
+ {
+ return null;
+ }
+
+ TransformFeedbackDescriptor[] descs = new TransformFeedbackDescriptor[Constants.TotalTransformFeedbackBuffers];
+
+ for (int i = 0; i < Constants.TotalTransformFeedbackBuffers; i++)
+ {
+ var tf = state.Get<TfState>(MethodOffset.TfState, i);
+
+ int length = (int)Math.Min((uint)tf.VaryingsCount, 0x80);
+
+ var varyingLocations = state.GetSpan(MethodOffset.TfVaryingLocations + i * 0x80, length).ToArray();
+
+ descs[i] = new TransformFeedbackDescriptor(tf.BufferIndex, tf.Stride, varyingLocations);
+ }
+
+ return descs;
+ }
+
+ /// <summary>
/// Checks if compute shader code in memory is equal to the cached shader.
/// </summary>
/// <param name="cpShader">Cached compute shader</param>
diff --git a/Ryujinx.Graphics.Gpu/State/GpuState.cs b/Ryujinx.Graphics.Gpu/State/GpuState.cs
index 264719b4..9e7d9492 100644
--- a/Ryujinx.Graphics.Gpu/State/GpuState.cs
+++ b/Ryujinx.Graphics.Gpu/State/GpuState.cs
@@ -346,7 +346,7 @@ namespace Ryujinx.Graphics.Gpu.State
/// <param name="offset">Register offset</param>
/// <param name="index">Index for indexed data</param>
/// <returns>The data at the specified location</returns>
- public T Get<T>(MethodOffset offset, int index) where T : struct
+ public T Get<T>(MethodOffset offset, int index) where T : unmanaged
{
Register register = _registers[(int)offset];
@@ -364,19 +364,30 @@ namespace Ryujinx.Graphics.Gpu.State
/// <typeparam name="T">Type of the data</typeparam>
/// <param name="offset">Register offset</param>
/// <returns>The data at the specified location</returns>
- public T Get<T>(MethodOffset offset) where T : struct
+ public T Get<T>(MethodOffset offset) where T : unmanaged
{
return MemoryMarshal.Cast<int, T>(_memory.AsSpan().Slice((int)offset))[0];
}
/// <summary>
+ /// Gets a span of the data at a given register offset.
+ /// </summary>
+ /// <param name="offset">Register offset</param>
+ /// <param name="length">Length of the data in bytes</param>
+ /// <returns>The data at the specified location</returns>
+ public Span<byte> GetSpan(MethodOffset offset, int length)
+ {
+ return MemoryMarshal.Cast<int, byte>(_memory.AsSpan().Slice((int)offset)).Slice(0, length);
+ }
+
+ /// <summary>
/// Sets indexed data to a given register offset.
/// </summary>
/// <typeparam name="T">Type of the data</typeparam>
/// <param name="offset">Register offset</param>
/// <param name="index">Index for indexed data</param>
/// <param name="data">The data to set</param>
- public void Set<T>(MethodOffset offset, int index, T data) where T : struct
+ public void Set<T>(MethodOffset offset, int index, T data) where T : unmanaged
{
Register register = _registers[(int)offset];
@@ -394,7 +405,7 @@ namespace Ryujinx.Graphics.Gpu.State
/// <typeparam name="T">Type of the data</typeparam>
/// <param name="offset">Register offset</param>
/// <param name="data">The data to set</param>
- public void Set<T>(MethodOffset offset, T data) where T : struct
+ public void Set<T>(MethodOffset offset, T data) where T : unmanaged
{
ReadOnlySpan<int> intSpan = MemoryMarshal.Cast<T, int>(MemoryMarshal.CreateReadOnlySpan(ref data, 1));
intSpan.CopyTo(_memory.AsSpan().Slice((int)offset, intSpan.Length));
diff --git a/Ryujinx.Graphics.Gpu/State/GpuStateTable.cs b/Ryujinx.Graphics.Gpu/State/GpuStateTable.cs
index 65df5f4e..acc0fe85 100644
--- a/Ryujinx.Graphics.Gpu/State/GpuStateTable.cs
+++ b/Ryujinx.Graphics.Gpu/State/GpuStateTable.cs
@@ -53,32 +53,34 @@ namespace Ryujinx.Graphics.Gpu.State
/// </summary>
public static TableItem[] Table = new TableItem[]
{
- new TableItem(MethodOffset.RtColorState, typeof(RtColorState), Constants.TotalRenderTargets),
- new TableItem(MethodOffset.ViewportTransform, typeof(ViewportTransform), Constants.TotalViewports),
- new TableItem(MethodOffset.ViewportExtents, typeof(ViewportExtents), Constants.TotalViewports),
- new TableItem(MethodOffset.VertexBufferDrawState, typeof(VertexBufferDrawState), 1),
- new TableItem(MethodOffset.DepthBiasState, typeof(DepthBiasState), 1),
- new TableItem(MethodOffset.ScissorState, typeof(ScissorState), Constants.TotalViewports),
- new TableItem(MethodOffset.StencilBackMasks, typeof(StencilBackMasks), 1),
- new TableItem(MethodOffset.RtDepthStencilState, typeof(RtDepthStencilState), 1),
- new TableItem(MethodOffset.VertexAttribState, typeof(VertexAttribState), 16),
- new TableItem(MethodOffset.RtDepthStencilSize, typeof(Size3D), 1),
- new TableItem(MethodOffset.BlendEnable, typeof(Boolean32), Constants.TotalRenderTargets),
- new TableItem(MethodOffset.StencilTestState, typeof(StencilTestState), 1),
- new TableItem(MethodOffset.SamplerPoolState, typeof(PoolState), 1),
- new TableItem(MethodOffset.TexturePoolState, typeof(PoolState), 1),
- new TableItem(MethodOffset.StencilBackTestState, typeof(StencilBackTestState), 1),
- new TableItem(MethodOffset.ShaderBaseAddress, typeof(GpuVa), 1),
- new TableItem(MethodOffset.PrimitiveRestartState, typeof(PrimitiveRestartState), 1),
- new TableItem(MethodOffset.IndexBufferState, typeof(IndexBufferState), 1),
- new TableItem(MethodOffset.VertexBufferInstanced, typeof(Boolean32), 16),
- new TableItem(MethodOffset.FaceState, typeof(FaceState), 1),
- new TableItem(MethodOffset.RtColorMask, typeof(RtColorMask), Constants.TotalRenderTargets),
- new TableItem(MethodOffset.VertexBufferState, typeof(VertexBufferState), 16),
- new TableItem(MethodOffset.BlendConstant, typeof(ColorF), 1),
- new TableItem(MethodOffset.BlendState, typeof(BlendState), Constants.TotalRenderTargets),
- new TableItem(MethodOffset.VertexBufferEndAddress, typeof(GpuVa), 16),
- new TableItem(MethodOffset.ShaderState, typeof(ShaderState), 6),
+ new TableItem(MethodOffset.TfBufferState, typeof(TfBufferState), Constants.TotalTransformFeedbackBuffers),
+ new TableItem(MethodOffset.TfState, typeof(TfState), Constants.TotalTransformFeedbackBuffers),
+ new TableItem(MethodOffset.RtColorState, typeof(RtColorState), Constants.TotalRenderTargets),
+ new TableItem(MethodOffset.ViewportTransform, typeof(ViewportTransform), Constants.TotalViewports),
+ new TableItem(MethodOffset.ViewportExtents, typeof(ViewportExtents), Constants.TotalViewports),
+ new TableItem(MethodOffset.VertexBufferDrawState, typeof(VertexBufferDrawState), 1),
+ new TableItem(MethodOffset.DepthBiasState, typeof(DepthBiasState), 1),
+ new TableItem(MethodOffset.ScissorState, typeof(ScissorState), Constants.TotalViewports),
+ new TableItem(MethodOffset.StencilBackMasks, typeof(StencilBackMasks), 1),
+ new TableItem(MethodOffset.RtDepthStencilState, typeof(RtDepthStencilState), 1),
+ new TableItem(MethodOffset.VertexAttribState, typeof(VertexAttribState), Constants.TotalVertexAttribs),
+ new TableItem(MethodOffset.RtDepthStencilSize, typeof(Size3D), 1),
+ new TableItem(MethodOffset.BlendEnable, typeof(Boolean32), Constants.TotalRenderTargets),
+ new TableItem(MethodOffset.StencilTestState, typeof(StencilTestState), 1),
+ new TableItem(MethodOffset.SamplerPoolState, typeof(PoolState), 1),
+ new TableItem(MethodOffset.TexturePoolState, typeof(PoolState), 1),
+ new TableItem(MethodOffset.StencilBackTestState, typeof(StencilBackTestState), 1),
+ new TableItem(MethodOffset.ShaderBaseAddress, typeof(GpuVa), 1),
+ new TableItem(MethodOffset.PrimitiveRestartState, typeof(PrimitiveRestartState), 1),
+ new TableItem(MethodOffset.IndexBufferState, typeof(IndexBufferState), 1),
+ new TableItem(MethodOffset.VertexBufferInstanced, typeof(Boolean32), Constants.TotalVertexBuffers),
+ new TableItem(MethodOffset.FaceState, typeof(FaceState), 1),
+ new TableItem(MethodOffset.RtColorMask, typeof(RtColorMask), Constants.TotalRenderTargets),
+ new TableItem(MethodOffset.VertexBufferState, typeof(VertexBufferState), Constants.TotalVertexBuffers),
+ new TableItem(MethodOffset.BlendConstant, typeof(ColorF), 1),
+ new TableItem(MethodOffset.BlendState, typeof(BlendState), Constants.TotalRenderTargets),
+ new TableItem(MethodOffset.VertexBufferEndAddress, typeof(GpuVa), Constants.TotalVertexBuffers),
+ new TableItem(MethodOffset.ShaderState, typeof(ShaderState), Constants.ShaderStages + 1),
};
}
} \ No newline at end of file
diff --git a/Ryujinx.Graphics.Gpu/State/MethodOffset.cs b/Ryujinx.Graphics.Gpu/State/MethodOffset.cs
index d7d5d903..b0eb6f32 100644
--- a/Ryujinx.Graphics.Gpu/State/MethodOffset.cs
+++ b/Ryujinx.Graphics.Gpu/State/MethodOffset.cs
@@ -28,10 +28,13 @@ namespace Ryujinx.Graphics.Gpu.State
SyncpointAction = 0xb2,
CopyBuffer = 0xc0,
RasterizeEnable = 0xdf,
+ TfBufferState = 0xe0,
CopyBufferParams = 0x100,
+ TfState = 0x1c0,
CopyBufferSwizzle = 0x1c2,
CopyBufferDstTexture = 0x1c3,
CopyBufferSrcTexture = 0x1ca,
+ TfEnable = 0x1d1,
RtColorState = 0x200,
CopyTextureControl = 0x223,
CopyRegion = 0x22c,
@@ -116,6 +119,7 @@ namespace Ryujinx.Graphics.Gpu.State
UniformBufferBindTessEvaluation = 0x914,
UniformBufferBindGeometry = 0x91c,
UniformBufferBindFragment = 0x924,
- TextureBufferIndex = 0x982
+ TextureBufferIndex = 0x982,
+ TfVaryingLocations = 0xa00
}
} \ No newline at end of file
diff --git a/Ryujinx.Graphics.Gpu/State/ReportCounterType.cs b/Ryujinx.Graphics.Gpu/State/ReportCounterType.cs
index cface55d..6bde2844 100644
--- a/Ryujinx.Graphics.Gpu/State/ReportCounterType.cs
+++ b/Ryujinx.Graphics.Gpu/State/ReportCounterType.cs
@@ -11,18 +11,19 @@ namespace Ryujinx.Graphics.Gpu.State
VertexShaderInvocations = 5,
GeometryShaderInvocations = 7,
GeometryShaderPrimitives = 9,
+ ZcullStats0 = 0xa,
TransformFeedbackPrimitivesWritten = 0xb,
+ ZcullStats1 = 0xc,
+ ZcullStats2 = 0xe,
ClipperInputPrimitives = 0xf,
+ ZcullStats3 = 0x10,
ClipperOutputPrimitives = 0x11,
PrimitivesGenerated = 0x12,
FragmentShaderInvocations = 0x13,
SamplesPassed = 0x15,
+ TransformFeedbackOffset = 0x1a,
TessControlShaderInvocations = 0x1b,
TessEvaluationShaderInvocations = 0x1d,
- TessEvaluationShaderPrimitives = 0x1f,
- ZcullStats0 = 0x2a,
- ZcullStats1 = 0x2c,
- ZcullStats2 = 0x2e,
- ZcullStats3 = 0x30
+ TessEvaluationShaderPrimitives = 0x1f
}
} \ No newline at end of file
diff --git a/Ryujinx.Graphics.Gpu/State/TfBufferState.cs b/Ryujinx.Graphics.Gpu/State/TfBufferState.cs
new file mode 100644
index 00000000..24dc0952
--- /dev/null
+++ b/Ryujinx.Graphics.Gpu/State/TfBufferState.cs
@@ -0,0 +1,18 @@
+namespace Ryujinx.Graphics.Gpu.State
+{
+ /// <summary>
+ /// Transform feedback buffer state.
+ /// </summary>
+ struct TfBufferState
+ {
+#pragma warning disable CS0649
+ public Boolean32 Enable;
+ public GpuVa Address;
+ public int Size;
+ public int Offset;
+ public uint Padding0;
+ public uint Padding1;
+ public uint Padding2;
+#pragma warning restore CS0649
+ }
+}
diff --git a/Ryujinx.Graphics.Gpu/State/TfState.cs b/Ryujinx.Graphics.Gpu/State/TfState.cs
new file mode 100644
index 00000000..fb8b950b
--- /dev/null
+++ b/Ryujinx.Graphics.Gpu/State/TfState.cs
@@ -0,0 +1,15 @@
+namespace Ryujinx.Graphics.Gpu.State
+{
+ /// <summary>
+ /// Transform feedback state.
+ /// </summary>
+ struct TfState
+ {
+#pragma warning disable CS0649
+ public int BufferIndex;
+ public int VaryingsCount;
+ public int Stride;
+ public uint Padding;
+#pragma warning restore CS0649
+ }
+}