renderer_vulkan: Use more depth-stencil dynamic state. (#2749)
Some checks failed
Build and Release / clang-format (push) Has been cancelled
Build and Release / get-info (push) Has been cancelled
Build and Release / reuse (push) Has been cancelled
Build and Release / windows-sdl (push) Has been cancelled
Build and Release / windows-qt (push) Has been cancelled
Build and Release / macos-sdl (push) Has been cancelled
Build and Release / macos-qt (push) Has been cancelled
Build and Release / linux-sdl (push) Has been cancelled
Build and Release / linux-qt (push) Has been cancelled
Build and Release / linux-sdl-gcc (push) Has been cancelled
Build and Release / linux-qt-gcc (push) Has been cancelled
Build and Release / pre-release (push) Has been cancelled

This commit is contained in:
squidbus 2025-04-05 13:14:27 -07:00 committed by GitHub
parent 54b4d7fc78
commit 0c6f2b470f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 116 additions and 117 deletions

View file

@ -1423,6 +1423,10 @@ struct Liverpool {
return num_samples;
}
bool IsClipDisabled() const {
return clipper_control.clip_disable || primitive_type == PrimitiveType::RectList;
}
void SetDefaults();
};

View file

@ -105,7 +105,6 @@ GraphicsPipeline::GraphicsPipeline(
.frontFace = key.front_face == Liverpool::FrontFace::Clockwise
? vk::FrontFace::eClockwise
: vk::FrontFace::eCounterClockwise,
.depthBiasEnable = key.depth_bias_enable,
.lineWidth = 1.0f,
};
@ -123,18 +122,20 @@ GraphicsPipeline::GraphicsPipeline(
.pNext = instance.IsDepthClipControlSupported() ? &clip_control : nullptr,
};
boost::container::static_vector<vk::DynamicState, 14> dynamic_states = {
vk::DynamicState::eViewportWithCountEXT,
vk::DynamicState::eScissorWithCountEXT,
vk::DynamicState::eBlendConstants,
vk::DynamicState::eDepthBounds,
vk::DynamicState::eDepthBias,
vk::DynamicState::eStencilReference,
vk::DynamicState::eStencilCompareMask,
vk::DynamicState::eStencilWriteMask,
boost::container::static_vector<vk::DynamicState, 17> dynamic_states = {
vk::DynamicState::eViewportWithCountEXT, vk::DynamicState::eScissorWithCountEXT,
vk::DynamicState::eBlendConstants, vk::DynamicState::eDepthTestEnableEXT,
vk::DynamicState::eDepthWriteEnableEXT, vk::DynamicState::eDepthCompareOpEXT,
vk::DynamicState::eDepthBiasEnableEXT, vk::DynamicState::eDepthBias,
vk::DynamicState::eStencilTestEnableEXT, vk::DynamicState::eStencilReference,
vk::DynamicState::eStencilCompareMask, vk::DynamicState::eStencilWriteMask,
vk::DynamicState::eStencilOpEXT,
};
if (instance.IsDepthBoundsSupported()) {
dynamic_states.push_back(vk::DynamicState::eDepthBoundsTestEnableEXT);
dynamic_states.push_back(vk::DynamicState::eDepthBounds);
}
if (instance.IsDynamicColorWriteMaskSupported()) {
dynamic_states.push_back(vk::DynamicState::eColorWriteMaskEXT);
}
@ -149,14 +150,6 @@ GraphicsPipeline::GraphicsPipeline(
.pDynamicStates = dynamic_states.data(),
};
const vk::PipelineDepthStencilStateCreateInfo depth_info = {
.depthTestEnable = key.depth_test_enable,
.depthWriteEnable = key.depth_write_enable,
.depthCompareOp = key.depth_compare_op,
.depthBoundsTestEnable = key.depth_bounds_test_enable,
.stencilTestEnable = key.stencil_test_enable,
};
boost::container::static_vector<vk::PipelineShaderStageCreateInfo, MaxShaderStages>
shader_stages;
auto stage = u32(Shader::LogicalStage::Vertex);
@ -292,7 +285,6 @@ GraphicsPipeline::GraphicsPipeline(
.pViewportState = &viewport_info,
.pRasterizationState = &raster_state,
.pMultisampleState = &multisampling,
.pDepthStencilState = &depth_info,
.pColorBlendState = &color_blending,
.pDynamicState = &dynamic_info,
.layout = *pipeline_layout,

View file

@ -39,18 +39,6 @@ struct GraphicsPipelineKey {
vk::Format depth_format;
vk::Format stencil_format;
struct {
bool clip_disable : 1;
bool depth_test_enable : 1;
bool depth_write_enable : 1;
bool depth_bounds_test_enable : 1;
bool depth_bias_enable : 1;
bool stencil_test_enable : 1;
// Must be named to be zero-initialized.
u8 _unused : 2;
};
vk::CompareOp depth_compare_op;
u32 num_samples;
u32 mrt_mask;
AmdGpu::PrimitiveType prim_type;
@ -94,10 +82,6 @@ public:
return key.mrt_mask;
}
auto IsClipDisabled() const {
return key.clip_disable;
}
[[nodiscard]] bool IsPrimitiveListTopology() const {
return key.prim_type == AmdGpu::PrimitiveType::PointList ||
key.prim_type == AmdGpu::PrimitiveType::LineList ||

View file

@ -247,6 +247,7 @@ bool Instance::CreateDevice() {
add_extension(VK_EXT_SHADER_DEMOTE_TO_HELPER_INVOCATION_EXTENSION_NAME);
add_extension(VK_KHR_SYNCHRONIZATION_2_EXTENSION_NAME);
add_extension(VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME);
add_extension(VK_EXT_EXTENDED_DYNAMIC_STATE_2_EXTENSION_NAME);
add_extension(VK_EXT_TOOLING_INFO_EXTENSION_NAME);
const bool maintenance4 = add_extension(VK_KHR_MAINTENANCE_4_EXTENSION_NAME);
@ -380,6 +381,9 @@ bool Instance::CreateDevice() {
vk::PhysicalDeviceExtendedDynamicStateFeaturesEXT{
.extendedDynamicState = true,
},
vk::PhysicalDeviceExtendedDynamicState2FeaturesEXT{
.extendedDynamicState2 = true,
},
vk::PhysicalDeviceMaintenance4FeaturesKHR{
.maintenance4 = true,
},

View file

@ -84,6 +84,11 @@ public:
return features.samplerAnisotropy;
}
/// Returns true if depth bounds testing is supported
bool IsDepthBoundsSupported() const {
return features.depthBounds;
}
/// Returns true when VK_EXT_custom_border_color is supported
bool IsCustomBorderColorSupported() const {
return custom_border_color;

View file

@ -123,7 +123,7 @@ const Shader::RuntimeInfo& PipelineCache::BuildRuntimeInfo(Stage stage, LogicalS
info.vs_info.emulate_depth_negative_one_to_one =
!instance.IsDepthClipControlSupported() &&
regs.clipper_control.clip_space == Liverpool::ClipSpace::MinusWToW;
info.vs_info.clip_disable = graphics_key.clip_disable;
info.vs_info.clip_disable = regs.IsClipDisabled();
if (l_stage == LogicalStage::TessellationEval) {
info.vs_info.tess_type = regs.tess_config.type;
info.vs_info.tess_topology = regs.tess_config.topology;
@ -267,16 +267,6 @@ bool PipelineCache::RefreshGraphicsKey() {
auto& regs = liverpool->regs;
auto& key = graphics_key;
key.clip_disable =
regs.clipper_control.clip_disable || regs.primitive_type == AmdGpu::PrimitiveType::RectList;
key.depth_test_enable = regs.depth_control.depth_enable;
key.depth_write_enable =
regs.depth_control.depth_write_enable && !regs.depth_render_control.depth_clear_enable;
key.depth_bounds_test_enable = regs.depth_control.depth_bounds_enable;
key.depth_bias_enable = regs.polygon_control.NeedsBias();
key.depth_compare_op = LiverpoolToVK::CompareOp(regs.depth_control.depth_func);
key.stencil_test_enable = regs.depth_control.stencil_enable;
const auto depth_format = instance.GetSupportedFormat(
LiverpoolToVK::DepthFormat(regs.depth_buffer.z_info.format,
regs.depth_buffer.stencil_info.format),
@ -285,13 +275,11 @@ bool PipelineCache::RefreshGraphicsKey() {
key.depth_format = depth_format;
} else {
key.depth_format = vk::Format::eUndefined;
key.depth_test_enable = false;
}
if (regs.depth_buffer.StencilValid()) {
key.stencil_format = depth_format;
} else {
key.stencil_format = vk::Format::eUndefined;
key.stencil_test_enable = false;
}
key.prim_type = regs.primitive_type;

View file

@ -947,81 +947,18 @@ void Rasterizer::UnmapMemory(VAddr addr, u64 size) {
}
void Rasterizer::UpdateDynamicState(const GraphicsPipeline& pipeline) {
UpdateViewportScissorState(pipeline);
UpdateViewportScissorState();
UpdateDepthStencilState();
auto& regs = liverpool->regs;
const auto& regs = liverpool->regs;
const auto cmdbuf = scheduler.CommandBuffer();
cmdbuf.setBlendConstants(&regs.blend_constants.red);
if (instance.IsDynamicColorWriteMaskSupported()) {
cmdbuf.setColorWriteMaskEXT(0, pipeline.GetWriteMasks());
}
if (regs.depth_control.depth_bounds_enable) {
cmdbuf.setDepthBounds(regs.depth_bounds_min, regs.depth_bounds_max);
}
if (regs.polygon_control.enable_polygon_offset_front) {
cmdbuf.setDepthBias(regs.poly_offset.front_offset, regs.poly_offset.depth_bias,
regs.poly_offset.front_scale / 16.f);
} else if (regs.polygon_control.enable_polygon_offset_back) {
cmdbuf.setDepthBias(regs.poly_offset.back_offset, regs.poly_offset.depth_bias,
regs.poly_offset.back_scale / 16.f);
}
if (regs.depth_control.stencil_enable) {
const auto front_fail_op =
LiverpoolToVK::StencilOp(regs.stencil_control.stencil_fail_front);
const auto front_pass_op =
LiverpoolToVK::StencilOp(regs.stencil_control.stencil_zpass_front);
const auto front_depth_fail_op =
LiverpoolToVK::StencilOp(regs.stencil_control.stencil_zfail_front);
const auto front_compare_op = LiverpoolToVK::CompareOp(regs.depth_control.stencil_ref_func);
if (regs.depth_control.backface_enable) {
const auto back_fail_op =
LiverpoolToVK::StencilOp(regs.stencil_control.stencil_fail_back);
const auto back_pass_op =
LiverpoolToVK::StencilOp(regs.stencil_control.stencil_zpass_back);
const auto back_depth_fail_op =
LiverpoolToVK::StencilOp(regs.stencil_control.stencil_zfail_back);
const auto back_compare_op =
LiverpoolToVK::CompareOp(regs.depth_control.stencil_bf_func);
cmdbuf.setStencilOpEXT(vk::StencilFaceFlagBits::eFront, front_fail_op, front_pass_op,
front_depth_fail_op, front_compare_op);
cmdbuf.setStencilOpEXT(vk::StencilFaceFlagBits::eBack, back_fail_op, back_pass_op,
back_depth_fail_op, back_compare_op);
} else {
cmdbuf.setStencilOpEXT(vk::StencilFaceFlagBits::eFrontAndBack, front_fail_op,
front_pass_op, front_depth_fail_op, front_compare_op);
}
const auto front = regs.stencil_ref_front;
const auto back = regs.stencil_ref_back;
if (front.stencil_test_val == back.stencil_test_val) {
cmdbuf.setStencilReference(vk::StencilFaceFlagBits::eFrontAndBack,
front.stencil_test_val);
} else {
cmdbuf.setStencilReference(vk::StencilFaceFlagBits::eFront, front.stencil_test_val);
cmdbuf.setStencilReference(vk::StencilFaceFlagBits::eBack, back.stencil_test_val);
}
if (front.stencil_write_mask == back.stencil_write_mask) {
cmdbuf.setStencilWriteMask(vk::StencilFaceFlagBits::eFrontAndBack,
front.stencil_write_mask);
} else {
cmdbuf.setStencilWriteMask(vk::StencilFaceFlagBits::eFront, front.stencil_write_mask);
cmdbuf.setStencilWriteMask(vk::StencilFaceFlagBits::eBack, back.stencil_write_mask);
}
if (front.stencil_mask == back.stencil_mask) {
cmdbuf.setStencilCompareMask(vk::StencilFaceFlagBits::eFrontAndBack,
front.stencil_mask);
} else {
cmdbuf.setStencilCompareMask(vk::StencilFaceFlagBits::eFront, front.stencil_mask);
cmdbuf.setStencilCompareMask(vk::StencilFaceFlagBits::eBack, back.stencil_mask);
}
}
}
void Rasterizer::UpdateViewportScissorState(const GraphicsPipeline& pipeline) {
void Rasterizer::UpdateViewportScissorState() {
const auto& regs = liverpool->regs;
const auto combined_scissor_value_tl = [](s16 scr, s16 win, s16 gen, s16 win_offset) {
@ -1072,7 +1009,7 @@ void Rasterizer::UpdateViewportScissorState(const GraphicsPipeline& pipeline) {
const auto zoffset = vp_ctl.zoffset_enable ? vp.zoffset : 0.f;
const auto zscale = vp_ctl.zscale_enable ? vp.zscale : 1.f;
if (pipeline.IsClipDisabled()) {
if (regs.IsClipDisabled()) {
// In case if clipping is disabled we patch the shader to convert vertex position
// from screen space coordinates to NDC by defining a render space as full hardware
// window range [0..16383, 0..16383] and setting the viewport to its size.
@ -1139,6 +1076,90 @@ void Rasterizer::UpdateViewportScissorState(const GraphicsPipeline& pipeline) {
cmdbuf.setScissorWithCountEXT(scissors);
}
void Rasterizer::UpdateDepthStencilState() {
auto& regs = liverpool->regs;
const auto cmdbuf = scheduler.CommandBuffer();
bool depth_test = regs.depth_control.depth_enable && regs.depth_buffer.DepthValid();
cmdbuf.setDepthTestEnableEXT(depth_test);
cmdbuf.setDepthWriteEnableEXT(regs.depth_control.depth_write_enable &&
!regs.depth_render_control.depth_clear_enable);
if (depth_test) {
cmdbuf.setDepthCompareOpEXT(LiverpoolToVK::CompareOp(regs.depth_control.depth_func));
}
if (instance.IsDepthBoundsSupported()) {
cmdbuf.setDepthBoundsTestEnableEXT(regs.depth_control.depth_bounds_enable);
if (regs.depth_control.depth_bounds_enable) {
cmdbuf.setDepthBounds(regs.depth_bounds_min, regs.depth_bounds_max);
}
}
cmdbuf.setDepthBiasEnableEXT(regs.polygon_control.NeedsBias());
if (regs.polygon_control.enable_polygon_offset_front) {
cmdbuf.setDepthBias(regs.poly_offset.front_offset, regs.poly_offset.depth_bias,
regs.poly_offset.front_scale / 16.f);
} else if (regs.polygon_control.enable_polygon_offset_back) {
cmdbuf.setDepthBias(regs.poly_offset.back_offset, regs.poly_offset.depth_bias,
regs.poly_offset.back_scale / 16.f);
}
cmdbuf.setStencilTestEnableEXT(regs.depth_control.stencil_enable &&
regs.depth_buffer.StencilValid());
if (regs.depth_control.stencil_enable) {
const auto front_fail_op =
LiverpoolToVK::StencilOp(regs.stencil_control.stencil_fail_front);
const auto front_pass_op =
LiverpoolToVK::StencilOp(regs.stencil_control.stencil_zpass_front);
const auto front_depth_fail_op =
LiverpoolToVK::StencilOp(regs.stencil_control.stencil_zfail_front);
const auto front_compare_op = LiverpoolToVK::CompareOp(regs.depth_control.stencil_ref_func);
if (regs.depth_control.backface_enable) {
const auto back_fail_op =
LiverpoolToVK::StencilOp(regs.stencil_control.stencil_fail_back);
const auto back_pass_op =
LiverpoolToVK::StencilOp(regs.stencil_control.stencil_zpass_back);
const auto back_depth_fail_op =
LiverpoolToVK::StencilOp(regs.stencil_control.stencil_zfail_back);
const auto back_compare_op =
LiverpoolToVK::CompareOp(regs.depth_control.stencil_bf_func);
cmdbuf.setStencilOpEXT(vk::StencilFaceFlagBits::eFront, front_fail_op, front_pass_op,
front_depth_fail_op, front_compare_op);
cmdbuf.setStencilOpEXT(vk::StencilFaceFlagBits::eBack, back_fail_op, back_pass_op,
back_depth_fail_op, back_compare_op);
} else {
cmdbuf.setStencilOpEXT(vk::StencilFaceFlagBits::eFrontAndBack, front_fail_op,
front_pass_op, front_depth_fail_op, front_compare_op);
}
const auto front = regs.stencil_ref_front;
const auto back = regs.stencil_ref_back;
if (front.stencil_test_val == back.stencil_test_val) {
cmdbuf.setStencilReference(vk::StencilFaceFlagBits::eFrontAndBack,
front.stencil_test_val);
} else {
cmdbuf.setStencilReference(vk::StencilFaceFlagBits::eFront, front.stencil_test_val);
cmdbuf.setStencilReference(vk::StencilFaceFlagBits::eBack, back.stencil_test_val);
}
if (front.stencil_write_mask == back.stencil_write_mask) {
cmdbuf.setStencilWriteMask(vk::StencilFaceFlagBits::eFrontAndBack,
front.stencil_write_mask);
} else {
cmdbuf.setStencilWriteMask(vk::StencilFaceFlagBits::eFront, front.stencil_write_mask);
cmdbuf.setStencilWriteMask(vk::StencilFaceFlagBits::eBack, back.stencil_write_mask);
}
if (front.stencil_mask == back.stencil_mask) {
cmdbuf.setStencilCompareMask(vk::StencilFaceFlagBits::eFrontAndBack,
front.stencil_mask);
} else {
cmdbuf.setStencilCompareMask(vk::StencilFaceFlagBits::eFront, front.stencil_mask);
cmdbuf.setStencilCompareMask(vk::StencilFaceFlagBits::eBack, back.stencil_mask);
}
}
}
void Rasterizer::ScopeMarkerBegin(const std::string_view& str, bool from_guest) {
if ((from_guest && !Config::getVkGuestMarkersEnabled()) ||
(!from_guest && !Config::getVkHostMarkersEnabled())) {

View file

@ -76,7 +76,8 @@ private:
void EliminateFastClear();
void UpdateDynamicState(const GraphicsPipeline& pipeline);
void UpdateViewportScissorState(const GraphicsPipeline& pipeline);
void UpdateViewportScissorState();
void UpdateDepthStencilState();
bool FilterDraw();