Module: Mesa
Branch: main
Commit: bcc37775f1c3dc57f35eed3c739dc90a317d14aa
URL:    
http://cgit.freedesktop.org/mesa/mesa/commit/?id=bcc37775f1c3dc57f35eed3c739dc90a317d14aa

Author: Iago Toral Quiroga <[email protected]>
Date:   Fri Sep  2 08:49:12 2022 +0200

v3dv: implement VK_EXT_depth_clip_control

Reviewed-by: Alejandro PiƱeiro <[email protected]>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/18387>

---

 docs/features.txt                      |  2 +-
 src/broadcom/vulkan/v3dv_cmd_buffer.c  | 27 +++++++++++++++++++++++++++
 src/broadcom/vulkan/v3dv_device.c      |  8 ++++++++
 src/broadcom/vulkan/v3dv_pipeline.c    |  8 ++++++++
 src/broadcom/vulkan/v3dv_private.h     |  6 ++++++
 src/broadcom/vulkan/v3dv_uniforms.c    | 16 ++++++++++++----
 src/broadcom/vulkan/v3dvx_cmd_buffer.c | 20 +++++++++++++++-----
 7 files changed, 77 insertions(+), 10 deletions(-)

diff --git a/docs/features.txt b/docs/features.txt
index b48590053f1..c8a5b9b7560 100644
--- a/docs/features.txt
+++ b/docs/features.txt
@@ -545,7 +545,7 @@ Khronos extensions that are not part of any Vulkan version:
   VK_EXT_custom_border_color                            DONE (anv, lvp, panvk, 
radv, tu, v3dv, vn)
   VK_EXT_debug_marker                                   DONE (radv)
   VK_EXT_depth_clip_enable                              DONE (anv, lvp, radv, 
tu, vn)
-  VK_EXT_depth_clip_control                             DONE (anv, lvp, radv, 
tu)
+  VK_EXT_depth_clip_control                             DONE (anv, lvp, radv, 
tu, v3dv)
   VK_EXT_depth_range_unrestricted                       DONE (radv, lvp)
   VK_EXT_discard_rectangles                             DONE (radv)
   VK_EXT_display_control                                DONE (anv, radv, tu)
diff --git a/src/broadcom/vulkan/v3dv_cmd_buffer.c 
b/src/broadcom/vulkan/v3dv_cmd_buffer.c
index bb29d0b5f62..78ce5944311 100644
--- a/src/broadcom/vulkan/v3dv_cmd_buffer.c
+++ b/src/broadcom/vulkan/v3dv_cmd_buffer.c
@@ -2112,6 +2112,33 @@ v3dv_viewport_compute_xform(const VkViewport *viewport,
       scale[2] = min_abs_scale * (scale[2] < 0 ? -1.0f : 1.0f);
 }
 
+/* Considers the pipeline's negative_one_to_one state and applies it to the
+ * current viewport transform if needed to produce the resulting Z translate
+ * and scale parameters.
+ */
+void
+v3dv_cmd_buffer_state_get_viewport_z_xform(struct v3dv_cmd_buffer_state *state,
+                                           uint32_t vp_idx,
+                                           float *translate_z, float *scale_z)
+{
+   const struct v3dv_viewport_state *vp_state = &state->dynamic.viewport;
+
+   float t = vp_state->translate[vp_idx][2];
+   float s = vp_state->scale[vp_idx][2];
+
+   assert(state->gfx.pipeline);
+   if (state->gfx.pipeline->negative_one_to_one) {
+      t = (t + vp_state->viewports[vp_idx].maxDepth) * 0.5f;
+      s *= 0.5f;
+   }
+
+   if (translate_z)
+      *translate_z = t;
+
+   if (scale_z)
+      *scale_z = s;
+}
+
 VKAPI_ATTR void VKAPI_CALL
 v3dv_CmdSetViewport(VkCommandBuffer commandBuffer,
                     uint32_t firstViewport,
diff --git a/src/broadcom/vulkan/v3dv_device.c 
b/src/broadcom/vulkan/v3dv_device.c
index ec0fc4ed6f9..741c8d47e4c 100644
--- a/src/broadcom/vulkan/v3dv_device.c
+++ b/src/broadcom/vulkan/v3dv_device.c
@@ -169,6 +169,7 @@ get_device_extensions(const struct v3dv_physical_device 
*device,
       .EXT_border_color_swizzle             = true,
       .EXT_color_write_enable               = true,
       .EXT_custom_border_color              = true,
+      .EXT_depth_clip_control               = true,
       .EXT_inline_uniform_block             = true,
       .EXT_external_memory_dma_buf          = true,
       .EXT_host_query_reset                 = true,
@@ -1314,6 +1315,13 @@ v3dv_GetPhysicalDeviceFeatures2(VkPhysicalDevice 
physicalDevice,
          break;
       }
 
+      case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEPTH_CLIP_CONTROL_FEATURES_EXT: {
+         VkPhysicalDeviceDepthClipControlFeaturesEXT *features =
+            (VkPhysicalDeviceDepthClipControlFeaturesEXT *)ext;
+         features->depthClipControl = true;
+         break;
+      }
+
       default:
          v3dv_debug_ignored_stype(ext->sType);
          break;
diff --git a/src/broadcom/vulkan/v3dv_pipeline.c 
b/src/broadcom/vulkan/v3dv_pipeline.c
index 08bf637e011..717dfd8b6ca 100644
--- a/src/broadcom/vulkan/v3dv_pipeline.c
+++ b/src/broadcom/vulkan/v3dv_pipeline.c
@@ -2977,6 +2977,14 @@ pipeline_init(struct v3dv_pipeline *pipeline,
                                      PIPELINE_COLOR_WRITE_CREATE_INFO_EXT) :
                 NULL;
 
+   if (vp_info) {
+      const VkPipelineViewportDepthClipControlCreateInfoEXT 
*depth_clip_control =
+         vk_find_struct_const(vp_info->pNext,
+                              
PIPELINE_VIEWPORT_DEPTH_CLIP_CONTROL_CREATE_INFO_EXT);
+      if (depth_clip_control)
+         pipeline->negative_one_to_one = depth_clip_control->negativeOneToOne;
+   }
+
    pipeline_init_dynamic_state(pipeline,
                                pCreateInfo->pDynamicState,
                                vp_info, ds_info, cb_info, rs_info, cw_info);
diff --git a/src/broadcom/vulkan/v3dv_private.h 
b/src/broadcom/vulkan/v3dv_private.h
index a2196386fcc..7e536d8104c 100644
--- a/src/broadcom/vulkan/v3dv_private.h
+++ b/src/broadcom/vulkan/v3dv_private.h
@@ -1432,6 +1432,11 @@ struct v3dv_cmd_buffer_state {
    } query;
 };
 
+void
+v3dv_cmd_buffer_state_get_viewport_z_xform(struct v3dv_cmd_buffer_state *state,
+                                           uint32_t vp_idx,
+                                           float *translate_z, float *scale_z);
+
 /* The following struct represents the info from a descriptor that we store on
  * the host memory. They are mostly links to other existing vulkan objects,
  * like the image_view in order to access to swizzle info, or the buffer used
@@ -2077,6 +2082,7 @@ struct v3dv_pipeline {
    uint32_t sample_mask;
 
    bool primitive_restart;
+   bool negative_one_to_one;
 
    /* Accessed by binding. So vb[binding]->stride is the stride of the vertex
     * array with such binding
diff --git a/src/broadcom/vulkan/v3dv_uniforms.c 
b/src/broadcom/vulkan/v3dv_uniforms.c
index 425b84e0e1a..f3a98ab7ef0 100644
--- a/src/broadcom/vulkan/v3dv_uniforms.c
+++ b/src/broadcom/vulkan/v3dv_uniforms.c
@@ -527,13 +527,21 @@ v3dv_write_uniforms_wg_offsets(struct v3dv_cmd_buffer 
*cmd_buffer,
          cl_aligned_f(&uniforms, dynamic->viewport.scale[0][1] * 256.0f);
          break;
 
-      case QUNIFORM_VIEWPORT_Z_OFFSET:
-         cl_aligned_f(&uniforms, dynamic->viewport.translate[0][2]);
+      case QUNIFORM_VIEWPORT_Z_OFFSET: {
+         float translate_z;
+         v3dv_cmd_buffer_state_get_viewport_z_xform(&cmd_buffer->state, 0,
+                                                    &translate_z, NULL);
+         cl_aligned_f(&uniforms, translate_z);
          break;
+      }
 
-      case QUNIFORM_VIEWPORT_Z_SCALE:
-         cl_aligned_f(&uniforms, dynamic->viewport.scale[0][2]);
+      case QUNIFORM_VIEWPORT_Z_SCALE: {
+         float scale_z;
+         v3dv_cmd_buffer_state_get_viewport_z_xform(&cmd_buffer->state, 0,
+                                                    NULL, &scale_z);
+         cl_aligned_f(&uniforms, scale_z);
          break;
+      }
 
       case QUNIFORM_SSBO_OFFSET:
       case QUNIFORM_UBO_ADDR:
diff --git a/src/broadcom/vulkan/v3dvx_cmd_buffer.c 
b/src/broadcom/vulkan/v3dvx_cmd_buffer.c
index 89f3b5a4ab4..3b283e2ad96 100644
--- a/src/broadcom/vulkan/v3dvx_cmd_buffer.c
+++ b/src/broadcom/vulkan/v3dvx_cmd_buffer.c
@@ -1008,6 +1008,9 @@ void
 v3dX(cmd_buffer_emit_viewport)(struct v3dv_cmd_buffer *cmd_buffer)
 {
    struct v3dv_dynamic_state *dynamic = &cmd_buffer->state.dynamic;
+   struct v3dv_pipeline *pipeline = cmd_buffer->state.gfx.pipeline;
+   assert(pipeline);
+
    /* FIXME: right now we only support one viewport. viewporst[0] would work
     * now, would need to change if we allow multiple viewports
     */
@@ -1030,14 +1033,21 @@ v3dX(cmd_buffer_emit_viewport)(struct v3dv_cmd_buffer 
*cmd_buffer)
       clip.viewport_half_height_in_1_256th_of_pixel = vpscale[1] * 256.0f;
    }
 
+   float translate_z, scale_z;
+   v3dv_cmd_buffer_state_get_viewport_z_xform(&cmd_buffer->state, 0,
+                                              &translate_z, &scale_z);
+
    cl_emit(&job->bcl, CLIPPER_Z_SCALE_AND_OFFSET, clip) {
-      clip.viewport_z_offset_zc_to_zs = vptranslate[2];
-      clip.viewport_z_scale_zc_to_zs = vpscale[2];
+      clip.viewport_z_offset_zc_to_zs = translate_z;
+      clip.viewport_z_scale_zc_to_zs = scale_z;
    }
    cl_emit(&job->bcl, CLIPPER_Z_MIN_MAX_CLIPPING_PLANES, clip) {
-      /* Vulkan's Z NDC is [0..1], unlile OpenGL which is [-1, 1] */
-      float z1 = vptranslate[2];
-      float z2 = vptranslate[2] + vpscale[2];
+      /* Vulkan's default Z NDC is [0..1]. If 'negative_one_to_one' is enabled,
+       * we are using OpenGL's [-1, 1] instead.
+       */
+      float z1 = pipeline->negative_one_to_one ? translate_z - scale_z :
+                                                 translate_z;
+      float z2 = translate_z + scale_z;
       clip.minimum_zw = MIN2(z1, z2);
       clip.maximum_zw = MAX2(z1, z2);
    }

Reply via email to