From de3134adbec9e35eba08dbb835c38bc305d2c150 Mon Sep 17 00:00:00 2001
From: riperiperi <rhy3756547@hotmail.com>
Date: Thu, 19 Jan 2023 00:30:42 +0000
Subject: [PATCH] Vulkan: Explicitly enable precise occlusion queries (#4292)

The only guarantee of the occlusion query type in Vulkan is that it will be zero when no samples pass, and non-zero when any samples pass. Of course, most GPUs implement this by just placing the # of samples in the result and calling it a day. However, this lax restriction means that GPUs could just report a boolean (1/0) or report a value after one is recorded, but before all samples have been counted.

MoltenVK falls in the first category - by default it only reports 1/0 for occlusion queries. Thankfully, there is a feature and flag that you can use to force compatible drivers to provide a "precise" query result, that being the real # of samples passed.

Should fix ink collision in Splatoon 2/3 on MoltenVK.
---
 Ryujinx.Graphics.Vulkan/HardwareCapabilities.cs | 3 +++
 Ryujinx.Graphics.Vulkan/PipelineFull.cs         | 4 ++--
 Ryujinx.Graphics.Vulkan/VulkanInitialization.cs | 1 +
 Ryujinx.Graphics.Vulkan/VulkanRenderer.cs       | 1 +
 4 files changed, 7 insertions(+), 2 deletions(-)

diff --git a/Ryujinx.Graphics.Vulkan/HardwareCapabilities.cs b/Ryujinx.Graphics.Vulkan/HardwareCapabilities.cs
index 0a4d365f25..8685d34421 100644
--- a/Ryujinx.Graphics.Vulkan/HardwareCapabilities.cs
+++ b/Ryujinx.Graphics.Vulkan/HardwareCapabilities.cs
@@ -28,6 +28,7 @@ namespace Ryujinx.Graphics.Vulkan
         public readonly bool SupportsExtendedDynamicState;
         public readonly bool SupportsMultiView;
         public readonly bool SupportsNullDescriptors;
+        public readonly bool SupportsPreciseOcclusionQueries;
         public readonly bool SupportsPushDescriptors;
         public readonly bool SupportsTransformFeedback;
         public readonly bool SupportsTransformFeedbackQueries;
@@ -53,6 +54,7 @@ namespace Ryujinx.Graphics.Vulkan
             bool supportsPushDescriptors,
             bool supportsTransformFeedback,
             bool supportsTransformFeedbackQueries,
+            bool supportsPreciseOcclusionQueries,
             bool supportsGeometryShader,
             uint minSubgroupSize,
             uint maxSubgroupSize,
@@ -74,6 +76,7 @@ namespace Ryujinx.Graphics.Vulkan
             SupportsPushDescriptors = supportsPushDescriptors;
             SupportsTransformFeedback = supportsTransformFeedback;
             SupportsTransformFeedbackQueries = supportsTransformFeedbackQueries;
+            SupportsPreciseOcclusionQueries = supportsPreciseOcclusionQueries;
             SupportsGeometryShader = supportsGeometryShader;
             MinSubgroupSize = minSubgroupSize;
             MaxSubgroupSize = maxSubgroupSize;
diff --git a/Ryujinx.Graphics.Vulkan/PipelineFull.cs b/Ryujinx.Graphics.Vulkan/PipelineFull.cs
index e4bf4fffac..5b4f4a6e9f 100644
--- a/Ryujinx.Graphics.Vulkan/PipelineFull.cs
+++ b/Ryujinx.Graphics.Vulkan/PipelineFull.cs
@@ -235,7 +235,7 @@ namespace Ryujinx.Graphics.Vulkan
             foreach (var queryPool in _activeQueries)
             {
                 Gd.Api.CmdResetQueryPool(CommandBuffer, queryPool, 0, 1);
-                Gd.Api.CmdBeginQuery(CommandBuffer, queryPool, 0, 0);
+                Gd.Api.CmdBeginQuery(CommandBuffer, queryPool, 0, Gd.Capabilities.SupportsPreciseOcclusionQueries ? QueryControlFlags.PreciseBit : 0);
             }
 
             Restore();
@@ -255,7 +255,7 @@ namespace Ryujinx.Graphics.Vulkan
                 }
             }
 
-            Gd.Api.CmdBeginQuery(CommandBuffer, pool, 0, 0);
+            Gd.Api.CmdBeginQuery(CommandBuffer, pool, 0, Gd.Capabilities.SupportsPreciseOcclusionQueries ? QueryControlFlags.PreciseBit : 0);
 
             _activeQueries.Add(pool);
         }
diff --git a/Ryujinx.Graphics.Vulkan/VulkanInitialization.cs b/Ryujinx.Graphics.Vulkan/VulkanInitialization.cs
index fe9462aa3e..00baad1036 100644
--- a/Ryujinx.Graphics.Vulkan/VulkanInitialization.cs
+++ b/Ryujinx.Graphics.Vulkan/VulkanInitialization.cs
@@ -416,6 +416,7 @@ namespace Ryujinx.Graphics.Vulkan
                 IndependentBlend = true,
                 LogicOp = supportedFeatures.LogicOp,
                 MultiViewport = true,
+                OcclusionQueryPrecise = supportedFeatures.OcclusionQueryPrecise,
                 PipelineStatisticsQuery = supportedFeatures.PipelineStatisticsQuery,
                 SamplerAnisotropy = true,
                 ShaderClipDistance = true,
diff --git a/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs b/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs
index f1922efed0..bec7b84755 100644
--- a/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs
+++ b/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs
@@ -270,6 +270,7 @@ namespace Ryujinx.Graphics.Vulkan
                 supportedExtensions.Contains(KhrPushDescriptor.ExtensionName),
                 supportsTransformFeedback,
                 propertiesTransformFeedback.TransformFeedbackQueries,
+                features2.Features.OcclusionQueryPrecise,
                 supportedFeatures.GeometryShader,
                 propertiesSubgroupSizeControl.MinSubgroupSize,
                 propertiesSubgroupSizeControl.MaxSubgroupSize,