diff --git a/Ryujinx.Graphics.Gpu/Engine/Threed/DrawManager.cs b/Ryujinx.Graphics.Gpu/Engine/Threed/DrawManager.cs
index 5a659f5550..cd14259a68 100644
--- a/Ryujinx.Graphics.Gpu/Engine/Threed/DrawManager.cs
+++ b/Ryujinx.Graphics.Gpu/Engine/Threed/DrawManager.cs
@@ -98,7 +98,12 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
/// Method call argument
public void DrawEnd(ThreedClass engine, int argument)
{
- DrawEnd(engine, _state.State.IndexBufferState.First, (int)_state.State.IndexBufferCount);
+ DrawEnd(
+ engine,
+ _state.State.IndexBufferState.First,
+ (int)_state.State.IndexBufferCount,
+ _state.State.VertexBufferDrawState.First,
+ _state.State.VertexBufferDrawState.Count);
}
///
@@ -108,7 +113,9 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
/// 3D engine where this method is being called
/// Index of the first index buffer element used on the draw
/// Number of index buffer elements used on the draw
- private void DrawEnd(ThreedClass engine, int firstIndex, int indexCount)
+ /// Index of the first vertex used on the draw
+ /// Number of vertices used on the draw
+ private void DrawEnd(ThreedClass engine, int firstIndex, int indexCount, int drawFirstVertex, int drawVertexCount)
{
ConditionalRenderEnabled renderEnable = ConditionalRendering.GetRenderEnable(
_context,
@@ -195,7 +202,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
{
var drawState = _state.State.VertexBufferDrawState;
- _context.Renderer.Pipeline.Draw(drawState.Count, 1, drawState.First, firstInstance);
+ _context.Renderer.Pipeline.Draw(drawVertexCount, 1, drawFirstVertex, firstInstance);
}
_drawState.DrawIndexed = false;
@@ -216,16 +223,8 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
bool incrementInstance = (argument & (1 << 26)) != 0;
bool resetInstance = (argument & (1 << 27)) == 0;
- if (_state.State.PrimitiveTypeOverrideEnable)
- {
- PrimitiveTypeOverride typeOverride = _state.State.PrimitiveTypeOverride;
- DrawBegin(incrementInstance, resetInstance, typeOverride.Convert());
- }
- else
- {
- PrimitiveType type = (PrimitiveType)(argument & 0xffff);
- DrawBegin(incrementInstance, resetInstance, type.Convert());
- }
+ PrimitiveType type = (PrimitiveType)(argument & 0xffff);
+ DrawBegin(incrementInstance, resetInstance, type);
}
///
@@ -234,8 +233,8 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
///
/// Indicates if the current instance should be incremented
/// Indicates if the current instance should be set to zero
- /// Primitive topology
- private void DrawBegin(bool incrementInstance, bool resetInstance, PrimitiveTopology topology)
+ /// Primitive type
+ private void DrawBegin(bool incrementInstance, bool resetInstance, PrimitiveType primitiveType)
{
if (incrementInstance)
{
@@ -248,6 +247,18 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
_instanceIndex = 0;
}
+ PrimitiveTopology topology;
+
+ if (_state.State.PrimitiveTypeOverrideEnable)
+ {
+ PrimitiveTypeOverride typeOverride = _state.State.PrimitiveTypeOverride;
+ topology = typeOverride.Convert();
+ }
+ else
+ {
+ topology = primitiveType.Convert();
+ }
+
UpdateTopology(topology);
}
@@ -276,46 +287,70 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
_drawState.DrawIndexed = true;
}
+ // TODO: Verify if the index type is implied from the method that is called,
+ // or if it uses the state index type on hardware.
+
///
- /// Performs a indexed draw with a low number of index buffer elements.
+ /// Performs a indexed draw with 8-bit index buffer elements.
///
/// 3D engine where this method is being called
/// Method call argument
- public void DrawIndexedSmall(ThreedClass engine, int argument)
+ public void DrawIndexBuffer8BeginEndInstanceFirst(ThreedClass engine, int argument)
{
- DrawIndexedSmall(engine, argument, false);
+ DrawIndexBufferBeginEndInstance(engine, argument, false);
}
///
- /// Performs a indexed draw with a low number of index buffer elements.
+ /// Performs a indexed draw with 16-bit index buffer elements.
///
/// 3D engine where this method is being called
/// Method call argument
- public void DrawIndexedSmall2(ThreedClass engine, int argument)
+ public void DrawIndexBuffer16BeginEndInstanceFirst(ThreedClass engine, int argument)
{
- DrawIndexedSmall(engine, argument);
+ DrawIndexBufferBeginEndInstance(engine, argument, false);
}
///
- /// Performs a indexed draw with a low number of index buffer elements,
+ /// Performs a indexed draw with 32-bit index buffer elements.
+ ///
+ /// 3D engine where this method is being called
+ /// Method call argument
+ public void DrawIndexBuffer32BeginEndInstanceFirst(ThreedClass engine, int argument)
+ {
+ DrawIndexBufferBeginEndInstance(engine, argument, false);
+ }
+
+ ///
+ /// Performs a indexed draw with 8-bit index buffer elements,
/// while also pre-incrementing the current instance value.
///
/// 3D engine where this method is being called
/// Method call argument
- public void DrawIndexedSmallIncInstance(ThreedClass engine, int argument)
+ public void DrawIndexBuffer8BeginEndInstanceSubsequent(ThreedClass engine, int argument)
{
- DrawIndexedSmall(engine, argument, true);
+ DrawIndexBufferBeginEndInstance(engine, argument, true);
}
///
- /// Performs a indexed draw with a low number of index buffer elements,
+ /// Performs a indexed draw with 16-bit index buffer elements,
/// while also pre-incrementing the current instance value.
///
/// 3D engine where this method is being called
/// Method call argument
- public void DrawIndexedSmallIncInstance2(ThreedClass engine, int argument)
+ public void DrawIndexBuffer16BeginEndInstanceSubsequent(ThreedClass engine, int argument)
{
- DrawIndexedSmallIncInstance(engine, argument);
+ DrawIndexBufferBeginEndInstance(engine, argument, true);
+ }
+
+ ///
+ /// Performs a indexed draw with 32-bit index buffer elements,
+ /// while also pre-incrementing the current instance value.
+ ///
+ /// 3D engine where this method is being called
+ /// Method call argument
+ public void DrawIndexBuffer32BeginEndInstanceSubsequent(ThreedClass engine, int argument)
+ {
+ DrawIndexBufferBeginEndInstance(engine, argument, true);
}
///
@@ -325,11 +360,9 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
/// 3D engine where this method is being called
/// Method call argument
/// True to increment the current instance value, false otherwise
- private void DrawIndexedSmall(ThreedClass engine, int argument, bool instanced)
+ private void DrawIndexBufferBeginEndInstance(ThreedClass engine, int argument, bool instanced)
{
- PrimitiveTypeOverride typeOverride = _state.State.PrimitiveTypeOverride;
-
- DrawBegin(instanced, !instanced, typeOverride.Convert());
+ DrawBegin(instanced, !instanced, (PrimitiveType)((argument >> 28) & 0xf));
int firstIndex = argument & 0xffff;
int indexCount = (argument >> 16) & 0xfff;
@@ -339,7 +372,51 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
_drawState.DrawIndexed = true;
engine.ForceStateDirty(IndexBufferCountMethodOffset * 4);
- DrawEnd(engine, firstIndex, indexCount);
+ DrawEnd(engine, firstIndex, indexCount, 0, 0);
+
+ _drawState.DrawIndexed = oldDrawIndexed;
+ }
+
+ ///
+ /// Performs a non-indexed draw with the specified topology, index and count.
+ ///
+ /// 3D engine where this method is being called
+ /// Method call argument
+ public void DrawVertexArrayBeginEndInstanceFirst(ThreedClass engine, int argument)
+ {
+ DrawVertexArrayBeginEndInstance(engine, argument, false);
+ }
+
+ ///
+ /// Performs a non-indexed draw with the specified topology, index and count,
+ /// while incrementing the current instance.
+ ///
+ /// 3D engine where this method is being called
+ /// Method call argument
+ public void DrawVertexArrayBeginEndInstanceSubsequent(ThreedClass engine, int argument)
+ {
+ DrawVertexArrayBeginEndInstance(engine, argument, true);
+ }
+
+ ///
+ /// Performs a indexed draw with a low number of index buffer elements,
+ /// while optionally also pre-incrementing the current instance value.
+ ///
+ /// 3D engine where this method is being called
+ /// Method call argument
+ /// True to increment the current instance value, false otherwise
+ private void DrawVertexArrayBeginEndInstance(ThreedClass engine, int argument, bool instanced)
+ {
+ DrawBegin(instanced, !instanced, (PrimitiveType)((argument >> 28) & 0xf));
+
+ int firstVertex = argument & 0xffff;
+ int vertexCount = (argument >> 16) & 0xfff;
+
+ bool oldDrawIndexed = _drawState.DrawIndexed;
+
+ _drawState.DrawIndexed = false;
+
+ DrawEnd(engine, 0, 0, firstVertex, vertexCount);
_drawState.DrawIndexed = oldDrawIndexed;
}
diff --git a/Ryujinx.Graphics.Gpu/Engine/Threed/StateUpdater.cs b/Ryujinx.Graphics.Gpu/Engine/Threed/StateUpdater.cs
index e6b4734507..014a173988 100644
--- a/Ryujinx.Graphics.Gpu/Engine/Threed/StateUpdater.cs
+++ b/Ryujinx.Graphics.Gpu/Engine/Threed/StateUpdater.cs
@@ -1,7 +1,5 @@
using Ryujinx.Common.Logging;
-using Ryujinx.Common.Memory;
using Ryujinx.Graphics.GAL;
-using Ryujinx.Graphics.Gpu.Engine.GPFifo;
using Ryujinx.Graphics.Gpu.Engine.Types;
using Ryujinx.Graphics.Gpu.Image;
using Ryujinx.Graphics.Gpu.Shader;
diff --git a/Ryujinx.Graphics.Gpu/Engine/Threed/ThreedClass.cs b/Ryujinx.Graphics.Gpu/Engine/Threed/ThreedClass.cs
index b254e95e0c..87dd1d8eef 100644
--- a/Ryujinx.Graphics.Gpu/Engine/Threed/ThreedClass.cs
+++ b/Ryujinx.Graphics.Gpu/Engine/Threed/ThreedClass.cs
@@ -42,6 +42,8 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
{ nameof(ThreedClassState.TextureBarrier), new RwCallback(TextureBarrier, null) },
{ nameof(ThreedClassState.TextureBarrierTiled), new RwCallback(TextureBarrierTiled, null) },
{ nameof(ThreedClassState.DrawTextureSrcY), new RwCallback(DrawTexture, null) },
+ { nameof(ThreedClassState.DrawVertexArrayBeginEndInstanceFirst), new RwCallback(DrawVertexArrayBeginEndInstanceFirst, null) },
+ { nameof(ThreedClassState.DrawVertexArrayBeginEndInstanceSubsequent), new RwCallback(DrawVertexArrayBeginEndInstanceSubsequent, null) },
{ nameof(ThreedClassState.VbElementU8), new RwCallback(VbElementU8, null) },
{ nameof(ThreedClassState.VbElementU16), new RwCallback(VbElementU16, null) },
{ nameof(ThreedClassState.VbElementU32), new RwCallback(VbElementU32, null) },
@@ -49,10 +51,12 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
{ nameof(ThreedClassState.RenderEnableCondition), new RwCallback(null, Zero) },
{ nameof(ThreedClassState.DrawEnd), new RwCallback(DrawEnd, null) },
{ nameof(ThreedClassState.DrawBegin), new RwCallback(DrawBegin, null) },
- { nameof(ThreedClassState.DrawIndexedSmall), new RwCallback(DrawIndexedSmall, null) },
- { nameof(ThreedClassState.DrawIndexedSmall2), new RwCallback(DrawIndexedSmall2, null) },
- { nameof(ThreedClassState.DrawIndexedSmallIncInstance), new RwCallback(DrawIndexedSmallIncInstance, null) },
- { nameof(ThreedClassState.DrawIndexedSmallIncInstance2), new RwCallback(DrawIndexedSmallIncInstance2, null) },
+ { nameof(ThreedClassState.DrawIndexBuffer32BeginEndInstanceFirst), new RwCallback(DrawIndexBuffer32BeginEndInstanceFirst, null) },
+ { nameof(ThreedClassState.DrawIndexBuffer16BeginEndInstanceFirst), new RwCallback(DrawIndexBuffer16BeginEndInstanceFirst, null) },
+ { nameof(ThreedClassState.DrawIndexBuffer8BeginEndInstanceFirst), new RwCallback(DrawIndexBuffer8BeginEndInstanceFirst, null) },
+ { nameof(ThreedClassState.DrawIndexBuffer32BeginEndInstanceSubsequent), new RwCallback(DrawIndexBuffer32BeginEndInstanceSubsequent, null) },
+ { nameof(ThreedClassState.DrawIndexBuffer16BeginEndInstanceSubsequent), new RwCallback(DrawIndexBuffer16BeginEndInstanceSubsequent, null) },
+ { nameof(ThreedClassState.DrawIndexBuffer8BeginEndInstanceSubsequent), new RwCallback(DrawIndexBuffer8BeginEndInstanceSubsequent, null) },
{ nameof(ThreedClassState.IndexBufferCount), new RwCallback(SetIndexBufferCount, null) },
{ nameof(ThreedClassState.Clear), new RwCallback(Clear, null) },
{ nameof(ThreedClassState.SemaphoreControl), new RwCallback(Report, null) },
@@ -303,6 +307,25 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
_drawManager.DrawTexture(this, argument);
}
+ ///
+ /// Performs a non-indexed draw with the specified topology, index and count.
+ ///
+ /// Method call argument
+ private void DrawVertexArrayBeginEndInstanceFirst(int argument)
+ {
+ _drawManager.DrawVertexArrayBeginEndInstanceFirst(this, argument);
+ }
+
+ ///
+ /// Performs a non-indexed draw with the specified topology, index and count,
+ /// while incrementing the current instance.
+ ///
+ /// Method call argument
+ private void DrawVertexArrayBeginEndInstanceSubsequent(int argument)
+ {
+ _drawManager.DrawVertexArrayBeginEndInstanceSubsequent(this, argument);
+ }
+
///
/// Pushes four 8-bit index buffer elements.
///
@@ -370,41 +393,60 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
}
///
- /// Performs a indexed draw with a low number of index buffer elements.
+ /// Performs a indexed draw with 8-bit index buffer elements.
///
/// Method call argument
- private void DrawIndexedSmall(int argument)
+ private void DrawIndexBuffer8BeginEndInstanceFirst(int argument)
{
- _drawManager.DrawIndexedSmall(this, argument);
+ _drawManager.DrawIndexBuffer8BeginEndInstanceFirst(this, argument);
}
///
- /// Performs a indexed draw with a low number of index buffer elements.
+ /// Performs a indexed draw with 16-bit index buffer elements.
///
/// Method call argument
- private void DrawIndexedSmall2(int argument)
+ private void DrawIndexBuffer16BeginEndInstanceFirst(int argument)
{
- _drawManager.DrawIndexedSmall2(this, argument);
+ _drawManager.DrawIndexBuffer16BeginEndInstanceFirst(this, argument);
}
///
- /// Performs a indexed draw with a low number of index buffer elements,
+ /// Performs a indexed draw with 32-bit index buffer elements.
+ ///
+ /// Method call argument
+ private void DrawIndexBuffer32BeginEndInstanceFirst(int argument)
+ {
+ _drawManager.DrawIndexBuffer32BeginEndInstanceFirst(this, argument);
+ }
+
+ ///
+ /// Performs a indexed draw with 8-bit index buffer elements,
/// while also pre-incrementing the current instance value.
///
/// Method call argument
- private void DrawIndexedSmallIncInstance(int argument)
+ private void DrawIndexBuffer8BeginEndInstanceSubsequent(int argument)
{
- _drawManager.DrawIndexedSmallIncInstance(this, argument);
+ _drawManager.DrawIndexBuffer8BeginEndInstanceSubsequent(this, argument);
}
///
- /// Performs a indexed draw with a low number of index buffer elements,
+ /// Performs a indexed draw with 16-bit index buffer elements,
/// while also pre-incrementing the current instance value.
///
/// Method call argument
- private void DrawIndexedSmallIncInstance2(int argument)
+ private void DrawIndexBuffer16BeginEndInstanceSubsequent(int argument)
{
- _drawManager.DrawIndexedSmallIncInstance2(this, argument);
+ _drawManager.DrawIndexBuffer16BeginEndInstanceSubsequent(this, argument);
+ }
+
+ ///
+ /// Performs a indexed draw with 32-bit index buffer elements,
+ /// while also pre-incrementing the current instance value.
+ ///
+ /// Method call argument
+ private void DrawIndexBuffer32BeginEndInstanceSubsequent(int argument)
+ {
+ _drawManager.DrawIndexBuffer32BeginEndInstanceSubsequent(this, argument);
}
///
diff --git a/Ryujinx.Graphics.Gpu/Engine/Threed/ThreedClassState.cs b/Ryujinx.Graphics.Gpu/Engine/Threed/ThreedClassState.cs
index e416cd583c..1498e27ba1 100644
--- a/Ryujinx.Graphics.Gpu/Engine/Threed/ThreedClassState.cs
+++ b/Ryujinx.Graphics.Gpu/Engine/Threed/ThreedClassState.cs
@@ -813,7 +813,9 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
public uint ClearFlags;
public fixed uint Reserved10FC[25];
public Array32 VertexAttribState;
- public fixed uint Reserved11E0[15];
+ public fixed uint Reserved11E0[13];
+ public uint DrawVertexArrayBeginEndInstanceFirst;
+ public uint DrawVertexArrayBeginEndInstanceSubsequent;
public RtControl RtControl;
public fixed uint Reserved1220[2];
public Size3D RtDepthStencilSize;
@@ -888,12 +890,13 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
public fixed uint Reserved164C[95];
public IndexBufferState IndexBufferState;
public uint IndexBufferCount;
- public uint DrawIndexedSmall;
- public uint DrawIndexedSmall2;
- public uint Reserved17EC;
- public uint DrawIndexedSmallIncInstance;
- public uint DrawIndexedSmallIncInstance2;
- public fixed uint Reserved17F8[33];
+ public uint DrawIndexBuffer32BeginEndInstanceFirst;
+ public uint DrawIndexBuffer16BeginEndInstanceFirst;
+ public uint DrawIndexBuffer8BeginEndInstanceFirst;
+ public uint DrawIndexBuffer32BeginEndInstanceSubsequent;
+ public uint DrawIndexBuffer16BeginEndInstanceSubsequent;
+ public uint DrawIndexBuffer8BeginEndInstanceSubsequent;
+ public fixed uint Reserved17FC[32];
public float DepthBiasClamp;
public Array16 VertexBufferInstanced;
public fixed uint Reserved18C0[20];