From ea30e543e62b4379a8ca3f5b66061b0987e4cedf Mon Sep 17 00:00:00 2001 From: riperiperi Date: Fri, 5 Jul 2024 09:35:17 +0100 Subject: [PATCH] Fix preload cbs optimization (for real) (#34) * Mostly fix preload cbs. There seems to be some random flickering... * fix index buffer usage range * fix missing preflush submit before present --- src/Ryujinx.Graphics.Metal/BufferHolder.cs | 4 ++-- src/Ryujinx.Graphics.Metal/Pipeline.cs | 26 ++++++++++++++++------ 2 files changed, 21 insertions(+), 9 deletions(-) diff --git a/src/Ryujinx.Graphics.Metal/BufferHolder.cs b/src/Ryujinx.Graphics.Metal/BufferHolder.cs index e0089322f..47e9cd0e3 100644 --- a/src/Ryujinx.Graphics.Metal/BufferHolder.cs +++ b/src/Ryujinx.Graphics.Metal/BufferHolder.cs @@ -191,14 +191,14 @@ namespace Ryujinx.Graphics.Metal } if (cbs != null && - _pipeline.RenderPassActive && + cbs.Value.Encoders.CurrentEncoderType == EncoderType.Render && !(_buffer.HasCommandBufferDependency(cbs.Value) && _waitable.IsBufferRangeInUse(cbs.Value.CommandBufferIndex, offset, dataSize))) { // If the buffer hasn't been used on the command buffer yet, try to preload the data. // This avoids ending and beginning render passes on each buffer data upload. - cbs = _pipeline.PreloadCbs; + cbs = _pipeline.GetPreloadCommandBuffer(); } if (allowCbsWait) diff --git a/src/Ryujinx.Graphics.Metal/Pipeline.cs b/src/Ryujinx.Graphics.Metal/Pipeline.cs index 32b520e0e..5e4e55ea3 100644 --- a/src/Ryujinx.Graphics.Metal/Pipeline.cs +++ b/src/Ryujinx.Graphics.Metal/Pipeline.cs @@ -36,7 +36,6 @@ namespace Ryujinx.Graphics.Metal internal CommandBufferScoped Cbs { get; private set; } internal CommandBufferEncoder Encoders => Cbs.Encoders; internal EncoderType CurrentEncoderType => Encoders.CurrentEncoderType; - internal bool RenderPassActive { get; private set; } public Pipeline(MTLDevice device, MetalRenderer renderer) { @@ -137,7 +136,7 @@ namespace Ryujinx.Graphics.Metal Cbs.CommandBuffer.PresentDrawable(drawable); - CommandBuffer = (Cbs = _renderer.CommandBufferPool.ReturnAndRent(Cbs)).CommandBuffer; + FlushCommandsImpl(); // TODO: Auto flush counting _renderer.SyncManager.GetAndResetWaitTicks(); @@ -146,6 +145,13 @@ namespace Ryujinx.Graphics.Metal dst.Dispose(); } + public CommandBufferScoped GetPreloadCommandBuffer() + { + PreloadCbs ??= _renderer.CommandBufferPool.Rent(); + + return PreloadCbs.Value; + } + public void FlushCommandsIfWeightExceeding(IAuto disposedResource, ulong byteWeight) { bool usedByCurrentCb = disposedResource.HasCommandBufferDependency(Cbs); @@ -383,12 +389,16 @@ namespace Ryujinx.Graphics.Metal var indexBuffer = _encoderStateManager.IndexBuffer; + ulong offset = _encoderStateManager.IndexBufferOffset; + MTLIndexType type = _encoderStateManager.IndexType; + int indexSize = type == MTLIndexType.UInt32 ? sizeof(int) : sizeof(short); + renderCommandEncoder.DrawIndexedPrimitives( primitiveType, (ulong)indexCount, - _encoderStateManager.IndexType, - indexBuffer.Get(Cbs, 0, indexCount * sizeof(int)).Value, - _encoderStateManager.IndexBufferOffset, + type, + indexBuffer.Get(Cbs, (int)offset, indexCount * indexSize).Value, + offset, (ulong)instanceCount, firstVertex, (ulong)firstInstance); @@ -533,11 +543,13 @@ namespace Ryujinx.Graphics.Metal public void SetPrimitiveRestart(bool enable, int index) { - // TODO: Supported for LineStrip and TriangleStrip + // Always active for LineStrip and TriangleStrip // https://github.com/gpuweb/gpuweb/issues/1220#issuecomment-732483263 // https://developer.apple.com/documentation/metal/mtlrendercommandencoder/1515520-drawindexedprimitives // https://stackoverflow.com/questions/70813665/how-to-render-multiple-trianglestrips-using-metal - Logger.Warning?.Print(LogClass.Gpu, "Not Implemented!"); + + // Emulating disabling this is very difficult. It's unlikely for an index buffer to use the largest possible index, + // so it's fine nearly all of the time. } public void SetPrimitiveTopology(PrimitiveTopology topology)