mirror of
https://git.eden-emu.dev/eden-emu/eden
synced 2026-05-26 17:27:06 +02:00
[vulkan] Fixing DynamicState wrong core feature callings
This commit is contained in:
parent
90b312617b
commit
6e17a47120
7 changed files with 151 additions and 28 deletions
|
|
@ -5,6 +5,7 @@
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include "video_core/renderer_vulkan/vk_texture_cache.h"
|
#include "video_core/renderer_vulkan/vk_texture_cache.h"
|
||||||
|
|
||||||
|
|
@ -761,10 +762,24 @@ void BlitImageHelper::ClearDepthStencil(const Framebuffer* dst_framebuffer, bool
|
||||||
const VkPipeline pipeline = FindOrEmplaceClearStencilPipeline(key);
|
const VkPipeline pipeline = FindOrEmplaceClearStencilPipeline(key);
|
||||||
const VkPipelineLayout layout = *clear_color_pipeline_layout;
|
const VkPipelineLayout layout = *clear_color_pipeline_layout;
|
||||||
scheduler.RequestRenderpass(dst_framebuffer);
|
scheduler.RequestRenderpass(dst_framebuffer);
|
||||||
scheduler.Record([pipeline, layout, clear_depth, dst_region](vk::CommandBuffer cmdbuf) {
|
scheduler.Record([pipeline, layout, clear_depth, dst_region, stencil_mask, stencil_ref,
|
||||||
|
stencil_compare_mask, dyn_stencil_compare, dyn_stencil_write,
|
||||||
|
dyn_stencil_ref, this](vk::CommandBuffer cmdbuf) {
|
||||||
constexpr std::array blend_constants{0.0f, 0.0f, 0.0f, 0.0f};
|
constexpr std::array blend_constants{0.0f, 0.0f, 0.0f, 0.0f};
|
||||||
cmdbuf.SetBlendConstants(blend_constants.data());
|
cmdbuf.SetBlendConstants(blend_constants.data());
|
||||||
cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
|
cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
|
||||||
|
if (dyn_stencil_compare) {
|
||||||
|
cmdbuf.SetStencilCompareMask(VK_STENCIL_FACE_FRONT_BIT | VK_STENCIL_FACE_BACK_BIT,
|
||||||
|
stencil_compare_mask);
|
||||||
|
}
|
||||||
|
if (dyn_stencil_write) {
|
||||||
|
cmdbuf.SetStencilWriteMask(VK_STENCIL_FACE_FRONT_BIT | VK_STENCIL_FACE_BACK_BIT,
|
||||||
|
stencil_mask);
|
||||||
|
}
|
||||||
|
if (dyn_stencil_ref) {
|
||||||
|
cmdbuf.SetStencilReference(VK_STENCIL_FACE_FRONT_BIT | VK_STENCIL_FACE_BACK_BIT,
|
||||||
|
stencil_ref);
|
||||||
|
}
|
||||||
BindBlitState(cmdbuf, dst_region);
|
BindBlitState(cmdbuf, dst_region);
|
||||||
cmdbuf.PushConstants(layout, VK_SHADER_STAGE_FRAGMENT_BIT, clear_depth);
|
cmdbuf.PushConstants(layout, VK_SHADER_STAGE_FRAGMENT_BIT, clear_depth);
|
||||||
cmdbuf.Draw(3, 1, 0, 0);
|
cmdbuf.Draw(3, 1, 0, 0);
|
||||||
|
|
@ -1010,14 +1025,19 @@ VkPipeline BlitImageHelper::FindOrEmplaceClearStencilPipeline(
|
||||||
}
|
}
|
||||||
clear_stencil_keys.push_back(key);
|
clear_stencil_keys.push_back(key);
|
||||||
const std::array stages = MakeStages(*clear_color_vert, *clear_stencil_frag);
|
const std::array stages = MakeStages(*clear_color_vert, *clear_stencil_frag);
|
||||||
|
// Allow using dynamic stencil masks if the device supports them.
|
||||||
|
const bool dyn_stencil_compare = device.SupportsDynamicStateStencilCompareMask();
|
||||||
|
const bool dyn_stencil_write = device.SupportsDynamicStateStencilWriteMask();
|
||||||
|
const bool dyn_stencil_ref = device.SupportsDynamicStateStencilReference();
|
||||||
|
|
||||||
const auto stencil = VkStencilOpState{
|
const auto stencil = VkStencilOpState{
|
||||||
.failOp = VK_STENCIL_OP_KEEP,
|
.failOp = VK_STENCIL_OP_KEEP,
|
||||||
.passOp = VK_STENCIL_OP_REPLACE,
|
.passOp = VK_STENCIL_OP_REPLACE,
|
||||||
.depthFailOp = VK_STENCIL_OP_KEEP,
|
.depthFailOp = VK_STENCIL_OP_KEEP,
|
||||||
.compareOp = VK_COMPARE_OP_ALWAYS,
|
.compareOp = VK_COMPARE_OP_ALWAYS,
|
||||||
.compareMask = key.stencil_compare_mask,
|
.compareMask = dyn_stencil_compare ? 0u : key.stencil_compare_mask,
|
||||||
.writeMask = key.stencil_mask,
|
.writeMask = dyn_stencil_write ? 0u : key.stencil_mask,
|
||||||
.reference = key.stencil_ref,
|
.reference = dyn_stencil_ref ? 0u : key.stencil_ref,
|
||||||
};
|
};
|
||||||
const VkPipelineDepthStencilStateCreateInfo depth_stencil_ci{
|
const VkPipelineDepthStencilStateCreateInfo depth_stencil_ci{
|
||||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,
|
.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,
|
||||||
|
|
@ -1034,6 +1054,29 @@ VkPipeline BlitImageHelper::FindOrEmplaceClearStencilPipeline(
|
||||||
.maxDepthBounds = 0.0f,
|
.maxDepthBounds = 0.0f,
|
||||||
};
|
};
|
||||||
const VkPipelineInputAssemblyStateCreateInfo input_assembly_ci = GetPipelineInputAssemblyStateCreateInfo(device);
|
const VkPipelineInputAssemblyStateCreateInfo input_assembly_ci = GetPipelineInputAssemblyStateCreateInfo(device);
|
||||||
|
|
||||||
|
// Build dynamic state list for this pipeline (base + optional stencil/linewidth)
|
||||||
|
std::vector<VkDynamicState> dyn_states(DYNAMIC_STATES.begin(), DYNAMIC_STATES.end());
|
||||||
|
if (device.SupportsDynamicStateLineWidth()) {
|
||||||
|
dyn_states.push_back(VK_DYNAMIC_STATE_LINE_WIDTH);
|
||||||
|
}
|
||||||
|
if (dyn_stencil_compare) {
|
||||||
|
dyn_states.push_back(VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK);
|
||||||
|
}
|
||||||
|
if (dyn_stencil_write) {
|
||||||
|
dyn_states.push_back(VK_DYNAMIC_STATE_STENCIL_WRITE_MASK);
|
||||||
|
}
|
||||||
|
if (dyn_stencil_ref) {
|
||||||
|
dyn_states.push_back(VK_DYNAMIC_STATE_STENCIL_REFERENCE);
|
||||||
|
}
|
||||||
|
const VkPipelineDynamicStateCreateInfo dynamic_state_ci{
|
||||||
|
.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,
|
||||||
|
.pNext = nullptr,
|
||||||
|
.flags = 0,
|
||||||
|
.dynamicStateCount = static_cast<u32>(dyn_states.size()),
|
||||||
|
.pDynamicStates = dyn_states.data(),
|
||||||
|
};
|
||||||
|
|
||||||
clear_stencil_pipelines.push_back(device.GetLogical().CreateGraphicsPipeline({
|
clear_stencil_pipelines.push_back(device.GetLogical().CreateGraphicsPipeline({
|
||||||
.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
|
.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
|
||||||
.pNext = nullptr,
|
.pNext = nullptr,
|
||||||
|
|
@ -1048,7 +1091,7 @@ VkPipeline BlitImageHelper::FindOrEmplaceClearStencilPipeline(
|
||||||
.pMultisampleState = &PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
|
.pMultisampleState = &PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
|
||||||
.pDepthStencilState = &depth_stencil_ci,
|
.pDepthStencilState = &depth_stencil_ci,
|
||||||
.pColorBlendState = &PIPELINE_COLOR_BLEND_STATE_GENERIC_CREATE_INFO,
|
.pColorBlendState = &PIPELINE_COLOR_BLEND_STATE_GENERIC_CREATE_INFO,
|
||||||
.pDynamicState = &PIPELINE_DYNAMIC_STATE_CREATE_INFO,
|
.pDynamicState = &dynamic_state_ci,
|
||||||
.layout = *clear_color_pipeline_layout,
|
.layout = *clear_color_pipeline_layout,
|
||||||
.renderPass = key.renderpass,
|
.renderPass = key.renderpass,
|
||||||
.subpass = 0,
|
.subpass = 0,
|
||||||
|
|
|
||||||
|
|
@ -171,6 +171,15 @@ void FixedPipelineState::Refresh(Tegra::Engines::Maxwell3D& maxwell3d, DynamicFe
|
||||||
if (!extended_dynamic_state_3_enables) {
|
if (!extended_dynamic_state_3_enables) {
|
||||||
dynamic_state.Refresh3(regs);
|
dynamic_state.Refresh3(regs);
|
||||||
}
|
}
|
||||||
|
if (features.has_depth_bounds) {
|
||||||
|
depth_bounds_min = 0;
|
||||||
|
depth_bounds_max = 0;
|
||||||
|
dynamic_state.depth_bounds_enable.Assign(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (features.has_depth_bias) {
|
||||||
|
dynamic_state.depth_bias_enable.Assign(0);
|
||||||
|
}
|
||||||
if (xfb_enabled) {
|
if (xfb_enabled) {
|
||||||
RefreshXfbState(xfb_state, regs);
|
RefreshXfbState(xfb_state, regs);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,15 @@ namespace Vulkan {
|
||||||
using Maxwell = Tegra::Engines::Maxwell3D::Regs;
|
using Maxwell = Tegra::Engines::Maxwell3D::Regs;
|
||||||
|
|
||||||
struct DynamicFeatures {
|
struct DynamicFeatures {
|
||||||
|
bool has_viewport;
|
||||||
|
bool has_scissor;
|
||||||
|
bool has_depth_bias;
|
||||||
|
bool has_blend_constants;
|
||||||
|
bool has_depth_bounds;
|
||||||
|
bool has_stencil_compare_mask;
|
||||||
|
bool has_stencil_write_mask;
|
||||||
|
bool has_stencil_reference;
|
||||||
|
bool has_line_width;
|
||||||
bool has_extended_dynamic_state;
|
bool has_extended_dynamic_state;
|
||||||
bool has_extended_dynamic_state_2;
|
bool has_extended_dynamic_state_2;
|
||||||
bool has_extended_dynamic_state_2_logic_op;
|
bool has_extended_dynamic_state_2_logic_op;
|
||||||
|
|
|
||||||
|
|
@ -815,13 +815,35 @@ void GraphicsPipeline::MakePipeline(VkRenderPass render_pass) {
|
||||||
.pAttachments = cb_attachments.data(),
|
.pAttachments = cb_attachments.data(),
|
||||||
.blendConstants = {}
|
.blendConstants = {}
|
||||||
};
|
};
|
||||||
static_vector<VkDynamicState, 34> dynamic_states{
|
static_vector<VkDynamicState, 34> dynamic_states;
|
||||||
VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR,
|
|
||||||
VK_DYNAMIC_STATE_DEPTH_BIAS, VK_DYNAMIC_STATE_BLEND_CONSTANTS,
|
if (device.SupportsDynamicStateViewport()) {
|
||||||
VK_DYNAMIC_STATE_DEPTH_BOUNDS, VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK,
|
dynamic_states.push_back(VK_DYNAMIC_STATE_VIEWPORT);
|
||||||
VK_DYNAMIC_STATE_STENCIL_WRITE_MASK, VK_DYNAMIC_STATE_STENCIL_REFERENCE,
|
}
|
||||||
VK_DYNAMIC_STATE_LINE_WIDTH,
|
if (device.SupportsDynamicStateScissor()) {
|
||||||
};
|
dynamic_states.push_back(VK_DYNAMIC_STATE_SCISSOR);
|
||||||
|
}
|
||||||
|
if (device.SupportsDynamicStateDepthBias()) {
|
||||||
|
dynamic_states.push_back(VK_DYNAMIC_STATE_DEPTH_BIAS);
|
||||||
|
}
|
||||||
|
if (device.SupportsDynamicStateBlendConstants()) {
|
||||||
|
dynamic_states.push_back(VK_DYNAMIC_STATE_BLEND_CONSTANTS);
|
||||||
|
}
|
||||||
|
if (device.SupportsDynamicStateDepthBounds()) {
|
||||||
|
dynamic_states.push_back(VK_DYNAMIC_STATE_DEPTH_BOUNDS);
|
||||||
|
}
|
||||||
|
if (device.SupportsDynamicStateStencilCompareMask()) {
|
||||||
|
dynamic_states.push_back(VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK);
|
||||||
|
}
|
||||||
|
if (device.SupportsDynamicStateStencilWriteMask()) {
|
||||||
|
dynamic_states.push_back(VK_DYNAMIC_STATE_STENCIL_WRITE_MASK);
|
||||||
|
}
|
||||||
|
if (device.SupportsDynamicStateStencilReference()) {
|
||||||
|
dynamic_states.push_back(VK_DYNAMIC_STATE_STENCIL_REFERENCE);
|
||||||
|
}
|
||||||
|
if (device.SupportsDynamicStateLineWidth()) {
|
||||||
|
dynamic_states.push_back(VK_DYNAMIC_STATE_LINE_WIDTH);
|
||||||
|
}
|
||||||
if (key.state.extended_dynamic_state) {
|
if (key.state.extended_dynamic_state) {
|
||||||
static constexpr std::array extended{
|
static constexpr std::array extended{
|
||||||
VK_DYNAMIC_STATE_CULL_MODE_EXT,
|
VK_DYNAMIC_STATE_CULL_MODE_EXT,
|
||||||
|
|
|
||||||
|
|
@ -418,12 +418,24 @@ PipelineCache::PipelineCache(Tegra::MaxwellDeviceMemoryManager& device_memory_,
|
||||||
|
|
||||||
dynamic_features = {};
|
dynamic_features = {};
|
||||||
|
|
||||||
// User granularity enforced in vulkan_device.cpp switch statement:
|
dynamic_features.has_viewport =
|
||||||
// Level 0: Core Dynamic States only
|
device.SupportsDynamicStateViewport();
|
||||||
// Level 1: Core + EDS1
|
dynamic_features.has_scissor =
|
||||||
// Level 2: Core + EDS1 + EDS2 (accumulative)
|
device.SupportsDynamicStateScissor();
|
||||||
// Level 3: Core + EDS1 + EDS2 + EDS3 (accumulative)
|
dynamic_features.has_depth_bias =
|
||||||
// Here we only verify if extensions were successfully loaded by the device
|
device.SupportsDynamicStateDepthBias();
|
||||||
|
dynamic_features.has_blend_constants =
|
||||||
|
device.SupportsDynamicStateBlendConstants();
|
||||||
|
dynamic_features.has_depth_bounds =
|
||||||
|
device.SupportsDynamicStateDepthBounds();
|
||||||
|
dynamic_features.has_stencil_compare_mask =
|
||||||
|
device.SupportsDynamicStateStencilCompareMask();
|
||||||
|
dynamic_features.has_stencil_write_mask =
|
||||||
|
device.SupportsDynamicStateStencilWriteMask();
|
||||||
|
dynamic_features.has_stencil_reference =
|
||||||
|
device.SupportsDynamicStateStencilReference();
|
||||||
|
dynamic_features.has_line_width =
|
||||||
|
device.SupportsDynamicStateLineWidth();
|
||||||
|
|
||||||
dynamic_features.has_extended_dynamic_state =
|
dynamic_features.has_extended_dynamic_state =
|
||||||
device.IsExtExtendedDynamicStateSupported();
|
device.IsExtExtendedDynamicStateSupported();
|
||||||
|
|
@ -439,7 +451,6 @@ PipelineCache::PipelineCache(Tegra::MaxwellDeviceMemoryManager& device_memory_,
|
||||||
dynamic_features.has_extended_dynamic_state_3_enables =
|
dynamic_features.has_extended_dynamic_state_3_enables =
|
||||||
device.IsExtExtendedDynamicState3EnablesSupported();
|
device.IsExtExtendedDynamicState3EnablesSupported();
|
||||||
|
|
||||||
// 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();
|
||||||
|
|
|
||||||
|
|
@ -682,13 +682,6 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR
|
||||||
|
|
||||||
const auto dyna_state = Settings::values.dyna_state.GetValue();
|
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) {
|
switch (dyna_state) {
|
||||||
case Settings::ExtendedDynamicState::Disabled:
|
case Settings::ExtendedDynamicState::Disabled:
|
||||||
// Level 0: Disable all extended dynamic state extensions
|
// Level 0: Disable all extended dynamic state extensions
|
||||||
|
|
@ -723,8 +716,7 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// VK_EXT_vertex_input_dynamic_state is independent from EDS
|
// VK_EXT_vertex_input_dynamic_state is independent from ExtendedDynamicState level
|
||||||
// It can be enabled even without extended_dynamic_state
|
|
||||||
if (!Settings::values.vertex_input_dynamic_state.GetValue()) {
|
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);
|
RemoveExtensionFeature(extensions.vertex_input_dynamic_state, features.vertex_input_dynamic_state, VK_EXT_VERTEX_INPUT_DYNAMIC_STATE_EXTENSION_NAME);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -704,6 +704,43 @@ public:
|
||||||
return dynamic_state3_alpha_to_one;
|
return dynamic_state3_alpha_to_one;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Core dynamic state support checks
|
||||||
|
bool SupportsDynamicStateViewport() const {
|
||||||
|
return dld.vkCmdSetViewport != nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SupportsDynamicStateScissor() const {
|
||||||
|
return dld.vkCmdSetScissor != nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SupportsDynamicStateDepthBias() const {
|
||||||
|
return dld.vkCmdSetDepthBias != nullptr || dld.vkCmdSetDepthBias2EXT != nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SupportsDynamicStateBlendConstants() const {
|
||||||
|
return dld.vkCmdSetBlendConstants != nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SupportsDynamicStateDepthBounds() const {
|
||||||
|
return dld.vkCmdSetDepthBounds != nullptr && IsDepthBoundsSupported();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SupportsDynamicStateStencilCompareMask() const {
|
||||||
|
return dld.vkCmdSetStencilCompareMask != nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SupportsDynamicStateStencilWriteMask() const {
|
||||||
|
return dld.vkCmdSetStencilWriteMask != nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SupportsDynamicStateStencilReference() const {
|
||||||
|
return dld.vkCmdSetStencilReference != nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SupportsDynamicStateLineWidth() const {
|
||||||
|
return dld.vkCmdSetLineWidth != nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns true if the device supports VK_EXT_vertex_input_dynamic_state.
|
/// Returns true if the device supports VK_EXT_vertex_input_dynamic_state.
|
||||||
bool IsExtVertexInputDynamicStateSupported() const {
|
bool IsExtVertexInputDynamicStateSupported() const {
|
||||||
return extensions.vertex_input_dynamic_state;
|
return extensions.vertex_input_dynamic_state;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue