From 10e17ab423ba84856eb7411ce04d38989ac70a58 Mon Sep 17 00:00:00 2001 From: riperiperi Date: Sun, 18 Jul 2021 15:45:50 +0100 Subject: [PATCH] Only use persistent buffers to flush on NVIDIA and Windows+AMD (#2489) It seems like this method of flushing data is much slower on Mesa drivers, and slightly slower on Intel Windows. Have not tested Intel Mesa, but I'm assuming it is the same as AMD. This also adds vendor detection for AMD on Unix, which counted as "Unknown" before. --- Ryujinx.Graphics.OpenGL/HwCapabilities.cs | 18 +++++++++++--- Ryujinx.Graphics.OpenGL/Image/TextureView.cs | 26 +++++++++++++++++++- Ryujinx.Graphics.OpenGL/PersistentBuffers.cs | 9 +------ Ryujinx.Graphics.OpenGL/Renderer.cs | 9 ++++++- 4 files changed, 48 insertions(+), 14 deletions(-) diff --git a/Ryujinx.Graphics.OpenGL/HwCapabilities.cs b/Ryujinx.Graphics.OpenGL/HwCapabilities.cs index a971d5fc..44365ca7 100644 --- a/Ryujinx.Graphics.OpenGL/HwCapabilities.cs +++ b/Ryujinx.Graphics.OpenGL/HwCapabilities.cs @@ -20,7 +20,8 @@ namespace Ryujinx.Graphics.OpenGL public enum GpuVendor { Unknown, - Amd, + AmdWindows, + AmdUnix, IntelWindows, IntelUnix, Nvidia @@ -28,10 +29,15 @@ namespace Ryujinx.Graphics.OpenGL private static readonly Lazy _gpuVendor = new Lazy(GetGpuVendor); + private static bool _isAMD => _gpuVendor.Value == GpuVendor.AmdWindows || _gpuVendor.Value == GpuVendor.AmdUnix; + private static bool _isIntel => _gpuVendor.Value == GpuVendor.IntelWindows || _gpuVendor.Value == GpuVendor.IntelUnix; + public static GpuVendor Vendor => _gpuVendor.Value; private static Lazy _maxSupportedAnisotropy = new Lazy(GL.GetFloat((GetPName)All.MaxTextureMaxAnisotropy)); + public static bool UsePersistentBufferForFlush => _gpuVendor.Value == GpuVendor.AmdWindows || _gpuVendor.Value == GpuVendor.Nvidia; + public static bool SupportsAstcCompression => _supportsAstcCompression.Value; public static bool SupportsImageLoadFormatted => _supportsImageLoadFormatted.Value; public static bool SupportsParallelShaderCompile => _supportsParallelShaderCompile.Value; @@ -41,9 +47,9 @@ namespace Ryujinx.Graphics.OpenGL public static bool SupportsTextureShadowLod => _supportsTextureShadowLod.Value; public static bool SupportsViewportSwizzle => _supportsViewportSwizzle.Value; - public static bool SupportsMismatchingViewFormat => _gpuVendor.Value != GpuVendor.Amd && _gpuVendor.Value != GpuVendor.IntelWindows; + public static bool SupportsMismatchingViewFormat => _gpuVendor.Value != GpuVendor.AmdWindows && _gpuVendor.Value != GpuVendor.IntelWindows; public static bool SupportsNonConstantTextureOffset => _gpuVendor.Value == GpuVendor.Nvidia; - public static bool RequiresSyncFlush => _gpuVendor.Value == GpuVendor.Amd || _gpuVendor.Value == GpuVendor.IntelWindows || _gpuVendor.Value == GpuVendor.IntelUnix; + public static bool RequiresSyncFlush => _gpuVendor.Value == GpuVendor.AmdWindows || _isIntel; public static int MaximumComputeSharedMemorySize => _maximumComputeSharedMemorySize.Value; public static int StorageBufferOffsetAlignment => _storageBufferOffsetAlignment.Value; @@ -86,7 +92,11 @@ namespace Ryujinx.Graphics.OpenGL } else if (vendor == "ati technologies inc." || vendor == "advanced micro devices, inc.") { - return GpuVendor.Amd; + return GpuVendor.AmdWindows; + } + else if (vendor == "amd" || vendor == "x.org") + { + return GpuVendor.AmdUnix; } else { diff --git a/Ryujinx.Graphics.OpenGL/Image/TextureView.cs b/Ryujinx.Graphics.OpenGL/Image/TextureView.cs index 770e99a0..5e7b5f22 100644 --- a/Ryujinx.Graphics.OpenGL/Image/TextureView.cs +++ b/Ryujinx.Graphics.OpenGL/Image/TextureView.cs @@ -121,7 +121,31 @@ namespace Ryujinx.Graphics.OpenGL.Image public byte[] GetData() { - return _renderer.PersistentBuffers.Default.GetTextureData(this); + int size = 0; + + for (int level = 0; level < Info.Levels; level++) + { + size += Info.GetMipSize(level); + } + + if (HwCapabilities.UsePersistentBufferForFlush) + { + return _renderer.PersistentBuffers.Default.GetTextureData(this, size); + } + else + { + byte[] data = new byte[size]; + + unsafe + { + fixed (byte* ptr = data) + { + WriteTo((IntPtr)ptr); + } + } + + return data; + } } public void WriteToPbo(int offset, bool forceBgra) diff --git a/Ryujinx.Graphics.OpenGL/PersistentBuffers.cs b/Ryujinx.Graphics.OpenGL/PersistentBuffers.cs index a7cefca3..740f8b98 100644 --- a/Ryujinx.Graphics.OpenGL/PersistentBuffers.cs +++ b/Ryujinx.Graphics.OpenGL/PersistentBuffers.cs @@ -63,15 +63,8 @@ namespace Ryujinx.Graphics.OpenGL GL.DeleteSync(sync); } - public byte[] GetTextureData(TextureView view) + public byte[] GetTextureData(TextureView view, int size) { - int size = 0; - - for (int level = 0; level < view.Info.Levels; level++) - { - size += view.Info.GetMipSize(level); - } - EnsureBuffer(size); GL.BindBuffer(BufferTarget.PixelPackBuffer, _copyBufferHandle); diff --git a/Ryujinx.Graphics.OpenGL/Renderer.cs b/Ryujinx.Graphics.OpenGL/Renderer.cs index 41629c1d..561f0684 100644 --- a/Ryujinx.Graphics.OpenGL/Renderer.cs +++ b/Ryujinx.Graphics.OpenGL/Renderer.cs @@ -93,7 +93,14 @@ namespace Ryujinx.Graphics.OpenGL public byte[] GetBufferData(BufferHandle buffer, int offset, int size) { - return PersistentBuffers.Default.GetBufferData(buffer, offset, size); + if (HwCapabilities.UsePersistentBufferForFlush) + { + return PersistentBuffers.Default.GetBufferData(buffer, offset, size); + } + else + { + return Buffer.GetData(buffer, offset, size); + } } public Capabilities GetCapabilities()