diff --git a/src/video_core/renderer_vulkan/fixed_pipeline_state.cpp b/src/video_core/renderer_vulkan/fixed_pipeline_state.cpp index c7a4985b87..d74831c529 100644 --- a/src/video_core/renderer_vulkan/fixed_pipeline_state.cpp +++ b/src/video_core/renderer_vulkan/fixed_pipeline_state.cpp @@ -11,7 +11,6 @@ #include #include "common/cityhash.h" #include "common/common_types.h" -#include "common/logging.h" #include "common/settings.h" #include "video_core/engines/maxwell_3d.h" #include "video_core/renderer_vulkan/fixed_pipeline_state.h" @@ -89,27 +88,6 @@ bool ComputeAttachment0DualSourceBlend(const Maxwell& regs) { : uses_dual_source(regs.blend); } -const char* GeometryClipName(Maxwell::ViewportClipControl::GeometryClip clip) { - switch (clip) { - case Maxwell::ViewportClipControl::GeometryClip::WZero: - return "WZero"; - case Maxwell::ViewportClipControl::GeometryClip::Passthrough: - return "Passthrough"; - case Maxwell::ViewportClipControl::GeometryClip::FrustumXY: - return "FrustumXY"; - case Maxwell::ViewportClipControl::GeometryClip::FrustumXYZ: - return "FrustumXYZ"; - case Maxwell::ViewportClipControl::GeometryClip::WZeroNoZCull: - return "WZeroNoZCull"; - case Maxwell::ViewportClipControl::GeometryClip::FrustumZ: - return "FrustumZ"; - case Maxwell::ViewportClipControl::GeometryClip::WZeroTriFillOrClip: - return "WZeroTriFillOrClip"; - default: - return "Unknown"; - } -} - void RefreshXfbState(VideoCommon::TransformFeedbackState& state, const Maxwell& regs) { std::ranges::transform(regs.transform_feedback.controls, state.layouts.begin(), [](const auto& layout) { @@ -127,29 +105,6 @@ void FixedPipelineState::Refresh(Tegra::Engines::Maxwell3D& maxwell3d, DynamicFe const Maxwell& regs = maxwell3d.regs; const auto topology_ = maxwell3d.draw_manager.draw_state.topology; - { - const auto& clip = regs.viewport_clip_control; - const u32 clip_key = (static_cast(clip.geometry_clip.Value()) << 8) | - (static_cast(clip.geometry_guardband_z.Value()) << 6) | - (static_cast(clip.geometry_guardband.Value()) << 5) | - (clip.pixel_max_z.Value() << 2) | (clip.pixel_min_z.Value() << 1) | - clip.depth_0_to_1.Value(); - static u32 last_clip_key = ~0U; - if (clip_key != last_clip_key) { - last_clip_key = clip_key; - LOG_WARNING(Render_Vulkan, - "Viewport clip control: geometry_clip={} guardband_z={} guardband={} " - "depth_0_to_1={} pixel_min_z={} pixel_max_z={} depth_mode={}", - GeometryClipName(clip.geometry_clip.Value()), - static_cast(clip.geometry_guardband_z.Value()), - static_cast(clip.geometry_guardband.Value()), - clip.depth_0_to_1.Value(), clip.pixel_min_z.Value(), - clip.pixel_max_z.Value(), - regs.depth_mode == Maxwell::DepthMode::MinusOneToOne ? "MinusOneToOne" - : "ZeroToOne"); - } - } - driver_id = features.driver_id; driver_version = features.driver_version; @@ -405,18 +360,32 @@ void FixedPipelineState::DynamicState::Refresh2(const Maxwell& regs, depth_bias_enable.Assign(enabled_lut[POLYGON_OFFSET_ENABLE_LUT[topology_index]] != 0 ? 1 : 0); } +bool IsDepthClipEnabled(const Maxwell& regs) { + const auto clip = regs.viewport_clip_control.geometry_clip.Value(); + return clip == Maxwell::ViewportClipControl::GeometryClip::Passthrough || + clip == Maxwell::ViewportClipControl::GeometryClip::FrustumXYZ || + clip == Maxwell::ViewportClipControl::GeometryClip::FrustumZ; +} + +bool IsDepthClampEnabled(const Maxwell& regs, bool has_depth_clip_enable) { + if (!has_depth_clip_enable) { + return !IsDepthClipEnabled(regs); + } + return regs.viewport_clip_control.pixel_min_z.Value() != 0 || + regs.viewport_clip_control.pixel_max_z.Value() != 0; +} + void FixedPipelineState::DynamicState::Refresh3(const Maxwell& regs, const DynamicFeatures& features) { if (!features.has_dynamic_state3_logic_op_enable) { logic_op_enable.Assign(regs.logic_op.enable != 0 ? 1 : 0); } + if (features.has_depth_clip_enable) { + depth_clip_disabled.Assign(IsDepthClipEnabled(regs) ? 0 : 1); + } if (!features.has_dynamic_state3_depth_clamp_enable) { - depth_clamp_disabled.Assign(regs.viewport_clip_control.geometry_clip == - Maxwell::ViewportClipControl::GeometryClip::Passthrough || - regs.viewport_clip_control.geometry_clip == - Maxwell::ViewportClipControl::GeometryClip::FrustumXYZ || - regs.viewport_clip_control.geometry_clip == - Maxwell::ViewportClipControl::GeometryClip::FrustumZ); + depth_clamp_disabled.Assign( + IsDepthClampEnabled(regs, features.has_depth_clip_enable) ? 0 : 1); } if (!features.has_dynamic_state3_line_stipple_enable) { line_stipple_enable.Assign(regs.line_stipple_enable); diff --git a/src/video_core/renderer_vulkan/fixed_pipeline_state.h b/src/video_core/renderer_vulkan/fixed_pipeline_state.h index 36a4b4b7a2..b3b5c6bc7e 100644 --- a/src/video_core/renderer_vulkan/fixed_pipeline_state.h +++ b/src/video_core/renderer_vulkan/fixed_pipeline_state.h @@ -30,6 +30,7 @@ struct DynamicFeatures { bool has_extended_dynamic_state_3_blend; bool has_extended_dynamic_state_3_enables; bool has_dynamic_state3_depth_clamp_enable; + bool has_depth_clip_enable; bool has_dynamic_state3_logic_op_enable; bool has_dynamic_state3_line_stipple_enable; bool has_dynamic_vertex_input; @@ -165,6 +166,7 @@ struct FixedPipelineState { BitField<10, 1, u32> logic_op_enable; BitField<11, 1, u32> depth_clamp_disabled; BitField<12, 1, u32> line_stipple_enable; + BitField<13, 1, u32> depth_clip_disabled; }; union { u32 raw2; @@ -298,6 +300,9 @@ static_assert(std::has_unique_object_representations_v); static_assert(std::is_trivially_copyable_v); static_assert(std::is_trivially_constructible_v); +bool IsDepthClipEnabled(const Maxwell& regs); +bool IsDepthClampEnabled(const Maxwell& regs, bool has_depth_clip_enable); + } // namespace Vulkan namespace std { diff --git a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp index 9815157b97..f687922141 100644 --- a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp +++ b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp @@ -808,6 +808,16 @@ void GraphicsPipeline::MakePipeline(VkRenderPass render_pass) { if (device.IsExtProvokingVertexSupported()) { provoking_vertex.pNext = std::exchange(rasterization_ci.pNext, &provoking_vertex); } + VkPipelineRasterizationDepthClipStateCreateInfoEXT depth_clip_state{ + .sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_DEPTH_CLIP_STATE_CREATE_INFO_EXT, + .pNext = nullptr, + .flags = 0, + .depthClipEnable = static_cast(dynamic.depth_clip_disabled == 0 ? VK_TRUE + : VK_FALSE), + }; + if (device.IsExtDepthClipEnableSupported()) { + depth_clip_state.pNext = std::exchange(rasterization_ci.pNext, &depth_clip_state); + } const bool supports_alpha_output = fragment_has_color0_output; const bool alpha_to_one_supported = device.SupportsAlphaToOne(); diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp index 04368eb3f8..d339a676f0 100644 --- a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp @@ -515,6 +515,8 @@ PipelineCache::PipelineCache(Tegra::MaxwellDeviceMemoryManager& device_memory_, dynamic_features.has_dynamic_state3_depth_clamp_enable = dynamic_features.has_extended_dynamic_state_3_enables && device.SupportsDynamicState3DepthClampEnable(); + dynamic_features.has_depth_clip_enable = + device.IsExtDepthClipEnableSupported(); dynamic_features.has_dynamic_state3_logic_op_enable = dynamic_features.has_extended_dynamic_state_3_enables && device.SupportsDynamicState3LogicOpEnable(); @@ -527,7 +529,8 @@ PipelineCache::PipelineCache(Tegra::MaxwellDeviceMemoryManager& device_memory_, device.IsExtVertexInputDynamicStateSupported() && Settings::values.vertex_input_dynamic_state.GetValue(); - dynamic_features.has_provoking_vertex = device.IsExtProvokingVertexSupported(); + dynamic_features.has_provoking_vertex = + device.IsExtProvokingVertexSupported(); dynamic_features.has_provoking_vertex_first_mode = device.SupportsProvokingVertexFirstMode(); dynamic_features.has_provoking_vertex_last_mode = diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp index aa5bf1cdd6..8560b3cbb1 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp +++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp @@ -103,26 +103,8 @@ VkViewport GetViewportState(const Device& device, const Maxwell& regs, size_t in .maxDepth = src.translate_z + src.scale_z, }; if (!device.IsExtDepthRangeUnrestrictedSupported()) { - const float requested_min = viewport.minDepth; - const float requested_max = viewport.maxDepth; - viewport.minDepth = std::clamp(requested_min, 0.0f, 1.0f); - viewport.maxDepth = std::clamp(requested_max, 0.0f, 1.0f); - if (viewport.minDepth != requested_min || viewport.maxDepth != requested_max) { - static float last_min = std::numeric_limits::quiet_NaN(); - static float last_max = std::numeric_limits::quiet_NaN(); - if (requested_min != last_min || requested_max != last_max) { - last_min = requested_min; - last_max = requested_max; - LOG_WARNING(Render_Vulkan, - "Viewport {} depth range squashed: requested [{}, {}] applied [{}, {}] " - "translate_z={} scale_z={} depth_mode={} clamp_zero_one={}", - index, requested_min, requested_max, viewport.minDepth, - viewport.maxDepth, src.translate_z, src.scale_z, - regs.depth_mode == Maxwell::DepthMode::MinusOneToOne ? "MinusOneToOne" - : "ZeroToOne", - device.IsExtDepthClampZeroOneSupported()); - } - } + viewport.minDepth = std::clamp(viewport.minDepth, 0.0f, 1.0f); + viewport.maxDepth = std::clamp(viewport.maxDepth, 0.0f, 1.0f); } return viewport; } @@ -1684,12 +1666,7 @@ void RasterizerVulkan::UpdateDepthClampEnable(Tegra::Engines::Maxwell3D::Regs& r if (!device.SupportsDynamicState3DepthClampEnable()) { return; } - bool is_enabled = !(regs.viewport_clip_control.geometry_clip == - Maxwell::ViewportClipControl::GeometryClip::Passthrough || - regs.viewport_clip_control.geometry_clip == - Maxwell::ViewportClipControl::GeometryClip::FrustumXYZ || - regs.viewport_clip_control.geometry_clip == - Maxwell::ViewportClipControl::GeometryClip::FrustumZ); + const bool is_enabled = IsDepthClampEnabled(regs, device.IsExtDepthClipEnableSupported()); scheduler.Record( [is_enabled](vk::CommandBuffer cmdbuf) { cmdbuf.SetDepthClampEnableEXT(is_enabled); }); } diff --git a/src/video_core/vulkan_common/vulkan_device.cpp b/src/video_core/vulkan_common/vulkan_device.cpp index 342c962799..55e8ce5bd1 100644 --- a/src/video_core/vulkan_common/vulkan_device.cpp +++ b/src/video_core/vulkan_common/vulkan_device.cpp @@ -1241,6 +1241,10 @@ void Device::RemoveUnsuitableExtensions() { extensions.depth_clip_control = features.depth_clip_control.depthClipControl; RemoveExtensionFeatureIfUnsuitable(extensions.depth_clip_control, features.depth_clip_control, VK_EXT_DEPTH_CLIP_CONTROL_EXTENSION_NAME); + // VK_EXT_depth_clip_enable + extensions.depth_clip_enable = features.depth_clip_enable.depthClipEnable; + RemoveExtensionFeatureIfUnsuitable(extensions.depth_clip_enable, features.depth_clip_enable, + VK_EXT_DEPTH_CLIP_ENABLE_EXTENSION_NAME); // VK_EXT_extended_dynamic_state extensions.extended_dynamic_state = features.extended_dynamic_state.extendedDynamicState; diff --git a/src/video_core/vulkan_common/vulkan_device.h b/src/video_core/vulkan_common/vulkan_device.h index 4e0a2614fd..9a7b604dd2 100644 --- a/src/video_core/vulkan_common/vulkan_device.h +++ b/src/video_core/vulkan_common/vulkan_device.h @@ -57,6 +57,7 @@ VK_DEFINE_HANDLE(VmaAllocator) FEATURE(EXT, DepthBiasControl, DEPTH_BIAS_CONTROL, depth_bias_control) \ FEATURE(EXT, DepthClampZeroOne, DEPTH_CLAMP_ZERO_ONE, depth_clamp_zero_one) \ FEATURE(EXT, DepthClipControl, DEPTH_CLIP_CONTROL, depth_clip_control) \ + FEATURE(EXT, DepthClipEnable, DEPTH_CLIP_ENABLE, depth_clip_enable) \ FEATURE(EXT, ExtendedDynamicState, EXTENDED_DYNAMIC_STATE, extended_dynamic_state) \ FEATURE(EXT, ExtendedDynamicState2, EXTENDED_DYNAMIC_STATE_2, extended_dynamic_state2) \ FEATURE(EXT, ExtendedDynamicState3, EXTENDED_DYNAMIC_STATE_3, extended_dynamic_state3) \ @@ -618,6 +619,11 @@ FN_MAX_LIMIT_LIST return extensions.depth_clamp_zero_one; } + /// Returns true if the device supports VK_EXT_depth_clip_enable. + bool IsExtDepthClipEnableSupported() const { + return extensions.depth_clip_enable; + } + /// Returns true if the device supports VK_EXT_depth_bias_control. bool IsExtDepthBiasControlSupported() const { return extensions.depth_bias_control;