From 473caaff5b02dc75404943dee6b12234995136d4 Mon Sep 17 00:00:00 2001
From: Liam <byteslice@airmail.cc>
Date: Sun, 19 Nov 2023 11:27:12 -0500
Subject: [PATCH] renderer_vulkan: ignore viewport stores on non-supporting
 drivers

---
 src/shader_recompiler/backend/spirv/emit_spirv.cpp            | 2 +-
 .../backend/spirv/emit_spirv_context_get_set.cpp              | 4 ++++
 src/shader_recompiler/profile.h                               | 1 +
 src/video_core/renderer_vulkan/vk_pipeline_cache.cpp          | 1 +
 src/video_core/vulkan_common/vulkan_device.h                  | 4 ++++
 5 files changed, 11 insertions(+), 1 deletion(-)

diff --git a/src/shader_recompiler/backend/spirv/emit_spirv.cpp b/src/shader_recompiler/backend/spirv/emit_spirv.cpp
index 34592a01ff..0031fa5fbe 100644
--- a/src/shader_recompiler/backend/spirv/emit_spirv.cpp
+++ b/src/shader_recompiler/backend/spirv/emit_spirv.cpp
@@ -407,7 +407,7 @@ void SetupCapabilities(const Profile& profile, const Info& info, EmitContext& ct
         }
         ctx.AddCapability(spv::Capability::DemoteToHelperInvocation);
     }
-    if (info.stores[IR::Attribute::ViewportIndex]) {
+    if (info.stores[IR::Attribute::ViewportIndex] && profile.support_multi_viewport) {
         ctx.AddCapability(spv::Capability::MultiViewport);
     }
     if (info.stores[IR::Attribute::ViewportMask] && profile.support_viewport_mask) {
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp
index 1d77426e01..e5a78a9140 100644
--- a/src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp
+++ b/src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp
@@ -84,6 +84,10 @@ std::optional<OutAttr> OutputAttrPointer(EmitContext& ctx, IR::Attribute attr) {
         }
         return std::nullopt;
     case IR::Attribute::ViewportIndex:
+        if (!ctx.profile.support_multi_viewport) {
+            LOG_WARNING(Shader, "Ignoring viewport index store on non-supporting driver");
+            return std::nullopt;
+        }
         if (ctx.profile.support_viewport_index_layer_non_geometry ||
             ctx.stage == Shader::Stage::Geometry) {
             return OutAttr{ctx.viewport_index, ctx.U32[1]};
diff --git a/src/shader_recompiler/profile.h b/src/shader_recompiler/profile.h
index 38d820db20..a9de9f4a95 100644
--- a/src/shader_recompiler/profile.h
+++ b/src/shader_recompiler/profile.h
@@ -43,6 +43,7 @@ struct Profile {
     bool support_gl_sparse_textures{};
     bool support_gl_derivative_control{};
     bool support_scaled_attributes{};
+    bool support_multi_viewport{};
 
     bool warp_size_potentially_larger_than_guest{};
 
diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp
index 16ad8d6252..89b455bff8 100644
--- a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp
+++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp
@@ -351,6 +351,7 @@ PipelineCache::PipelineCache(RasterizerVulkan& rasterizer_, const Device& device
         .support_geometry_shader_passthrough = device.IsNvGeometryShaderPassthroughSupported(),
         .support_native_ndc = device.IsExtDepthClipControlSupported(),
         .support_scaled_attributes = !device.MustEmulateScaledFormats(),
+        .support_multi_viewport = device.SupportsMultiViewport(),
 
         .warp_size_potentially_larger_than_guest = device.IsWarpSizePotentiallyBiggerThanGuest(),
 
diff --git a/src/video_core/vulkan_common/vulkan_device.h b/src/video_core/vulkan_common/vulkan_device.h
index 355de06169..4f3846345c 100644
--- a/src/video_core/vulkan_common/vulkan_device.h
+++ b/src/video_core/vulkan_common/vulkan_device.h
@@ -669,6 +669,10 @@ public:
         return supports_conditional_barriers;
     }
 
+    bool SupportsMultiViewport() const {
+        return features2.features.multiViewport;
+    }
+
     [[nodiscard]] static constexpr bool CheckBrokenCompute(VkDriverId driver_id,
                                                            u32 driver_version) {
         if (driver_id == VK_DRIVER_ID_INTEL_PROPRIETARY_WINDOWS) {