From 7c04884d549f952265f371392485f9f765387b18 Mon Sep 17 00:00:00 2001 From: CamilleLaVey Date: Wed, 15 Apr 2026 18:54:10 -0400 Subject: [PATCH] Revert "[vulkan] Rework DynamicState - ExtendedDynamicState" --- .../renderer_vulkan/fixed_pipeline_state.cpp | 55 +----- .../renderer_vulkan/fixed_pipeline_state.h | 59 ++---- .../renderer_vulkan/vk_graphics_pipeline.cpp | 106 ++++------- .../renderer_vulkan/vk_pipeline_cache.cpp | 71 ++----- .../vulkan_common/vulkan_device.cpp | 173 +----------------- src/video_core/vulkan_common/vulkan_device.h | 114 +----------- 6 files changed, 92 insertions(+), 486 deletions(-) diff --git a/src/video_core/renderer_vulkan/fixed_pipeline_state.cpp b/src/video_core/renderer_vulkan/fixed_pipeline_state.cpp index 67d3affacb..d53cf70b37 100644 --- a/src/video_core/renderer_vulkan/fixed_pipeline_state.cpp +++ b/src/video_core/renderer_vulkan/fixed_pipeline_state.cpp @@ -57,11 +57,6 @@ void FixedPipelineState::Refresh(Tegra::Engines::Maxwell3D& maxwell3d, DynamicFe const auto topology_ = maxwell3d.draw_manager->GetDrawState().topology; raw1 = 0; - core_dynamic_viewport_scissor.Assign(features.has_core_dynamic_viewport_scissor ? 1 : 0); - core_dynamic_depth_bias.Assign(features.has_core_dynamic_depth_bias ? 1 : 0); - core_dynamic_depth_bounds.Assign(features.has_core_dynamic_depth_bounds ? 1 : 0); - core_dynamic_line_width.Assign(features.has_core_dynamic_line_width ? 1 : 0); - core_dynamic_stencil_masks.Assign(features.has_core_dynamic_stencil_masks ? 1 : 0); extended_dynamic_state.Assign(features.has_extended_dynamic_state ? 1 : 0); extended_dynamic_state_2.Assign(features.has_extended_dynamic_state_2 ? 1 : 0); extended_dynamic_state_2_logic_op.Assign(features.has_extended_dynamic_state_2_logic_op ? 1 : 0); @@ -81,7 +76,6 @@ void FixedPipelineState::Refresh(Tegra::Engines::Maxwell3D& maxwell3d, DynamicFe raw2 = 0; - const auto test_func = regs.alpha_test_enabled != 0 ? regs.alpha_test_func : Maxwell::ComparisonOp::Always_GL; alpha_test_func.Assign(PackComparisonOp(test_func)); @@ -112,18 +106,10 @@ void FixedPipelineState::Refresh(Tegra::Engines::Maxwell3D& maxwell3d, DynamicFe } provoking_vertex_last.Assign(use_last_provoking_vertex ? 1 : 0); - if (!features.has_dynamic_state3_conservative_rasterization_mode) { - conservative_raster_enable.Assign(regs.conservative_raster_enable != 0 ? 1 : 0); - } - if (!features.has_dynamic_state3_line_rasterization_mode) { - smooth_lines.Assign(regs.line_anti_alias_enable != 0 ? 1 : 0); - } - if (!features.has_dynamic_state3_alpha_to_coverage_enable) { - alpha_to_coverage_enabled.Assign(regs.anti_alias_alpha_control.alpha_to_coverage != 0 ? 1 : 0); - } - if (!features.has_dynamic_state3_alpha_to_one_enable) { - alpha_to_one_enabled.Assign(regs.anti_alias_alpha_control.alpha_to_one != 0 ? 1 : 0); - } + conservative_raster_enable.Assign(regs.conservative_raster_enable != 0 ? 1 : 0); + smooth_lines.Assign(regs.line_anti_alias_enable != 0 ? 1 : 0); + alpha_to_coverage_enabled.Assign(regs.anti_alias_alpha_control.alpha_to_coverage != 0 ? 1 : 0); + alpha_to_one_enabled.Assign(regs.anti_alias_alpha_control.alpha_to_one != 0 ? 1 : 0); app_stage.Assign(maxwell3d.engine_state); depth_bounds_min = static_cast(regs.depth_bounds[0]); @@ -187,49 +173,24 @@ void FixedPipelineState::Refresh(Tegra::Engines::Maxwell3D& maxwell3d, DynamicFe } dynamic_state.raw1 = 0; dynamic_state.raw2 = 0; - - const bool any_eds1_baked = !features.has_extended_dynamic_state || - !features.has_eds1_cull_mode || !features.has_eds1_front_face || - !features.has_eds1_depth_test_enable || !features.has_eds1_depth_write_enable || - !features.has_eds1_depth_compare_op || - !(features.has_eds1_depth_bounds_test_enable || features.has_core_dynamic_depth_bounds) || - !features.has_eds1_stencil_test_enable || !features.has_eds1_stencil_op; - - if (any_eds1_baked) { + if (!extended_dynamic_state) { dynamic_state.Refresh(regs); - } - - if (!features.has_extended_dynamic_state || !features.has_eds1_vertex_input_binding_stride) { std::ranges::transform(regs.vertex_streams, vertex_strides.begin(), [](const auto& array) { return static_cast(array.stride.Value()); }); } - - const bool any_eds2_baked = !features.has_extended_dynamic_state_2 || - !(features.has_eds2_depth_bias_enable || features.has_core_dynamic_depth_bias) || - !features.has_eds2_primitive_restart_enable || - !features.has_eds2_rasterizer_discard_enable || !features.has_extended_dynamic_state_2_logic_op; - - if (any_eds2_baked) { + if (!extended_dynamic_state_2_logic_op) { dynamic_state.Refresh2(regs, topology_, extended_dynamic_state_2); } - - const bool any_eds3_baked = !features.has_extended_dynamic_state_3_blend || - !features.has_dynamic_state3_depth_clamp_enable || !features.has_dynamic_state3_logic_op_enable || - !features.has_dynamic_state3_line_stipple_enable || !features.has_dynamic_state3_alpha_to_coverage_enable || - !features.has_dynamic_state3_alpha_to_one_enable || !features.has_dynamic_state3_line_rasterization_mode || - !features.has_dynamic_state3_conservative_rasterization_mode; - - if (any_eds3_baked) { + if (!extended_dynamic_state_3_blend) { if (maxwell3d.dirty.flags[Dirty::Blending]) { maxwell3d.dirty.flags[Dirty::Blending] = false; for (size_t index = 0; index < attachments.size(); ++index) { attachments[index].Refresh(regs, index); } } - dynamic_state.Refresh3(regs, features); } - + dynamic_state.Refresh3(regs, features); if (xfb_enabled) { RefreshXfbState(xfb_state, regs); } diff --git a/src/video_core/renderer_vulkan/fixed_pipeline_state.h b/src/video_core/renderer_vulkan/fixed_pipeline_state.h index 28fe2ccb5c..44157d686d 100644 --- a/src/video_core/renderer_vulkan/fixed_pipeline_state.h +++ b/src/video_core/renderer_vulkan/fixed_pipeline_state.h @@ -21,25 +21,8 @@ namespace Vulkan { using Maxwell = Tegra::Engines::Maxwell3D::Regs; struct DynamicFeatures { - bool has_core_dynamic_viewport_scissor; - bool has_core_dynamic_depth_bias; - bool has_core_dynamic_depth_bounds; - bool has_core_dynamic_line_width; - bool has_core_dynamic_stencil_masks; bool has_extended_dynamic_state; - bool has_eds1_cull_mode; - bool has_eds1_front_face; - bool has_eds1_depth_test_enable; - bool has_eds1_depth_write_enable; - bool has_eds1_depth_compare_op; - bool has_eds1_depth_bounds_test_enable; - bool has_eds1_stencil_test_enable; - bool has_eds1_stencil_op; - bool has_eds1_vertex_input_binding_stride; bool has_extended_dynamic_state_2; - bool has_eds2_depth_bias_enable; - bool has_eds2_primitive_restart_enable; - bool has_eds2_rasterizer_discard_enable; bool has_extended_dynamic_state_2_logic_op; bool has_extended_dynamic_state_2_patch_control_points; bool has_extended_dynamic_state_3_blend; @@ -47,10 +30,6 @@ struct DynamicFeatures { bool has_dynamic_state3_depth_clamp_enable; bool has_dynamic_state3_logic_op_enable; bool has_dynamic_state3_line_stipple_enable; - bool has_dynamic_state3_alpha_to_coverage_enable; - bool has_dynamic_state3_alpha_to_one_enable; - bool has_dynamic_state3_line_rasterization_mode; - bool has_dynamic_state3_conservative_rasterization_mode; bool has_dynamic_vertex_input; bool has_provoking_vertex; bool has_provoking_vertex_first_mode; @@ -215,27 +194,23 @@ struct FixedPipelineState { }; union { - u64 raw1; - BitField<0, 1, u64> core_dynamic_viewport_scissor; - BitField<1, 1, u64> core_dynamic_depth_bias; - BitField<2, 1, u64> core_dynamic_depth_bounds; - BitField<3, 1, u64> core_dynamic_line_width; - BitField<4, 1, u64> core_dynamic_stencil_masks; - BitField<5, 1, u64> extended_dynamic_state; - BitField<6, 1, u64> extended_dynamic_state_2; - BitField<7, 1, u64> extended_dynamic_state_2_logic_op; - BitField<8, 1, u64> extended_dynamic_state_3_blend; - BitField<9, 1, u64> extended_dynamic_state_3_enables; - BitField<10, 1, u64> dynamic_vertex_input; - BitField<11, 1, u64> xfb_enabled; - BitField<12, 1, u64> ndc_minus_one_to_one; - BitField<13, 2, u64> polygon_mode; - BitField<15, 2, u64> tessellation_primitive; - BitField<17, 2, u64> tessellation_spacing; - BitField<19, 1, u64> tessellation_clockwise; - BitField<20, 5, u64> patch_control_points_minus_one; - BitField<25, 4, Maxwell::PrimitiveTopology> topology; - BitField<29, 4, Tegra::Texture::MsaaMode> msaa_mode; + u32 raw1; + BitField<0, 1, u32> extended_dynamic_state; + BitField<1, 1, u32> extended_dynamic_state_2; + BitField<2, 1, u32> extended_dynamic_state_2_logic_op; + BitField<3, 1, u32> extended_dynamic_state_3_blend; + BitField<4, 1, u32> extended_dynamic_state_3_enables; + BitField<5, 1, u32> dynamic_vertex_input; + BitField<6, 1, u32> xfb_enabled; + BitField<7, 1, u32> ndc_minus_one_to_one; + BitField<8, 2, u32> polygon_mode; + BitField<10, 2, u32> tessellation_primitive; + BitField<12, 2, u32> tessellation_spacing; + BitField<14, 1, u32> tessellation_clockwise; + BitField<15, 5, u32> patch_control_points_minus_one; + + BitField<24, 4, Maxwell::PrimitiveTopology> topology; + BitField<28, 4, Tegra::Texture::MsaaMode> msaa_mode; }; union { u32 raw2; diff --git a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp index 8f231a4352..43fbefe425 100644 --- a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp +++ b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp @@ -848,94 +848,62 @@ void GraphicsPipeline::MakePipeline(VkRenderPass render_pass) { .pAttachments = cb_attachments.data(), .blendConstants = {} }; - static_vector dynamic_states{}; - // Core dynamic states (Vulkan 1.0) - if (device.SupportsCoreDynamicViewportScissor()) { - dynamic_states.push_back(VK_DYNAMIC_STATE_VIEWPORT); - dynamic_states.push_back(VK_DYNAMIC_STATE_SCISSOR); - } - if (device.SupportsCoreDynamicDepthBias()) { - dynamic_states.push_back(VK_DYNAMIC_STATE_DEPTH_BIAS); - } - // Blend constants are commonly available; keep as default dynamic state. - dynamic_states.push_back(VK_DYNAMIC_STATE_BLEND_CONSTANTS); - if (device.SupportsCoreDynamicDepthBounds()) { - dynamic_states.push_back(VK_DYNAMIC_STATE_DEPTH_BOUNDS); - } - if (device.SupportsCoreDynamicStencilMasks()) { - dynamic_states.push_back(VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK); - dynamic_states.push_back(VK_DYNAMIC_STATE_STENCIL_WRITE_MASK); - dynamic_states.push_back(VK_DYNAMIC_STATE_STENCIL_REFERENCE); - } - if (device.SupportsCoreDynamicLineWidth()) { - dynamic_states.push_back(VK_DYNAMIC_STATE_LINE_WIDTH); - } + static_vector dynamic_states{ + VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR, + VK_DYNAMIC_STATE_DEPTH_BIAS, VK_DYNAMIC_STATE_BLEND_CONSTANTS, + VK_DYNAMIC_STATE_DEPTH_BOUNDS, VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK, + VK_DYNAMIC_STATE_STENCIL_WRITE_MASK, VK_DYNAMIC_STATE_STENCIL_REFERENCE, + VK_DYNAMIC_STATE_LINE_WIDTH, + }; if (key.state.extended_dynamic_state) { - if (device.SupportsEds1CullMode()) { - dynamic_states.push_back(VK_DYNAMIC_STATE_CULL_MODE_EXT); - } - if (device.SupportsEds1FrontFace()) { - dynamic_states.push_back(VK_DYNAMIC_STATE_FRONT_FACE_EXT); - } - if (device.SupportsEds1DepthTestEnable()) { - dynamic_states.push_back(VK_DYNAMIC_STATE_DEPTH_TEST_ENABLE_EXT); - } - if (device.SupportsEds1DepthWriteEnable()) { - dynamic_states.push_back(VK_DYNAMIC_STATE_DEPTH_WRITE_ENABLE_EXT); - } - if (device.SupportsEds1DepthCompareOp()) { - dynamic_states.push_back(VK_DYNAMIC_STATE_DEPTH_COMPARE_OP_EXT); - } - if (device.SupportsEds1DepthBoundsTestEnable()) { - dynamic_states.push_back(VK_DYNAMIC_STATE_DEPTH_BOUNDS_TEST_ENABLE_EXT); - } - if (device.SupportsEds1StencilTestEnable()) { - dynamic_states.push_back(VK_DYNAMIC_STATE_STENCIL_TEST_ENABLE_EXT); - } - if (device.SupportsEds1StencilOp()) { - dynamic_states.push_back(VK_DYNAMIC_STATE_STENCIL_OP_EXT); - } + static constexpr std::array extended{ + VK_DYNAMIC_STATE_CULL_MODE_EXT, + VK_DYNAMIC_STATE_FRONT_FACE_EXT, + VK_DYNAMIC_STATE_DEPTH_TEST_ENABLE_EXT, + VK_DYNAMIC_STATE_DEPTH_WRITE_ENABLE_EXT, + VK_DYNAMIC_STATE_DEPTH_COMPARE_OP_EXT, + VK_DYNAMIC_STATE_DEPTH_BOUNDS_TEST_ENABLE_EXT, + VK_DYNAMIC_STATE_STENCIL_TEST_ENABLE_EXT, + VK_DYNAMIC_STATE_STENCIL_OP_EXT, + }; + dynamic_states.insert(dynamic_states.end(), extended.begin(), extended.end()); - // VK_DYNAMIC_STATE_VERTEX_INPUT_BINDING_STRIDE_EXT - if (!key.state.dynamic_vertex_input && device.SupportsEds1VertexInputBindingStride()) { + // VK_DYNAMIC_STATE_VERTEX_INPUT_BINDING_STRIDE_EXT is part of EDS1 + // Only use it if VIDS is not active (VIDS replaces it with full vertex input control) + if (!key.state.dynamic_vertex_input) { dynamic_states.push_back(VK_DYNAMIC_STATE_VERTEX_INPUT_BINDING_STRIDE_EXT); } } - // VK_DYNAMIC_STATE_VERTEX_INPUT_EXT (VIDS) replaces VERTEX_INPUT_BINDING_STRIDE + // VK_DYNAMIC_STATE_VERTEX_INPUT_EXT (VIDS) - Independent from EDS + // Provides full dynamic vertex input control, replaces VERTEX_INPUT_BINDING_STRIDE if (key.state.dynamic_vertex_input) { dynamic_states.push_back(VK_DYNAMIC_STATE_VERTEX_INPUT_EXT); } - // EDS2 - Core (3 states) — include only supported subfeatures + // EDS2 - Core (3 states) if (key.state.extended_dynamic_state_2) { - if (device.SupportsEds2DepthBiasEnable()) { - dynamic_states.push_back(VK_DYNAMIC_STATE_DEPTH_BIAS_ENABLE_EXT); - } - if (device.SupportsEds2PrimitiveRestartEnable()) { - dynamic_states.push_back(VK_DYNAMIC_STATE_PRIMITIVE_RESTART_ENABLE_EXT); - } - if (device.SupportsEds2RasterizerDiscardEnable()) { - dynamic_states.push_back(VK_DYNAMIC_STATE_RASTERIZER_DISCARD_ENABLE_EXT); - } + static constexpr std::array extended2{ + VK_DYNAMIC_STATE_DEPTH_BIAS_ENABLE_EXT, + VK_DYNAMIC_STATE_PRIMITIVE_RESTART_ENABLE_EXT, + VK_DYNAMIC_STATE_RASTERIZER_DISCARD_ENABLE_EXT, + }; + dynamic_states.insert(dynamic_states.end(), extended2.begin(), extended2.end()); } // EDS2 - LogicOp (granular) - if (key.state.extended_dynamic_state_2_logic_op && device.SupportsDynamicState2LogicOp()) { + if (key.state.extended_dynamic_state_2_logic_op) { dynamic_states.push_back(VK_DYNAMIC_STATE_LOGIC_OP_EXT); } // EDS3 - Blending (composite: 3 states) if (key.state.extended_dynamic_state_3_blend) { - if (device.SupportsDynamicState3ColorBlendEnable()) { - dynamic_states.push_back(VK_DYNAMIC_STATE_COLOR_BLEND_ENABLE_EXT); - } - if (device.SupportsDynamicState3ColorBlendEquation()) { - dynamic_states.push_back(VK_DYNAMIC_STATE_COLOR_BLEND_EQUATION_EXT); - } - if (device.SupportsDynamicState3ColorWriteMask()) { - dynamic_states.push_back(VK_DYNAMIC_STATE_COLOR_WRITE_MASK_EXT); - } + static constexpr std::array extended3{ + VK_DYNAMIC_STATE_COLOR_BLEND_ENABLE_EXT, + VK_DYNAMIC_STATE_COLOR_BLEND_EQUATION_EXT, + VK_DYNAMIC_STATE_COLOR_WRITE_MASK_EXT, + }; + dynamic_states.insert(dynamic_states.end(), extended3.begin(), extended3.end()); } // EDS3 - Enables (composite: per-feature) diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp index bcfc4b8b4d..7b5ac7fac0 100644 --- a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp @@ -58,7 +58,7 @@ using VideoCommon::FileEnvironment; using VideoCommon::GenericEnvironment; using VideoCommon::GraphicsEnvironment; -constexpr u32 CACHE_VERSION = 17; +constexpr u32 CACHE_VERSION = 16; constexpr std::array VULKAN_CACHE_MAGIC_NUMBER{'y', 'u', 'z', 'u', 'v', 'k', 'c', 'h'}; template @@ -465,46 +465,18 @@ PipelineCache::PipelineCache(Tegra::MaxwellDeviceMemoryManager& device_memory_, dynamic_features = {}; - dynamic_features.has_core_dynamic_viewport_scissor = - device.SupportsCoreDynamicViewportScissor(); - dynamic_features.has_core_dynamic_depth_bias = - device.SupportsCoreDynamicDepthBias(); - dynamic_features.has_core_dynamic_depth_bounds = - device.SupportsCoreDynamicDepthBounds(); - dynamic_features.has_core_dynamic_line_width = - device.SupportsCoreDynamicLineWidth(); - dynamic_features.has_core_dynamic_stencil_masks = - device.SupportsCoreDynamicStencilMasks(); + // User granularity enforced in vulkan_device.cpp switch statement: + // Level 0: Core Dynamic States only + // Level 1: Core + EDS1 + // Level 2: Core + EDS1 + EDS2 (accumulative) + // Level 3: Core + EDS1 + EDS2 + EDS3 (accumulative) + // Here we only verify if extensions were successfully loaded by the device dynamic_features.has_extended_dynamic_state = device.IsExtExtendedDynamicStateSupported(); - dynamic_features.has_eds1_cull_mode = - device.SupportsEds1CullMode(); - dynamic_features.has_eds1_front_face = - device.SupportsEds1FrontFace(); - dynamic_features.has_eds1_depth_test_enable = - device.SupportsEds1DepthTestEnable(); - dynamic_features.has_eds1_depth_write_enable = - device.SupportsEds1DepthWriteEnable(); - dynamic_features.has_eds1_depth_compare_op = - device.SupportsEds1DepthCompareOp(); - dynamic_features.has_eds1_depth_bounds_test_enable = - device.SupportsEds1DepthBoundsTestEnable(); - dynamic_features.has_eds1_stencil_test_enable = - device.SupportsEds1StencilTestEnable(); - dynamic_features.has_eds1_stencil_op = - device.SupportsEds1StencilOp(); - dynamic_features.has_eds1_vertex_input_binding_stride = - device.SupportsEds1VertexInputBindingStride(); dynamic_features.has_extended_dynamic_state_2 = device.IsExtExtendedDynamicState2Supported(); - dynamic_features.has_eds2_depth_bias_enable = - device.SupportsEds2DepthBiasEnable(); - dynamic_features.has_eds2_primitive_restart_enable = - device.SupportsEds2PrimitiveRestartEnable(); - dynamic_features.has_eds2_rasterizer_discard_enable = - device.SupportsEds2RasterizerDiscardEnable(); dynamic_features.has_extended_dynamic_state_2_logic_op = device.IsExtExtendedDynamicState2ExtrasSupported(); dynamic_features.has_extended_dynamic_state_2_patch_control_points = false; @@ -519,21 +491,13 @@ PipelineCache::PipelineCache(Tegra::MaxwellDeviceMemoryManager& device_memory_, device.SupportsDynamicState3LogicOpEnable(); dynamic_features.has_dynamic_state3_line_stipple_enable = device.SupportsDynamicState3LineStippleEnable(); - dynamic_features.has_dynamic_state3_alpha_to_coverage_enable = - device.SupportsDynamicState3AlphaToCoverageEnable(); - dynamic_features.has_dynamic_state3_alpha_to_one_enable = - device.SupportsDynamicState3AlphaToOneEnable(); - dynamic_features.has_dynamic_state3_line_rasterization_mode = - device.SupportsDynamicState3LineRasterizationMode(); - dynamic_features.has_dynamic_state3_conservative_rasterization_mode = - device.SupportsDynamicState3ConservativeRasterizationMode(); + // VIDS: Independent toggle (not affected by dyna_state levels) dynamic_features.has_dynamic_vertex_input = device.IsExtVertexInputDynamicStateSupported() && Settings::values.vertex_input_dynamic_state.GetValue(); - dynamic_features.has_provoking_vertex = - device.IsExtProvokingVertexSupported(); + dynamic_features.has_provoking_vertex = device.IsExtProvokingVertexSupported(); dynamic_features.has_provoking_vertex_first_mode = device.SupportsProvokingVertexFirstMode(); dynamic_features.has_provoking_vertex_last_mode = @@ -640,20 +604,8 @@ void PipelineCache::LoadDiskResources(u64 title_id, std::stop_token stop_loading GraphicsPipelineCacheKey key; file.read(reinterpret_cast(&key), sizeof(key)); - if ((key.state.core_dynamic_viewport_scissor != 0) != - dynamic_features.has_core_dynamic_viewport_scissor || - (key.state.core_dynamic_depth_bias != 0) != - dynamic_features.has_core_dynamic_depth_bias || - (key.state.core_dynamic_depth_bounds != 0) != - dynamic_features.has_core_dynamic_depth_bounds || - (key.state.core_dynamic_line_width != 0) != - dynamic_features.has_core_dynamic_line_width || - (key.state.core_dynamic_stencil_masks != 0) != - dynamic_features.has_core_dynamic_stencil_masks || - (key.state.extended_dynamic_state != 0) != + if ((key.state.extended_dynamic_state != 0) != dynamic_features.has_extended_dynamic_state || - (key.state.dynamic_vertex_input != 0) != - dynamic_features.has_dynamic_vertex_input || (key.state.extended_dynamic_state_2 != 0) != dynamic_features.has_extended_dynamic_state_2 || (key.state.extended_dynamic_state_2_logic_op != 0) != @@ -661,7 +613,8 @@ void PipelineCache::LoadDiskResources(u64 title_id, std::stop_token stop_loading (key.state.extended_dynamic_state_3_blend != 0) != dynamic_features.has_extended_dynamic_state_3_blend || (key.state.extended_dynamic_state_3_enables != 0) != - dynamic_features.has_extended_dynamic_state_3_enables) { + dynamic_features.has_extended_dynamic_state_3_enables || + (key.state.dynamic_vertex_input != 0) != dynamic_features.has_dynamic_vertex_input) { return; } diff --git a/src/video_core/vulkan_common/vulkan_device.cpp b/src/video_core/vulkan_common/vulkan_device.cpp index ba088441d2..f48fe39e4e 100644 --- a/src/video_core/vulkan_common/vulkan_device.cpp +++ b/src/video_core/vulkan_common/vulkan_device.cpp @@ -648,9 +648,16 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR const auto dyna_state = Settings::values.dyna_state.GetValue(); + // Base dynamic states (VIEWPORT, SCISSOR, DEPTH_BIAS, etc.) are ALWAYS active in vk_graphics_pipeline.cpp + // This slider controls EXTENDED dynamic states with accumulative levels per Vulkan specs: + // Level 0 = Core Dynamic States only (Vulkan 1.0) + // Level 1 = Core + VK_EXT_extended_dynamic_state + // Level 2 = Core + VK_EXT_extended_dynamic_state + VK_EXT_extended_dynamic_state2 + // Level 3 = Core + VK_EXT_extended_dynamic_state + VK_EXT_extended_dynamic_state2 + VK_EXT_extended_dynamic_state3 + switch (dyna_state) { case Settings::ExtendedDynamicState::Disabled: - // Level 0: Enable DynamicState (Static) + Disable all extended dynamic state extensions + // Level 0: Disable all extended dynamic state extensions RemoveExtensionFeature(extensions.extended_dynamic_state, features.extended_dynamic_state, VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME); RemoveExtensionFeature(extensions.extended_dynamic_state2, features.extended_dynamic_state2, @@ -659,60 +666,9 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR VK_EXT_EXTENDED_DYNAMIC_STATE_3_EXTENSION_NAME); dynamic_state3_blending = false; dynamic_state3_enables = false; - - core_dynamic_viewport_scissor = (dld.vkCmdSetViewport != nullptr) && (dld.vkCmdSetScissor != nullptr); - core_dynamic_depth_bias = (dld.vkCmdSetDepthBias != nullptr) || (dld.vkCmdSetDepthBias2EXT != nullptr) || - (features.depth_bias_control.depthBiasControl != VK_FALSE); - - if (features.core.features.depthBounds && dld.vkCmdSetDepthBounds == nullptr) { - features.core.features.depthBounds = VK_FALSE; - core_dynamic_depth_bounds = false; - } else { - core_dynamic_depth_bounds = (dld.vkCmdSetDepthBounds != nullptr) && features.core.features.depthBounds; - } - - if (features.core.features.wideLines && dld.vkCmdSetLineWidth == nullptr) { - features.core.features.wideLines = VK_FALSE; - core_dynamic_line_width = false; - } else { - core_dynamic_line_width = (dld.vkCmdSetLineWidth != nullptr) && features.core.features.wideLines; - } - - core_dynamic_stencil_masks = (dld.vkCmdSetStencilCompareMask != nullptr) && - (dld.vkCmdSetStencilWriteMask != nullptr) && - (dld.vkCmdSetStencilReference != nullptr); break; case Settings::ExtendedDynamicState::EDS1: // Level 1: Enable EDS1, disable EDS2 and EDS3 - if (dyna_state_enabled && extensions.extended_dynamic_state) { - eds1_cull_mode = features.extended_dynamic_state.extendedDynamicState && (dld.vkCmdSetCullModeEXT != nullptr); - eds1_front_face = features.extended_dynamic_state.extendedDynamicState && (dld.vkCmdSetFrontFaceEXT != nullptr); - eds1_depth_test_enable = features.extended_dynamic_state.extendedDynamicState && (dld.vkCmdSetDepthTestEnableEXT != nullptr); - eds1_depth_write_enable = features.extended_dynamic_state.extendedDynamicState && (dld.vkCmdSetDepthWriteEnableEXT != nullptr); - eds1_depth_compare_op = features.extended_dynamic_state.extendedDynamicState && (dld.vkCmdSetDepthCompareOpEXT != nullptr); - eds1_depth_bounds_test_enable = features.extended_dynamic_state.extendedDynamicState && (dld.vkCmdSetDepthBoundsTestEnableEXT != nullptr); - eds1_stencil_test_enable = features.extended_dynamic_state.extendedDynamicState && (dld.vkCmdSetStencilTestEnableEXT != nullptr); - eds1_stencil_op = features.extended_dynamic_state.extendedDynamicState && (dld.vkCmdSetStencilOpEXT != nullptr); - - vertex_input_binding_stride = features.extended_dynamic_state.extendedDynamicState && (dld.vkCmdBindVertexBuffers2EXT != nullptr); - - const bool eds1_any = eds1_cull_mode || eds1_front_face || eds1_depth_test_enable || - eds1_depth_write_enable || eds1_depth_compare_op || eds1_depth_bounds_test_enable || - eds1_stencil_test_enable || eds1_stencil_op || vertex_input_binding_stride; - if (!eds1_any) { - extensions.extended_dynamic_state = false; - RemoveExtensionFeature(extensions.extended_dynamic_state, features.extended_dynamic_state, VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME); - // Clear flags - eds1_cull_mode = eds1_front_face = eds1_depth_test_enable = eds1_depth_write_enable = false; - eds1_depth_compare_op = eds1_depth_bounds_test_enable = eds1_stencil_test_enable = eds1_stencil_op = false; - vertex_input_binding_stride = false; - } - } else { - extensions.extended_dynamic_state = false; - eds1_cull_mode = eds1_front_face = eds1_depth_test_enable = eds1_depth_write_enable = false; - eds1_depth_compare_op = eds1_depth_bounds_test_enable = eds1_stencil_test_enable = eds1_stencil_op = false; - vertex_input_binding_stride = false; - } RemoveExtensionFeature(extensions.extended_dynamic_state2, features.extended_dynamic_state2, VK_EXT_EXTENDED_DYNAMIC_STATE_2_EXTENSION_NAME); RemoveExtensionFeature(extensions.extended_dynamic_state3, features.extended_dynamic_state3, @@ -722,32 +678,6 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR break; case Settings::ExtendedDynamicState::EDS2: // Level 2: Enable EDS1 + EDS2, disable EDS3 - { - bool eds1_any = (features.extended_dynamic_state.extendedDynamicState && - ((dld.vkCmdBindVertexBuffers2EXT != nullptr) || (dld.vkCmdSetCullModeEXT != nullptr))); - if (!eds1_any) { - extensions.extended_dynamic_state2 = false; - } - } - if (dyna_state_enabled && extensions.extended_dynamic_state2) { - eds2_depth_bias_enable = features.extended_dynamic_state2.extendedDynamicState2 && (dld.vkCmdSetDepthBiasEnableEXT != nullptr); - eds2_primitive_restart_enable = features.extended_dynamic_state2.extendedDynamicState2 && (dld.vkCmdSetPrimitiveRestartEnableEXT != nullptr); - eds2_rasterizer_discard_enable = features.extended_dynamic_state2.extendedDynamicState2 && (dld.vkCmdSetRasterizerDiscardEnableEXT != nullptr); - - if (features.extended_dynamic_state2.extendedDynamicState2LogicOp && (dld.vkCmdSetLogicOpEXT == nullptr)) { - features.extended_dynamic_state2.extendedDynamicState2LogicOp = VK_FALSE; - } - - const bool eds2_any = eds2_depth_bias_enable || eds2_primitive_restart_enable || eds2_rasterizer_discard_enable || - (features.extended_dynamic_state2.extendedDynamicState2LogicOp && (dld.vkCmdSetLogicOpEXT != nullptr)); - if (!eds2_any) { - extensions.extended_dynamic_state2 = false; - RemoveExtensionFeature(extensions.extended_dynamic_state2, features.extended_dynamic_state2, VK_EXT_EXTENDED_DYNAMIC_STATE_2_EXTENSION_NAME); - eds2_depth_bias_enable = eds2_primitive_restart_enable = eds2_rasterizer_discard_enable = false; - } - } else { - extensions.extended_dynamic_state2 = false; - } RemoveExtensionFeature(extensions.extended_dynamic_state3, features.extended_dynamic_state3, VK_EXT_EXTENDED_DYNAMIC_STATE_3_EXTENSION_NAME); dynamic_state3_blending = false; @@ -756,96 +686,13 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR case Settings::ExtendedDynamicState::EDS3: default: // Level 3: Enable all (EDS1 + EDS2 + EDS3) - { - bool eds1_any = (features.extended_dynamic_state.extendedDynamicState && - ((dld.vkCmdBindVertexBuffers2EXT != nullptr) || (dld.vkCmdSetCullModeEXT != nullptr))); - bool eds2_any = ((features.extended_dynamic_state2.extendedDynamicState2 && - ((dld.vkCmdSetDepthBiasEnableEXT != nullptr) || (dld.vkCmdSetPrimitiveRestartEnableEXT != nullptr))) || - (features.extended_dynamic_state2.extendedDynamicState2LogicOp && (dld.vkCmdSetLogicOpEXT != nullptr))); - if (!(eds1_any || eds2_any)) { - extensions.extended_dynamic_state3 = false; - } - } - if (dyna_state_enabled && extensions.extended_dynamic_state3) { - if (!(features.extended_dynamic_state3.extendedDynamicState3ColorBlendEnable && (dld.vkCmdSetColorBlendEnableEXT != nullptr))) { - features.extended_dynamic_state3.extendedDynamicState3ColorBlendEnable = VK_FALSE; - } - if (!(features.extended_dynamic_state3.extendedDynamicState3ColorBlendEquation && (dld.vkCmdSetColorBlendEquationEXT != nullptr))) { - features.extended_dynamic_state3.extendedDynamicState3ColorBlendEquation = VK_FALSE; - } - if (!(features.extended_dynamic_state3.extendedDynamicState3ColorWriteMask && (dld.vkCmdSetColorWriteMaskEXT != nullptr))) { - features.extended_dynamic_state3.extendedDynamicState3ColorWriteMask = VK_FALSE; - } - if (!(features.extended_dynamic_state3.extendedDynamicState3DepthClampEnable && (dld.vkCmdSetDepthClampEnableEXT != nullptr))) { - features.extended_dynamic_state3.extendedDynamicState3DepthClampEnable = VK_FALSE; - } - if (!(features.extended_dynamic_state3.extendedDynamicState3LogicOpEnable && (dld.vkCmdSetLogicOpEnableEXT != nullptr))) { - features.extended_dynamic_state3.extendedDynamicState3LogicOpEnable = VK_FALSE; - } - if (!(features.extended_dynamic_state3.extendedDynamicState3AlphaToCoverageEnable && (dld.vkCmdSetAlphaToCoverageEnableEXT != nullptr))) { - features.extended_dynamic_state3.extendedDynamicState3AlphaToCoverageEnable = VK_FALSE; - } - if (!(features.extended_dynamic_state3.extendedDynamicState3AlphaToOneEnable && (dld.vkCmdSetAlphaToOneEnableEXT != nullptr))) { - features.extended_dynamic_state3.extendedDynamicState3AlphaToOneEnable = VK_FALSE; - } - if (!(features.extended_dynamic_state3.extendedDynamicState3LineRasterizationMode && (dld.vkCmdSetLineRasterizationModeEXT != nullptr))) { - features.extended_dynamic_state3.extendedDynamicState3LineRasterizationMode = VK_FALSE; - } - if (!(features.extended_dynamic_state3.extendedDynamicState3ConservativeRasterizationMode && (dld.vkCmdSetConservativeRasterizationModeEXT != nullptr))) { - features.extended_dynamic_state3.extendedDynamicState3ConservativeRasterizationMode = VK_FALSE; - } - if (!(features.extended_dynamic_state3.extendedDynamicState3LineStippleEnable && (dld.vkCmdSetLineStippleEnableEXT != nullptr))) { - features.extended_dynamic_state3.extendedDynamicState3LineStippleEnable = VK_FALSE; - } - - bool blending = features.extended_dynamic_state3.extendedDynamicState3ColorBlendEnable || - features.extended_dynamic_state3.extendedDynamicState3ColorBlendEquation || - features.extended_dynamic_state3.extendedDynamicState3ColorWriteMask; - bool enables = features.extended_dynamic_state3.extendedDynamicState3DepthClampEnable || - features.extended_dynamic_state3.extendedDynamicState3LogicOpEnable || - features.extended_dynamic_state3.extendedDynamicState3LineStippleEnable || - features.extended_dynamic_state3.extendedDynamicState3AlphaToCoverageEnable || - features.extended_dynamic_state3.extendedDynamicState3AlphaToOneEnable || - features.extended_dynamic_state3.extendedDynamicState3LineRasterizationMode || - features.extended_dynamic_state3.extendedDynamicState3ConservativeRasterizationMode; - if (!blending && !enables) { - extensions.extended_dynamic_state3 = false; - RemoveExtensionFeature(extensions.extended_dynamic_state3, features.extended_dynamic_state3, VK_EXT_EXTENDED_DYNAMIC_STATE_3_EXTENSION_NAME); - } else { - dynamic_state3_blending = blending; - dynamic_state3_enables = enables; - } - } else { - extensions.extended_dynamic_state3 = false; - } break; } - // VK_EXT_vertex_input_dynamic_state and features.vertex_input_binding_stride + // VK_EXT_vertex_input_dynamic_state is independent from EDS + // It can be enabled even without extended_dynamic_state if (!Settings::values.vertex_input_dynamic_state.GetValue()) { RemoveExtensionFeature(extensions.vertex_input_dynamic_state, features.vertex_input_dynamic_state, VK_EXT_VERTEX_INPUT_DYNAMIC_STATE_EXTENSION_NAME); - } else { - bool vids_entrypoint = dld.vkCmdSetVertexInputEXT != nullptr; - bool vb2_entrypoint = dld.vkCmdBindVertexBuffers2EXT != nullptr; - - if (!vids_entrypoint) { - features.vertex_input_dynamic_state.vertexInputDynamicState = VK_FALSE; - } - - if (vids_entrypoint && features.vertex_input_dynamic_state.vertexInputDynamicState) { - vertex_input_binding_stride = false; - } else { - // Only enable binding stride if EDS1 and the VB2 entrypoint are available. - vertex_input_binding_stride = features.extended_dynamic_state.extendedDynamicState && vb2_entrypoint; - } - - if (!features.vertex_input_dynamic_state.vertexInputDynamicState) { - extensions.vertex_input_dynamic_state = false; - } - } - - if (!features.extended_dynamic_state.extendedDynamicState) { - extensions.extended_dynamic_state = false; } logical = vk::Device::Create(physical, queue_cis, ExtensionListForVulkan(loaded_extensions), first_next, dld); diff --git a/src/video_core/vulkan_common/vulkan_device.h b/src/video_core/vulkan_common/vulkan_device.h index d435126a2f..cf341726a7 100644 --- a/src/video_core/vulkan_common/vulkan_device.h +++ b/src/video_core/vulkan_common/vulkan_device.h @@ -569,112 +569,31 @@ public: return features.custom_border_color.customBorderColorWithoutFormat; } - /// Core dynamic states availability (Vulkan 1.0) - bool SupportsCoreDynamicViewportScissor() const { - return core_dynamic_viewport_scissor; - } - bool SupportsCoreDynamicDepthBias() const { - return core_dynamic_depth_bias; - } - bool SupportsCoreDynamicDepthBounds() const { - return core_dynamic_depth_bounds; - } - bool SupportsCoreDynamicLineWidth() const { - return core_dynamic_line_width; - } - bool SupportsCoreDynamicStencilMasks() const { - return core_dynamic_stencil_masks; - } - /// Returns true if the device supports VK_EXT_extended_dynamic_state. bool IsExtExtendedDynamicStateSupported() const { return extensions.extended_dynamic_state; } - /// VK_EXT_extended_dynamic_state core dynamic states availability - bool SupportsEds1CullMode() const { - return eds1_cull_mode; - } - bool SupportsEds1FrontFace() const { - return eds1_front_face; - } - bool SupportsEds1DepthTestEnable() const { - return eds1_depth_test_enable; - } - bool SupportsEds1DepthWriteEnable() const { - return eds1_depth_write_enable; - } - bool SupportsEds1DepthCompareOp() const { - return eds1_depth_compare_op; - } - bool SupportsEds1DepthBoundsTestEnable() const { - return eds1_depth_bounds_test_enable; - } - bool SupportsEds1StencilTestEnable() const { - return eds1_stencil_test_enable; - } - bool SupportsEds1StencilOp() const { - return eds1_stencil_op; - } - bool SupportsEds1VertexInputBindingStride() const { - return eds1_vertex_input_binding_stride; - } - /// Returns true if the device supports VK_EXT_extended_dynamic_state2. bool IsExtExtendedDynamicState2Supported() const { return extensions.extended_dynamic_state2; } - /// VK_EXT_extended_dynamic_state2 core dynamic states availability - bool SupportsEds2DepthBiasEnable() const { - return eds2_depth_bias_enable; - } - bool SupportsEds2PrimitiveRestartEnable() const { - return eds2_primitive_restart_enable; - } - bool SupportsEds2RasterizerDiscardEnable() const { - return eds2_rasterizer_discard_enable; - } - bool IsExtExtendedDynamicState2ExtrasSupported() const { return features.extended_dynamic_state2.extendedDynamicState2LogicOp; } - bool SupportsDynamicState2LogicOp() const { - return extensions.extended_dynamic_state2 && - features.extended_dynamic_state2.extendedDynamicState2LogicOp; - } - - /// Returns true if the device supports VK_EXT_extended_dynamic_state3. bool IsExtExtendedDynamicState3Supported() const { return extensions.extended_dynamic_state3; } - /// Returns true if the device supports VK_EXT_extended_dynamic_state3 color blend enable. - bool SupportsDynamicState3ColorBlendEnable() const { - return extensions.extended_dynamic_state3 && - features.extended_dynamic_state3.extendedDynamicState3ColorBlendEnable; - } - - /// Returns true if the device supports VK_EXT_extended_dynamic_state3 color blend equation. - bool SupportsDynamicState3ColorBlendEquation() const { - return extensions.extended_dynamic_state3 && - features.extended_dynamic_state3.extendedDynamicState3ColorBlendEquation; - } - - /// Returns true if the device supports VK_EXT_extended_dynamic_state3 color write mask. - bool SupportsDynamicState3ColorWriteMask() const { - return extensions.extended_dynamic_state3 && - features.extended_dynamic_state3.extendedDynamicState3ColorWriteMask; - } - /// Returns true if the device supports VK_EXT_4444_formats. bool IsExt4444FormatsSupported() const { return features.format_a4b4g4r4.formatA4B4G4R4; } - /// Returns true if the device supports VK_EXT_extended_dynamic_state3 blending. + /// Returns true if the device supports VK_EXT_extended_dynamic_state3. bool IsExtExtendedDynamicState3BlendingSupported() const { return dynamic_state3_blending; } @@ -1103,32 +1022,15 @@ private: bool supports_d24_depth{}; ///< Supports D24 depth buffers. bool cant_blit_msaa{}; ///< Does not support MSAA<->MSAA blitting. bool must_emulate_scaled_formats{}; ///< Requires scaled vertex format emulation - bool core_dynamic_viewport_scissor{}; ///< vkCmdSetViewport && vkCmdSetScissor - bool core_dynamic_depth_bias{}; ///< vkCmdSetDepthBias (or alternative) - bool core_dynamic_depth_bounds{}; ///< vkCmdSetDepthBounds - bool core_dynamic_line_width{}; ///< vkCmdSetLineWidth - bool core_dynamic_stencil_masks{}; ///< vkCmdSetStencilCompareMask/WriteMask/Reference - bool eds1_cull_mode{}; ///< Has EDS1 support for dynamic cull mode state. - bool eds1_front_face{}; ///< Has EDS1 support for dynamic front face state. - bool eds1_depth_test_enable{}; ///< Has EDS1 support for dynamic depth test enable state. - bool eds1_depth_write_enable{}; ///< Has EDS1 support for dynamic depth write enable state. - bool eds1_depth_compare_op{}; ///< Has EDS1 support for dynamic depth compare op state. - bool eds1_depth_bounds_test_enable{}; ///< Has EDS1 support for dynamic depth bounds test enable state. - bool eds1_stencil_test_enable{}; ///< Has EDS1 support for dynamic stencil test enable state. - bool eds1_stencil_op{}; ///< Has EDS1 support for dynamic stencil op state. - bool eds1_vertex_input_binding_stride{}; ///< Has EDS1 support for dynamic vertex input binding stride state. - bool eds2_depth_bias_enable{}; ///< Has EDS2 support for depth bias enable state. - bool eds2_primitive_restart_enable{}; ///< Has EDS2 support for primitive restart enable state. - bool eds2_rasterizer_discard_enable{}; ///< Has EDS2 support for rasterizer discard enable state. bool dynamic_state3_blending{}; ///< Has blending features of dynamic_state3. bool dynamic_state3_enables{}; ///< Has at least one enable feature of dynamic_state3. - bool dynamic_state3_depth_clamp_enable{}; ///< Has dynamic_state3 support for depth clamp enable state. - bool dynamic_state3_logic_op_enable{}; ///< Has dynamic_state3 support for logic op enable state. - bool dynamic_state3_line_raster_mode{}; ///< Has dynamic_state3 support for line raster mode state. - bool dynamic_state3_conservative_raster_mode{}; ///< Has dynamic_state3 support for conservative raster mode state. - bool dynamic_state3_line_stipple_enable{}; ///< Has dynamic_state3 support for line stipple enable state. - bool dynamic_state3_alpha_to_coverage{}; ///< Has dynamic_state3 support for alpha to coverage state. - bool dynamic_state3_alpha_to_one{}; ///< Has dynamic_state3 support for alpha to one state. + bool dynamic_state3_depth_clamp_enable{}; + bool dynamic_state3_logic_op_enable{}; + bool dynamic_state3_line_raster_mode{}; + bool dynamic_state3_conservative_raster_mode{}; + bool dynamic_state3_line_stipple_enable{}; + bool dynamic_state3_alpha_to_coverage{}; + bool dynamic_state3_alpha_to_one{}; bool supports_conditional_barriers{}; ///< Allows barriers in conditional control flow. size_t sampler_heap_budget{}; ///< Sampler budget for buggy drivers (0 = unlimited). u64 device_access_memory{}; ///< Total size of device local memory in bytes.