[vulkan] Adjusting DynamicState functionality + including Static Pipelines Mode

This commit is contained in:
CamilleLaVey
2026-02-01 02:07:47 -04:00
parent 55db1d862b
commit 3a70dddf80
10 changed files with 76 additions and 64 deletions

View File

@@ -611,7 +611,8 @@
</integer-array>
<string-array name="dynaStateEntries">
<item>@string/disabled</item>
<item>Static</item>
<item>Core</item>
<item>ExtendedDynamicState 1</item>
<item>ExtendedDynamicState 2</item>
<item>ExtendedDynamicState 3</item>
@@ -622,6 +623,7 @@
<item>1</item>
<item>2</item>
<item>3</item>
<item>4</item>
</integer-array>
<string-array name="installKeysResults">

View File

@@ -535,9 +535,9 @@ struct Values {
#elif defined (__FreeBSD__)
ExtendedDynamicState::EDS3,
#elif defined (ANDROID)
ExtendedDynamicState::Disabled,
ExtendedDynamicState::Static,
#elif defined (__APPLE__)
ExtendedDynamicState::Disabled,
ExtendedDynamicState::Static,
#else
ExtendedDynamicState::EDS2,
#endif

View File

@@ -153,7 +153,7 @@ ENUM(GpuUnswizzleSize, VerySmall, Small, Normal, Large, VeryLarge)
ENUM(GpuUnswizzle, VeryLow, Low, Normal, Medium, High)
ENUM(GpuUnswizzleChunk, VeryLow, Low, Normal, Medium, High)
ENUM(TemperatureUnits, Celsius, Fahrenheit)
ENUM(ExtendedDynamicState, Disabled, EDS1, EDS2, EDS3);
ENUM(ExtendedDynamicState, Static, Core, EDS1, EDS2, EDS3);
ENUM(GpuLogLevel, Off, Errors, Standard, Verbose, All)
template <typename Type>

View File

@@ -57,6 +57,7 @@ void FixedPipelineState::Refresh(Tegra::Engines::Maxwell3D& maxwell3d, DynamicFe
const auto topology_ = maxwell3d.draw_manager->GetDrawState().topology;
raw1 = 0;
dynamic_state_enabled.Assign(features.has_dynamic_state ? 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);

View File

@@ -21,6 +21,7 @@ namespace Vulkan {
using Maxwell = Tegra::Engines::Maxwell3D::Regs;
struct DynamicFeatures {
bool has_dynamic_state;
bool has_extended_dynamic_state;
bool has_extended_dynamic_state_2;
bool has_extended_dynamic_state_2_logic_op;
@@ -188,19 +189,20 @@ struct FixedPipelineState {
union {
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<0, 1, u32> dynamic_state_enabled;
BitField<1, 1, u32> extended_dynamic_state;
BitField<2, 1, u32> extended_dynamic_state_2;
BitField<3, 1, u32> extended_dynamic_state_2_logic_op;
BitField<4, 1, u32> extended_dynamic_state_3_blend;
BitField<5, 1, u32> extended_dynamic_state_3_enables;
BitField<6, 1, u32> dynamic_vertex_input;
BitField<7, 1, u32> xfb_enabled;
BitField<8, 1, u32> ndc_minus_one_to_one;
BitField<9, 2, u32> polygon_mode;
BitField<11, 2, u32> tessellation_primitive;
BitField<13, 2, u32> tessellation_spacing;
BitField<15, 1, u32> tessellation_clockwise;
BitField<16, 5, u32> patch_control_points_minus_one;
BitField<24, 4, Maxwell::PrimitiveTopology> topology;
BitField<28, 4, Tegra::Texture::MsaaMode> msaa_mode;

View File

@@ -826,13 +826,22 @@ void GraphicsPipeline::MakePipeline(VkRenderPass render_pass) {
.pAttachments = cb_attachments.data(),
.blendConstants = {}
};
static_vector<VkDynamicState, 34> 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,
};
// Dynamic states configuration based on feature support
static_vector<VkDynamicState, 34> dynamic_states;
// Core dynamic states (Vulkan 1.0) - Only if not in Static mode
if (key.state.dynamic_state_enabled) {
static constexpr std::array core_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,
};
dynamic_states.insert(dynamic_states.end(), core_states.begin(), core_states.end());
}
if (key.state.extended_dynamic_state) {
static constexpr std::array extended{
VK_DYNAMIC_STATE_CULL_MODE_EXT,

View File

@@ -437,13 +437,7 @@ PipelineCache::PipelineCache(Tegra::MaxwellDeviceMemoryManager& device_memory_,
dynamic_features = {};
// 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_dynamic_state = device.IsCoreDynamicStateSupported();
dynamic_features.has_extended_dynamic_state =
device.IsExtExtendedDynamicStateSupported();

View File

@@ -1009,16 +1009,16 @@ bool AccelerateDMA::BufferToImage(const Tegra::DMA::ImageCopy& copy_info,
void RasterizerVulkan::UpdateDynamicStates() {
auto& regs = maxwell3d->regs;
// Core Dynamic States (Vulkan 1.0) - Always active regardless of dyna_state setting
UpdateViewportsState(regs);
UpdateScissorsState(regs);
UpdateDepthBias(regs);
UpdateBlendConstants(regs);
UpdateDepthBounds(regs);
UpdateStencilFaces(regs);
UpdateLineWidth(regs);
if (device.IsCoreDynamicStateSupported()) {
UpdateViewportsState(regs);
UpdateScissorsState(regs);
UpdateDepthBias(regs);
UpdateBlendConstants(regs);
UpdateDepthBounds(regs);
UpdateStencilFaces(regs);
UpdateLineWidth(regs);
}
// EDS1: CullMode, DepthCompare, FrontFace, StencilOp, DepthBoundsTest, DepthTest, DepthWrite, StencilTest
if (device.IsExtExtendedDynamicStateSupported()) {
UpdateCullMode(regs);
UpdateDepthCompareOp(regs);
@@ -1032,22 +1032,18 @@ void RasterizerVulkan::UpdateDynamicStates() {
}
}
// EDS2: PrimitiveRestart, RasterizerDiscard, DepthBias enable/disable
if (device.IsExtExtendedDynamicState2Supported()) {
UpdatePrimitiveRestartEnable(regs);
UpdateRasterizerDiscardEnable(regs);
UpdateDepthBiasEnable(regs);
}
// EDS2 Extras: LogicOp operation selection
if (device.IsExtExtendedDynamicState2ExtrasSupported()) {
UpdateLogicOp(regs);
}
// EDS3 Enables: LogicOpEnable, DepthClamp, LineStipple, ConservativeRaster
if (device.IsExtExtendedDynamicState3EnablesSupported()) {
using namespace Tegra::Engines;
// AMD Workaround: LogicOp incompatible with float render targets
if (device.GetDriverID() == VkDriverIdKHR::VK_DRIVER_ID_AMD_OPEN_SOURCE ||
device.GetDriverID() == VkDriverIdKHR::VK_DRIVER_ID_AMD_PROPRIETARY) {
const auto has_float = std::any_of(
@@ -1069,13 +1065,10 @@ void RasterizerVulkan::UpdateDynamicStates() {
UpdateAlphaToOneEnable(regs);
}
// EDS3 Blending: ColorBlendEnable, ColorBlendEquation, ColorWriteMask
// or VK_EXT_color_write_enable if EDS3 is not available
if (device.IsExtExtendedDynamicState3BlendingSupported()) {
UpdateBlending(regs);
}
// Vertex Input Dynamic State: Independent from EDS levels
if (device.IsExtVertexInputDynamicStateSupported()) {
if (auto* gp = pipeline_cache.CurrentGraphicsPipeline(); gp && gp->HasDynamicVertexInput()) {
UpdateVertexInput(regs);

View File

@@ -650,16 +650,21 @@ 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: Disable all extended dynamic state extensions
case Settings::ExtendedDynamicState::Static:
LOG_INFO(Render_Vulkan, "STATIC Mode (fully static pipelines)");
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;
supports_dynamic_state = false;
break;
case Settings::ExtendedDynamicState::Core:
LOG_INFO(Render_Vulkan, "DynamicState - Enabled");
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,
@@ -670,7 +675,7 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR
dynamic_state3_enables = false;
break;
case Settings::ExtendedDynamicState::EDS1:
// Level 1: Enable EDS1, disable EDS2 and EDS3
LOG_INFO(Render_Vulkan, "ExtededDynamicState1 - Enabled");
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,
@@ -679,7 +684,7 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR
dynamic_state3_enables = false;
break;
case Settings::ExtendedDynamicState::EDS2:
// Level 2: Enable EDS1 + EDS2, disable EDS3
LOG_INFO(Render_Vulkan, "ExtededDynamicState2 - Enabled");
RemoveExtensionFeature(extensions.extended_dynamic_state3, features.extended_dynamic_state3,
VK_EXT_EXTENDED_DYNAMIC_STATE_3_EXTENSION_NAME);
dynamic_state3_blending = false;
@@ -687,12 +692,10 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR
break;
case Settings::ExtendedDynamicState::EDS3:
default:
// Level 3: Enable all (EDS1 + EDS2 + EDS3)
LOG_INFO(Render_Vulkan, "ExtededDynamicState3 - Enabled");
break;
}
// 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);
}
@@ -1206,8 +1209,10 @@ bool Device::GetSuitability(bool requires_swapchain) {
}
}
if (u32(Settings::values.dyna_state.GetValue()) == 0) {
LOG_INFO(Render_Vulkan, "Extended Dynamic State disabled by user setting, clearing all EDS features");
const auto dyna_state_setting = Settings::values.dyna_state.GetValue();
if (dyna_state_setting == Settings::ExtendedDynamicState::Static) {
LOG_INFO(Render_Vulkan, "Static pipeline mode: All dynamic states disabled");
supports_dynamic_state = false;
features.custom_border_color.customBorderColors = false;
features.custom_border_color.customBorderColorWithoutFormat = false;
features.extended_dynamic_state.extendedDynamicState = false;
@@ -1219,7 +1224,7 @@ bool Device::GetSuitability(bool requires_swapchain) {
features.extended_dynamic_state3.extendedDynamicState3LogicOpEnable = false;
}
// Return whether we were suitable.
return suitable;
return suitable;
}

View File

@@ -609,6 +609,11 @@ public:
return features.custom_border_color.customBorderColorWithoutFormat;
}
/// Returns true if the device supports core Vulkan 1.0 dynamic states.
bool IsCoreDynamicStateSupported() const {
return supports_dynamic_state;
}
/// Returns true if the device supports VK_EXT_extended_dynamic_state.
bool IsExtExtendedDynamicStateSupported() const {
return extensions.extended_dynamic_state;
@@ -1067,6 +1072,7 @@ private:
bool dynamic_state3_alpha_to_coverage{};
bool dynamic_state3_alpha_to_one{};
bool supports_conditional_barriers{}; ///< Allows barriers in conditional control flow.
bool supports_dynamic_state{true}; ///< Core Vulkan 1.0 dynamic states
size_t sampler_heap_budget{}; ///< Sampler budget for buggy drivers (0 = unlimited).
u64 device_access_memory{}; ///< Total size of device local memory in bytes.
u32 sets_per_pool{}; ///< Sets per Description Pool