Compare commits

...

6 Commits

Author SHA1 Message Date
Bix
d4cfe0b44e [vk] Reordering disabled broken DynamicState and ExtendedDynamicState 2025-11-22 19:05:10 +01:00
Bix
f3a50cfcf7 [vk] compiler baka baka 2025-11-22 19:04:43 +01:00
Bix
6cfdecbc7b [vk] Handling padding (compiler tomto) 2025-11-22 19:04:04 +01:00
Bix
d06ef6b83b Adding missing headers 2025-11-22 19:03:42 +01:00
Bix
963365716e [vk] Simplifying DynamicState and ExtendedState with Bitfield 2025-11-22 19:03:05 +01:00
Bix
587c601dfe [vk] Refactor to DynamicState and ExtendedState 2025-11-22 19:02:27 +01:00
7 changed files with 306 additions and 236 deletions

View File

@@ -59,39 +59,40 @@ void FixedPipelineState::Refresh(Tegra::Engines::Maxwell3D& maxwell3d, DynamicFe
raw1 = 0;
raw1_eds3_extended = 0;
pad_align_u64 = 0;
// EDS1
extended_dynamic_state.Assign(features.has_extended_dynamic_state ? 1 : 0);
extended_dynamic_state.Assign(features.has_extended_dynamic_state);
// EDS2
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);
extended_dynamic_state_2_patch_control_points.Assign(features.has_extended_dynamic_state_2_patch_control_points ? 1 : 0);
extended_dynamic_state_2.Assign(features.has_extended_dynamic_state_2);
extended_dynamic_state_2_logic_op.Assign(features.has_extended_dynamic_state_2_logic_op);
extended_dynamic_state_2_patch_control_points.Assign(features.has_extended_dynamic_state_2_patch_control_points);
// EDS3 - Blending/Enables
extended_dynamic_state_3_blend.Assign(features.has_extended_dynamic_state_3_blend ? 1 : 0);
extended_dynamic_state_3_enables.Assign(features.has_extended_dynamic_state_3_enables ? 1 : 0);
extended_dynamic_state_3_blend.Assign(features.has_extended_dynamic_state_3_blend);
extended_dynamic_state_3_enables.Assign(features.has_extended_dynamic_state_3_enables);
// EDS3 - Granular features
extended_dynamic_state_3_depth_clamp.Assign(features.has_extended_dynamic_state_3_depth_clamp ? 1 : 0);
extended_dynamic_state_3_logic_op_enable.Assign(features.has_extended_dynamic_state_3_logic_op_enable ? 1 : 0);
extended_dynamic_state_3_tessellation_domain_origin.Assign(features.has_extended_dynamic_state_3_tessellation_domain_origin ? 1 : 0);
extended_dynamic_state_3_polygon_mode.Assign(features.has_extended_dynamic_state_3_polygon_mode ? 1 : 0);
extended_dynamic_state_3_rasterization_samples.Assign(features.has_extended_dynamic_state_3_rasterization_samples ? 1 : 0);
extended_dynamic_state_3_sample_mask.Assign(features.has_extended_dynamic_state_3_sample_mask ? 1 : 0);
extended_dynamic_state_3_alpha_to_coverage_enable.Assign(features.has_extended_dynamic_state_3_alpha_to_coverage_enable ? 1 : 0);
extended_dynamic_state_3_alpha_to_one_enable.Assign(features.has_extended_dynamic_state_3_alpha_to_one_enable ? 1 : 0);
extended_dynamic_state_3_depth_clip_enable.Assign(features.has_extended_dynamic_state_3_depth_clip_enable ? 1 : 0);
extended_dynamic_state_3_depth_clip_negative_one_to_one.Assign(features.has_extended_dynamic_state_3_depth_clip_negative_one_to_one ? 1 : 0);
extended_dynamic_state_3_line_rasterization_mode.Assign(features.has_extended_dynamic_state_3_line_rasterization_mode ? 1 : 0);
extended_dynamic_state_3_line_stipple_enable.Assign(features.has_extended_dynamic_state_3_line_stipple_enable ? 1 : 0);
extended_dynamic_state_3_provoking_vertex_mode.Assign(features.has_extended_dynamic_state_3_provoking_vertex_mode ? 1 : 0);
extended_dynamic_state_3_conservative_rasterization_mode.Assign(features.has_extended_dynamic_state_3_conservative_rasterization_mode ? 1 : 0);
extended_dynamic_state_3_sample_locations_enable.Assign(features.has_extended_dynamic_state_3_sample_locations_enable ? 1 : 0);
extended_dynamic_state_3_rasterization_stream.Assign(features.has_extended_dynamic_state_3_rasterization_stream ? 1 : 0);
extended_dynamic_state_3_depth_clamp.Assign(features.has_extended_dynamic_state_3_depth_clamp);
extended_dynamic_state_3_logic_op_enable.Assign(features.has_extended_dynamic_state_3_logic_op_enable);
extended_dynamic_state_3_tessellation_domain_origin.Assign(features.has_extended_dynamic_state_3_tessellation_domain_origin);
extended_dynamic_state_3_polygon_mode.Assign(features.has_extended_dynamic_state_3_polygon_mode);
extended_dynamic_state_3_rasterization_samples.Assign(features.has_extended_dynamic_state_3_rasterization_samples);
extended_dynamic_state_3_sample_mask.Assign(features.has_extended_dynamic_state_3_sample_mask);
extended_dynamic_state_3_alpha_to_coverage_enable.Assign(features.has_extended_dynamic_state_3_alpha_to_coverage_enable);
extended_dynamic_state_3_alpha_to_one_enable.Assign(features.has_extended_dynamic_state_3_alpha_to_one_enable);
extended_dynamic_state_3_depth_clip_enable.Assign(features.has_extended_dynamic_state_3_depth_clip_enable);
extended_dynamic_state_3_depth_clip_negative_one_to_one.Assign(features.has_extended_dynamic_state_3_depth_clip_negative_one_to_one);
extended_dynamic_state_3_line_rasterization_mode.Assign(features.has_extended_dynamic_state_3_line_rasterization_mode);
extended_dynamic_state_3_line_stipple_enable.Assign(features.has_extended_dynamic_state_3_line_stipple_enable);
extended_dynamic_state_3_provoking_vertex_mode.Assign(features.has_extended_dynamic_state_3_provoking_vertex_mode);
extended_dynamic_state_3_conservative_rasterization_mode.Assign(features.has_extended_dynamic_state_3_conservative_rasterization_mode);
extended_dynamic_state_3_sample_locations_enable.Assign(features.has_extended_dynamic_state_3_sample_locations_enable);
extended_dynamic_state_3_rasterization_stream.Assign(features.has_extended_dynamic_state_3_rasterization_stream);
// Vertex Input
dynamic_vertex_input.Assign(features.has_dynamic_vertex_input ? 1 : 0);
dynamic_vertex_input.Assign(features.has_dynamic_vertex_input);
xfb_enabled.Assign(regs.transform_feedback_enabled != 0);
ndc_minus_one_to_one.Assign(regs.depth_mode == Maxwell::DepthMode::MinusOneToOne ? 1 : 0);
@@ -187,7 +188,7 @@ void FixedPipelineState::Refresh(Tegra::Engines::Maxwell3D& maxwell3d, DynamicFe
return static_cast<u16>(array.stride.Value());
});
}
if (!extended_dynamic_state_2_extra) {
if (!extended_dynamic_state_2_logic_op) {
dynamic_state.Refresh2(regs, topology_, extended_dynamic_state_2);
}
if (!extended_dynamic_state_3_blend) {

View File

@@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
@@ -18,37 +21,45 @@ namespace Vulkan {
using Maxwell = Tegra::Engines::Maxwell3D::Regs;
struct DynamicFeatures {
// VK_EXT_extended_dynamic_state (EDS1) - All-or-nothing
bool has_extended_dynamic_state;
// VK_EXT_extended_dynamic_state2 (EDS2) - Granular features
bool has_extended_dynamic_state_2; // Core EDS2 (RasterizerDiscard, DepthBias, PrimitiveRestart)
bool has_extended_dynamic_state_2_logic_op; // LogicOp support
bool has_extended_dynamic_state_2_patch_control_points; // TessellationPatchControlPoints
// VK_EXT_extended_dynamic_state3 (EDS3) - Highly granular features
bool has_extended_dynamic_state_3_blend; // ColorBlendEnable + ColorBlendEquation + ColorWriteMask
bool has_extended_dynamic_state_3_enables; // DepthClampEnable + LogicOpEnable
bool has_extended_dynamic_state_3_depth_clamp; // DepthClampEnable only
bool has_extended_dynamic_state_3_logic_op_enable; // LogicOpEnable only
bool has_extended_dynamic_state_3_tessellation_domain_origin; // TessellationDomainOrigin
bool has_extended_dynamic_state_3_polygon_mode; // PolygonMode
bool has_extended_dynamic_state_3_rasterization_samples; // RasterizationSamples
bool has_extended_dynamic_state_3_sample_mask; // SampleMask
bool has_extended_dynamic_state_3_alpha_to_coverage_enable; // AlphaToCoverageEnable
bool has_extended_dynamic_state_3_alpha_to_one_enable; // AlphaToOneEnable
bool has_extended_dynamic_state_3_depth_clip_enable; // DepthClipEnable
bool has_extended_dynamic_state_3_depth_clip_negative_one_to_one; // DepthClipNegativeOneToOne
bool has_extended_dynamic_state_3_line_rasterization_mode; // LineRasterizationMode
bool has_extended_dynamic_state_3_line_stipple_enable; // LineStippleEnable
bool has_extended_dynamic_state_3_provoking_vertex_mode; // ProvokingVertexMode
bool has_extended_dynamic_state_3_conservative_rasterization_mode; // ConservativeRasterizationMode
bool has_extended_dynamic_state_3_sample_locations_enable; // SampleLocationsEnable
bool has_extended_dynamic_state_3_rasterization_stream; // RasterizationStream
// VK_EXT_vertex_input_dynamic_state
bool has_dynamic_vertex_input;
union {
u32 raw0;
// VK_EXT_extended_dynamic_state (EDS1) - Bit 0
BitField<0, 1, u32> has_extended_dynamic_state;
// VK_EXT_extended_dynamic_state2 (EDS2) - Bits 1-3
BitField<1, 1, u32> has_extended_dynamic_state_2; // Core EDS2
BitField<2, 1, u32> has_extended_dynamic_state_2_logic_op; // LogicOp
BitField<3, 1, u32> has_extended_dynamic_state_2_patch_control_points; // Tessellation
// VK_EXT_extended_dynamic_state3 (EDS3) - Bits 4-5
BitField<4, 1, u32> has_extended_dynamic_state_3_blend; // Blending composite
BitField<5, 1, u32> has_extended_dynamic_state_3_enables; // Enables composite
// VK_EXT_vertex_input_dynamic_state - Bit 6
BitField<6, 1, u32> has_dynamic_vertex_input;
// EDS3 Granular Features - Bits 7-15
BitField<7, 1, u32> has_extended_dynamic_state_3_depth_clamp;
BitField<8, 1, u32> has_extended_dynamic_state_3_logic_op_enable;
BitField<9, 1, u32> has_extended_dynamic_state_3_tessellation_domain_origin;
BitField<10, 1, u32> has_extended_dynamic_state_3_polygon_mode;
BitField<11, 1, u32> has_extended_dynamic_state_3_rasterization_samples;
BitField<12, 1, u32> has_extended_dynamic_state_3_sample_mask;
BitField<13, 1, u32> has_extended_dynamic_state_3_alpha_to_coverage_enable;
BitField<14, 1, u32> has_extended_dynamic_state_3_alpha_to_one_enable;
BitField<15, 1, u32> has_extended_dynamic_state_3_depth_clip_enable;
// EDS3 Additional Features - Bits 16-22
BitField<16, 1, u32> has_extended_dynamic_state_3_depth_clip_negative_one_to_one;
BitField<17, 1, u32> has_extended_dynamic_state_3_line_rasterization_mode;
BitField<18, 1, u32> has_extended_dynamic_state_3_line_stipple_enable;
BitField<19, 1, u32> has_extended_dynamic_state_3_provoking_vertex_mode;
BitField<20, 1, u32> has_extended_dynamic_state_3_conservative_rasterization_mode;
BitField<21, 1, u32> has_extended_dynamic_state_3_sample_locations_enable;
BitField<22, 1, u32> has_extended_dynamic_state_3_rasterization_stream;
};
};
static_assert(std::has_unique_object_representations_v<DynamicFeatures>);
struct FixedPipelineState {
static u32 PackComparisonOp(Maxwell::ComparisonOp op) noexcept;
@@ -272,12 +283,15 @@ struct FixedPipelineState {
BitField<16, 1, u32> alpha_to_one_enabled;
BitField<17, 3, Tegra::Engines::Maxwell3D::EngineHint> app_stage;
};
std::array<u8, Maxwell::NumRenderTargets> color_formats;
u32 alpha_test_ref;
u32 point_size;
std::array<u8, Maxwell::NumRenderTargets> color_formats;
std::array<u16, Maxwell::NumViewports> viewport_swizzles;
u32 pad_align_u64;
union {
u64 attribute_types; // Used with VK_EXT_vertex_input_dynamic_state
u64 enabled_divisors;

View File

@@ -900,7 +900,7 @@ void GraphicsPipeline::MakePipeline(VkRenderPass render_pass) {
}
// EDS2 - Logic Op (granular feature)
if (key.state.extended_dynamic_state_2_extra) {
if (key.state.extended_dynamic_state_2_logic_op) {
dynamic_states.push_back(VK_DYNAMIC_STATE_LOGIC_OP_EXT);
}

View File

@@ -342,14 +342,15 @@ PipelineCache::PipelineCache(Tegra::MaxwellDeviceMemoryManager& device_memory_,
.support_fp64_signed_zero_nan_preserve =
float_control.shaderSignedZeroInfNanPreserveFloat64 != VK_FALSE,
// Switch/Maxwell native float behavior (auto-configured on Qualcomm)
// Switch/Maxwell native float behavior - ONLY for Turnip Mesa (Stock Qualcomm broken)
// Stock Adreno drivers have broken float controls disabled in vulkan_device.cpp
.force_fp32_denorm_flush = driver_id == VK_DRIVER_ID_QUALCOMM_PROPRIETARY &&
device.IsKhrShaderFloatControlsSupported(),
device.IsKhrShaderFloatControlsSupported(), // false on Stock, true on Turnip
.force_fp32_denorm_preserve = false, // FTZ dominates
.force_fp32_rte_rounding = driver_id == VK_DRIVER_ID_QUALCOMM_PROPRIETARY &&
device.IsKhrShaderFloatControlsSupported(),
device.IsKhrShaderFloatControlsSupported(), // false on Stock, true on Turnip
.force_fp32_signed_zero_inf_nan = driver_id == VK_DRIVER_ID_QUALCOMM_PROPRIETARY &&
device.IsKhrShaderFloatControlsSupported(),
device.IsKhrShaderFloatControlsSupported(), // false on Stock, true on Turnip
.support_explicit_workgroup_layout = device.IsKhrWorkgroupMemoryExplicitLayoutSupported(),
.support_vote = device.IsSubgroupFeatureSupported(VK_SUBGROUP_FEATURE_VOTE_BIT),
@@ -381,7 +382,8 @@ PipelineCache::PipelineCache(Tegra::MaxwellDeviceMemoryManager& device_memory_,
.has_broken_spirv_position_input = driver_id == VK_DRIVER_ID_QUALCOMM_PROPRIETARY,
.has_broken_unsigned_image_offsets = false,
.has_broken_signed_operations = false,
.has_broken_fp16_float_controls = driver_id == VK_DRIVER_ID_NVIDIA_PROPRIETARY,
.has_broken_fp16_float_controls = driver_id == VK_DRIVER_ID_NVIDIA_PROPRIETARY ||
driver_id == VK_DRIVER_ID_QUALCOMM_PROPRIETARY,
.ignore_nan_fp_comparisons = false,
.has_broken_spirv_subgroup_mask_vector_extract_dynamic =
driver_id == VK_DRIVER_ID_QUALCOMM_PROPRIETARY,
@@ -424,39 +426,39 @@ PipelineCache::PipelineCache(Tegra::MaxwellDeviceMemoryManager& device_memory_,
LOG_INFO(Render_Vulkan, "DynamicState value is set to {}", (u32) dynamic_state);
dynamic_features = DynamicFeatures{
// EDS1 - All-or-nothing (enabled if driver supports AND setting > 0)
.has_extended_dynamic_state = device.IsExtExtendedDynamicStateSupported() && dynamic_state > 0,
// EDS2 - Core features (enabled if driver supports AND setting > 1)
.has_extended_dynamic_state_2 = device.IsExtExtendedDynamicState2Supported() && dynamic_state > 1,
.has_extended_dynamic_state_2_logic_op = device.IsExtExtendedDynamicState2LogicOpSupported() && dynamic_state > 1,
.has_extended_dynamic_state_2_patch_control_points = device.IsExtExtendedDynamicState2PatchControlPointsSupported() && dynamic_state > 1,
// EDS3 - Granular features (enabled if driver supports AND setting > 2)
.has_extended_dynamic_state_3_blend = device.IsExtExtendedDynamicState3BlendingSupported() && dynamic_state > 2,
.has_extended_dynamic_state_3_enables = device.IsExtExtendedDynamicState3EnablesSupported() && dynamic_state > 2,
.has_extended_dynamic_state_3_depth_clamp = device.IsExtExtendedDynamicState3DepthClampEnableSupported() && dynamic_state > 2,
.has_extended_dynamic_state_3_logic_op_enable = device.IsExtExtendedDynamicState3LogicOpEnableSupported() && dynamic_state > 2,
.has_extended_dynamic_state_3_tessellation_domain_origin = device.IsExtExtendedDynamicState3TessellationDomainOriginSupported() && dynamic_state > 2,
.has_extended_dynamic_state_3_polygon_mode = device.IsExtExtendedDynamicState3PolygonModeSupported() && dynamic_state > 2,
.has_extended_dynamic_state_3_rasterization_samples = device.IsExtExtendedDynamicState3RasterizationSamplesSupported() && dynamic_state > 2,
.has_extended_dynamic_state_3_sample_mask = device.IsExtExtendedDynamicState3SampleMaskSupported() && dynamic_state > 2,
.has_extended_dynamic_state_3_alpha_to_coverage_enable = device.IsExtExtendedDynamicState3AlphaToCoverageEnableSupported() && dynamic_state > 2,
.has_extended_dynamic_state_3_alpha_to_one_enable = device.IsExtExtendedDynamicState3AlphaToOneEnableSupported() && dynamic_state > 2,
.has_extended_dynamic_state_3_depth_clip_enable = device.IsExtExtendedDynamicState3DepthClipEnableSupported() && dynamic_state > 2,
.has_extended_dynamic_state_3_depth_clip_negative_one_to_one = device.IsExtExtendedDynamicState3DepthClipNegativeOneToOneSupported() && dynamic_state > 2,
.has_extended_dynamic_state_3_line_rasterization_mode = device.IsExtExtendedDynamicState3LineRasterizationModeSupported() && dynamic_state > 2,
.has_extended_dynamic_state_3_line_stipple_enable = device.IsExtExtendedDynamicState3LineStippleEnableSupported() && dynamic_state > 2,
.has_extended_dynamic_state_3_provoking_vertex_mode = device.IsExtExtendedDynamicState3ProvokingVertexModeSupported() && dynamic_state > 2,
.has_extended_dynamic_state_3_conservative_rasterization_mode = device.IsExtExtendedDynamicState3ConservativeRasterizationModeSupported() && dynamic_state > 2,
.has_extended_dynamic_state_3_sample_locations_enable = device.IsExtExtendedDynamicState3SampleLocationsEnableSupported() && dynamic_state > 2,
.has_extended_dynamic_state_3_rasterization_stream = device.IsExtExtendedDynamicState3RasterizationStreamSupported() && dynamic_state > 2,
// Vertex input dynamic state
.has_dynamic_vertex_input = device.IsExtVertexInputDynamicStateSupported() &&
Settings::values.vertex_input_dynamic_state.GetValue(),
};
dynamic_features.raw0 = 0;
// EDS1 - All-or-nothing (enabled if driver supports AND setting > 0)
dynamic_features.has_extended_dynamic_state.Assign(device.IsExtExtendedDynamicStateSupported() && dynamic_state > 0);
// EDS2 - Core features (enabled if driver supports AND setting > 1)
dynamic_features.has_extended_dynamic_state_2.Assign(device.IsExtExtendedDynamicState2Supported() && dynamic_state > 1);
dynamic_features.has_extended_dynamic_state_2_logic_op.Assign(device.IsExtExtendedDynamicState2LogicOpSupported() && dynamic_state > 1);
dynamic_features.has_extended_dynamic_state_2_patch_control_points.Assign(device.IsExtExtendedDynamicState2PatchControlPointsSupported() && dynamic_state > 1);
// EDS3 - Granular features (enabled if driver supports AND setting > 2)
dynamic_features.has_extended_dynamic_state_3_blend.Assign(device.IsExtExtendedDynamicState3BlendingSupported() && dynamic_state > 2);
dynamic_features.has_extended_dynamic_state_3_enables.Assign(device.IsExtExtendedDynamicState3EnablesSupported() && dynamic_state > 2);
dynamic_features.has_extended_dynamic_state_3_depth_clamp.Assign(device.IsExtExtendedDynamicState3DepthClampEnableSupported() && dynamic_state > 2);
dynamic_features.has_extended_dynamic_state_3_logic_op_enable.Assign(device.IsExtExtendedDynamicState3LogicOpEnableSupported() && dynamic_state > 2);
dynamic_features.has_extended_dynamic_state_3_tessellation_domain_origin.Assign(device.IsExtExtendedDynamicState3TessellationDomainOriginSupported() && dynamic_state > 2);
dynamic_features.has_extended_dynamic_state_3_polygon_mode.Assign(device.IsExtExtendedDynamicState3PolygonModeSupported() && dynamic_state > 2);
dynamic_features.has_extended_dynamic_state_3_rasterization_samples.Assign(device.IsExtExtendedDynamicState3RasterizationSamplesSupported() && dynamic_state > 2);
dynamic_features.has_extended_dynamic_state_3_sample_mask.Assign(device.IsExtExtendedDynamicState3SampleMaskSupported() && dynamic_state > 2);
dynamic_features.has_extended_dynamic_state_3_alpha_to_coverage_enable.Assign(device.IsExtExtendedDynamicState3AlphaToCoverageEnableSupported() && dynamic_state > 2);
dynamic_features.has_extended_dynamic_state_3_alpha_to_one_enable.Assign(device.IsExtExtendedDynamicState3AlphaToOneEnableSupported() && dynamic_state > 2);
dynamic_features.has_extended_dynamic_state_3_depth_clip_enable.Assign(device.IsExtExtendedDynamicState3DepthClipEnableSupported() && dynamic_state > 2);
dynamic_features.has_extended_dynamic_state_3_depth_clip_negative_one_to_one.Assign(device.IsExtExtendedDynamicState3DepthClipNegativeOneToOneSupported() && dynamic_state > 2);
dynamic_features.has_extended_dynamic_state_3_line_rasterization_mode.Assign(device.IsExtExtendedDynamicState3LineRasterizationModeSupported() && dynamic_state > 2);
dynamic_features.has_extended_dynamic_state_3_line_stipple_enable.Assign(device.IsExtExtendedDynamicState3LineStippleEnableSupported() && dynamic_state > 2);
dynamic_features.has_extended_dynamic_state_3_provoking_vertex_mode.Assign(device.IsExtExtendedDynamicState3ProvokingVertexModeSupported() && dynamic_state > 2);
dynamic_features.has_extended_dynamic_state_3_conservative_rasterization_mode.Assign(device.IsExtExtendedDynamicState3ConservativeRasterizationModeSupported() && dynamic_state > 2);
dynamic_features.has_extended_dynamic_state_3_sample_locations_enable.Assign(device.IsExtExtendedDynamicState3SampleLocationsEnableSupported() && dynamic_state > 2);
dynamic_features.has_extended_dynamic_state_3_rasterization_stream.Assign(device.IsExtExtendedDynamicState3RasterizationStreamSupported() && dynamic_state > 2);
// Vertex input dynamic state (independent toggle)
dynamic_features.has_dynamic_vertex_input.Assign(device.IsExtVertexInputDynamicStateSupported() &&
Settings::values.vertex_input_dynamic_state.GetValue());
}
PipelineCache::~PipelineCache() {

View File

@@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later

View File

@@ -518,19 +518,20 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR
// Driver-specific handling for VK_EXT_custom_border_color
// On some Qualcomm/Turnip/ARM drivers the extension may be partially implemented.
// Enable it if ANY useful feature bit is reported; otherwise, let the removal pass drop it.
// Disable completely if no feature bits are reported to avoid crashes/undefined behavior.
if (is_qualcomm || is_turnip || is_arm) {
const bool has_any_custom_border_color =
features.custom_border_color.customBorderColors ||
features.custom_border_color.customBorderColorWithoutFormat;
if (!has_any_custom_border_color) {
LOG_WARNING(Render_Vulkan,
"Disabling VK_EXT_custom_border_color on '{}' — no usable custom border color features reported",
"Disabling VK_EXT_custom_border_color on '{}' — no usable features reported",
properties.driver.driverName);
// Do not clear here; final removal happens in RemoveUnsuitableExtensions based on bits.
RemoveExtensionFeature(extensions.custom_border_color, features.custom_border_color,
VK_EXT_CUSTOM_BORDER_COLOR_EXTENSION_NAME);
} else {
LOG_INFO(Render_Vulkan,
"Partial VK_EXT_custom_border_color support detected on '{}' — enabling available features",
"VK_EXT_custom_border_color enabled on '{}' (partial support detected)",
properties.driver.driverName);
}
}
@@ -542,32 +543,32 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR
// Log Qualcomm-specific optimizations
if (extensions.render_pass_store_ops) {
LOG_INFO(Render_Vulkan, "VK_QCOM_render_pass_store_ops: ENABLED");
LOG_INFO(Render_Vulkan, "VK_QCOM_render_pass_store_ops: Enabled");
}
if (extensions.tile_properties) {
LOG_INFO(Render_Vulkan, "VK_QCOM_tile_properties: ENABLED (tile size queries available)");
LOG_INFO(Render_Vulkan, "VK_QCOM_tile_properties: Enabled");
}
if (extensions.render_pass_shader_resolve) {
LOG_INFO(Render_Vulkan, "VK_QCOM_render_pass_shader_resolve: ENABLED");
LOG_INFO(Render_Vulkan, "VK_QCOM_render_pass_shader_resolve: Enabled");
}
if (extensions.render_pass_transform) {
LOG_INFO(Render_Vulkan, "VK_QCOM_render_pass_transform: Enabled");
}
if (extensions.rotated_copy_commands) {
LOG_INFO(Render_Vulkan, "VK_QCOM_rotated_copy_commands: Enabled");
}
if (extensions.image_processing) {
LOG_INFO(Render_Vulkan, "VK_QCOM_image_processing: Enabled");
}
// Shader Float Controls for Qualcomm Adreno
LOG_INFO(Render_Vulkan, "Enabling Shader Float Controls with Switch/Maxwell native configuration");
// Log driver capabilities
const auto& fc = properties.float_controls;
LOG_INFO(Render_Vulkan, "Driver Capabilities:");
LOG_INFO(Render_Vulkan, " - Denorm Flush FP32: {}", fc.shaderDenormFlushToZeroFloat32 ? "YES" : "NO");
LOG_INFO(Render_Vulkan, " - RTE Rounding FP32: {}", fc.shaderRoundingModeRTEFloat32 ? "YES" : "NO");
LOG_INFO(Render_Vulkan, " - Signed Zero/Inf/Nan FP32: {}", fc.shaderSignedZeroInfNanPreserveFloat32 ? "YES" : "NO");
// Apply Switch/Maxwell native float behavior
LOG_INFO(Render_Vulkan, "Applying Switch/Maxwell native float behavior:");
LOG_INFO(Render_Vulkan, " - FTZ (Flush-To-Zero): ON - Matches Switch hardware behavior");
LOG_INFO(Render_Vulkan, " - RTE (Round-To-Even): ON - IEEE 754 standard precision");
LOG_INFO(Render_Vulkan, " - SignedZero/Inf/NaN: ON - Mathematical correctness");
LOG_INFO(Render_Vulkan, "VK_KHR_shader_float_controls: ENABLED (auto-configured)");
// Shader Float Controls: Completely broken on Stock Qualcomm
// The extension causes rendering issues regardless of FP16/FP32 mode
// Turnip Mesa: Works correctly, keep enabled
if (!is_turnip) {
LOG_WARNING(Render_Vulkan, "Disabling Shader Float Controls for Stock Qualcomm (broken implementation)");
RemoveExtensionFeature(extensions.shader_float_controls, features.shader_float_controls,
VK_KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME);
}
// Int64 atomics - genuinely broken, always disable
RemoveExtensionFeature(extensions.shader_atomic_int64, features.shader_atomic_int64,
@@ -616,83 +617,7 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR
cant_blit_msaa = true;
}
}
if (extensions.extended_dynamic_state && is_radv) {
// Mask driver version variant
const u32 version = (properties.properties.driverVersion << 3) >> 3;
if (version < VK_MAKE_API_VERSION(0, 21, 2, 0)) {
LOG_WARNING(Render_Vulkan,
"RADV versions older than 21.2 have broken VK_EXT_extended_dynamic_state");
//RemoveExtensionFeature(extensions.extended_dynamic_state,
//features.extended_dynamic_state,
//VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME);
}
}
if (extensions.extended_dynamic_state2 && is_radv) {
const u32 version = (properties.properties.driverVersion << 3) >> 3;
if (version < VK_MAKE_API_VERSION(0, 22, 3, 1)) {
LOG_WARNING(
Render_Vulkan,
"RADV versions older than 22.3.1 have broken VK_EXT_extended_dynamic_state2");
// RemoveExtensionFeature(extensions.extended_dynamic_state2,
// features.extended_dynamic_state2,
// VK_EXT_EXTENDED_DYNAMIC_STATE_2_EXTENSION_NAME);
}
}
if (extensions.extended_dynamic_state2 && is_qualcomm) {
const u32 version = (properties.properties.driverVersion << 3) >> 3;
if (version >= VK_MAKE_API_VERSION(0, 0, 676, 0) &&
version < VK_MAKE_API_VERSION(0, 0, 680, 0)) {
// Qualcomm Adreno 7xx drivers do not properly support extended_dynamic_state2.
LOG_WARNING(Render_Vulkan,
"Qualcomm Adreno 7xx drivers have broken VK_EXT_extended_dynamic_state2");
//RemoveExtensionFeature(extensions.extended_dynamic_state2,
//features.extended_dynamic_state2,
//VK_EXT_EXTENDED_DYNAMIC_STATE_2_EXTENSION_NAME);
}
}
if (extensions.extended_dynamic_state3 && is_radv) {
LOG_WARNING(Render_Vulkan, "RADV has broken extendedDynamicState3ColorBlendEquation");
features.extended_dynamic_state3.extendedDynamicState3ColorBlendEnable = true;
features.extended_dynamic_state3.extendedDynamicState3ColorBlendEquation = true;
dynamic_state3_blending = true;
const u32 version = (properties.properties.driverVersion << 3) >> 3;
if (version < VK_MAKE_API_VERSION(0, 23, 1, 0)) {
LOG_WARNING(Render_Vulkan,
"RADV versions older than 23.1.0 have broken depth clamp dynamic state");
features.extended_dynamic_state3.extendedDynamicState3DepthClampEnable = true;
dynamic_state3_enables = true;
}
}
if (extensions.extended_dynamic_state3 && (is_amd_driver || driver_id == VK_DRIVER_ID_SAMSUNG_PROPRIETARY)) {
// AMD and Samsung drivers have broken extendedDynamicState3ColorBlendEquation
LOG_WARNING(Render_Vulkan,
"AMD and Samsung drivers have broken extendedDynamicState3ColorBlendEquation");
features.extended_dynamic_state3.extendedDynamicState3ColorBlendEnable = true;
features.extended_dynamic_state3.extendedDynamicState3ColorBlendEquation = true;
dynamic_state3_blending = true;
}
if (extensions.vertex_input_dynamic_state && is_radv) {
// TODO(ameerj): Blacklist only offending driver versions
// TODO(ameerj): Confirm if RDNA1 is affected
const bool is_rdna2 =
supported_extensions.contains(VK_KHR_FRAGMENT_SHADING_RATE_EXTENSION_NAME);
if (is_rdna2) {
LOG_WARNING(Render_Vulkan,
"RADV has broken VK_EXT_vertex_input_dynamic_state on RDNA2 hardware");
// RemoveExtensionFeature(extensions.vertex_input_dynamic_state,
// features.vertex_input_dynamic_state,
// VK_EXT_VERTEX_INPUT_DYNAMIC_STATE_EXTENSION_NAME);
}
}
if (extensions.vertex_input_dynamic_state && is_qualcomm) {
// Qualcomm drivers do not properly support vertex_input_dynamic_state.
LOG_WARNING(Render_Vulkan,
"Qualcomm drivers have broken VK_EXT_vertex_input_dynamic_state");
//RemoveExtensionFeature(extensions.vertex_input_dynamic_state,
// features.vertex_input_dynamic_state,
// VK_EXT_VERTEX_INPUT_DYNAMIC_STATE_EXTENSION_NAME);
}
// Dynamic state blacklists moved to GetSuitability() for proper ordering
sets_per_pool = 64;
if (is_amd_driver) {
@@ -721,15 +646,7 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR
}
}
if (extensions.vertex_input_dynamic_state && is_intel_windows) {
const u32 version = (properties.properties.driverVersion << 3) >> 3;
if (version < VK_MAKE_API_VERSION(27, 20, 100, 0)) {
LOG_WARNING(Render_Vulkan, "Intel has broken VK_EXT_vertex_input_dynamic_state");
//RemoveExtensionFeature(extensions.vertex_input_dynamic_state,
//features.vertex_input_dynamic_state,
//VK_EXT_VERTEX_INPUT_DYNAMIC_STATE_EXTENSION_NAME);
}
}
// VertexInputDynamicState blacklist moved to GetSuitability() for proper ordering
if (features.shader_float16_int8.shaderFloat16 && is_intel_windows) {
// Intel's compiler crashes when using fp16 on Astral Chain, disable it for the time being.
LOG_WARNING(Render_Vulkan, "Intel has broken float16 math");
@@ -820,35 +737,7 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR
VK_EXT_EXTENDED_DYNAMIC_STATE_2_EXTENSION_NAME);
}
if (!extensions.extended_dynamic_state2 && extensions.extended_dynamic_state3) {
LOG_INFO(Render_Vulkan,
"Removing extendedDynamicState3 due to missing extendedDynamicState2");
RemoveExtensionFeature(extensions.extended_dynamic_state3, features.extended_dynamic_state3,
VK_EXT_EXTENDED_DYNAMIC_STATE_3_EXTENSION_NAME);
dynamic_state3_blending = true;
dynamic_state3_enables = true;
}
// Mesa Intel drivers on UHD 620 have broken EDS causing extreme flickering - unknown if it affects other iGPUs
// ALSO affects ALL versions of UHD drivers on Windows 10+, seems to cause even worse issues like straight up crashing
// So... Yeah, UHD drivers fucking suck -- maybe one day we can work past this, maybe; some driver hacking?
// And then we can rest in peace by doing `< VK_MAKE_API_VERSION(26, 0, 0)` for our beloved mesa drivers... one day
if ((is_mvk || (is_integrated && is_intel_anv) || (is_integrated && is_intel_windows)) && Settings::values.dyna_state.GetValue() != 0) {
LOG_WARNING(Render_Vulkan, "Driver has broken dynamic state, forcing to 0 to prevent graphical issues");
Settings::values.dyna_state.SetValue(0);
}
if (Settings::values.dyna_state.GetValue() == 0) {
RemoveExtensionFeature(extensions.custom_border_color, features.custom_border_color, VK_EXT_CUSTOM_BORDER_COLOR_EXTENSION_NAME);
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, VK_EXT_EXTENDED_DYNAMIC_STATE_2_EXTENSION_NAME);
RemoveExtensionFeature(extensions.extended_dynamic_state3, features.extended_dynamic_state3, VK_EXT_EXTENDED_DYNAMIC_STATE_3_EXTENSION_NAME);
dynamic_state3_blending = false;
dynamic_state3_enables = false;
LOG_INFO(Render_Vulkan, "Extended dynamic state is fully disabled");
// Note: vertex_input_dynamic_state has its own independent toggle and is NOT affected by dyna_state = 0
}
// Intel iGPU/MoltenVK blacklist moved to GetSuitability() for proper ordering
#ifdef ANDROID
// Stock Qualcomm and ARM Mali drivers don't report VK_FORMAT_*_SSCALED/USCALED formats
@@ -903,7 +792,7 @@ Device::~Device() {
VkFormat Device::GetSupportedFormat(VkFormat wanted_format, VkFormatFeatureFlags wanted_usage,
FormatType format_type) const {
if (IsFormatSupported(wanted_format, wanted_usage, format_type)) {
// CRITICAL FIX: Even if format is "supported", check for STORAGE + HDR + no MSAA support
// Critical: Even if format is "supported", check for STORAGE + HDR + no MSAA support
// Driver may report STORAGE_IMAGE_BIT but shaderStorageImageMultisample=false means
// it will fail at runtime when used with MSAA (CopyImageMSAA silently fails)
const bool requests_storage = (wanted_usage & VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT) != 0;
@@ -1330,6 +1219,148 @@ bool Device::GetSuitability(bool requires_swapchain) {
}
}
// CRITICAL: Apply driver-specific feature workarounds BEFORE validation
// These blacklists disable broken features on specific drivers to prevent
// rendering issues and crashes.
// MUST execute before RemoveUnsuitableExtensions() calculates feature flags.
const VkDriverId driver_id = properties.driver.driverID;
const bool is_radv = driver_id == VK_DRIVER_ID_MESA_RADV;
const bool is_amd_driver =
driver_id == VK_DRIVER_ID_AMD_PROPRIETARY || driver_id == VK_DRIVER_ID_AMD_OPEN_SOURCE;
const bool is_intel_windows = driver_id == VK_DRIVER_ID_INTEL_PROPRIETARY_WINDOWS;
const bool is_intel_anv = driver_id == VK_DRIVER_ID_INTEL_OPEN_SOURCE_MESA;
const bool is_qualcomm = driver_id == VK_DRIVER_ID_QUALCOMM_PROPRIETARY;
const bool is_mvk = driver_id == VK_DRIVER_ID_MOLTENVK;
const bool is_integrated = properties.properties.deviceType == VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU;
// VK_DYNAMIC_STATE
// Mesa Intel drivers on UHD 620 have broken EDS causing extreme flickering - unknown if it affects other iGPUs
// ALSO affects ALL versions of UHD drivers on Windows 10+, seems to cause even worse issues like straight up crashing
// So... Yeah, UHD drivers fucking suck -- maybe one day we can work past this, maybe; some driver hacking?
// And then we can rest in peace by doing `< VK_MAKE_API_VERSION(26, 0, 0)` for our beloved mesa drivers... one day
// Disable dynamic state on affected drivers
if ((is_mvk || (is_integrated && is_intel_anv) || (is_integrated && is_intel_windows)) &&
Settings::values.dyna_state.GetValue() != 0) {
LOG_WARNING(Render_Vulkan,
"Intel iGPU/MoltenVK: Forcing dyna_state=0 due to broken dynamic state implementation");
Settings::values.dyna_state.SetValue(0);
}
// VK_EXT_extended_dynamic_state
// RADV < 21.2.0: Broken ExtendedDynamicState implementation
// Disable entire extension on old drivers
if (extensions.extended_dynamic_state && is_radv) {
const u32 version = (properties.properties.driverVersion << 3) >> 3;
if (version < VK_MAKE_API_VERSION(0, 21, 2, 0)) {
LOG_WARNING(Render_Vulkan,
"RADV < 21.2.0: Disabling broken VK_EXT_extended_dynamic_state");
features.extended_dynamic_state.extendedDynamicState = false;
}
}
// VK_EXT_extended_dynamic_state2
// RADV < 22.3.1: Broken ExtendedDynamicState2 implementation
// Disable entire extension on old drivers
if (extensions.extended_dynamic_state2 && is_radv) {
const u32 version = (properties.properties.driverVersion << 3) >> 3;
if (version < VK_MAKE_API_VERSION(0, 22, 3, 1)) {
LOG_WARNING(Render_Vulkan,
"RADV < 22.3.1: Disabling broken VK_EXT_extended_dynamic_state2");
features.extended_dynamic_state2.extendedDynamicState2 = false;
}
}
// Qualcomm Adreno 7xx (drivers 676.0 - 679.x): Broken ExtendedDynamicState2
// Disable ExtendedDynamicState2 on affected driver versions
if (extensions.extended_dynamic_state2 && is_qualcomm) {
const u32 version = (properties.properties.driverVersion << 3) >> 3;
if (version >= VK_MAKE_API_VERSION(0, 0, 676, 0) &&
version < VK_MAKE_API_VERSION(0, 0, 680, 0)) {
LOG_WARNING(Render_Vulkan,
"Qualcomm Adreno 7xx (676-679): Disabling broken VK_EXT_extended_dynamic_state2");
features.extended_dynamic_state2.extendedDynamicState2 = false;
}
}
// VK_EXT_extended_dynamic_state3
// AMD/Samsung: Broken extendedDynamicState3ColorBlendEquation
// Disable blend equation dynamic state, force static pipeline state
if (extensions.extended_dynamic_state3 &&
(is_amd_driver || driver_id == VK_DRIVER_ID_SAMSUNG_PROPRIETARY)) {
LOG_WARNING(Render_Vulkan,
"AMD/Samsung: Disabling broken extendedDynamicState3ColorBlendEquation");
features.extended_dynamic_state3.extendedDynamicState3ColorBlendEnable = false;
features.extended_dynamic_state3.extendedDynamicState3ColorBlendEquation = false;
}
// RADV: Broken extendedDynamicState3ColorBlendEquation
// Disable problematic features based on driver version < 23.1.0
if (extensions.extended_dynamic_state3 && is_radv) {
LOG_WARNING(Render_Vulkan, "RADV: Disabling broken extendedDynamicState3ColorBlendEquation");
features.extended_dynamic_state3.extendedDynamicState3ColorBlendEnable = false;
features.extended_dynamic_state3.extendedDynamicState3ColorBlendEquation = false;
const u32 version = (properties.properties.driverVersion << 3) >> 3;
if (version < VK_MAKE_API_VERSION(0, 23, 1, 0)) {
LOG_WARNING(Render_Vulkan,
"RADV < 23.1.0: Disabling broken depth clamp dynamic state");
features.extended_dynamic_state3.extendedDynamicState3DepthClampEnable = false;
}
}
// VK_EXT_vertex_input_dynamic_state
// RADV + RDNA2: Broken VertexInputDynamicState on RDNA2 hardware
// Disable VertexInputDynamicState on RDNA2
if (extensions.vertex_input_dynamic_state && is_radv) {
const bool is_rdna2 =
supported_extensions.contains(VK_KHR_FRAGMENT_SHADING_RATE_EXTENSION_NAME);
if (is_rdna2) {
LOG_WARNING(Render_Vulkan,
"RADV + RDNA2: Disabling broken VK_EXT_vertex_input_dynamic_state");
features.vertex_input_dynamic_state.vertexInputDynamicState = false;
}
}
// Qualcomm: Broken VertexInputDynamicState implementation
// Disable VertexInputDynamicState on all Qualcomm drivers
if (extensions.vertex_input_dynamic_state && is_qualcomm) {
LOG_WARNING(Render_Vulkan,
"Qualcomm: Disabling broken VK_EXT_vertex_input_dynamic_state");
features.vertex_input_dynamic_state.vertexInputDynamicState = false;
}
// Intel Windows < 27.20.100.0: Broken VertexInputDynamicState
// Disable VertexInputDynamicState on old Intel Windows drivers
if (extensions.vertex_input_dynamic_state && is_intel_windows) {
const u32 version = (properties.properties.driverVersion << 3) >> 3;
if (version < VK_MAKE_API_VERSION(27, 20, 100, 0)) {
LOG_WARNING(Render_Vulkan,
"Intel Windows < 27.20.100.0: Disabling broken VK_EXT_vertex_input_dynamic_state");
features.vertex_input_dynamic_state.vertexInputDynamicState = false;
}
}
// If user setting is dyna_state=0, disable all dynamic state features
if (Settings::values.dyna_state.GetValue() == 0) {
LOG_INFO(Render_Vulkan, "Dynamic state disabled by user setting, clearing all EDS features");
features.custom_border_color.customBorderColors = false;
features.custom_border_color.customBorderColorWithoutFormat = false;
features.extended_dynamic_state.extendedDynamicState = false;
features.extended_dynamic_state2.extendedDynamicState2 = false;
features.extended_dynamic_state3.extendedDynamicState3ColorBlendEnable = false;
features.extended_dynamic_state3.extendedDynamicState3ColorBlendEquation = false;
features.extended_dynamic_state3.extendedDynamicState3ColorWriteMask = false;
features.extended_dynamic_state3.extendedDynamicState3DepthClampEnable = false;
features.extended_dynamic_state3.extendedDynamicState3LogicOpEnable = false;
// Note: vertex_input_dynamic_state has independent toggle, NOT affected by dyna_state=0
}
// Return whether we were suitable.
return suitable;
}

View File

@@ -64,6 +64,7 @@ VK_DEFINE_HANDLE(VmaAllocator)
pipeline_executable_properties) \
FEATURE(KHR, WorkgroupMemoryExplicitLayout, WORKGROUP_MEMORY_EXPLICIT_LAYOUT, \
workgroup_memory_explicit_layout) \
FEATURE(QCOM, ImageProcessing, IMAGE_PROCESSING, image_processing_qcom) \
FEATURE(QCOM, TileProperties, TILE_PROPERTIES, tile_properties_qcom)
// Define miscellaneous extensions which may be used by the implementation here.
@@ -98,6 +99,9 @@ VK_DEFINE_HANDLE(VmaAllocator)
EXTENSION(QCOM, FILTER_CUBIC_WEIGHTS, filter_cubic_weights) \
EXTENSION(QCOM, RENDER_PASS_SHADER_RESOLVE, render_pass_shader_resolve) \
EXTENSION(QCOM, RENDER_PASS_STORE_OPS, render_pass_store_ops) \
EXTENSION(QCOM, RENDER_PASS_TRANSFORM, render_pass_transform) \
EXTENSION(QCOM, ROTATED_COPY_COMMANDS, rotated_copy_commands) \
EXTENSION(QCOM, IMAGE_PROCESSING, image_processing) \
EXTENSION(QCOM, TILE_PROPERTIES, tile_properties) \
EXTENSION(KHR, MAINTENANCE_1, maintenance1) \
EXTENSION(KHR, MAINTENANCE_2, maintenance2) \
@@ -714,6 +718,21 @@ public:
return extensions.tile_properties;
}
/// Returns true if the device supports VK_QCOM_render_pass_transform
bool IsQcomRenderPassTransformSupported() const {
return extensions.render_pass_transform;
}
/// Returns true if the device supports VK_QCOM_rotated_copy_commands
bool IsQcomRotatedCopyCommandsSupported() const {
return extensions.rotated_copy_commands;
}
/// Returns true if the device supports VK_QCOM_image_processing
bool IsQcomImageProcessingSupported() const {
return extensions.image_processing;
}
/// Returns Qualcomm tile size (width, height, depth). Returns {0,0,0} if not queried or unsupported
VkExtent3D GetQcomTileSize() const {
return properties.qcom_tile_size;