Support inline index buffer data (#1351)
* Support inline index buffer data * Sort usings
This commit is contained in:
parent
b0d9ec8a82
commit
dbeb50684d
5 changed files with 146 additions and 5 deletions
|
@ -74,7 +74,7 @@ namespace Ryujinx.Graphics.Gpu.Engine
|
||||||
|
|
||||||
if (_isLinear && _params.LineCount == 1)
|
if (_isLinear && _params.LineCount == 1)
|
||||||
{
|
{
|
||||||
ulong address = _context.MemoryManager.Translate( _params.DstAddress.Pack());
|
ulong address = _context.MemoryManager.Translate(_params.DstAddress.Pack());
|
||||||
|
|
||||||
_context.PhysicalMemory.Write(address, data);
|
_context.PhysicalMemory.Write(address, data);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,9 @@
|
||||||
using Ryujinx.Graphics.Gpu.State;
|
using Ryujinx.Common;
|
||||||
|
using Ryujinx.Graphics.GAL;
|
||||||
using Ryujinx.Graphics.Gpu.Image;
|
using Ryujinx.Graphics.Gpu.Image;
|
||||||
|
using Ryujinx.Graphics.Gpu.State;
|
||||||
|
using System;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
namespace Ryujinx.Graphics.Gpu.Engine
|
namespace Ryujinx.Graphics.Gpu.Engine
|
||||||
{
|
{
|
||||||
|
@ -22,6 +26,10 @@ namespace Ryujinx.Graphics.Gpu.Engine
|
||||||
|
|
||||||
private int _instanceIndex;
|
private int _instanceIndex;
|
||||||
|
|
||||||
|
private BufferHandle _inlineIndexBuffer = BufferHandle.Null;
|
||||||
|
private int _inlineIndexBufferSize;
|
||||||
|
private int _inlineIndexCount;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Primitive type of the current draw.
|
/// Primitive type of the current draw.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -87,10 +95,25 @@ namespace Ryujinx.Graphics.Gpu.Engine
|
||||||
|
|
||||||
int firstInstance = state.Get<int>(MethodOffset.FirstInstance);
|
int firstInstance = state.Get<int>(MethodOffset.FirstInstance);
|
||||||
|
|
||||||
if (_drawIndexed)
|
if (_inlineIndexCount != 0)
|
||||||
{
|
{
|
||||||
_drawIndexed = false;
|
int firstVertex = state.Get<int>(MethodOffset.FirstVertex);
|
||||||
|
|
||||||
|
BufferRange br = new BufferRange(_inlineIndexBuffer, 0, _inlineIndexCount * 4);
|
||||||
|
|
||||||
|
_context.Methods.BufferManager.SetIndexBuffer(br, IndexType.UInt);
|
||||||
|
|
||||||
|
_context.Renderer.Pipeline.DrawIndexed(
|
||||||
|
_inlineIndexCount,
|
||||||
|
1,
|
||||||
|
_firstIndex,
|
||||||
|
firstVertex,
|
||||||
|
firstInstance);
|
||||||
|
|
||||||
|
_inlineIndexCount = 0;
|
||||||
|
}
|
||||||
|
else if (_drawIndexed)
|
||||||
|
{
|
||||||
int firstVertex = state.Get<int>(MethodOffset.FirstVertex);
|
int firstVertex = state.Get<int>(MethodOffset.FirstVertex);
|
||||||
|
|
||||||
_context.Renderer.Pipeline.DrawIndexed(
|
_context.Renderer.Pipeline.DrawIndexed(
|
||||||
|
@ -111,6 +134,8 @@ namespace Ryujinx.Graphics.Gpu.Engine
|
||||||
firstInstance);
|
firstInstance);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_drawIndexed = false;
|
||||||
|
|
||||||
if (renderEnable == ConditionalRenderEnabled.Host)
|
if (renderEnable == ConditionalRenderEnabled.Host)
|
||||||
{
|
{
|
||||||
_context.Renderer.Pipeline.EndHostConditionalRendering();
|
_context.Renderer.Pipeline.EndHostConditionalRendering();
|
||||||
|
@ -154,6 +179,103 @@ namespace Ryujinx.Graphics.Gpu.Engine
|
||||||
_drawIndexed = true;
|
_drawIndexed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Pushes four 8-bit 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)
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
|
||||||
|
_context.Renderer.SetBufferData(GetInlineIndexBuffer(offset), offset, MemoryMarshal.Cast<uint, byte>(data));
|
||||||
|
|
||||||
|
_inlineIndexCount += 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Pushes two 16-bit index buffer elements.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="state">Current GPU state</param>
|
||||||
|
/// <param name="argument">Method call argument</param>
|
||||||
|
private void VbElementU16(GpuState state, 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;
|
||||||
|
|
||||||
|
_context.Renderer.SetBufferData(GetInlineIndexBuffer(offset), offset, MemoryMarshal.Cast<uint, byte>(data));
|
||||||
|
|
||||||
|
_inlineIndexCount += 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <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)
|
||||||
|
{
|
||||||
|
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));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the handle of a buffer large enough to hold the data that will be written to <paramref name="offset"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="offset">Offset where the data will be written</param>
|
||||||
|
/// <returns>Buffer handle</returns>
|
||||||
|
private BufferHandle GetInlineIndexBuffer(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 = _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);
|
||||||
|
}
|
||||||
|
|
||||||
|
return _inlineIndexBuffer;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Perform any deferred draws.
|
/// Perform any deferred draws.
|
||||||
/// This is used for instanced draws.
|
/// This is used for instanced draws.
|
||||||
|
|
|
@ -78,6 +78,10 @@ namespace Ryujinx.Graphics.Gpu.Engine
|
||||||
state.RegisterCallback(MethodOffset.InvalidateTextures, InvalidateTextures);
|
state.RegisterCallback(MethodOffset.InvalidateTextures, InvalidateTextures);
|
||||||
state.RegisterCallback(MethodOffset.TextureBarrierTiled, TextureBarrierTiled);
|
state.RegisterCallback(MethodOffset.TextureBarrierTiled, TextureBarrierTiled);
|
||||||
|
|
||||||
|
state.RegisterCallback(MethodOffset.VbElementU8, VbElementU8);
|
||||||
|
state.RegisterCallback(MethodOffset.VbElementU16, VbElementU16);
|
||||||
|
state.RegisterCallback(MethodOffset.VbElementU32, VbElementU32);
|
||||||
|
|
||||||
state.RegisterCallback(MethodOffset.ResetCounter, ResetCounter);
|
state.RegisterCallback(MethodOffset.ResetCounter, ResetCounter);
|
||||||
|
|
||||||
state.RegisterCallback(MethodOffset.DrawEnd, DrawEnd);
|
state.RegisterCallback(MethodOffset.DrawEnd, DrawEnd);
|
||||||
|
@ -726,7 +730,7 @@ namespace Ryujinx.Graphics.Gpu.Engine
|
||||||
|
|
||||||
ulong size;
|
ulong size;
|
||||||
|
|
||||||
if (_drawIndexed || stride == 0 || instanced)
|
if (_inlineIndexCount != 0 || _drawIndexed || stride == 0 || instanced)
|
||||||
{
|
{
|
||||||
// This size may be (much) larger than the real vertex buffer size.
|
// 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.
|
// Avoid calculating it this way, unless we don't have any other option.
|
||||||
|
|
|
@ -103,6 +103,18 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
||||||
_indexBufferDirty = true;
|
_indexBufferDirty = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sets a new index buffer that overrides the one set on the call to <see cref="CommitGraphicsBindings"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="buffer">Buffer to be used as index buffer</param>
|
||||||
|
/// <param name="type">Type of each index buffer element</param>
|
||||||
|
public void SetIndexBuffer(BufferRange buffer, IndexType type)
|
||||||
|
{
|
||||||
|
_context.Renderer.Pipeline.SetIndexBuffer(buffer, type);
|
||||||
|
|
||||||
|
_indexBufferDirty = true;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Sets the memory range with vertex buffer data, to be used for subsequent draw calls.
|
/// Sets the memory range with vertex buffer data, to be used for subsequent draw calls.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -58,6 +58,7 @@ namespace Ryujinx.Graphics.Gpu.State
|
||||||
DepthTestEnable = 0x4b3,
|
DepthTestEnable = 0x4b3,
|
||||||
BlendIndependent = 0x4b9,
|
BlendIndependent = 0x4b9,
|
||||||
DepthWriteEnable = 0x4ba,
|
DepthWriteEnable = 0x4ba,
|
||||||
|
VbElementU8 = 0x4c1,
|
||||||
DepthTestFunc = 0x4c3,
|
DepthTestFunc = 0x4c3,
|
||||||
BlendConstant = 0x4c7,
|
BlendConstant = 0x4c7,
|
||||||
BlendStateCommon = 0x4cf,
|
BlendStateCommon = 0x4cf,
|
||||||
|
@ -78,6 +79,8 @@ namespace Ryujinx.Graphics.Gpu.State
|
||||||
StencilBackTestState = 0x565,
|
StencilBackTestState = 0x565,
|
||||||
DepthBiasUnits = 0x56f,
|
DepthBiasUnits = 0x56f,
|
||||||
RtMsaaMode = 0x574,
|
RtMsaaMode = 0x574,
|
||||||
|
VbElementU32 = 0x57a,
|
||||||
|
VbElementU16 = 0x57c,
|
||||||
ShaderBaseAddress = 0x582,
|
ShaderBaseAddress = 0x582,
|
||||||
DrawEnd = 0x585,
|
DrawEnd = 0x585,
|
||||||
DrawBegin = 0x586,
|
DrawBegin = 0x586,
|
||||||
|
|
Reference in a new issue