Переглянути джерело

Implement clear buffer (fast path) (#1902)

* Implement clear buffer (fast path)

* Remove blank line
gdkchan 5 роки тому
батько
коміт
df820a72de

+ 2 - 0
Ryujinx.Graphics.GAL/IPipeline.cs

@@ -9,6 +9,8 @@ namespace Ryujinx.Graphics.GAL
 
 
         void BeginTransformFeedback(PrimitiveTopology topology);
         void BeginTransformFeedback(PrimitiveTopology topology);
 
 
+        void ClearBuffer(BufferHandle destination, int offset, int size, uint value);
+
         void ClearRenderTargetColor(int index, uint componentMask, ColorF color);
         void ClearRenderTargetColor(int index, uint componentMask, ColorF color);
 
 
         void ClearRenderTargetDepthStencil(
         void ClearRenderTargetDepthStencil(

+ 18 - 2
Ryujinx.Graphics.Gpu/Engine/MethodCopyBuffer.cs

@@ -200,8 +200,24 @@ namespace Ryujinx.Graphics.Gpu.Engine
             }
             }
             else
             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);
+                }
             }
             }
         }
         }
     }
     }

+ 22 - 0
Ryujinx.Graphics.Gpu/Memory/BufferManager.cs

@@ -821,6 +821,28 @@ namespace Ryujinx.Graphics.Gpu.Memory
             dstBuffer.Flush(dstAddress, size);
             dstBuffer.Flush(dstAddress, size);
         }
         }
 
 
+        /// <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>
         /// <summary>
         /// Gets a buffer sub-range for a given memory range.
         /// Gets a buffer sub-range for a given memory range.
         /// </summary>
         /// </summary>

+ 16 - 0
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
+    }
+}

+ 36 - 0
Ryujinx.Graphics.Gpu/State/CopyBufferSwizzle.cs

@@ -9,6 +9,42 @@ namespace Ryujinx.Graphics.Gpu.State
         public uint Swizzle;
         public uint Swizzle;
 #pragma warning restore CS0649
 #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>
         /// <summary>
         /// Unpacks the size of each vector component of the copy.
         /// Unpacks the size of each vector component of the copy.
         /// </summary>
         /// </summary>

+ 2 - 0
Ryujinx.Graphics.Gpu/State/MethodOffset.cs

@@ -23,6 +23,8 @@ namespace Ryujinx.Graphics.Gpu.State
         TfBufferState                   = 0xe0,
         TfBufferState                   = 0xe0,
         CopyBufferParams                = 0x100,
         CopyBufferParams                = 0x100,
         TfState                         = 0x1c0,
         TfState                         = 0x1c0,
+        CopyBufferConstA                = 0x1c0,
+        CopyBufferConstB                = 0x1c1,
         CopyBufferSwizzle               = 0x1c2,
         CopyBufferSwizzle               = 0x1c2,
         CopyBufferDstTexture            = 0x1c3,
         CopyBufferDstTexture            = 0x1c3,
         CopyBufferSrcTexture            = 0x1ca,
         CopyBufferSrcTexture            = 0x1ca,

+ 21 - 0
Ryujinx.Graphics.OpenGL/Buffer.cs

@@ -6,6 +6,27 @@ namespace Ryujinx.Graphics.OpenGL
 {
 {
     static class Buffer
     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()
         public static BufferHandle Create()
         {
         {
             return Handle.FromInt32<BufferHandle>(GL.GenBuffer());
             return Handle.FromInt32<BufferHandle>(GL.GenBuffer());

+ 8 - 3
Ryujinx.Graphics.OpenGL/Pipeline.cs

@@ -91,6 +91,11 @@ namespace Ryujinx.Graphics.OpenGL
             _tfEnabled = true;
             _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)
         public void ClearRenderTargetColor(int index, uint componentMask, ColorF color)
         {
         {
             GL.ColorMask(
             GL.ColorMask(
@@ -102,7 +107,7 @@ namespace Ryujinx.Graphics.OpenGL
 
 
             float[] colors = new float[] { color.Red, color.Green, color.Blue, color.Alpha };
             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);
             RestoreComponentMask(index);
 
 
@@ -133,11 +138,11 @@ namespace Ryujinx.Graphics.OpenGL
             }
             }
             else if (depthMask)
             else if (depthMask)
             {
             {
-                GL.ClearBuffer(ClearBuffer.Depth, 0, ref depthValue);
+                GL.ClearBuffer(OpenTK.Graphics.OpenGL.ClearBuffer.Depth, 0, ref depthValue);
             }
             }
             else if (stencilMask != 0)
             else if (stencilMask != 0)
             {
             {
-                GL.ClearBuffer(ClearBuffer.Stencil, 0, ref stencilValue);
+                GL.ClearBuffer(OpenTK.Graphics.OpenGL.ClearBuffer.Stencil, 0, ref stencilValue);
             }
             }
 
 
             if (stencilMaskChanged)
             if (stencilMaskChanged)