From 94244437de48561cc299c5afc4ee70c9dcd086ce Mon Sep 17 00:00:00 2001 From: Liam Date: Mon, 18 Dec 2023 22:15:44 -0500 Subject: [PATCH] shader_recompiler: ignore clip distances beyond driver support level --- .../backend/spirv/emit_spirv_context_get_set.cpp | 5 +++++ src/shader_recompiler/backend/spirv/spirv_emit_context.cpp | 2 +- src/shader_recompiler/profile.h | 2 ++ src/video_core/renderer_opengl/gl_shader_cache.cpp | 1 + src/video_core/renderer_vulkan/vk_pipeline_cache.cpp | 1 + src/video_core/vulkan_common/vulkan_device.h | 4 ++++ 6 files changed, 14 insertions(+), 1 deletion(-) 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 e5a78a914..feca5105f 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 @@ -74,6 +74,11 @@ std::optional OutputAttrPointer(EmitContext& ctx, IR::Attribute attr) { case IR::Attribute::ClipDistance7: { const u32 base{static_cast(IR::Attribute::ClipDistance0)}; const u32 index{static_cast(attr) - base}; + if (index >= ctx.profile.max_user_clip_distances) { + LOG_WARNING(Shader, "Ignoring clip distance store {} >= {} supported", index, + ctx.profile.max_user_clip_distances); + return std::nullopt; + } const Id clip_num{ctx.Const(index)}; return OutputAccessChain(ctx, ctx.output_f32, ctx.clip_distances, clip_num); } diff --git a/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp b/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp index 3350f1f85..4d24e02de 100644 --- a/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp +++ b/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp @@ -1528,7 +1528,7 @@ void EmitContext::DefineOutputs(const IR::Program& program) { if (stage == Stage::Fragment) { throw NotImplementedException("Storing ClipDistance in fragment stage"); } - const Id type{TypeArray(F32[1], Const(8U))}; + const Id type{TypeArray(F32[1], Const(std::min(8U, profile.max_user_clip_distances)))}; clip_distances = DefineOutput(*this, type, invocations, spv::BuiltIn::ClipDistance); } if (info.stores[IR::Attribute::Layer] && diff --git a/src/shader_recompiler/profile.h b/src/shader_recompiler/profile.h index 66901a965..7578d41cc 100644 --- a/src/shader_recompiler/profile.h +++ b/src/shader_recompiler/profile.h @@ -87,6 +87,8 @@ struct Profile { bool has_broken_robust{}; u64 min_ssbo_alignment{}; + + u32 max_user_clip_distances{}; }; } // namespace Shader diff --git a/src/video_core/renderer_opengl/gl_shader_cache.cpp b/src/video_core/renderer_opengl/gl_shader_cache.cpp index 26f2d0ea7..b5999362a 100644 --- a/src/video_core/renderer_opengl/gl_shader_cache.cpp +++ b/src/video_core/renderer_opengl/gl_shader_cache.cpp @@ -233,6 +233,7 @@ ShaderCache::ShaderCache(RasterizerOpenGL& rasterizer_, Core::Frontend::EmuWindo .ignore_nan_fp_comparisons = true, .gl_max_compute_smem_size = device.GetMaxComputeSharedMemorySize(), .min_ssbo_alignment = device.GetShaderStorageBufferAlignment(), + .max_user_clip_distances = 8, }, host_info{ .support_float64 = true, diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp index 2a13b2a72..fa63d6228 100644 --- a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp @@ -374,6 +374,7 @@ PipelineCache::PipelineCache(RasterizerVulkan& rasterizer_, const Device& device .has_broken_robust = device.IsNvidia() && device.GetNvidiaArch() <= NvidiaArchitecture::Arch_Pascal, .min_ssbo_alignment = device.GetStorageBufferAlignment(), + .max_user_clip_distances = device.GetMaxUserClipDistances(), }; host_info = Shader::HostTranslateInfo{ diff --git a/src/video_core/vulkan_common/vulkan_device.h b/src/video_core/vulkan_common/vulkan_device.h index 4f3846345..701817086 100644 --- a/src/video_core/vulkan_common/vulkan_device.h +++ b/src/video_core/vulkan_common/vulkan_device.h @@ -665,6 +665,10 @@ public: return properties.properties.limits.maxViewports; } + u32 GetMaxUserClipDistances() const { + return properties.properties.limits.maxClipDistances; + } + bool SupportsConditionalBarriers() const { return supports_conditional_barriers; }