diff --git a/docs/features.txt b/docs/features.txt index 1f276d7fc2c..c7e38b2e561 100644 --- a/docs/features.txt +++ b/docs/features.txt @@ -677,7 +677,7 @@ Khronos extensions that are not part of any Vulkan version: VK_ARM_rasterization_order_attachment_access DONE (lvp, tu) VK_EXT_mutable_descriptor_type DONE (anv, lvp, nvk, radv, tu, vn) VK_EXT_swapchain_colorspace DONE (anv, lvp, nvk, radv, tu, v3dv) - VK_EXT_depth_clamp_zero_one DONE (anv, radv, tu, v3dv/vc7+) + VK_EXT_depth_clamp_zero_one DONE (anv, nvk, radv, tu, v3dv/vc7+) VK_INTEL_shader_integer_functions2 DONE (anv, hasvk, radv) VK_KHR_map_memory2 DONE (anv, nvk, radv, tu) VK_EXT_map_memory_placed DONE (anv, nvk, radv, tu) diff --git a/docs/relnotes/new_features.txt b/docs/relnotes/new_features.txt index 443cb2f96e7..06d44f65c6c 100644 --- a/docs/relnotes/new_features.txt +++ b/docs/relnotes/new_features.txt @@ -25,3 +25,4 @@ GL_EXT_draw_buffers2 on etnaviv/HALTI5+ GL_ARB_draw_buffers_blend on etnaviv/HALTI5+ VK_KHR_fragment_shading_rate on NVK GL_ARB_draw_indirect on etnaviv/HALTI5+ +VK_EXT_depth_clamp_zero_one on NVK diff --git a/src/nouveau/vulkan/nvk_cmd_draw.c b/src/nouveau/vulkan/nvk_cmd_draw.c index 0e93609583f..3a5c5696142 100644 --- a/src/nouveau/vulkan/nvk_cmd_draw.c +++ b/src/nouveau/vulkan/nvk_cmd_draw.c @@ -599,6 +599,10 @@ nvk_cmd_buffer_dirty_render_pass(struct nvk_cmd_buffer *cmd) /* This may depend on render targets */ BITSET_SET(dyn->dirty, MESA_VK_DYNAMIC_COLOR_ATTACHMENT_MAP); + + /* Might be required for depthClampZeroOne */ + BITSET_SET(dyn->dirty, MESA_VK_DYNAMIC_RS_DEPTH_CLAMP_ENABLE); + BITSET_SET(dyn->dirty, MESA_VK_DYNAMIC_RS_DEPTH_CLIP_ENABLE); } static void @@ -1777,6 +1781,8 @@ nvk_flush_ts_state(struct nvk_cmd_buffer *cmd) static void nvk_flush_vp_state(struct nvk_cmd_buffer *cmd) { + const struct nvk_device *dev = nvk_cmd_buffer_device(cmd); + const struct vk_dynamic_graphics_state *dyn = &cmd->vk.dynamic_graphics_state; @@ -1835,6 +1841,11 @@ nvk_flush_vp_state(struct nvk_cmd_buffer *cmd) ymin = CLAMP(ymin, 0, max_dim); ymax = CLAMP(ymax, 0, max_dim); + if (!dev->vk.enabled_extensions.EXT_depth_range_unrestricted) { + assert(0.0 <= zmin && zmin <= 1.0); + assert(0.0 <= zmax && zmax <= 1.0); + } + P_MTHD(p, NV9097, SET_VIEWPORT_CLIP_HORIZONTAL(i)); P_NV9097_SET_VIEWPORT_CLIP_HORIZONTAL(p, i, { .x0 = xmin, @@ -2026,10 +2037,13 @@ nvk_mme_set_z_clamp(struct mme_builder *b) static void nvk_flush_rs_state(struct nvk_cmd_buffer *cmd) { - struct nv_push *p = nvk_cmd_buffer_push(cmd, 46); - + const struct nvk_device *dev = nvk_cmd_buffer_device(cmd); const struct vk_dynamic_graphics_state *dyn = &cmd->vk.dynamic_graphics_state; + const struct nvk_rendering_state *render = + &cmd->state.gfx.render; + + struct nv_push *p = nvk_cmd_buffer_push(cmd, 46); if (BITSET_TEST(dyn->dirty, MESA_VK_DYNAMIC_RS_RASTERIZER_DISCARD_ENABLE)) P_IMMD(p, NV9097, SET_RASTER_ENABLE, !dyn->rs.rasterizer_discard_enable); @@ -2038,12 +2052,39 @@ nvk_flush_rs_state(struct nvk_cmd_buffer *cmd) BITSET_TEST(dyn->dirty, MESA_VK_DYNAMIC_RS_DEPTH_CLAMP_ENABLE)) { const bool z_clamp = dyn->rs.depth_clamp_enable; const bool z_clip = vk_rasterization_state_depth_clip_enable(&dyn->rs); + /* z_clamp_zero_one accounts for the interaction between + * depthClampZeroOne and depthRangeUnrestricted as mentioned in the + * Vulkan spec. depthClampZeroOne adds an additional clamp and doesn't + * modify the clip/clamp threshold. We are expected to clamp to [0,1] + * when any one of these conditions are fulfilled: + * - depth_range_unrestricted is not enabled + * - depthClampZeroOne is enabled but depth + * format is not floating point or depthRangeUnrestricted + * is not enabled + * - fixed point depth format + */ + const bool z_clamp_zero_one = + !vk_format_has_float_depth(render->depth_att.vk_format) || + (dev->vk.enabled_features.depthClampZeroOne && + !dev->vk.enabled_extensions.EXT_depth_range_unrestricted); + P_IMMD(p, NVC397, SET_VIEWPORT_CLIP_CONTROL, { /* We only set Z clip range if clamp is requested. Otherwise, we * leave it set to -/+INF and clip using the guardband below. + * + * depthClampZeroOne is independent of normal depth clamping and + * does not modify the clip/clamp threshold. The Vulkan spec + * guarantees that, in the cases where depthClampZeroOne applies, + * the [zmin, zmax] is inside [0, 1]. This means that, if z_clamp + * is enabled, we can just do the regular clamp. If z_clamp is + * disabled and z_clamp_zero_one is enabled then we need to + * apply the [0, 1] clamp. */ - .min_z_zero_max_z_one = MIN_Z_ZERO_MAX_Z_ONE_FALSE, - .z_clip_range = nvk_cmd_buffer_3d_cls(cmd) >= VOLTA_A + .min_z_zero_max_z_one = (!z_clamp && z_clamp_zero_one) + ? MIN_Z_ZERO_MAX_Z_ONE_TRUE + : MIN_Z_ZERO_MAX_Z_ONE_FALSE, + .z_clip_range = (nvk_cmd_buffer_3d_cls(cmd) >= VOLTA_A && + (z_clamp || !z_clamp_zero_one)) ? (z_clamp ? Z_CLIP_RANGE_MIN_Z_MAX_Z : Z_CLIP_RANGE_MINUS_INF_PLUS_INF) : Z_CLIP_RANGE_USE_FIELD_MIN_Z_ZERO_MAX_Z_ONE, diff --git a/src/nouveau/vulkan/nvk_physical_device.c b/src/nouveau/vulkan/nvk_physical_device.c index 193ad11d3d4..fe30ac5536d 100644 --- a/src/nouveau/vulkan/nvk_physical_device.c +++ b/src/nouveau/vulkan/nvk_physical_device.c @@ -191,6 +191,7 @@ nvk_get_device_extensions(const struct nvk_instance *instance, .EXT_custom_border_color = true, .EXT_depth_bias_control = true, .EXT_depth_clamp_control = true, + .EXT_depth_clamp_zero_one = true, .EXT_depth_clip_control = true, .EXT_depth_clip_enable = true, .EXT_depth_range_unrestricted = info->cls_eng3d >= VOLTA_A, @@ -527,6 +528,9 @@ nvk_get_device_features(const struct nv_device_info *info, /* VK_EXT_depth_clamp_control */ .depthClampControl = true, + /* VK_EXT_depth_clamp_zero_one */ + .depthClampZeroOne = true, + /* VK_EXT_depth_clip_control */ .depthClipControl = true,