aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorgdkchan <gab.dark.100@gmail.com>2021-01-12 18:50:54 -0300
committerGitHub <noreply@github.com>2021-01-13 08:50:54 +1100
commitdf820a72def62319fe97236a2006c64bfb7c065a (patch)
tree0e5d2c4f278548245e828e67194ff03d04532ce3
parent68f6b79fd3f06ea572d5f0edd5fc8cbaee1ae449 (diff)
Implement clear buffer (fast path) (#1902)
* Implement clear buffer (fast path) * Remove blank line
-rw-r--r--Ryujinx.Graphics.GAL/IPipeline.cs2
-rw-r--r--Ryujinx.Graphics.Gpu/Engine/MethodCopyBuffer.cs20
-rw-r--r--Ryujinx.Graphics.Gpu/Memory/BufferManager.cs22
-rw-r--r--Ryujinx.Graphics.Gpu/State/BufferSwizzleComponent.cs16
-rw-r--r--Ryujinx.Graphics.Gpu/State/CopyBufferSwizzle.cs36
-rw-r--r--Ryujinx.Graphics.Gpu/State/MethodOffset.cs2
-rw-r--r--Ryujinx.Graphics.OpenGL/Buffer.cs21
-rw-r--r--Ryujinx.Graphics.OpenGL/Pipeline.cs11
8 files changed, 125 insertions, 5 deletions
diff --git a/Ryujinx.Graphics.GAL/IPipeline.cs b/Ryujinx.Graphics.GAL/IPipeline.cs
index 1da34b96..96ccfb28 100644
--- a/Ryujinx.Graphics.GAL/IPipeline.cs
+++ b/Ryujinx.Graphics.GAL/IPipeline.cs
@@ -9,6 +9,8 @@ namespace Ryujinx.Graphics.GAL
void BeginTransformFeedback(PrimitiveTopology topology);
+ void ClearBuffer(BufferHandle destination, int offset, int size, uint value);
+
void ClearRenderTargetColor(int index, uint componentMask, ColorF color);
void ClearRenderTargetDepthStencil(
diff --git a/Ryujinx.Graphics.Gpu/Engine/MethodCopyBuffer.cs b/Ryujinx.Graphics.Gpu/Engine/MethodCopyBuffer.cs
index 6f03dc5d..15ebb236 100644
--- a/Ryujinx.Graphics.Gpu/Engine/MethodCopyBuffer.cs
+++ b/Ryujinx.Graphics.Gpu/Engine/MethodCopyBuffer.cs
@@ -200,8 +200,24 @@ namespace Ryujinx.Graphics.Gpu.Engine
}
else
{
- // Buffer to buffer copy.
- BufferManager.CopyBuffer(cbp.SrcAddress, cbp.DstAddress, (uint)size);
+ if (remap &&
+ swizzle.UnpackDstX() == BufferSwizzleComponent.ConstA &&
+ swizzle.UnpackDstY() == BufferSwizzleComponent.ConstA &&
+ swizzle.UnpackDstZ() == BufferSwizzleComponent.ConstA &&
+ swizzle.UnpackDstW() == BufferSwizzleComponent.ConstA &&
+ swizzle.UnpackSrcComponentsCount() == 1 &&
+ swizzle.UnpackDstComponentsCount() == 1 &&
+ swizzle.UnpackComponentSize() == 4)
+ {
+ // Fast path for clears when remap is enabled.
+ BufferManager.ClearBuffer(cbp.DstAddress, (uint)size * 4, state.Get<uint>(MethodOffset.CopyBufferConstA));
+ }
+ else
+ {
+ // TODO: Implement remap functionality.
+ // Buffer to buffer copy.
+ BufferManager.CopyBuffer(cbp.SrcAddress, cbp.DstAddress, (uint)size);
+ }
}
}
}
diff --git a/Ryujinx.Graphics.Gpu/Memory/BufferManager.cs b/Ryujinx.Graphics.Gpu/Memory/BufferManager.cs
index 1d48b38c..0c643191 100644
--- a/Ryujinx.Graphics.Gpu/Memory/BufferManager.cs
+++ b/Ryujinx.Graphics.Gpu/Memory/BufferManager.cs
@@ -822,6 +822,28 @@ namespace Ryujinx.Graphics.Gpu.Memory
}
/// <summary>
+ /// Clears a buffer at a given address with the specified value.
+ /// </summary>
+ /// <remarks>
+ /// Both the address and size must be aligned to 4 bytes.
+ /// </remarks>
+ /// <param name="gpuVa">GPU virtual address of the region to clear</param>
+ /// <param name="size">Number of bytes to clear</param>
+ /// <param name="value">Value to be written into the buffer</param>
+ public void ClearBuffer(GpuVa gpuVa, ulong size, uint value)
+ {
+ ulong address = TranslateAndCreateBuffer(gpuVa.Pack(), size);
+
+ Buffer buffer = GetBuffer(address, size);
+
+ int offset = (int)(address - buffer.Address);
+
+ _context.Renderer.Pipeline.ClearBuffer(buffer.Handle, offset, (int)size, value);
+
+ buffer.Flush(address, size);
+ }
+
+ /// <summary>
/// Gets a buffer sub-range for a given memory range.
/// </summary>
/// <param name="address">Start address of the memory range</param>
diff --git a/Ryujinx.Graphics.Gpu/State/BufferSwizzleComponent.cs b/Ryujinx.Graphics.Gpu/State/BufferSwizzleComponent.cs
new file mode 100644
index 00000000..5c23cb2d
--- /dev/null
+++ b/Ryujinx.Graphics.Gpu/State/BufferSwizzleComponent.cs
@@ -0,0 +1,16 @@
+namespace Ryujinx.Graphics.Gpu.State
+{
+ /// <summary>
+ /// Buffer swizzle component.
+ /// </summary>
+ enum BufferSwizzleComponent
+ {
+ SrcX,
+ SrcY,
+ SrcZ,
+ SrcW,
+ ConstA,
+ ConstB,
+ NoWrite
+ }
+}
diff --git a/Ryujinx.Graphics.Gpu/State/CopyBufferSwizzle.cs b/Ryujinx.Graphics.Gpu/State/CopyBufferSwizzle.cs
index b4a9d9c2..94b650c4 100644
--- a/Ryujinx.Graphics.Gpu/State/CopyBufferSwizzle.cs
+++ b/Ryujinx.Graphics.Gpu/State/CopyBufferSwizzle.cs
@@ -10,6 +10,42 @@ namespace Ryujinx.Graphics.Gpu.State
#pragma warning restore CS0649
/// <summary>
+ /// Unpacks the source for the buffer destination vector X component.
+ /// </summary>
+ /// <returns>Destination component</returns>
+ public BufferSwizzleComponent UnpackDstX()
+ {
+ return (BufferSwizzleComponent)(Swizzle & 7);
+ }
+
+ /// <summary>
+ /// Unpacks the source for the buffer destination vector Y component.
+ /// </summary>
+ /// <returns>Destination component</returns>
+ public BufferSwizzleComponent UnpackDstY()
+ {
+ return (BufferSwizzleComponent)((Swizzle >> 4) & 7);
+ }
+
+ /// <summary>
+ /// Unpacks the source for the buffer destination vector Z component.
+ /// </summary>
+ /// <returns>Destination component</returns>
+ public BufferSwizzleComponent UnpackDstZ()
+ {
+ return (BufferSwizzleComponent)((Swizzle >> 8) & 7);
+ }
+
+ /// <summary>
+ /// Unpacks the source for the buffer destination vector W component.
+ /// </summary>
+ /// <returns>Destination component</returns>
+ public BufferSwizzleComponent UnpackDstW()
+ {
+ return (BufferSwizzleComponent)((Swizzle >> 12) & 7);
+ }
+
+ /// <summary>
/// Unpacks the size of each vector component of the copy.
/// </summary>
/// <returns>Vector component size</returns>
diff --git a/Ryujinx.Graphics.Gpu/State/MethodOffset.cs b/Ryujinx.Graphics.Gpu/State/MethodOffset.cs
index 6ec94c1b..4504e6b1 100644
--- a/Ryujinx.Graphics.Gpu/State/MethodOffset.cs
+++ b/Ryujinx.Graphics.Gpu/State/MethodOffset.cs
@@ -23,6 +23,8 @@ namespace Ryujinx.Graphics.Gpu.State
TfBufferState = 0xe0,
CopyBufferParams = 0x100,
TfState = 0x1c0,
+ CopyBufferConstA = 0x1c0,
+ CopyBufferConstB = 0x1c1,
CopyBufferSwizzle = 0x1c2,
CopyBufferDstTexture = 0x1c3,
CopyBufferSrcTexture = 0x1ca,
diff --git a/Ryujinx.Graphics.OpenGL/Buffer.cs b/Ryujinx.Graphics.OpenGL/Buffer.cs
index 89216b83..ecb7dc90 100644
--- a/Ryujinx.Graphics.OpenGL/Buffer.cs
+++ b/Ryujinx.Graphics.OpenGL/Buffer.cs
@@ -6,6 +6,27 @@ namespace Ryujinx.Graphics.OpenGL
{
static class Buffer
{
+ public static void Clear(BufferHandle destination, int offset, int size, uint value)
+ {
+ GL.BindBuffer(BufferTarget.CopyWriteBuffer, destination.ToInt32());
+
+ unsafe
+ {
+ uint* valueArr = stackalloc uint[1];
+
+ valueArr[0] = value;
+
+ GL.ClearBufferSubData(
+ BufferTarget.CopyWriteBuffer,
+ PixelInternalFormat.Rgba8ui,
+ (IntPtr)offset,
+ (IntPtr)size,
+ PixelFormat.RgbaInteger,
+ PixelType.UnsignedByte,
+ (IntPtr)valueArr);
+ }
+ }
+
public static BufferHandle Create()
{
return Handle.FromInt32<BufferHandle>(GL.GenBuffer());
diff --git a/Ryujinx.Graphics.OpenGL/Pipeline.cs b/Ryujinx.Graphics.OpenGL/Pipeline.cs
index 8b0a86aa..b6a34e9c 100644
--- a/Ryujinx.Graphics.OpenGL/Pipeline.cs
+++ b/Ryujinx.Graphics.OpenGL/Pipeline.cs
@@ -91,6 +91,11 @@ namespace Ryujinx.Graphics.OpenGL
_tfEnabled = true;
}
+ public void ClearBuffer(BufferHandle destination, int offset, int size, uint value)
+ {
+ Buffer.Clear(destination, offset, size, value);
+ }
+
public void ClearRenderTargetColor(int index, uint componentMask, ColorF color)
{
GL.ColorMask(
@@ -102,7 +107,7 @@ namespace Ryujinx.Graphics.OpenGL
float[] colors = new float[] { color.Red, color.Green, color.Blue, color.Alpha };
- GL.ClearBuffer(ClearBuffer.Color, index, colors);
+ GL.ClearBuffer(OpenTK.Graphics.OpenGL.ClearBuffer.Color, index, colors);
RestoreComponentMask(index);
@@ -133,11 +138,11 @@ namespace Ryujinx.Graphics.OpenGL
}
else if (depthMask)
{
- GL.ClearBuffer(ClearBuffer.Depth, 0, ref depthValue);
+ GL.ClearBuffer(OpenTK.Graphics.OpenGL.ClearBuffer.Depth, 0, ref depthValue);
}
else if (stencilMask != 0)
{
- GL.ClearBuffer(ClearBuffer.Stencil, 0, ref stencilValue);
+ GL.ClearBuffer(OpenTK.Graphics.OpenGL.ClearBuffer.Stencil, 0, ref stencilValue);
}
if (stencilMaskChanged)