From 203afc9351b2b79dbe8865481b18cceeba02a2a2 Mon Sep 17 00:00:00 2001 From: Samuel Pitoiset Date: Thu, 5 May 2022 16:53:13 +0200 Subject: [PATCH] radv: disable viewport depth clamping only when necessary MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When the application uses depth values outside of the [0.0,1.0] range with VK_EXT_depth_range_unrestricted, or when explicitly disabled. Otherwise, the driver can clamp to [0.0,1.0] internally for optimal performance. From the Vulkan spec "in 28.10.1. Depth Clamping and Range Adjustment": "If depth clamping is not enabled and zf is not in the range [0, 1] and either VK_EXT_depth_range_unrestricted is not enabled, or the depth attachment has a fixed-point format, then zf is undefined following this step." Signed-off-by: Samuel Pitoiset Reviewed-by: Timur Kristóf Part-of: --- src/amd/vulkan/radv_cmd_buffer.c | 16 ++++++++++++---- src/amd/vulkan/radv_pipeline.c | 32 +++++++++++++++++--------------- src/amd/vulkan/radv_private.h | 7 +++++++ 3 files changed, 36 insertions(+), 19 deletions(-) diff --git a/src/amd/vulkan/radv_cmd_buffer.c b/src/amd/vulkan/radv_cmd_buffer.c index 8f39dacbec3..7c1c90d72f6 100644 --- a/src/amd/vulkan/radv_cmd_buffer.c +++ b/src/amd/vulkan/radv_cmd_buffer.c @@ -1426,7 +1426,7 @@ radv_emit_graphics_pipeline(struct radv_cmd_buffer *cmd_buffer) static void radv_emit_viewport(struct radv_cmd_buffer *cmd_buffer) { - bool negative_one_to_one = cmd_buffer->state.graphics_pipeline->negative_one_to_one; + const struct radv_graphics_pipeline *pipeline = cmd_buffer->state.graphics_pipeline; const struct radv_viewport_state *viewport = &cmd_buffer->state.dynamic.viewport; int i; const unsigned count = viewport->count; @@ -1441,7 +1441,7 @@ radv_emit_viewport(struct radv_cmd_buffer *cmd_buffer) radeon_emit(cmd_buffer->cs, fui(viewport->xform[i].translate[1])); double scale_z, translate_z; - if (negative_one_to_one) { + if (pipeline->negative_one_to_one) { scale_z = viewport->xform[i].scale[2] * 0.5f; translate_z = (viewport->xform[i].translate[2] + viewport->viewports[i].maxDepth) * 0.5f; } else { @@ -1455,8 +1455,16 @@ radv_emit_viewport(struct radv_cmd_buffer *cmd_buffer) radeon_set_context_reg_seq(cmd_buffer->cs, R_0282D0_PA_SC_VPORT_ZMIN_0, count * 2); for (i = 0; i < count; i++) { - float zmin = MIN2(viewport->viewports[i].minDepth, viewport->viewports[i].maxDepth); - float zmax = MAX2(viewport->viewports[i].minDepth, viewport->viewports[i].maxDepth); + float zmin, zmax; + + if (pipeline->depth_clamp_mode == RADV_DEPTH_CLAMP_MODE_ZERO_TO_ONE) { + zmin = 0.0f; + zmax = 1.0f; + } else { + zmin = MIN2(viewport->viewports[i].minDepth, viewport->viewports[i].maxDepth); + zmax = MAX2(viewport->viewports[i].minDepth, viewport->viewports[i].maxDepth); + } + radeon_emit(cmd_buffer->cs, fui(zmin)); radeon_emit(cmd_buffer->cs, fui(zmax)); } diff --git a/src/amd/vulkan/radv_pipeline.c b/src/amd/vulkan/radv_pipeline.c index 2fe53407d2f..c9a2cd88f58 100644 --- a/src/amd/vulkan/radv_pipeline.c +++ b/src/amd/vulkan/radv_pipeline.c @@ -2145,7 +2145,7 @@ static void radv_pipeline_init_raster_state(struct radv_graphics_pipeline *pipeline, const struct radv_graphics_pipeline_info *info) { - const struct radv_physical_device *pdevice = pipeline->base.device->physical_device; + const struct radv_device *device = pipeline->base.device; pipeline->pa_su_sc_mode_cntl = S_028814_FACE(info->rs.front_face) | @@ -2159,7 +2159,7 @@ radv_pipeline_init_raster_state(struct radv_graphics_pipeline *pipeline, S_028814_POLY_OFFSET_PARA_ENABLE(info->rs.depth_bias_enable) | S_028814_PROVOKING_VTX_LAST(info->rs.provoking_vtx_last); - if (pdevice->rad_info.gfx_level >= GFX10) { + if (device->physical_device->rad_info.gfx_level >= GFX10) { /* It should also be set if PERPENDICULAR_ENDCAP_ENA is set. */ pipeline->pa_su_sc_mode_cntl |= S_028814_KEEP_TOGETHER_ENABLE(info->rs.polygon_mode != V_028814_X_DRAW_TRIANGLES); @@ -2174,6 +2174,20 @@ radv_pipeline_init_raster_state(struct radv_graphics_pipeline *pipeline, pipeline->uses_conservative_overestimate = info->rs.conservative_mode == VK_CONSERVATIVE_RASTERIZATION_MODE_OVERESTIMATE_EXT; + + pipeline->depth_clamp_mode = RADV_DEPTH_CLAMP_MODE_VIEWPORT; + if (!info->rs.depth_clamp_enable) { + /* For optimal performance, depth clamping should always be enabled except if the + * application disables clamping explicitly or uses depth values outside of the [0.0, 1.0] + * range. + */ + if (info->rs.depth_clip_disable || + device->vk.enabled_extensions.EXT_depth_range_unrestricted) { + pipeline->depth_clamp_mode = RADV_DEPTH_CLAMP_MODE_DISABLED; + } else { + pipeline->depth_clamp_mode = RADV_DEPTH_CLAMP_MODE_ZERO_TO_ONE; + } + } } static struct radv_depth_stencil_state @@ -2181,7 +2195,6 @@ radv_pipeline_init_depth_stencil_state(struct radv_graphics_pipeline *pipeline, const struct radv_graphics_pipeline_info *info) { const struct radv_physical_device *pdevice = pipeline->base.device->physical_device; - struct radv_shader *ps = pipeline->base.shaders[MESA_SHADER_FRAGMENT]; struct radv_depth_stencil_state ds_state = {0}; uint32_t db_depth_control = 0; @@ -2210,19 +2223,8 @@ radv_pipeline_init_depth_stencil_state(struct radv_graphics_pipeline *pipeline, ds_state.db_render_override |= S_02800C_FORCE_HIS_ENABLE0(V_02800C_FORCE_DISABLE) | S_02800C_FORCE_HIS_ENABLE1(V_02800C_FORCE_DISABLE); - if (!info->rs.depth_clamp_enable && ps->info.ps.writes_z) { - /* From VK_EXT_depth_range_unrestricted spec: - * - * "The behavior described in Primitive Clipping still applies. - * If depth clamping is disabled the depth values are still - * clipped to 0 ≤ zc ≤ wc before the viewport transform. If - * depth clamping is enabled the above equation is ignored and - * the depth values are instead clamped to the VkViewport - * minDepth and maxDepth values, which in the case of this - * extension can be outside of the 0.0 to 1.0 range." - */ + if (pipeline->depth_clamp_mode == RADV_DEPTH_CLAMP_MODE_DISABLED) ds_state.db_render_override |= S_02800C_DISABLE_VIEWPORT_CLAMP(1); - } if (pdevice->rad_info.gfx_level >= GFX11) { unsigned max_allowed_tiles_in_wave = 0; diff --git a/src/amd/vulkan/radv_private.h b/src/amd/vulkan/radv_private.h index 10f54a6f2b2..a6a5c645728 100644 --- a/src/amd/vulkan/radv_private.h +++ b/src/amd/vulkan/radv_private.h @@ -2078,6 +2078,12 @@ struct radv_graphics_pipeline_info { uint8_t ds_att_samples; }; +enum radv_depth_clamp_mode { + RADV_DEPTH_CLAMP_MODE_VIEWPORT = 0, /* Clamp to the viewport min/max depth bounds */ + RADV_DEPTH_CLAMP_MODE_ZERO_TO_ONE = 1, /* Clamp between 0.0f and 1.0f */ + RADV_DEPTH_CLAMP_MODE_DISABLED = 2, /* Disable depth clamping */ +}; + struct radv_pipeline { struct vk_object_base base; enum radv_pipeline_type type; @@ -2153,6 +2159,7 @@ struct radv_graphics_pipeline { bool uses_dynamic_stride; bool uses_conservative_overestimate; bool negative_one_to_one; + enum radv_depth_clamp_mode depth_clamp_mode; bool use_per_attribute_vb_descs; bool can_use_simple_input; bool uses_user_sample_locations;