From 8c4e3926bb5403ef245aabb6a25cf838e6fc28d7 Mon Sep 17 00:00:00 2001 From: squidbus <175574877+squidbus@users.noreply.github.com> Date: Fri, 12 Jun 2026 16:30:59 -0700 Subject: [PATCH] video_core: Fix a few validation errors (#4555) * shader_recompiler: Don't add SignedZeroInfNanPreserve if not supported * renderer_vulkan: Respect patch list restart support flag --- .../backend/spirv/emit_spirv.cpp | 18 +++++++++++++++--- src/video_core/renderer_vulkan/vk_instance.cpp | 14 ++++++++++---- src/video_core/renderer_vulkan/vk_instance.h | 10 ++++++++-- .../renderer_vulkan/vk_rasterizer.cpp | 11 ++++++++--- 4 files changed, 41 insertions(+), 12 deletions(-) diff --git a/src/shader_recompiler/backend/spirv/emit_spirv.cpp b/src/shader_recompiler/backend/spirv/emit_spirv.cpp index 1eee8d90b..5efce9292 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv.cpp +++ b/src/shader_recompiler/backend/spirv/emit_spirv.cpp @@ -559,9 +559,21 @@ void SetupRoundingMode(EmitContext& ctx, const Profile& profile, const RuntimeIn void SetupInfNanPreserveMode(EmitContext& ctx, const Profile& profile, const RuntimeInfo& runtime_info, Id main_func) { - ctx.AddCapability(spv::Capability::SignedZeroInfNanPreserve); - // universally supported (98.85% on gpuinfo) so no flag checked - ctx.AddExecutionMode(main_func, spv::ExecutionMode::SignedZeroInfNanPreserve, 32U); + if (profile.support_fp16_signed_zero_inf_nan_preserve || + profile.support_fp32_signed_zero_inf_nan_preserve || + profile.support_fp64_signed_zero_inf_nan_preserve) { + ctx.AddCapability(spv::Capability::SignedZeroInfNanPreserve); + } + + if (profile.support_fp32_signed_zero_inf_nan_preserve) { + ctx.AddExecutionMode(main_func, spv::ExecutionMode::SignedZeroInfNanPreserve, 32U); + } else { + static std::once_flag logged; + std::call_once(logged, [] { + LOG_WARNING(Render_Vulkan, + "Float32 signed zero/inf/nan preserve mode is not supported by the GPU"); + }); + } if (ctx.info.uses_fp16) { if (profile.support_fp16_signed_zero_inf_nan_preserve) { ctx.AddExecutionMode(main_func, spv::ExecutionMode::SignedZeroInfNanPreserve, 16U); diff --git a/src/video_core/renderer_vulkan/vk_instance.cpp b/src/video_core/renderer_vulkan/vk_instance.cpp index c69eda24a..411a5caef 100644 --- a/src/video_core/renderer_vulkan/vk_instance.cpp +++ b/src/video_core/renderer_vulkan/vk_instance.cpp @@ -280,6 +280,14 @@ bool Instance::CreateDevice() { depth_clip_enable = add_extension(VK_EXT_DEPTH_CLIP_ENABLE_EXTENSION_NAME); vertex_input_dynamic_state = add_extension(VK_EXT_VERTEX_INPUT_DYNAMIC_STATE_EXTENSION_NAME); list_restart = add_extension(VK_EXT_PRIMITIVE_TOPOLOGY_LIST_RESTART_EXTENSION_NAME); + if (list_restart) { + list_restart_features = + feature_chain.get(); + LOG_INFO(Render_Vulkan, "- primitiveTopologyListRestart: {}", + list_restart_features.primitiveTopologyListRestart); + LOG_INFO(Render_Vulkan, "- primitiveTopologyPatchListRestart: {}", + list_restart_features.primitiveTopologyPatchListRestart); + } amd_shader_explicit_vertex_parameter = add_extension(VK_AMD_SHADER_EXPLICIT_VERTEX_PARAMETER_EXTENSION_NAME); if (!amd_shader_explicit_vertex_parameter) { @@ -369,8 +377,6 @@ bool Instance::CreateDevice() { .pQueuePriorities = queue_priorities.data(), }; - const auto topology_list_restart_features = - feature_chain.get(); const auto vk11_features = feature_chain.get(); vk12_features = feature_chain.get(); vk13_features = feature_chain.get(); @@ -464,9 +470,9 @@ bool Instance::CreateDevice() { .vertexInputDynamicState = true, }, vk::PhysicalDevicePrimitiveTopologyListRestartFeaturesEXT{ - .primitiveTopologyListRestart = true, + .primitiveTopologyListRestart = list_restart_features.primitiveTopologyListRestart, .primitiveTopologyPatchListRestart = - topology_list_restart_features.primitiveTopologyPatchListRestart, + list_restart_features.primitiveTopologyPatchListRestart, }, vk::PhysicalDeviceFragmentShaderBarycentricFeaturesKHR{ .fragmentShaderBarycentric = true, diff --git a/src/video_core/renderer_vulkan/vk_instance.h b/src/video_core/renderer_vulkan/vk_instance.h index 529d493fd..f170e3f34 100644 --- a/src/video_core/renderer_vulkan/vk_instance.h +++ b/src/video_core/renderer_vulkan/vk_instance.h @@ -180,9 +180,14 @@ public: return amd_shader_explicit_vertex_parameter; } - /// Returns true when VK_EXT_primitive_topology_list_restart is supported. + /// Returns true when VK_EXT_primitive_topology_list_restart is supported for regular lists. bool IsListRestartSupported() const { - return list_restart; + return list_restart && list_restart_features.primitiveTopologyListRestart; + } + + /// Returns true when VK_EXT_primitive_topology_list_restart is supported for patch lists. + bool IsPatchListRestartSupported() const { + return list_restart && list_restart_features.primitiveTopologyPatchListRestart; } /// Returns true when VK_EXT_legacy_vertex_attributes is supported. @@ -485,6 +490,7 @@ private: vk::PhysicalDeviceWorkgroupMemoryExplicitLayoutFeaturesKHR workgroup_memory_explicit_layout_features; vk::PhysicalDeviceImage2DViewOf3DFeaturesEXT image_2d_view_of_3d_features; + vk::PhysicalDevicePrimitiveTopologyListRestartFeaturesEXT list_restart_features; vk::DriverIdKHR driver_id; vk::UniqueDebugUtilsMessengerEXT debug_callback{}; std::string vendor_name; diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp index 3b734fde3..cff21bcf1 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp +++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp @@ -1295,13 +1295,18 @@ void Rasterizer::UpdatePrimitiveState(const bool is_indexed) const { topology == vk::PrimitiveTopology::eLineList || topology == vk::PrimitiveTopology::eTriangleList || topology == vk::PrimitiveTopology::eLineListWithAdjacency || - topology == vk::PrimitiveTopology::eTriangleListWithAdjacency || - topology == vk::PrimitiveTopology::ePatchList; + topology == vk::PrimitiveTopology::eTriangleListWithAdjacency; + }; + const auto is_patch_list_topology = [](const AmdGpu::PrimitiveType type) { + // Quad and rect lists are emulated using tessellation. + return type == AmdGpu::PrimitiveType::PatchPrimitive || + type == AmdGpu::PrimitiveType::QuadList || type == AmdGpu::PrimitiveType::RectList; }; const auto prim_restart = (regs.enable_primitive_restart & 1) != 0 && - (instance.IsListRestartSupported() || !is_list_topology(regs.primitive_type)); + (instance.IsListRestartSupported() || !is_list_topology(regs.primitive_type)) && + (instance.IsPatchListRestartSupported() || !is_patch_list_topology(regs.primitive_type)); ASSERT_MSG(!is_indexed || !prim_restart || regs.primitive_restart_index == 0xFFFF || regs.primitive_restart_index == 0xFFFFFFFF, "Primitive restart index other than -1 is not supported yet");