aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Ryujinx.Graphics.Gpu/Engine/ConditionalRenderEnabled.cs9
-rw-r--r--Ryujinx.Graphics.Gpu/Engine/IbStreamer.cs139
-rw-r--r--Ryujinx.Graphics.Gpu/Engine/MethodClear.cs2
-rw-r--r--Ryujinx.Graphics.Gpu/Engine/MethodConditionalRendering.cs7
-rw-r--r--Ryujinx.Graphics.Gpu/Engine/MethodDraw.cs214
-rw-r--r--Ryujinx.Graphics.Gpu/Engine/Methods.cs29
-rw-r--r--Ryujinx.Graphics.Gpu/Image/TextureManager.cs2
-rw-r--r--Ryujinx.Graphics.Gpu/Shader/GpuAccessor.cs24
-rw-r--r--Ryujinx.Graphics.Gpu/State/MethodOffset.cs5
-rw-r--r--Ryujinx.Graphics.Gpu/State/PrimitiveType.cs (renamed from Ryujinx.Graphics.Gpu/State/PrimitiveTopology.cs)43
10 files changed, 349 insertions, 125 deletions
diff --git a/Ryujinx.Graphics.Gpu/Engine/ConditionalRenderEnabled.cs b/Ryujinx.Graphics.Gpu/Engine/ConditionalRenderEnabled.cs
new file mode 100644
index 00000000..451f4963
--- /dev/null
+++ b/Ryujinx.Graphics.Gpu/Engine/ConditionalRenderEnabled.cs
@@ -0,0 +1,9 @@
+namespace Ryujinx.Graphics.Gpu.Engine
+{
+ enum ConditionalRenderEnabled
+ {
+ False,
+ True,
+ Host
+ }
+}
diff --git a/Ryujinx.Graphics.Gpu/Engine/IbStreamer.cs b/Ryujinx.Graphics.Gpu/Engine/IbStreamer.cs
new file mode 100644
index 00000000..b407c941
--- /dev/null
+++ b/Ryujinx.Graphics.Gpu/Engine/IbStreamer.cs
@@ -0,0 +1,139 @@
+using Ryujinx.Common;
+using Ryujinx.Graphics.GAL;
+using System;
+using System.Runtime.InteropServices;
+
+namespace Ryujinx.Graphics.Gpu.Engine
+{
+ /// <summary>
+ /// Holds inline index buffer state.
+ /// The inline index buffer data is sent to the GPU through the command buffer.
+ /// </summary>
+ struct IbStreamer
+ {
+ private BufferHandle _inlineIndexBuffer;
+ private int _inlineIndexBufferSize;
+ private int _inlineIndexCount;
+
+ public bool HasInlineIndexData => _inlineIndexCount != 0;
+
+ /// <summary>
+ /// Gets the handle for the host buffer currently holding the inline index buffer data.
+ /// </summary>
+ /// <returns>Host buffer handle</returns>
+ public BufferHandle GetInlineIndexBuffer()
+ {
+ return _inlineIndexBuffer;
+ }
+
+ /// <summary>
+ /// Gets the number of elements on the current inline index buffer,
+ /// while also reseting it to zero for the next draw.
+ /// </summary>
+ /// <returns>Inline index bufffer count</returns>
+ public int GetAndResetInlineIndexCount()
+ {
+ int temp = _inlineIndexCount;
+ _inlineIndexCount = 0;
+ return temp;
+ }
+
+ /// <summary>
+ /// Pushes four 8-bit index buffer elements.
+ /// </summary>
+ /// <param name="renderer">Host renderer</param>
+ /// <param name="argument">Method call argument</param>
+ public void VbElementU8(IRenderer renderer, int argument)
+ {
+ byte i0 = (byte)argument;
+ byte i1 = (byte)(argument >> 8);
+ byte i2 = (byte)(argument >> 16);
+ byte i3 = (byte)(argument >> 24);
+
+ Span<uint> data = stackalloc uint[4];
+
+ data[0] = i0;
+ data[1] = i1;
+ data[2] = i2;
+ data[3] = i3;
+
+ int offset = _inlineIndexCount * 4;
+
+ renderer.SetBufferData(GetInlineIndexBuffer(renderer, offset), offset, MemoryMarshal.Cast<uint, byte>(data));
+
+ _inlineIndexCount += 4;
+ }
+
+ /// <summary>
+ /// Pushes two 16-bit index buffer elements.
+ /// </summary>
+ /// <param name="renderer">Host renderer</param>
+ /// <param name="argument">Method call argument</param>
+ public void VbElementU16(IRenderer renderer, int argument)
+ {
+ ushort i0 = (ushort)argument;
+ ushort i1 = (ushort)(argument >> 16);
+
+ Span<uint> data = stackalloc uint[2];
+
+ data[0] = i0;
+ data[1] = i1;
+
+ int offset = _inlineIndexCount * 4;
+
+ renderer.SetBufferData(GetInlineIndexBuffer(renderer, offset), offset, MemoryMarshal.Cast<uint, byte>(data));
+
+ _inlineIndexCount += 2;
+ }
+
+ /// <summary>
+ /// Pushes one 32-bit index buffer element.
+ /// </summary>
+ /// <param name="renderer">Host renderer</param>
+ /// <param name="argument">Method call argument</param>
+ public void VbElementU32(IRenderer renderer, int argument)
+ {
+ uint i0 = (uint)argument;
+
+ Span<uint> data = stackalloc uint[1];
+
+ data[0] = i0;
+
+ int offset = _inlineIndexCount++ * 4;
+
+ renderer.SetBufferData(GetInlineIndexBuffer(renderer, offset), offset, MemoryMarshal.Cast<uint, byte>(data));
+ }
+
+ /// <summary>
+ /// Gets the handle of a buffer large enough to hold the data that will be written to <paramref name="offset"/>.
+ /// </summary>
+ /// <param name="renderer">Host renderer</param>
+ /// <param name="offset">Offset where the data will be written</param>
+ /// <returns>Buffer handle</returns>
+ private BufferHandle GetInlineIndexBuffer(IRenderer renderer, int offset)
+ {
+ // Calculate a reasonable size for the buffer that can fit all the data,
+ // and that also won't require frequent resizes if we need to push more data.
+ int size = BitUtils.AlignUp(offset + 0x10, 0x200);
+
+ if (_inlineIndexBuffer == BufferHandle.Null)
+ {
+ _inlineIndexBuffer = renderer.CreateBuffer(size);
+ _inlineIndexBufferSize = size;
+ }
+ else if (_inlineIndexBufferSize < size)
+ {
+ BufferHandle oldBuffer = _inlineIndexBuffer;
+ int oldSize = _inlineIndexBufferSize;
+
+ _inlineIndexBuffer = renderer.CreateBuffer(size);
+ _inlineIndexBufferSize = size;
+
+ renderer.Pipeline.CopyBuffer(oldBuffer, _inlineIndexBuffer, 0, 0, oldSize);
+ renderer.DeleteBuffer(oldBuffer);
+ }
+
+ return _inlineIndexBuffer;
+ }
+ }
+}
diff --git a/Ryujinx.Graphics.Gpu/Engine/MethodClear.cs b/Ryujinx.Graphics.Gpu/Engine/MethodClear.cs
index 5da87e6c..82c4a990 100644
--- a/Ryujinx.Graphics.Gpu/Engine/MethodClear.cs
+++ b/Ryujinx.Graphics.Gpu/Engine/MethodClear.cs
@@ -30,7 +30,7 @@ namespace Ryujinx.Graphics.Gpu.Engine
UpdateRenderTargetState(state, useControl: false, singleUse: index);
- TextureManager.CommitGraphicsBindings();
+ TextureManager.UpdateRenderTargets();
bool clearDepth = (argument & 1) != 0;
bool clearStencil = (argument & 2) != 0;
diff --git a/Ryujinx.Graphics.Gpu/Engine/MethodConditionalRendering.cs b/Ryujinx.Graphics.Gpu/Engine/MethodConditionalRendering.cs
index c508f3b6..7e7964c4 100644
--- a/Ryujinx.Graphics.Gpu/Engine/MethodConditionalRendering.cs
+++ b/Ryujinx.Graphics.Gpu/Engine/MethodConditionalRendering.cs
@@ -6,13 +6,6 @@ namespace Ryujinx.Graphics.Gpu.Engine
{
partial class Methods
{
- enum ConditionalRenderEnabled
- {
- False,
- True,
- Host
- }
-
/// <summary>
/// Checks if draws and clears should be performed, according
/// to currently set conditional rendering conditions.
diff --git a/Ryujinx.Graphics.Gpu/Engine/MethodDraw.cs b/Ryujinx.Graphics.Gpu/Engine/MethodDraw.cs
index 5d41dafd..88f2e8fe 100644
--- a/Ryujinx.Graphics.Gpu/Engine/MethodDraw.cs
+++ b/Ryujinx.Graphics.Gpu/Engine/MethodDraw.cs
@@ -1,9 +1,6 @@
-using Ryujinx.Common;
using Ryujinx.Graphics.GAL;
using Ryujinx.Graphics.Gpu.Image;
using Ryujinx.Graphics.Gpu.State;
-using System;
-using System.Runtime.InteropServices;
namespace Ryujinx.Graphics.Gpu.Engine
{
@@ -11,9 +8,6 @@ namespace Ryujinx.Graphics.Gpu.Engine
{
private bool _drawIndexed;
- private int _firstIndex;
- private int _indexCount;
-
private bool _instancedDrawPending;
private bool _instancedIndexed;
@@ -26,23 +20,35 @@ namespace Ryujinx.Graphics.Gpu.Engine
private int _instanceIndex;
- private BufferHandle _inlineIndexBuffer = BufferHandle.Null;
- private int _inlineIndexBufferSize;
- private int _inlineIndexCount;
+ private IbStreamer _ibStreamer;
/// <summary>
- /// Primitive type of the current draw.
+ /// Primitive topology of the current draw.
/// </summary>
- public PrimitiveType PrimitiveType { get; private set; }
+ public PrimitiveTopology Topology { get; private set; }
/// <summary>
- /// Finishes draw call.
+ /// Finishes the 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)
{
+ var indexBuffer = state.Get<IndexBufferState>(MethodOffset.IndexBufferState);
+
+ DrawEnd(state, indexBuffer.First, indexBuffer.Count);
+ }
+
+ /// <summary>
+ /// Finishes the 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="firstIndex">Index of the first index buffer element used on the draw</param>
+ /// <param name="indexCount">Number of index buffer elements used on the draw</param>
+ private void DrawEnd(GpuState state, int firstIndex, int indexCount)
+ {
ConditionalRenderEnabled renderEnable = GetRenderEnable(state);
if (renderEnable == ConditionalRenderEnabled.False || _instancedDrawPending)
@@ -62,7 +68,7 @@ namespace Ryujinx.Graphics.Gpu.Engine
return;
}
- UpdateState(state);
+ UpdateState(state, firstIndex, indexCount);
bool instanced = _vsUsesInstanceId || _isAnyVbInstanced;
@@ -72,11 +78,11 @@ namespace Ryujinx.Graphics.Gpu.Engine
_instancedIndexed = _drawIndexed;
- _instancedFirstIndex = _firstIndex;
- _instancedFirstVertex = state.Get<int>(MethodOffset.FirstVertex);
+ _instancedFirstIndex = firstIndex;
+ _instancedFirstVertex = state.Get<int>(MethodOffset.FirstVertex);
_instancedFirstInstance = state.Get<int>(MethodOffset.FirstInstance);
- _instancedIndexCount = _indexCount;
+ _instancedIndexCount = indexCount;
var drawState = state.Get<VertexBufferDrawState>(MethodOffset.VertexBufferDrawState);
@@ -95,31 +101,31 @@ namespace Ryujinx.Graphics.Gpu.Engine
int firstInstance = state.Get<int>(MethodOffset.FirstInstance);
- if (_inlineIndexCount != 0)
+ int inlineIndexCount = _ibStreamer.GetAndResetInlineIndexCount();
+
+ if (inlineIndexCount != 0)
{
int firstVertex = state.Get<int>(MethodOffset.FirstVertex);
- BufferRange br = new BufferRange(_inlineIndexBuffer, 0, _inlineIndexCount * 4);
+ BufferRange br = new BufferRange(_ibStreamer.GetInlineIndexBuffer(), 0, inlineIndexCount * 4);
_context.Methods.BufferManager.SetIndexBuffer(br, IndexType.UInt);
_context.Renderer.Pipeline.DrawIndexed(
- _inlineIndexCount,
+ inlineIndexCount,
1,
- _firstIndex,
+ firstIndex,
firstVertex,
firstInstance);
-
- _inlineIndexCount = 0;
}
else if (_drawIndexed)
{
int firstVertex = state.Get<int>(MethodOffset.FirstVertex);
_context.Renderer.Pipeline.DrawIndexed(
- _indexCount,
+ indexCount,
1,
- _firstIndex,
+ firstIndex,
firstVertex,
firstInstance);
}
@@ -150,22 +156,46 @@ namespace Ryujinx.Graphics.Gpu.Engine
/// <param name="argument">Method call argument</param>
private void DrawBegin(GpuState state, int argument)
{
- if ((argument & (1 << 26)) != 0)
+ bool incrementInstance = (argument & (1 << 26)) != 0;
+ bool resetInstance = (argument & (1 << 27)) == 0;
+
+ PrimitiveType type = (PrimitiveType)(argument & 0xffff);
+
+ PrimitiveTypeOverride typeOverride = state.Get<PrimitiveTypeOverride>(MethodOffset.PrimitiveTypeOverride);
+
+ if (typeOverride != PrimitiveTypeOverride.Invalid)
+ {
+ DrawBegin(incrementInstance, resetInstance, typeOverride.Convert());
+ }
+ else
+ {
+ DrawBegin(incrementInstance, resetInstance, type.Convert());
+ }
+ }
+
+ /// <summary>
+ /// Starts draw.
+ /// This sets primitive type and instanced draw parameters.
+ /// </summary>
+ /// <param name="incrementInstance">Indicates if the current instance should be incremented</param>
+ /// <param name="resetInstance">Indicates if the current instance should be set to zero</param>
+ /// <param name="topology">Primitive topology</param>
+ private void DrawBegin(bool incrementInstance, bool resetInstance, PrimitiveTopology topology)
+ {
+ if (incrementInstance)
{
_instanceIndex++;
}
- else if ((argument & (1 << 27)) == 0)
+ else if (resetInstance)
{
PerformDeferredDraws();
_instanceIndex = 0;
}
- PrimitiveType type = (PrimitiveType)(argument & 0xffff);
-
- _context.Renderer.Pipeline.SetPrimitiveTopology(type.Convert());
+ _context.Renderer.Pipeline.SetPrimitiveTopology(topology);
- PrimitiveType = type;
+ Topology = topology;
}
/// <summary>
@@ -180,100 +210,100 @@ namespace Ryujinx.Graphics.Gpu.Engine
}
/// <summary>
- /// Pushes four 8-bit index buffer elements.
+ /// Performs a indexed draw with a low number of index buffer elements.
/// </summary>
/// <param name="state">Current GPU state</param>
/// <param name="argument">Method call argument</param>
- private void VbElementU8(GpuState state, int argument)
+ private void DrawIndexedSmall(GpuState state, int argument)
{
- byte i0 = (byte)argument;
- byte i1 = (byte)(argument >> 8);
- byte i2 = (byte)(argument >> 16);
- byte i3 = (byte)(argument >> 24);
-
- Span<uint> data = stackalloc uint[4];
-
- data[0] = i0;
- data[1] = i1;
- data[2] = i2;
- data[3] = i3;
+ DrawIndexedSmall(state, argument, false);
+ }
- int offset = _inlineIndexCount * 4;
+ /// <summary>
+ /// Performs a indexed draw with a low number of index buffer elements.
+ /// </summary>
+ /// <param name="state">Current GPU state</param>
+ /// <param name="argument">Method call argument</param>
+ private void DrawIndexedSmall2(GpuState state, int argument)
+ {
+ DrawIndexedSmall(state, argument);
+ }
- _context.Renderer.SetBufferData(GetInlineIndexBuffer(offset), offset, MemoryMarshal.Cast<uint, byte>(data));
+ /// <summary>
+ /// Performs a indexed draw with a low number of index buffer elements,
+ /// while also pre-incrementing the current instance value.
+ /// </summary>
+ /// <param name="state">Current GPU state</param>
+ /// <param name="argument">Method call argument</param>
+ private void DrawIndexedSmallIncInstance(GpuState state, int argument)
+ {
+ DrawIndexedSmall(state, argument, true);
+ }
- _inlineIndexCount += 4;
+ /// <summary>
+ /// Performs a indexed draw with a low number of index buffer elements,
+ /// while also pre-incrementing the current instance value.
+ /// </summary>
+ /// <param name="state">Current GPU state</param>
+ /// <param name="argument">Method call argument</param>
+ private void DrawIndexedSmallIncInstance2(GpuState state, int argument)
+ {
+ DrawIndexedSmallIncInstance(state, argument);
}
/// <summary>
- /// Pushes two 16-bit index buffer elements.
+ /// Performs a indexed draw with a low number of index buffer elements,
+ /// while optionally also pre-incrementing the current instance value.
/// </summary>
/// <param name="state">Current GPU state</param>
/// <param name="argument">Method call argument</param>
- private void VbElementU16(GpuState state, int argument)
+ /// <param name="instanced">True to increment the current instance value, false otherwise</param>
+ private void DrawIndexedSmall(GpuState state, int argument, bool instanced)
{
- ushort i0 = (ushort)argument;
- ushort i1 = (ushort)(argument >> 16);
+ PrimitiveTypeOverride typeOverride = state.Get<PrimitiveTypeOverride>(MethodOffset.PrimitiveTypeOverride);
+
+ DrawBegin(instanced, !instanced, typeOverride.Convert());
- Span<uint> data = stackalloc uint[2];
+ int firstIndex = argument & 0xffff;
+ int indexCount = (argument >> 16) & 0xfff;
- data[0] = i0;
- data[1] = i1;
+ bool oldDrawIndexed = _drawIndexed;
- int offset = _inlineIndexCount * 4;
+ _drawIndexed = true;
- _context.Renderer.SetBufferData(GetInlineIndexBuffer(offset), offset, MemoryMarshal.Cast<uint, byte>(data));
+ DrawEnd(state, firstIndex, indexCount);
- _inlineIndexCount += 2;
+ _drawIndexed = oldDrawIndexed;
}
/// <summary>
- /// Pushes one 32-bit index buffer element.
+ /// Pushes four 8-bit index buffer elements.
/// </summary>
/// <param name="state">Current GPU state</param>
/// <param name="argument">Method call argument</param>
- private void VbElementU32(GpuState state, int argument)
+ private void VbElementU8(GpuState state, int argument)
{
- uint i0 = (uint)argument;
-
- Span<uint> data = stackalloc uint[1];
-
- data[0] = i0;
-
- int offset = _inlineIndexCount++ * 4;
-
- _context.Renderer.SetBufferData(GetInlineIndexBuffer(offset), offset, MemoryMarshal.Cast<uint, byte>(data));
+ _ibStreamer.VbElementU8(_context.Renderer, argument);
}
/// <summary>
- /// Gets the handle of a buffer large enough to hold the data that will be written to <paramref name="offset"/>.
+ /// Pushes two 16-bit index buffer elements.
/// </summary>
- /// <param name="offset">Offset where the data will be written</param>
- /// <returns>Buffer handle</returns>
- private BufferHandle GetInlineIndexBuffer(int offset)
+ /// <param name="state">Current GPU state</param>
+ /// <param name="argument">Method call argument</param>
+ private void VbElementU16(GpuState state, int argument)
{
- // Calculate a reasonable size for the buffer that can fit all the data,
- // and that also won't require frequent resizes if we need to push more data.
- int size = BitUtils.AlignUp(offset + 0x10, 0x200);
-
- if (_inlineIndexBuffer == BufferHandle.Null)
- {
- _inlineIndexBuffer = _context.Renderer.CreateBuffer(size);
- _inlineIndexBufferSize = size;
- }
- else if (_inlineIndexBufferSize < size)
- {
- BufferHandle oldBuffer = _inlineIndexBuffer;
- int oldSize = _inlineIndexBufferSize;
-
- _inlineIndexBuffer = _context.Renderer.CreateBuffer(size);
- _inlineIndexBufferSize = size;
-
- _context.Renderer.Pipeline.CopyBuffer(oldBuffer, _inlineIndexBuffer, 0, 0, oldSize);
- _context.Renderer.DeleteBuffer(oldBuffer);
- }
+ _ibStreamer.VbElementU16(_context.Renderer, argument);
+ }
- return _inlineIndexBuffer;
+ /// <summary>
+ /// Pushes one 32-bit index buffer element.
+ /// </summary>
+ /// <param name="state">Current GPU state</param>
+ /// <param name="argument">Method call argument</param>
+ private void VbElementU32(GpuState state, int argument)
+ {
+ _ibStreamer.VbElementU32(_context.Renderer, argument);
}
/// <summary>
diff --git a/Ryujinx.Graphics.Gpu/Engine/Methods.cs b/Ryujinx.Graphics.Gpu/Engine/Methods.cs
index 618f6440..df40e19e 100644
--- a/Ryujinx.Graphics.Gpu/Engine/Methods.cs
+++ b/Ryujinx.Graphics.Gpu/Engine/Methods.cs
@@ -87,8 +87,12 @@ namespace Ryujinx.Graphics.Gpu.Engine
state.RegisterCallback(MethodOffset.ResetCounter, ResetCounter);
- state.RegisterCallback(MethodOffset.DrawEnd, DrawEnd);
- state.RegisterCallback(MethodOffset.DrawBegin, DrawBegin);
+ state.RegisterCallback(MethodOffset.DrawEnd, DrawEnd);
+ state.RegisterCallback(MethodOffset.DrawBegin, DrawBegin);
+ state.RegisterCallback(MethodOffset.DrawIndexedSmall, DrawIndexedSmall);
+ state.RegisterCallback(MethodOffset.DrawIndexedSmall2, DrawIndexedSmall2);
+ state.RegisterCallback(MethodOffset.DrawIndexedSmallIncInstance, DrawIndexedSmallIncInstance);
+ state.RegisterCallback(MethodOffset.DrawIndexedSmallIncInstance2, DrawIndexedSmallIncInstance2);
state.RegisterCallback(MethodOffset.IndexBufferCount, SetIndexBufferCount);
@@ -111,7 +115,9 @@ namespace Ryujinx.Graphics.Gpu.Engine
/// Updates host state based on the current guest GPU state.
/// </summary>
/// <param name="state">Guest GPU state</param>
- private void UpdateState(GpuState state)
+ /// <param name="firstIndex">Index of the first index buffer element used on the draw</param>
+ /// <param name="indexCount">Number of index buffer elements used on the draw</param>
+ private void UpdateState(GpuState state, int firstIndex, int indexCount)
{
bool tfEnable = state.Get<Boolean32>(MethodOffset.TfEnable);
@@ -233,7 +239,7 @@ namespace Ryujinx.Graphics.Gpu.Engine
if (state.QueryModified(MethodOffset.IndexBufferState))
{
- UpdateIndexBufferState(state);
+ UpdateIndexBufferState(state, firstIndex, indexCount);
}
if (state.QueryModified(MethodOffset.VertexBufferDrawState,
@@ -273,7 +279,7 @@ namespace Ryujinx.Graphics.Gpu.Engine
if (tfEnable && !_prevTfEnable)
{
- _context.Renderer.Pipeline.BeginTransformFeedback(PrimitiveType.Convert());
+ _context.Renderer.Pipeline.BeginTransformFeedback(Topology);
_prevTfEnable = true;
}
}
@@ -742,14 +748,13 @@ namespace Ryujinx.Graphics.Gpu.Engine
/// Updates host index buffer binding based on guest GPU state.
/// </summary>
/// <param name="state">Current GPU state</param>
- private void UpdateIndexBufferState(GpuState state)
+ /// <param name="firstIndex">Index of the first index buffer element used on the draw</param>
+ /// <param name="indexCount">Number of index buffer elements used on the draw</param>
+ private void UpdateIndexBufferState(GpuState state, int firstIndex, int indexCount)
{
var indexBuffer = state.Get<IndexBufferState>(MethodOffset.IndexBufferState);
- _firstIndex = indexBuffer.First;
- _indexCount = indexBuffer.Count;
-
- if (_indexCount == 0)
+ if (indexCount == 0)
{
return;
}
@@ -758,7 +763,7 @@ namespace Ryujinx.Graphics.Gpu.Engine
// Do not use the end address to calculate the size, because
// the result may be much larger than the real size of the index buffer.
- ulong size = (ulong)(_firstIndex + _indexCount);
+ ulong size = (ulong)(firstIndex + indexCount);
switch (indexBuffer.Type)
{
@@ -806,7 +811,7 @@ namespace Ryujinx.Graphics.Gpu.Engine
ulong size;
- if (_inlineIndexCount != 0 || _drawIndexed || stride == 0 || instanced)
+ if (_ibStreamer.HasInlineIndexData || _drawIndexed || stride == 0 || instanced)
{
// This size may be (much) larger than the real vertex buffer size.
// Avoid calculating it this way, unless we don't have any other option.
diff --git a/Ryujinx.Graphics.Gpu/Image/TextureManager.cs b/Ryujinx.Graphics.Gpu/Image/TextureManager.cs
index f8720695..ea321aae 100644
--- a/Ryujinx.Graphics.Gpu/Image/TextureManager.cs
+++ b/Ryujinx.Graphics.Gpu/Image/TextureManager.cs
@@ -348,7 +348,7 @@ namespace Ryujinx.Graphics.Gpu.Image
/// <summary>
/// Update host framebuffer attachments based on currently bound render target buffers.
/// </summary>
- private void UpdateRenderTargets()
+ public void UpdateRenderTargets()
{
bool anyChanged = false;
diff --git a/Ryujinx.Graphics.Gpu/Shader/GpuAccessor.cs b/Ryujinx.Graphics.Gpu/Shader/GpuAccessor.cs
index fd0a6b0d..d726bcb8 100644
--- a/Ryujinx.Graphics.Gpu/Shader/GpuAccessor.cs
+++ b/Ryujinx.Graphics.Gpu/Shader/GpuAccessor.cs
@@ -147,23 +147,23 @@ namespace Ryujinx.Graphics.Gpu.Shader
/// <returns>Current primitive topology</returns>
public InputTopology QueryPrimitiveTopology()
{
- switch (_context.Methods.PrimitiveType)
+ switch (_context.Methods.Topology)
{
- case PrimitiveType.Points:
+ case PrimitiveTopology.Points:
return InputTopology.Points;
- case PrimitiveType.Lines:
- case PrimitiveType.LineLoop:
- case PrimitiveType.LineStrip:
+ case PrimitiveTopology.Lines:
+ case PrimitiveTopology.LineLoop:
+ case PrimitiveTopology.LineStrip:
return InputTopology.Lines;
- case PrimitiveType.LinesAdjacency:
- case PrimitiveType.LineStripAdjacency:
+ case PrimitiveTopology.LinesAdjacency:
+ case PrimitiveTopology.LineStripAdjacency:
return InputTopology.LinesAdjacency;
- case PrimitiveType.Triangles:
- case PrimitiveType.TriangleStrip:
- case PrimitiveType.TriangleFan:
+ case PrimitiveTopology.Triangles:
+ case PrimitiveTopology.TriangleStrip:
+ case PrimitiveTopology.TriangleFan:
return InputTopology.Triangles;
- case PrimitiveType.TrianglesAdjacency:
- case PrimitiveType.TriangleStripAdjacency:
+ case PrimitiveTopology.TrianglesAdjacency:
+ case PrimitiveTopology.TriangleStripAdjacency:
return InputTopology.TrianglesAdjacency;
}
diff --git a/Ryujinx.Graphics.Gpu/State/MethodOffset.cs b/Ryujinx.Graphics.Gpu/State/MethodOffset.cs
index 13b699f3..8d2df79a 100644
--- a/Ryujinx.Graphics.Gpu/State/MethodOffset.cs
+++ b/Ryujinx.Graphics.Gpu/State/MethodOffset.cs
@@ -86,12 +86,17 @@ namespace Ryujinx.Graphics.Gpu.State
PrimitiveRestartState = 0x591,
IndexBufferState = 0x5f2,
IndexBufferCount = 0x5f8,
+ DrawIndexedSmall = 0x5f9,
+ DrawIndexedSmall2 = 0x5fa,
+ DrawIndexedSmallIncInstance = 0x5fc,
+ DrawIndexedSmallIncInstance2 = 0x5fd,
DepthBiasClamp = 0x61f,
VertexBufferInstanced = 0x620,
VertexProgramPointSize = 0x644,
FaceState = 0x646,
ViewportTransformEnable = 0x64b,
ViewVolumeClipControl = 0x64f,
+ PrimitiveTypeOverride = 0x65c,
LogicOpState = 0x671,
Clear = 0x674,
RtColorMask = 0x680,
diff --git a/Ryujinx.Graphics.Gpu/State/PrimitiveTopology.cs b/Ryujinx.Graphics.Gpu/State/PrimitiveType.cs
index 340991c2..b49088aa 100644
--- a/Ryujinx.Graphics.Gpu/State/PrimitiveTopology.cs
+++ b/Ryujinx.Graphics.Gpu/State/PrimitiveType.cs
@@ -24,6 +24,25 @@ namespace Ryujinx.Graphics.Gpu.State
Patches
}
+ /// <summary>
+ /// Alternative primitive type that might override <see cref="PrimitiveType"/>.
+ /// </summary>
+ enum PrimitiveTypeOverride
+ {
+ Invalid = 0,
+ Points = 1,
+ Lines = 2,
+ LineStrip = 3,
+ Triangles = 4,
+ TriangleStrip = 5,
+ TriangleFan = 0x1015,
+ LinesAdjacency = 10,
+ LineStripAdjacency = 11,
+ TrianglesAdjacency = 12,
+ TriangleStripAdjacency = 13,
+ Patches = 14
+ }
+
static class PrimitiveTypeConverter
{
/// <summary>
@@ -53,5 +72,29 @@ namespace Ryujinx.Graphics.Gpu.State
_ => PrimitiveTopology.Triangles
};
}
+
+ /// <summary>
+ /// Converts the primitive type into something that can be used with the host API.
+ /// </summary>
+ /// <param name="type">The primitive type to convert</param>
+ /// <returns>A host compatible enum value</returns>
+ public static PrimitiveTopology Convert(this PrimitiveTypeOverride type)
+ {
+ return type switch
+ {
+ PrimitiveTypeOverride.Points => PrimitiveTopology.Points,
+ PrimitiveTypeOverride.Lines => PrimitiveTopology.Lines,
+ PrimitiveTypeOverride.LineStrip => PrimitiveTopology.LineStrip,
+ PrimitiveTypeOverride.Triangles => PrimitiveTopology.Triangles,
+ PrimitiveTypeOverride.TriangleStrip => PrimitiveTopology.TriangleStrip,
+ PrimitiveTypeOverride.TriangleFan => PrimitiveTopology.TriangleFan,
+ PrimitiveTypeOverride.LinesAdjacency => PrimitiveTopology.LinesAdjacency,
+ PrimitiveTypeOverride.LineStripAdjacency => PrimitiveTopology.LineStripAdjacency,
+ PrimitiveTypeOverride.TrianglesAdjacency => PrimitiveTopology.TrianglesAdjacency,
+ PrimitiveTypeOverride.TriangleStripAdjacency => PrimitiveTopology.TriangleStripAdjacency,
+ PrimitiveTypeOverride.Patches => PrimitiveTopology.Patches,
+ _ => PrimitiveTopology.Triangles
+ };
+ }
}
} \ No newline at end of file