mirror of
https://git.eden-emu.dev/eden-emu/eden
synced 2026-04-28 09:08:58 +02:00
[vk] ExtendedDynamicState impl close to Vulkan specs
This commit is contained in:
parent
b1ec27dfce
commit
7867c19b2c
3 changed files with 97 additions and 69 deletions
|
|
@ -404,30 +404,32 @@ PipelineCache::PipelineCache(Tegra::MaxwellDeviceMemoryManager& device_memory_,
|
||||||
device.GetMaxVertexInputBindings(), Maxwell::NumVertexArrays);
|
device.GetMaxVertexInputBindings(), Maxwell::NumVertexArrays);
|
||||||
}
|
}
|
||||||
|
|
||||||
const u8 dynamic_state = Settings::values.dyna_state.GetValue();
|
LOG_INFO(Render_Vulkan, "DynamicState setting value: {}", Settings::values.dyna_state.GetValue());
|
||||||
|
|
||||||
LOG_INFO(Render_Vulkan, "DynamicState value is set to {}", static_cast<u32>(dynamic_state));
|
|
||||||
|
|
||||||
dynamic_features = {};
|
dynamic_features = {};
|
||||||
|
|
||||||
// EDS1 - Level 1 (all-or-nothing, enabled if driver supports AND setting > 0)
|
// User granularity enforced in vulkan_device.cpp switch statement:
|
||||||
dynamic_features.has_extended_dynamic_state =
|
// Level 0: Core Dynamic States only
|
||||||
device.IsExtExtendedDynamicStateSupported() && dynamic_state > 0;
|
// 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();
|
||||||
|
|
||||||
// EDS2 - Level 2 (core + granular features, enabled if driver supports AND setting > 1)
|
|
||||||
dynamic_features.has_extended_dynamic_state_2 =
|
dynamic_features.has_extended_dynamic_state_2 =
|
||||||
device.IsExtExtendedDynamicState2Supported() && dynamic_state > 1;
|
device.IsExtExtendedDynamicState2Supported();
|
||||||
dynamic_features.has_extended_dynamic_state_2_logic_op =
|
dynamic_features.has_extended_dynamic_state_2_logic_op =
|
||||||
device.IsExtExtendedDynamicState2ExtrasSupported() && dynamic_state > 1;
|
device.IsExtExtendedDynamicState2ExtrasSupported();
|
||||||
dynamic_features.has_extended_dynamic_state_2_patch_control_points = false;
|
dynamic_features.has_extended_dynamic_state_2_patch_control_points = false;
|
||||||
|
|
||||||
// EDS3 - Level 3 (granular features, enabled if driver supports AND setting > 2)
|
|
||||||
dynamic_features.has_extended_dynamic_state_3_blend =
|
dynamic_features.has_extended_dynamic_state_3_blend =
|
||||||
device.IsExtExtendedDynamicState3BlendingSupported() && dynamic_state > 2;
|
device.IsExtExtendedDynamicState3BlendingSupported();
|
||||||
dynamic_features.has_extended_dynamic_state_3_enables =
|
dynamic_features.has_extended_dynamic_state_3_enables =
|
||||||
device.IsExtExtendedDynamicState3EnablesSupported() && dynamic_state > 2;
|
device.IsExtExtendedDynamicState3EnablesSupported();
|
||||||
|
|
||||||
// VIDS - Independent toggle (not affected by dyna_state levels)
|
// VIDS: Independent toggle (not affected by dyna_state levels)
|
||||||
dynamic_features.has_dynamic_vertex_input =
|
dynamic_features.has_dynamic_vertex_input =
|
||||||
device.IsExtVertexInputDynamicStateSupported() &&
|
device.IsExtVertexInputDynamicStateSupported() &&
|
||||||
Settings::values.vertex_input_dynamic_state.GetValue();
|
Settings::values.vertex_input_dynamic_state.GetValue();
|
||||||
|
|
|
||||||
|
|
@ -931,6 +931,8 @@ bool AccelerateDMA::BufferToImage(const Tegra::DMA::ImageCopy& copy_info,
|
||||||
|
|
||||||
void RasterizerVulkan::UpdateDynamicStates() {
|
void RasterizerVulkan::UpdateDynamicStates() {
|
||||||
auto& regs = maxwell3d->regs;
|
auto& regs = maxwell3d->regs;
|
||||||
|
|
||||||
|
// Core Dynamic States (Vulkan 1.0) - Always active regardless of dyna_state setting
|
||||||
UpdateViewportsState(regs);
|
UpdateViewportsState(regs);
|
||||||
UpdateScissorsState(regs);
|
UpdateScissorsState(regs);
|
||||||
UpdateDepthBias(regs);
|
UpdateDepthBias(regs);
|
||||||
|
|
@ -938,6 +940,15 @@ void RasterizerVulkan::UpdateDynamicStates() {
|
||||||
UpdateDepthBounds(regs);
|
UpdateDepthBounds(regs);
|
||||||
UpdateStencilFaces(regs);
|
UpdateStencilFaces(regs);
|
||||||
UpdateLineWidth(regs);
|
UpdateLineWidth(regs);
|
||||||
|
|
||||||
|
// Extended Dynamic States (EDS) - Controlled by dyna_state setting in vulkan_device.cpp
|
||||||
|
// User granularity levels (accumulative):
|
||||||
|
// Level 0: Core only
|
||||||
|
// Level 1: Core + EDS1
|
||||||
|
// Level 2: Core + EDS1 + EDS2
|
||||||
|
// Level 3: Core + EDS1 + EDS2 + EDS3
|
||||||
|
|
||||||
|
// EDS1: CullMode, DepthCompare, FrontFace, StencilOp, DepthBoundsTest, DepthTest, DepthWrite, StencilTest
|
||||||
if (device.IsExtExtendedDynamicStateSupported()) {
|
if (device.IsExtExtendedDynamicStateSupported()) {
|
||||||
UpdateCullMode(regs);
|
UpdateCullMode(regs);
|
||||||
UpdateDepthCompareOp(regs);
|
UpdateDepthCompareOp(regs);
|
||||||
|
|
@ -949,42 +960,49 @@ void RasterizerVulkan::UpdateDynamicStates() {
|
||||||
UpdateDepthWriteEnable(regs);
|
UpdateDepthWriteEnable(regs);
|
||||||
UpdateStencilTestEnable(regs);
|
UpdateStencilTestEnable(regs);
|
||||||
}
|
}
|
||||||
// EDS2 states must always be set, not just when TouchStateEnable() is true
|
}
|
||||||
if (device.IsExtExtendedDynamicState2Supported()) {
|
|
||||||
UpdatePrimitiveRestartEnable(regs);
|
// EDS2: PrimitiveRestart, RasterizerDiscard, DepthBias enable/disable
|
||||||
UpdateRasterizerDiscardEnable(regs);
|
if (device.IsExtExtendedDynamicState2Supported()) {
|
||||||
UpdateDepthBiasEnable(regs);
|
UpdatePrimitiveRestartEnable(regs);
|
||||||
}
|
UpdateRasterizerDiscardEnable(regs);
|
||||||
if (state_tracker.TouchStateEnable()) {
|
UpdateDepthBiasEnable(regs);
|
||||||
if (device.IsExtExtendedDynamicState3EnablesSupported()) {
|
}
|
||||||
using namespace Tegra::Engines;
|
|
||||||
if (device.GetDriverID() == VkDriverIdKHR::VK_DRIVER_ID_AMD_OPEN_SOURCE || device.GetDriverID() == VkDriverIdKHR::VK_DRIVER_ID_AMD_PROPRIETARY) {
|
// EDS2 Extras: LogicOp operation selection
|
||||||
const auto has_float = std::any_of(
|
if (device.IsExtExtendedDynamicState2ExtrasSupported()) {
|
||||||
regs.vertex_attrib_format.begin(),
|
UpdateLogicOp(regs);
|
||||||
regs.vertex_attrib_format.end(),
|
}
|
||||||
[](const auto& attrib) {
|
|
||||||
return attrib.type == Maxwell3D::Regs::VertexAttribute::Type::Float;
|
// EDS3 Enables: LogicOpEnable, DepthClamp, LineStipple, ConservativeRaster
|
||||||
}
|
if (device.IsExtExtendedDynamicState3EnablesSupported()) {
|
||||||
);
|
using namespace Tegra::Engines;
|
||||||
if (regs.logic_op.enable) {
|
// AMD Workaround: LogicOp incompatible with float render targets
|
||||||
regs.logic_op.enable = static_cast<u32>(!has_float);
|
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(
|
||||||
|
regs.vertex_attrib_format.begin(),
|
||||||
|
regs.vertex_attrib_format.end(),
|
||||||
|
[](const auto& attrib) {
|
||||||
|
return attrib.type == Maxwell3D::Regs::VertexAttribute::Type::Float;
|
||||||
}
|
}
|
||||||
UpdateLogicOpEnable(regs);
|
);
|
||||||
UpdateDepthClampEnable(regs);
|
if (regs.logic_op.enable) {
|
||||||
|
regs.logic_op.enable = static_cast<u32>(!has_float);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (device.IsExtExtendedDynamicState2ExtrasSupported()) {
|
UpdateLogicOpEnable(regs);
|
||||||
UpdateLogicOp(regs);
|
UpdateDepthClampEnable(regs);
|
||||||
}
|
UpdateLineStippleEnable(regs);
|
||||||
if (device.IsExtExtendedDynamicState3BlendingSupported()) {
|
UpdateConservativeRasterizationMode(regs);
|
||||||
UpdateBlending(regs);
|
|
||||||
}
|
|
||||||
if (device.IsExtExtendedDynamicState3EnablesSupported()) {
|
|
||||||
UpdateLineStippleEnable(regs);
|
|
||||||
UpdateConservativeRasterizationMode(regs);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// EDS3 Blending: ColorBlendEnable, ColorBlendEquation, ColorWriteMask
|
||||||
|
if (device.IsExtExtendedDynamicState3BlendingSupported()) {
|
||||||
|
UpdateBlending(regs);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Vertex Input Dynamic State: Independent from EDS levels
|
||||||
if (device.IsExtVertexInputDynamicStateSupported()) {
|
if (device.IsExtVertexInputDynamicStateSupported()) {
|
||||||
if (auto* gp = pipeline_cache.CurrentGraphicsPipeline(); gp && gp->HasDynamicVertexInput()) {
|
if (auto* gp = pipeline_cache.CurrentGraphicsPipeline(); gp && gp->HasDynamicVertexInput()) {
|
||||||
UpdateVertexInput(regs);
|
UpdateVertexInput(regs);
|
||||||
|
|
|
||||||
|
|
@ -655,24 +655,12 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR
|
||||||
properties.properties.limits.maxVertexInputBindings = 32;
|
properties.properties.limits.maxVertexInputBindings = 32;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!extensions.extended_dynamic_state && extensions.extended_dynamic_state2) {
|
|
||||||
LOG_INFO(Render_Vulkan,
|
|
||||||
"Removing extendedDynamicState2 due to missing extendedDynamicState");
|
|
||||||
RemoveExtensionFeature(extensions.extended_dynamic_state2, features.extended_dynamic_state2,
|
|
||||||
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 = false;
|
|
||||||
dynamic_state3_enables = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Base dynamic states (VIEWPORT, SCISSOR, DEPTH_BIAS, etc.) are ALWAYS active in vk_graphics_pipeline.cpp
|
// Base dynamic states (VIEWPORT, SCISSOR, DEPTH_BIAS, etc.) are ALWAYS active in vk_graphics_pipeline.cpp
|
||||||
// This slider only controls EXTENDED dynamic states (VK_EXT_extended_dynamic_state 1/2/3)
|
// 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
|
||||||
|
|
||||||
// Mesa Intel drivers on UHD 620 have broken EDS causing extreme flickering - unknown if it affects other iGPUs
|
// 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
|
// ALSO affects ALL versions of UHD drivers on Windows 10+, seems to cause even worse issues like straight up crashing
|
||||||
|
|
@ -685,16 +673,36 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR
|
||||||
|
|
||||||
switch (Settings::values.dyna_state.GetValue()) {
|
switch (Settings::values.dyna_state.GetValue()) {
|
||||||
case 0:
|
case 0:
|
||||||
RemoveExtensionFeature(extensions.extended_dynamic_state, features.extended_dynamic_state, VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME);
|
// Level 0: Disable all extended dynamic state extensions
|
||||||
[[fallthrough]];
|
RemoveExtensionFeature(extensions.extended_dynamic_state, features.extended_dynamic_state,
|
||||||
case 1:
|
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_state2, features.extended_dynamic_state2,
|
||||||
[[fallthrough]];
|
VK_EXT_EXTENDED_DYNAMIC_STATE_2_EXTENSION_NAME);
|
||||||
case 2:
|
RemoveExtensionFeature(extensions.extended_dynamic_state3, features.extended_dynamic_state3,
|
||||||
RemoveExtensionFeature(extensions.extended_dynamic_state3, features.extended_dynamic_state3, VK_EXT_EXTENDED_DYNAMIC_STATE_3_EXTENSION_NAME);
|
VK_EXT_EXTENDED_DYNAMIC_STATE_3_EXTENSION_NAME);
|
||||||
dynamic_state3_blending = false;
|
dynamic_state3_blending = false;
|
||||||
dynamic_state3_enables = false;
|
dynamic_state3_enables = false;
|
||||||
break;
|
break;
|
||||||
|
case 1:
|
||||||
|
// Level 1: Enable EDS1, disable EDS2 and EDS3
|
||||||
|
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;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
// Level 2: Enable EDS1 + EDS2, disable EDS3
|
||||||
|
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;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
default:
|
||||||
|
// Level 3: Enable all (EDS1 + EDS2 + EDS3)
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// VK_EXT_vertex_input_dynamic_state is independent from EDS
|
// VK_EXT_vertex_input_dynamic_state is independent from EDS
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue