diff --git a/src/Ryujinx.Graphics.Vulkan/BackgroundResources.cs b/src/Ryujinx.Graphics.Vulkan/BackgroundResources.cs index b8906a62c..0290987fd 100644 --- a/src/Ryujinx.Graphics.Vulkan/BackgroundResources.cs +++ b/src/Ryujinx.Graphics.Vulkan/BackgroundResources.cs @@ -35,7 +35,7 @@ namespace Ryujinx.Graphics.Vulkan queue, queueLock, _gd.QueueFamilyIndex, - _gd.IsConcurrentFenceWaitUnsupported, + _gd.IsQualcommProprietary, isLight: true); } } diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs index 00fcc0783..2b2caeaec 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs @@ -1021,7 +1021,7 @@ namespace Ryujinx.Graphics.Vulkan _newState.RasterizerDiscardEnable = discard; SignalStateChange(); - if (!discard && Gd.Vendor == Vendor.Qualcomm) + if (!discard && Gd.IsQualcommProprietary) { // On Adreno, enabling rasterizer discard somehow corrupts the viewport state. // Force it to be updated on next use to work around this bug. diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineFull.cs b/src/Ryujinx.Graphics.Vulkan/PipelineFull.cs index 357d517eb..5808406dc 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineFull.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineFull.cs @@ -47,10 +47,11 @@ namespace Ryujinx.Graphics.Vulkan return; } - if (componentMask != 0xf) + if (componentMask != 0xf || Gd.IsQualcommProprietary) { // We can't use CmdClearAttachments if not writing all components, // because on Vulkan, the pipeline state does not affect clears. + // On proprietary Adreno drivers, CmdClearAttachments appears to execute out of order, so it's better to not use it at all. var dstTexture = FramebufferParams.GetColorView(index); if (dstTexture == null) { @@ -87,10 +88,11 @@ namespace Ryujinx.Graphics.Vulkan return; } - if (stencilMask != 0 && stencilMask != 0xff) + if ((stencilMask != 0 && stencilMask != 0xff) || Gd.IsQualcommProprietary) { // We can't use CmdClearAttachments if not clearing all (mask is all ones, 0xFF) or none (mask is 0) of the stencil bits, // because on Vulkan, the pipeline state does not affect clears. + // On proprietary Adreno drivers, CmdClearAttachments appears to execute out of order, so it's better to not use it at all. var dstTexture = FramebufferParams.GetDepthStencilView(); if (dstTexture == null) { diff --git a/src/Ryujinx.Graphics.Vulkan/ShaderCollection.cs b/src/Ryujinx.Graphics.Vulkan/ShaderCollection.cs index eec2a3180..b1547b795 100644 --- a/src/Ryujinx.Graphics.Vulkan/ShaderCollection.cs +++ b/src/Ryujinx.Graphics.Vulkan/ShaderCollection.cs @@ -133,7 +133,7 @@ namespace Ryujinx.Graphics.Vulkan Templates = BuildTemplates(usePushDescriptors); // Updating buffer texture bindings using template updates crashes the Adreno driver on Windows. - UpdateTexturesWithoutTemplate = gd.Vendor == Vendor.Qualcomm && usesBufferTextures; + UpdateTexturesWithoutTemplate = gd.IsQualcommProprietary && usesBufferTextures; _compileTask = Task.CompletedTask; _firstBackgroundUse = false; diff --git a/src/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs b/src/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs index c16896517..e46eac95f 100644 --- a/src/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs +++ b/src/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs @@ -87,10 +87,10 @@ namespace Ryujinx.Graphics.Vulkan internal bool IsAmdGcn { get; private set; } internal bool IsNvidiaPreTuring { get; private set; } internal bool IsIntelArc { get; private set; } + internal bool IsQualcommProprietary { get; private set; } internal bool IsMoltenVk { get; private set; } internal bool IsTBDR { get; private set; } internal bool IsSharedMemory { get; private set; } - internal bool IsConcurrentFenceWaitUnsupported { get; private set; } public string GpuVendor { get; private set; } public string GpuDriver { get; private set; } @@ -325,8 +325,6 @@ namespace Ryujinx.Graphics.Vulkan Vendor == Vendor.Broadcom || Vendor == Vendor.ImgTec; - IsConcurrentFenceWaitUnsupported = Vendor == Vendor.Qualcomm; - GpuVendor = VendorUtils.GetNameFromId(properties.VendorID); GpuDriver = hasDriverProperties && !OperatingSystem.IsMacOS() ? VendorUtils.GetFriendlyDriverName(driverProperties.DriverID) : GpuVendor; // Fallback to vendor name if driver is unavailable or on MacOS where vendor is preferred. @@ -348,7 +346,7 @@ namespace Ryujinx.Graphics.Vulkan { IsNvidiaPreTuring = gpuNumber < 2000; } - else if (GpuDriver.Contains("TITAN") && !GpuDriver.Contains("RTX")) + else if (GpuRenderer.Contains("TITAN") && !GpuRenderer.Contains("RTX")) { IsNvidiaPreTuring = true; } @@ -358,6 +356,8 @@ namespace Ryujinx.Graphics.Vulkan IsIntelArc = GpuRenderer.StartsWith("Intel(R) Arc(TM)"); } + IsQualcommProprietary = hasDriverProperties && driverProperties.DriverID == DriverId.QualcommProprietary; + ulong minResourceAlignment = Math.Max( Math.Max( properties.Limits.MinStorageBufferOffsetAlignment, @@ -415,7 +415,7 @@ namespace Ryujinx.Graphics.Vulkan Api.TryGetDeviceExtension(_instance.Instance, _device, out ExtExternalMemoryHost hostMemoryApi); HostMemoryAllocator = new HostMemoryAllocator(MemoryAllocator, Api, hostMemoryApi, _device); - CommandBufferPool = new CommandBufferPool(Api, _device, Queue, QueueLock, queueFamilyIndex, IsConcurrentFenceWaitUnsupported); + CommandBufferPool = new CommandBufferPool(Api, _device, Queue, QueueLock, queueFamilyIndex, IsQualcommProprietary); PipelineLayoutCache = new PipelineLayoutCache(); @@ -692,7 +692,7 @@ namespace Ryujinx.Graphics.Vulkan GpuVendor, memoryType: memoryType, hasFrontFacingBug: IsIntelWindows, - hasVectorIndexingBug: Vendor == Vendor.Qualcomm, + hasVectorIndexingBug: IsQualcommProprietary, needsFragmentOutputSpecialization: IsMoltenVk, reduceShaderPrecision: IsMoltenVk, supportsAstcCompression: features2.Features.TextureCompressionAstcLdr && supportsAstcFormats,