Mesa (main): d3d12: Support clip halfz

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Fri Jul 22 00:17:40 UTC 2022


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

Author: Jesse Natalie <jenatali at microsoft.com>
Date:   Mon Feb  7 09:49:33 2022 -0800

d3d12: Support clip halfz

Reviewed-by: Giancarlo Devich <gdevich at microsoft.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/17567>

---

 docs/features.txt                               |  2 +-
 src/gallium/drivers/d3d12/ci/d3d12-quick_gl.txt |  7 ++-----
 src/gallium/drivers/d3d12/d3d12_compiler.cpp    | 10 +++++++---
 src/gallium/drivers/d3d12/d3d12_compiler.h      |  1 +
 src/gallium/drivers/d3d12/d3d12_context.cpp     | 18 +++++++++++++++++-
 src/gallium/drivers/d3d12/d3d12_nir_passes.c    | 14 ++++++++++----
 src/gallium/drivers/d3d12/d3d12_nir_passes.h    |  2 +-
 src/gallium/drivers/d3d12/d3d12_screen.cpp      |  1 +
 8 files changed, 40 insertions(+), 15 deletions(-)

diff --git a/docs/features.txt b/docs/features.txt
index 47ba684337e..56b8adacdf2 100644
--- a/docs/features.txt
+++ b/docs/features.txt
@@ -213,7 +213,7 @@ GL 4.4, GLSL 4.40 -- all DONE: i965/gen8+, nvc0, r600, radeonsi, llvmpipe, zink
 GL 4.5, GLSL 4.50 -- all DONE: nvc0, r600, radeonsi, llvmpipe, zink
 
   GL_ARB_ES3_1_compatibility                            DONE (i965/hsw+, softpipe, virgl)
-  GL_ARB_clip_control                                   DONE (freedreno, i965, nv50, softpipe, virgl, lima)
+  GL_ARB_clip_control                                   DONE (freedreno, i965, nv50, softpipe, virgl, lima, d3d12)
   GL_ARB_conditional_render_inverted                    DONE (freedreno, i965, nv50, softpipe, virgl, panfrost, d3d12)
   GL_ARB_cull_distance                                  DONE (freedreno/a6xx, i965, nv50, softpipe, virgl)
   GL_ARB_derivative_control                             DONE (i965, nv50, softpipe, virgl)
diff --git a/src/gallium/drivers/d3d12/ci/d3d12-quick_gl.txt b/src/gallium/drivers/d3d12/ci/d3d12-quick_gl.txt
index c6dbead427b..61c1d393f9f 100644
--- a/src/gallium/drivers/d3d12/ci/d3d12-quick_gl.txt
+++ b/src/gallium/drivers/d3d12/ci/d3d12-quick_gl.txt
@@ -319,9 +319,6 @@ spec/arb_clear_texture/arb_clear_texture-sized-formats: skip
 spec/arb_clear_texture/arb_clear_texture-srgb: skip
 spec/arb_clear_texture/arb_clear_texture-stencil: skip
 spec/arb_clear_texture/arb_clear_texture-texview: skip
-spec/arb_clip_control/arb_clip_control-clip-control: skip
-spec/arb_clip_control/arb_clip_control-depth-precision: skip
-spec/arb_clip_control/arb_clip_control-viewport: skip
 spec/arb_compute_shader/compute-and-render-bug-109630: fail
 spec/arb_copy_image/arb_copy_image-api_errors: skip
 spec/arb_copy_image/arb_copy_image-format-swizzle: skip
@@ -3515,10 +3512,10 @@ wgl/wgl-sanity: skip
 summary:
        name:  results
        ----  --------
-       pass:    17870
+       pass:    17873
        fail:     2035
       crash:       12
-       skip:     1448
+       skip:     1445
     timeout:        0
        warn:       10
  incomplete:        0
diff --git a/src/gallium/drivers/d3d12/d3d12_compiler.cpp b/src/gallium/drivers/d3d12/d3d12_compiler.cpp
index b88255b1368..d6f9620bedc 100644
--- a/src/gallium/drivers/d3d12/d3d12_compiler.cpp
+++ b/src/gallium/drivers/d3d12/d3d12_compiler.cpp
@@ -123,8 +123,9 @@ compile_nir(struct d3d12_context *ctx, struct d3d12_shader_selector *sel,
 
    if (key->last_vertex_processing_stage) {
       if (key->invert_depth)
-         NIR_PASS_V(nir, d3d12_nir_invert_depth, key->invert_depth);
-      NIR_PASS_V(nir, nir_lower_clip_halfz);
+         NIR_PASS_V(nir, d3d12_nir_invert_depth, key->invert_depth, key->halfz);
+      if (!key->halfz)
+         NIR_PASS_V(nir, nir_lower_clip_halfz);
       NIR_PASS_V(nir, d3d12_lower_yflip);
    }
    NIR_PASS_V(nir, nir_lower_packed_ubo_loads);
@@ -790,7 +791,8 @@ d3d12_compare_shader_keys(const d3d12_shader_key *expect, const d3d12_shader_key
       expect->n_images * sizeof(struct d3d12_image_format_conversion_info)))
       return false;
 
-   if (expect->invert_depth != have->invert_depth)
+   if (expect->invert_depth != have->invert_depth ||
+       expect->halfz != have->halfz)
       return false;
 
    if (expect->stage == PIPE_SHADER_VERTEX) {
@@ -930,6 +932,8 @@ d3d12_fill_shader_key(struct d3d12_selection_context *sel_ctx,
           (!next || next->stage == PIPE_SHADER_FRAGMENT))) {
       key->last_vertex_processing_stage = 1;
       key->invert_depth = sel_ctx->ctx->reverse_depth_range;
+      key->halfz = sel_ctx->ctx->gfx_pipeline_state.rast ?
+         sel_ctx->ctx->gfx_pipeline_state.rast->base.clip_halfz : false;
       if (sel_ctx->ctx->pstipple.enabled &&
          sel_ctx->ctx->gfx_pipeline_state.rast->base.poly_stipple_enable)
          key->next_varying_inputs |= VARYING_BIT_POS;
diff --git a/src/gallium/drivers/d3d12/d3d12_compiler.h b/src/gallium/drivers/d3d12/d3d12_compiler.h
index aed79f95c1e..20298e2353f 100644
--- a/src/gallium/drivers/d3d12/d3d12_compiler.h
+++ b/src/gallium/drivers/d3d12/d3d12_compiler.h
@@ -92,6 +92,7 @@ struct d3d12_shader_key {
    uint64_t prev_varying_outputs;
    unsigned last_vertex_processing_stage : 1;
    unsigned invert_depth : 16;
+   unsigned halfz : 1;
    unsigned samples_int_textures : 1;
    unsigned input_clip_size : 4;
    unsigned tex_saturate_s : PIPE_MAX_SAMPLERS;
diff --git a/src/gallium/drivers/d3d12/d3d12_context.cpp b/src/gallium/drivers/d3d12/d3d12_context.cpp
index 1b84a68d23f..fa4ab2dffca 100644
--- a/src/gallium/drivers/d3d12/d3d12_context.cpp
+++ b/src/gallium/drivers/d3d12/d3d12_context.cpp
@@ -1313,9 +1313,25 @@ d3d12_set_viewport_states(struct pipe_context *pctx,
       ctx->viewports[start_slot + i].TopLeftX = state[i].translate[0] - state[i].scale[0];
       ctx->viewports[start_slot + i].Width = state[i].scale[0] * 2;
 
-      float near_depth = state[i].translate[2] - state[i].scale[2];
+      float near_depth = state[i].translate[2];
       float far_depth = state[i].translate[2] + state[i].scale[2];
 
+      /* When the rasterizer is configured for "full" depth clipping ([-1, 1])
+       * the viewport that we get is set to cover the positive half of clip space.
+       * E.g. a [0, 1] viewport from the GL API will come to the driver as [0.5, 1].
+       * Since we halve clipping space from [-1, 1] to [0, 1], we need to double the
+       * viewport, treating translate as the center instead of the near plane. When
+       * the rasterizer is configured for "half" depth clipping ([0, 1]), the viewport
+       * covers the entire clip range, so no fixup is needed.
+       * 
+       * Note: If halfz mode changes, both the rasterizer and viewport are dirtied,
+       * and on the next draw we will get the rasterizer state first, and viewport
+       * second, because ST_NEW_RASTERIZER comes before ST_NEW_VIEWPORT.
+       */
+      if (ctx->gfx_pipeline_state.rast && !ctx->gfx_pipeline_state.rast->base.clip_halfz) {
+         near_depth -= state[i].scale[2];
+      }
+
       bool reverse_depth_range = near_depth > far_depth;
       if (reverse_depth_range) {
          float tmp = near_depth;
diff --git a/src/gallium/drivers/d3d12/d3d12_nir_passes.c b/src/gallium/drivers/d3d12/d3d12_nir_passes.c
index 9dddadaf9ee..3859abf955d 100644
--- a/src/gallium/drivers/d3d12/d3d12_nir_passes.c
+++ b/src/gallium/drivers/d3d12/d3d12_nir_passes.c
@@ -391,6 +391,7 @@ d3d12_lower_load_patch_vertices_in(struct nir_shader *nir)
 struct invert_depth_state
 {
    unsigned viewport_mask;
+   bool clip_halfz;
    nir_ssa_def *viewport_index;
    nir_instr *store_pos_instr;
 };
@@ -415,10 +416,14 @@ invert_depth_impl(nir_builder *b, struct invert_depth_state *state)
    if (state->viewport_index) {
       nir_push_if(b, nir_test_mask(b, nir_ishl(b, nir_imm_int(b, 1), state->viewport_index), state->viewport_mask));
    }
+   nir_ssa_def *old_depth = nir_channel(b, pos, 2);
+   nir_ssa_def *new_depth = nir_fneg(b, old_depth);
+   if (state->clip_halfz)
+      new_depth = nir_fadd_imm(b, new_depth, 1.0);
    nir_ssa_def *def = nir_vec4(b,
                                nir_channel(b, pos, 0),
                                nir_channel(b, pos, 1),
-                               nir_fneg(b, nir_channel(b, pos, 2)),
+                               new_depth,
                                nir_channel(b, pos, 3));
    if (state->viewport_index) {
       nir_pop_if(b, NULL);
@@ -453,19 +458,20 @@ invert_depth_instr(nir_builder *b, struct nir_instr *instr, struct invert_depth_
 }
 
 /* In OpenGL the windows space depth value z_w is evaluated according to "s * z_d + b"
- * with  "s + (far - near) / 2" (depth clip:minus_one_to_one) [OpenGL 3.3, 2.13.1].
+ * with  "s = (far - near) / 2" (depth clip:minus_one_to_one) [OpenGL 3.3, 2.13.1].
  * When we switch the far and near value to satisfy DirectX requirements we have
  * to compensate by inverting "z_d' = -z_d" with this lowering pass.
+ * When depth clip is set zero_to_one, we compensate with "z_d' = 1.0f - z_d" instead.
  */
 void
-d3d12_nir_invert_depth(nir_shader *shader, unsigned viewport_mask)
+d3d12_nir_invert_depth(nir_shader *shader, unsigned viewport_mask, bool clip_halfz)
 {
    if (shader->info.stage != MESA_SHADER_VERTEX &&
        shader->info.stage != MESA_SHADER_TESS_EVAL &&
        shader->info.stage != MESA_SHADER_GEOMETRY)
       return;
 
-   struct invert_depth_state state = { viewport_mask };
+   struct invert_depth_state state = { viewport_mask, clip_halfz };
    nir_foreach_function(function, shader) {
       if (function->impl) {
          nir_builder b;
diff --git a/src/gallium/drivers/d3d12/d3d12_nir_passes.h b/src/gallium/drivers/d3d12/d3d12_nir_passes.h
index 818b12abf31..62034f0b85f 100644
--- a/src/gallium/drivers/d3d12/d3d12_nir_passes.h
+++ b/src/gallium/drivers/d3d12/d3d12_nir_passes.h
@@ -88,7 +88,7 @@ bool
 d3d12_fix_io_uint_type(struct nir_shader *s, uint64_t in_mask, uint64_t out_mask);
 
 void
-d3d12_nir_invert_depth(nir_shader *s, unsigned viewport_mask);
+d3d12_nir_invert_depth(nir_shader *s, unsigned viewport_mask, bool clip_halfz);
 
 bool
 nir_lower_packed_ubo_loads(struct nir_shader *nir);
diff --git a/src/gallium/drivers/d3d12/d3d12_screen.cpp b/src/gallium/drivers/d3d12/d3d12_screen.cpp
index 88f8209709a..11dc0c35b2d 100644
--- a/src/gallium/drivers/d3d12/d3d12_screen.cpp
+++ b/src/gallium/drivers/d3d12/d3d12_screen.cpp
@@ -329,6 +329,7 @@ d3d12_get_param(struct pipe_screen *pscreen, enum pipe_cap param)
    case PIPE_CAP_MEMOBJ:
    case PIPE_CAP_FENCE_SIGNAL:
    case PIPE_CAP_TIMELINE_SEMAPHORE_IMPORT:
+   case PIPE_CAP_CLIP_HALFZ:
       return 1;
 
    case PIPE_CAP_MAX_VERTEX_STREAMS:



More information about the mesa-commit mailing list