diff --git a/src/shader_recompiler/shader_info.h b/src/shader_recompiler/shader_info.h index 894ae47011..482fcc8a42 100644 --- a/src/shader_recompiler/shader_info.h +++ b/src/shader_recompiler/shader_info.h @@ -382,6 +382,12 @@ struct Info { /// and storage buffer words (see EvaluateHandleProgram), evaluated for each draw. std::vector> handle_programs; ImageDescriptors image_descriptors; + + /// Whether the shader uses warp-level operations, which observe the subgroup size. + [[nodiscard]] bool UsesWarpOps() const noexcept { + return uses_subgroup_vote || uses_subgroup_invocation_id || uses_subgroup_shuffles || + uses_subgroup_mask || uses_quad_shuffles || uses_fswzadd; + } }; template diff --git a/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp b/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp index c425106bcf..acbb088166 100644 --- a/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp +++ b/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp @@ -90,9 +90,7 @@ ComputePipeline::ComputePipeline(const Device& device_, Scheduler& scheduler, vk }; // Only warp-level ops observe the subgroup size. Forcing 32 on other shaders makes Intel // compile SIMD32, which can spill a register-heavy kernel for minutes (Mario Kart World). - const bool uses_warp_ops = info.uses_subgroup_vote || info.uses_subgroup_invocation_id || - info.uses_subgroup_shuffles || info.uses_subgroup_mask || - info.uses_quad_shuffles || info.uses_fswzadd; + const bool uses_warp_ops = info.UsesWarpOps(); VkPipelineCreateFlags flags{}; if (device.IsKhrPipelineExecutablePropertiesEnabled() && Settings::values.renderer_debug.GetValue()) { flags |= VK_PIPELINE_CREATE_CAPTURE_STATISTICS_BIT_KHR; diff --git a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp index fc7b96567d..f634ec412c 100644 --- a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp +++ b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp @@ -1184,7 +1184,7 @@ void GraphicsPipeline::MakePipeline(VkRenderPass render_pass) { .dynamicStateCount = static_cast(dynamic_states.size()), .pDynamicStates = dynamic_states.data(), }; - [[maybe_unused]] const VkPipelineShaderStageRequiredSubgroupSizeCreateInfoEXT subgroup_size_ci{ + const VkPipelineShaderStageRequiredSubgroupSizeCreateInfoEXT subgroup_size_ci{ .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_REQUIRED_SUBGROUP_SIZE_CREATE_INFO_EXT, .pNext = nullptr, .requiredSubgroupSize = GuestWarpSize, @@ -1194,7 +1194,7 @@ void GraphicsPipeline::MakePipeline(VkRenderPass render_pass) { if (!spv_modules[stage]) { continue; } - [[maybe_unused]] auto& stage_ci = + auto& stage_ci = shader_stages.emplace_back(VkPipelineShaderStageCreateInfo{ .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, .pNext = nullptr, @@ -1205,6 +1205,12 @@ void GraphicsPipeline::MakePipeline(VkRenderPass render_pass) { .pName = "main", .pSpecializationInfo = nullptr, }); + if ((stage_ci.stage == VK_SHADER_STAGE_MESH_BIT_EXT || + stage_ci.stage == VK_SHADER_STAGE_TASK_BIT_EXT) && + stage_infos[stage].UsesWarpOps() && device.IsExtSubgroupSizeControlSupported() && + device.IsGuestWarpSizeSupported(stage_ci.stage)) { + stage_ci.pNext = &subgroup_size_ci; + } } VkPipelineCreateFlags flags{}; if (device.IsKhrPipelineExecutablePropertiesEnabled() && Settings::values.renderer_debug.GetValue()) {