Mesa (main): d3d12: Update depth invert to deal with multi-viewport

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Fri Feb 4 21:01:14 UTC 2022


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

Author: Jesse Natalie <jenatali at microsoft.com>
Date:   Fri Feb  4 07:10:54 2022 -0800

d3d12: Update depth invert to deal with multi-viewport

Turn the context state and shader key into a bitmask. When lowering
the depth invert into the shader, scan for writes to viewport index.
If found, move position to the end of the function (or current vertex)
and check if the current viewport needs the depth invert before applying.

Reviewed-by: Sil Vilerino <sivileri at microsoft.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/14881>

---

 src/gallium/drivers/d3d12/d3d12_compiler.cpp |  2 +-
 src/gallium/drivers/d3d12/d3d12_compiler.h   |  2 +-
 src/gallium/drivers/d3d12/d3d12_context.cpp  |  8 +--
 src/gallium/drivers/d3d12/d3d12_context.h    |  2 +-
 src/gallium/drivers/d3d12/d3d12_nir_passes.c | 74 ++++++++++++++++++++++------
 src/gallium/drivers/d3d12/d3d12_nir_passes.h |  2 +-
 6 files changed, 69 insertions(+), 21 deletions(-)

diff --git a/src/gallium/drivers/d3d12/d3d12_compiler.cpp b/src/gallium/drivers/d3d12/d3d12_compiler.cpp
index 37c705856a6..ff3a105502a 100644
--- a/src/gallium/drivers/d3d12/d3d12_compiler.cpp
+++ b/src/gallium/drivers/d3d12/d3d12_compiler.cpp
@@ -165,7 +165,7 @@ 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);
+         NIR_PASS_V(nir, d3d12_nir_invert_depth, key->invert_depth);
       NIR_PASS_V(nir, nir_lower_clip_halfz);
       NIR_PASS_V(nir, d3d12_lower_yflip);
    }
diff --git a/src/gallium/drivers/d3d12/d3d12_compiler.h b/src/gallium/drivers/d3d12/d3d12_compiler.h
index b14f9e39ff7..de16ff23711 100644
--- a/src/gallium/drivers/d3d12/d3d12_compiler.h
+++ b/src/gallium/drivers/d3d12/d3d12_compiler.h
@@ -94,7 +94,7 @@ struct d3d12_shader_key {
    uint64_t next_varying_inputs;
    uint64_t prev_varying_outputs;
    unsigned last_vertex_processing_stage : 1;
-   unsigned invert_depth : 1;
+   unsigned invert_depth : 16;
    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 aec5501d721..3a2d6ee3731 100644
--- a/src/gallium/drivers/d3d12/d3d12_context.cpp
+++ b/src/gallium/drivers/d3d12/d3d12_context.cpp
@@ -1300,12 +1300,14 @@ d3d12_set_viewport_states(struct pipe_context *pctx,
       float near_depth = state[i].translate[2] - state[i].scale[2];
       float far_depth = state[i].translate[2] + state[i].scale[2];
 
-      ctx->reverse_depth_range = near_depth > far_depth;
-      if (ctx->reverse_depth_range) {
+      bool reverse_depth_range = near_depth > far_depth;
+      if (reverse_depth_range) {
          float tmp = near_depth;
          near_depth = far_depth;
          far_depth = tmp;
-      }
+         ctx->reverse_depth_range |= (1 << (start_slot + i));
+      } else
+         ctx->reverse_depth_range &= ~(1 << (start_slot + i));
       ctx->viewports[start_slot + i].MinDepth = near_depth;
       ctx->viewports[start_slot + i].MaxDepth = far_depth;
       ctx->viewport_states[start_slot + i] = state[i];
diff --git a/src/gallium/drivers/d3d12/d3d12_context.h b/src/gallium/drivers/d3d12/d3d12_context.h
index befbbdd0eb7..2fdb5f8d6ba 100644
--- a/src/gallium/drivers/d3d12/d3d12_context.h
+++ b/src/gallium/drivers/d3d12/d3d12_context.h
@@ -234,7 +234,7 @@ struct d3d12_context {
    unsigned cmdlist_dirty;
    ID3D12PipelineState *current_gfx_pso;
    ID3D12PipelineState *current_compute_pso;
-   bool reverse_depth_range;
+   uint16_t reverse_depth_range;
 
    ID3D12Fence *cmdqueue_fence;
    uint64_t fence_value;
diff --git a/src/gallium/drivers/d3d12/d3d12_nir_passes.c b/src/gallium/drivers/d3d12/d3d12_nir_passes.c
index e0b30d20545..3532a9dcd05 100644
--- a/src/gallium/drivers/d3d12/d3d12_nir_passes.c
+++ b/src/gallium/drivers/d3d12/d3d12_nir_passes.c
@@ -388,30 +388,70 @@ d3d12_lower_load_patch_vertices_in(struct nir_shader *nir)
       nir_metadata_block_index | nir_metadata_dominance, &var);
 }
 
-static void
-invert_depth(nir_builder *b, struct nir_instr *instr)
+struct invert_depth_state
 {
-   if (instr->type != nir_instr_type_intrinsic)
-      return;
-
-   nir_intrinsic_instr *intr = nir_instr_as_intrinsic(instr);
-   if (intr->intrinsic != nir_intrinsic_store_deref)
-      return;
+   unsigned viewport_mask;
+   nir_ssa_def *viewport_index;
+   nir_instr *store_pos_instr;
+};
 
-   nir_variable *var = nir_intrinsic_get_var(intr, 0);
-   if (var->data.mode != nir_var_shader_out ||
-       var->data.location != VARYING_SLOT_POS)
-      return;
+static void
+invert_depth_impl(nir_builder *b, struct invert_depth_state *state)
+{
+   assert(state->store_pos_instr);
+
+   nir_intrinsic_instr *intr = nir_instr_as_intrinsic(state->store_pos_instr);
+   if (state->viewport_index) {
+      /* Cursor is assigned before calling. Make sure that storing pos comes
+       * after computing the viewport.
+       */
+      nir_instr_move(b->cursor, &intr->instr);
+   }
 
    b->cursor = nir_before_instr(&intr->instr);
 
    nir_ssa_def *pos = nir_ssa_for_src(b, intr->src[1], 4);
+
+   if (state->viewport_index) {
+      nir_push_if(b, nir_i2b1(b, nir_iand_imm(b,
+         nir_ishl(b, nir_imm_int(b, 1), state->viewport_index),
+         state->viewport_mask)));
+   }
    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)),
                                nir_channel(b, pos, 3));
+   if (state->viewport_index) {
+      nir_pop_if(b, NULL);
+      def = nir_if_phi(b, def, pos);
+   }
    nir_instr_rewrite_src(&intr->instr, intr->src + 1, nir_src_for_ssa(def));
+
+   state->viewport_index = NULL;
+   state->store_pos_instr = NULL;
+}
+
+static void
+invert_depth_instr(nir_builder *b, struct nir_instr *instr, struct invert_depth_state *state)
+{
+   if (instr->type != nir_instr_type_intrinsic)
+      return;
+
+   nir_intrinsic_instr *intr = nir_instr_as_intrinsic(instr);
+   if (intr->intrinsic == nir_intrinsic_store_deref) {
+      nir_variable *var = nir_intrinsic_get_var(intr, 0);
+      if (var->data.mode != nir_var_shader_out)
+         return;
+
+      if (var->data.location == VARYING_SLOT_VIEWPORT)
+         state->viewport_index = intr->src[1].ssa;
+      if (var->data.location == VARYING_SLOT_POS)
+         state->store_pos_instr = instr;
+   } else if (intr->intrinsic == nir_intrinsic_emit_vertex) {
+      b->cursor = nir_before_instr(instr);
+      invert_depth_impl(b, state);
+   }
 }
 
 /* In OpenGL the windows space depth value z_w is evaluated according to "s * z_d + b"
@@ -420,13 +460,14 @@ invert_depth(nir_builder *b, struct nir_instr *instr)
  * to compensate by inverting "z_d' = -z_d" with this lowering pass.
  */
 void
-d3d12_nir_invert_depth(nir_shader *shader)
+d3d12_nir_invert_depth(nir_shader *shader, unsigned viewport_mask)
 {
    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 };
    nir_foreach_function(function, shader) {
       if (function->impl) {
          nir_builder b;
@@ -434,10 +475,15 @@ d3d12_nir_invert_depth(nir_shader *shader)
 
          nir_foreach_block(block, function->impl) {
             nir_foreach_instr_safe(instr, block) {
-               invert_depth(&b, instr);
+               invert_depth_instr(&b, instr, &state);
             }
          }
 
+         if (state.store_pos_instr) {
+            b.cursor = nir_after_block(function->impl->end_block);
+            invert_depth_impl(&b, &state);
+         }
+
          nir_metadata_preserve(function->impl, nir_metadata_block_index |
                                                nir_metadata_dominance);
       }
diff --git a/src/gallium/drivers/d3d12/d3d12_nir_passes.h b/src/gallium/drivers/d3d12/d3d12_nir_passes.h
index 443341c010f..4550dc253a0 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);
+d3d12_nir_invert_depth(nir_shader *s, unsigned viewport_mask);
 
 bool
 d3d12_lower_int_cubmap_to_array(nir_shader *s);



More information about the mesa-commit mailing list