From f3cc2e5703e5df5c359ce1789a4fb0d73fb9a637 Mon Sep 17 00:00:00 2001 From: riperiperi Date: Thu, 24 Nov 2022 01:56:55 +0000 Subject: [PATCH] GPU: Access non-prefetch command buffers directly (#3882) * GPU: Access non-prefetch command buffers directly Saves allocating new arrays for them constantly - they can be quite small so it can be very wasteful. About 0.4% of GPU thread in SMO, but was a bit higher in S/V when I checked. Assumes that non-prefetch command buffers won't be randomly clobbered before they finish executing, though that's probably a safe bet. * Small change while I'm here * Address feedback --- .../Engine/GPFifo/GPFifoDevice.cs | 35 ++++++++++++++----- 1 file changed, 27 insertions(+), 8 deletions(-) diff --git a/Ryujinx.Graphics.Gpu/Engine/GPFifo/GPFifoDevice.cs b/Ryujinx.Graphics.Gpu/Engine/GPFifo/GPFifoDevice.cs index b3de738d69..cd29a9da0e 100644 --- a/Ryujinx.Graphics.Gpu/Engine/GPFifo/GPFifoDevice.cs +++ b/Ryujinx.Graphics.Gpu/Engine/GPFifo/GPFifoDevice.cs @@ -51,16 +51,35 @@ namespace Ryujinx.Graphics.Gpu.Engine.GPFifo /// public uint EntryCount; + /// + /// Get the entries for the command buffer from memory. + /// + /// The memory manager used to fetch the data + /// If true, flushes potential GPU written data before reading the command buffer + /// The fetched data + private ReadOnlySpan GetWords(MemoryManager memoryManager, bool flush) + { + return MemoryMarshal.Cast(memoryManager.GetSpan(EntryAddress, (int)EntryCount * 4, flush)); + } + + /// + /// Prefetch the command buffer. + /// + /// The memory manager used to fetch the data + public void Prefetch(MemoryManager memoryManager) + { + Words = GetWords(memoryManager, true).ToArray(); + } + /// /// Fetch the command buffer. /// + /// The memory manager used to fetch the data /// If true, flushes potential GPU written data before reading the command buffer - public void Fetch(MemoryManager memoryManager, bool flush = true) + /// The command buffer words + public ReadOnlySpan Fetch(MemoryManager memoryManager, bool flush) { - if (Words == null) - { - Words = MemoryMarshal.Cast(memoryManager.GetSpan(EntryAddress, (int)EntryCount * 4, flush)).ToArray(); - } + return Words ?? GetWords(memoryManager, flush); } } @@ -158,7 +177,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.GPFifo if (beforeBarrier && commandBuffer.Type == CommandBufferType.Prefetch) { - commandBuffer.Fetch(processor.MemoryManager); + commandBuffer.Prefetch(processor.MemoryManager); } if (commandBuffer.Type == CommandBufferType.NoPrefetch) @@ -199,7 +218,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.GPFifo } _currentCommandBuffer = entry; - _currentCommandBuffer.Fetch(entry.Processor.MemoryManager, flushCommandBuffer); + ReadOnlySpan words = entry.Fetch(entry.Processor.MemoryManager, flushCommandBuffer); // If we are changing the current channel, // we need to force all the host state to be updated. @@ -209,7 +228,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.GPFifo entry.Processor.ForceAllDirty(); } - entry.Processor.Process(entry.EntryAddress, _currentCommandBuffer.Words); + entry.Processor.Process(entry.EntryAddress, words); } _interrupt = false;