Mesa (main): microsoft/compiler: Use textures for SRVs

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Tue Nov 2 18:35:23 UTC 2021


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

Author: Jesse Natalie <jenatali at microsoft.com>
Date:   Fri Oct 15 14:56:03 2021 -0700

microsoft/compiler: Use textures for SRVs

After running the (renamed) dxil_nir_split_typed_samplers pass, the
shader will have either:
* Textures, which map to D3D SRVs
* Bare samplers, which map to D3D bare samplers
* Images, which map to D3D UAVs

There shouldn't be any remaining samplers with type information

Reviewed-by: Enrico Galli <enrico.galli at intel.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/13390>

---

 src/gallium/drivers/d3d12/d3d12_compiler.cpp |  15 +++-
 src/microsoft/clc/clc_compiler.c             |   4 +-
 src/microsoft/compiler/dxil_enums.c          |   4 +-
 src/microsoft/compiler/dxil_nir.c            | 127 +++++++++++++++++++++------
 src/microsoft/compiler/dxil_nir.h            |   2 +-
 src/microsoft/compiler/nir_to_dxil.c         |  28 +++---
 src/microsoft/spirv_to_dxil/spirv_to_dxil.c  |   4 +-
 7 files changed, 135 insertions(+), 49 deletions(-)

diff --git a/src/gallium/drivers/d3d12/d3d12_compiler.cpp b/src/gallium/drivers/d3d12/d3d12_compiler.cpp
index b2d4d9a9f58..35f253ac07d 100644
--- a/src/gallium/drivers/d3d12/d3d12_compiler.cpp
+++ b/src/gallium/drivers/d3d12/d3d12_compiler.cpp
@@ -124,6 +124,13 @@ resource_dimension(enum glsl_sampler_dim dim)
    }
 }
 
+static bool
+can_remove_dead_sampler(nir_variable *var, void *data)
+{
+   const struct glsl_type *base_type = glsl_without_array(var->type);
+   return glsl_type_is_sampler(base_type) && !glsl_type_is_bare_sampler(base_type);
+}
+
 static struct d3d12_shader *
 compile_nir(struct d3d12_context *ctx, struct d3d12_shader_selector *sel,
             struct d3d12_shader_key *key, struct nir_shader *nir)
@@ -135,7 +142,11 @@ compile_nir(struct d3d12_context *ctx, struct d3d12_shader_selector *sel,
    sel->current = shader;
 
    NIR_PASS_V(nir, nir_lower_samplers);
-   NIR_PASS_V(nir, dxil_nir_create_bare_samplers);
+   NIR_PASS_V(nir, dxil_nir_split_typed_samplers);
+
+   NIR_PASS_V(nir, nir_opt_dce);
+   struct nir_remove_dead_variables_options dead_var_opts = { .can_remove_var = can_remove_dead_sampler };
+   NIR_PASS_V(nir, nir_remove_dead_variables, nir_var_uniform, &dead_var_opts);
 
    if (key->samples_int_textures)
       NIR_PASS_V(nir, dxil_lower_sample_to_txf_for_integer_tex,
@@ -178,7 +189,7 @@ compile_nir(struct d3d12_context *ctx, struct d3d12_shader_selector *sel,
    shader->begin_srv_binding = (UINT_MAX);
    nir_foreach_variable_with_modes(var, nir, nir_var_uniform) {
       auto type = glsl_without_array(var->type);
-      if (glsl_type_is_sampler(type) && glsl_get_sampler_result_type(type) != GLSL_TYPE_VOID) {
+      if (glsl_type_is_texture(type)) {
          unsigned count = glsl_type_is_array(var->type) ? glsl_get_aoa_size(var->type) : 1;
          for (unsigned i = 0; i < count; ++i) {
             shader->srv_bindings[var->data.binding + i].binding = var->data.binding;
diff --git a/src/microsoft/clc/clc_compiler.c b/src/microsoft/clc/clc_compiler.c
index 7880a060740..d1400b94aac 100644
--- a/src/microsoft/clc/clc_compiler.c
+++ b/src/microsoft/clc/clc_compiler.c
@@ -78,8 +78,8 @@ lower_read_only_image_deref(nir_builder *b, struct clc_image_lower_context *cont
    // Non-writeable images should be converted to samplers,
    // since they may have texture operations done on them
    const struct glsl_type *new_var_type =
-      glsl_sampler_type(glsl_get_sampler_dim(in_var->type),
-            false, glsl_sampler_type_is_array(in_var->type),
+      glsl_texture_type(glsl_get_sampler_dim(in_var->type),
+            glsl_sampler_type_is_array(in_var->type),
             nir_get_glsl_base_type_for_nir_type(image_type | 32));
    return lower_image_deref_impl(b, context, new_var_type, nir_var_uniform, context->num_srvs);
 }
diff --git a/src/microsoft/compiler/dxil_enums.c b/src/microsoft/compiler/dxil_enums.c
index 98403eae5a4..44de92c7325 100644
--- a/src/microsoft/compiler/dxil_enums.c
+++ b/src/microsoft/compiler/dxil_enums.c
@@ -54,7 +54,7 @@ enum dxil_component_type dxil_get_comp_type(const struct glsl_type *type)
    type = glsl_without_array(type);
 
    enum glsl_base_type base_type = glsl_get_base_type(type);
-   if (glsl_type_is_sampler(type) || glsl_type_is_image(type))
+   if (glsl_type_is_texture(type) || glsl_type_is_image(type))
       base_type = glsl_get_sampler_result_type(type);
    switch (base_type) {
    case GLSL_TYPE_UINT: return DXIL_COMP_TYPE_U32;
@@ -82,7 +82,7 @@ enum dxil_resource_kind dxil_get_resource_kind(const struct glsl_type *type)
     * an array, key is the first refers to sampler[] and the second to samplerArray */
    bool is_array = glsl_sampler_type_is_array(type);
 
-   if (glsl_type_is_sampler(type) || glsl_type_is_image(type)) {
+   if (glsl_type_is_texture(type) || glsl_type_is_image(type)) {
       switch (glsl_get_sampler_dim(type)) {
          case GLSL_SAMPLER_DIM_1D:
             return is_array ? DXIL_RESOURCE_KIND_TEXTURE1D_ARRAY
diff --git a/src/microsoft/compiler/dxil_nir.c b/src/microsoft/compiler/dxil_nir.c
index b89c8118bf8..2d50ec2e34e 100644
--- a/src/microsoft/compiler/dxil_nir.c
+++ b/src/microsoft/compiler/dxil_nir.c
@@ -1358,26 +1358,18 @@ dxil_nir_lower_system_values_to_zero(nir_shader* shader,
 static const struct glsl_type *
 get_bare_samplers_for_type(const struct glsl_type *type, bool is_shadow)
 {
-   if (glsl_type_is_sampler(type)) {
-      if (is_shadow)
-         return glsl_bare_shadow_sampler_type();
-      else
-         return glsl_bare_sampler_type();
-   } else if (glsl_type_is_array(type)) {
-      return glsl_array_type(
-         get_bare_samplers_for_type(glsl_get_array_element(type), is_shadow),
-         glsl_get_length(type),
-         0 /*explicit size*/);
-   }
-   assert(!"Unexpected type");
-   return NULL;
+   const struct glsl_type *base_sampler_type =
+      is_shadow ?
+      glsl_bare_shadow_sampler_type() : glsl_bare_sampler_type();
+   return glsl_type_wrap_in_arrays(base_sampler_type, type);
 }
 
-static bool
-is_bare_sampler(const struct glsl_type *type)
+static const struct glsl_type *
+get_textures_for_sampler_type(const struct glsl_type *type)
 {
-   return glsl_get_sampler_result_type(glsl_without_array(type)) ==
-          GLSL_TYPE_VOID;
+   return glsl_type_wrap_in_arrays(
+      glsl_sampler_type_to_texture(
+         glsl_without_array(type)), type);
 }
 
 static bool
@@ -1407,7 +1399,7 @@ redirect_sampler_derefs(struct nir_builder *b, nir_instr *instr, void *data)
 
             /* Already have a bare sampler for this binding and it is of the
              * correct type, add it to the table */
-            if (is_bare_sampler(var->type) &&
+            if (glsl_type_is_bare_sampler(glsl_without_array(var->type)) &&
                 glsl_sampler_type_is_shadow(glsl_without_array(var->type)) ==
                    tex->is_shadow) {
                _mesa_hash_table_u64_insert(data, tex->sampler_index, var);
@@ -1422,7 +1414,7 @@ redirect_sampler_derefs(struct nir_builder *b, nir_instr *instr, void *data)
       nir_variable *bare_sampler = NULL;
 
       /* If it is already bare, we just need to fix the shadow information */
-      if (is_bare_sampler(old_sampler->type))
+      if (glsl_type_is_bare_sampler(glsl_without_array(old_sampler->type)))
          bare_sampler = old_sampler;
       else {
          /* Otherwise, clone the typed sampler to a bare sampler */
@@ -1443,7 +1435,7 @@ redirect_sampler_derefs(struct nir_builder *b, nir_instr *instr, void *data)
    nir_deref_instr *old_tail = path.path[0];
    assert(old_tail->deref_type == nir_deref_type_var);
    nir_variable *old_var = old_tail->var;
-   if (is_bare_sampler(old_var->type) &&
+   if (glsl_type_is_bare_sampler(glsl_without_array(old_var->type)) &&
        glsl_sampler_type_is_shadow(glsl_without_array(old_var->type)) ==
           tex->is_shadow) {
       nir_deref_path_finish(&path);
@@ -1455,7 +1447,7 @@ redirect_sampler_derefs(struct nir_builder *b, nir_instr *instr, void *data)
    if (hash_entry) {
       new_var = hash_entry->data;
    } else {
-      if (is_bare_sampler(old_var->type))
+      if (glsl_type_is_bare_sampler(glsl_without_array(old_var->type)))
          new_var = old_var;
       else {
          new_var = nir_variable_clone(old_var, b->shader);
@@ -1482,15 +1474,100 @@ redirect_sampler_derefs(struct nir_builder *b, nir_instr *instr, void *data)
    return true;
 }
 
+static bool
+redirect_texture_derefs(struct nir_builder *b, nir_instr *instr, void *data)
+{
+   if (instr->type != nir_instr_type_tex)
+      return false;
+
+   nir_tex_instr *tex = nir_instr_as_tex(instr);
+
+   int texture_idx = nir_tex_instr_src_index(tex, nir_tex_src_texture_deref);
+   if (texture_idx == -1) {
+      /* No derefs, must be using indices */
+      struct hash_entry *hash_entry = _mesa_hash_table_u64_search(data, tex->texture_index);
+
+      /* Already have a texture here */
+      if (hash_entry)
+         return false;
+
+      nir_variable *typed_sampler = NULL;
+      nir_foreach_variable_with_modes(var, b->shader, nir_var_uniform) {
+         if (var->data.binding <= tex->texture_index &&
+             var->data.binding + glsl_type_get_texture_count(var->type) > tex->texture_index) {
+            /* Already have a texture for this binding, add it to the table */
+            _mesa_hash_table_u64_insert(data, tex->texture_index, var);
+            return false;
+         }
+
+         if (var->data.binding <= tex->texture_index &&
+             var->data.binding + glsl_type_get_sampler_count(var->type) > tex->texture_index &&
+             !glsl_type_is_bare_sampler(glsl_without_array(var->type))) {
+            typed_sampler = var;
+         }
+      }
+
+      /* Clone the typed sampler to a texture and we're done */
+      assert(typed_sampler);
+      nir_variable *bare_sampler = nir_variable_clone(typed_sampler, b->shader);
+      bare_sampler->type = get_textures_for_sampler_type(typed_sampler->type);
+      nir_shader_add_variable(b->shader, bare_sampler);
+      _mesa_hash_table_u64_insert(data, tex->texture_index, bare_sampler);
+      return true;
+   }
+
+   /* Using derefs, means we have to rewrite the deref chain in addition to cloning */
+   nir_deref_instr *final_deref = nir_src_as_deref(tex->src[texture_idx].src);
+   nir_deref_path path;
+   nir_deref_path_init(&path, final_deref, NULL);
+
+   nir_deref_instr *old_tail = path.path[0];
+   assert(old_tail->deref_type == nir_deref_type_var);
+   nir_variable *old_var = old_tail->var;
+   if (glsl_type_is_texture(glsl_without_array(old_var->type))) {
+      nir_deref_path_finish(&path);
+      return false;
+   }
+
+   struct hash_entry *hash_entry = _mesa_hash_table_u64_search(data, old_var->data.binding);
+   nir_variable *new_var;
+   if (hash_entry) {
+      new_var = hash_entry->data;
+   } else {
+      new_var = nir_variable_clone(old_var, b->shader);
+      new_var->type = get_textures_for_sampler_type(old_var->type);
+      nir_shader_add_variable(b->shader, new_var);
+      _mesa_hash_table_u64_insert(data, old_var->data.binding, new_var);
+   }
+
+   b->cursor = nir_after_instr(&old_tail->instr);
+   nir_deref_instr *new_tail = nir_build_deref_var(b, new_var);
+
+   for (unsigned i = 1; path.path[i]; ++i) {
+      b->cursor = nir_after_instr(&path.path[i]->instr);
+      new_tail = nir_build_deref_follower(b, new_tail, path.path[i]);
+   }
+
+   nir_deref_path_finish(&path);
+   nir_instr_rewrite_src_ssa(&tex->instr, &tex->src[texture_idx].src, &new_tail->dest.ssa);
+
+   return true;
+}
+
 bool
-dxil_nir_create_bare_samplers(nir_shader *nir)
+dxil_nir_split_typed_samplers(nir_shader *nir)
 {
-   struct hash_table_u64 *sampler_to_bare = _mesa_hash_table_u64_create(NULL);
+   struct hash_table_u64 *hash_table = _mesa_hash_table_u64_create(NULL);
 
    bool progress = nir_shader_instructions_pass(nir, redirect_sampler_derefs,
-      nir_metadata_block_index | nir_metadata_dominance | nir_metadata_loop_analysis, sampler_to_bare);
+      nir_metadata_block_index | nir_metadata_dominance | nir_metadata_loop_analysis, hash_table);
+
+   _mesa_hash_table_u64_clear(hash_table);
+
+   progress |= nir_shader_instructions_pass(nir, redirect_texture_derefs,
+      nir_metadata_block_index | nir_metadata_dominance | nir_metadata_loop_analysis, hash_table);
 
-   _mesa_hash_table_u64_destroy(sampler_to_bare);
+   _mesa_hash_table_u64_destroy(hash_table);
    return progress;
 }
 
diff --git a/src/microsoft/compiler/dxil_nir.h b/src/microsoft/compiler/dxil_nir.h
index 9820405a60f..440bb8fc070 100644
--- a/src/microsoft/compiler/dxil_nir.h
+++ b/src/microsoft/compiler/dxil_nir.h
@@ -49,7 +49,7 @@ bool dxil_nir_lower_double_math(nir_shader *shader);
 bool dxil_nir_lower_system_values_to_zero(nir_shader *shader,
                                           gl_system_value* system_value,
                                           uint32_t count);
-bool dxil_nir_create_bare_samplers(nir_shader *shader);
+bool dxil_nir_split_typed_samplers(nir_shader *shader);
 bool dxil_nir_lower_bool_input(struct nir_shader *s);
 
 nir_ssa_def *
diff --git a/src/microsoft/compiler/nir_to_dxil.c b/src/microsoft/compiler/nir_to_dxil.c
index 805280fd6e9..9c9c18d8817 100644
--- a/src/microsoft/compiler/nir_to_dxil.c
+++ b/src/microsoft/compiler/nir_to_dxil.c
@@ -3745,7 +3745,8 @@ emit_deref(struct ntd_context* ctx, nir_deref_instr* instr)
    assert(var);
 
    if (!glsl_type_is_sampler(glsl_without_array(var->type)) &&
-       !glsl_type_is_image(glsl_without_array(var->type)))
+       !glsl_type_is_image(glsl_without_array(var->type)) &&
+       !glsl_type_is_texture(glsl_without_array(var->type)))
       return true;
 
    const struct glsl_type *type = instr->type;
@@ -3771,11 +3772,11 @@ emit_deref(struct ntd_context* ctx, nir_deref_instr* instr)
       return true;
    }
 
-   assert(glsl_type_is_sampler(type) || glsl_type_is_image(type));
+   assert(glsl_type_is_sampler(type) || glsl_type_is_image(type) || glsl_type_is_texture(type));
    enum dxil_resource_class res_class;
    if (glsl_type_is_image(type))
       res_class = DXIL_RESOURCE_CLASS_UAV;
-   else if (glsl_get_sampler_result_type(type) == GLSL_TYPE_VOID)
+   else if (glsl_type_is_sampler(type))
       res_class = DXIL_RESOURCE_CLASS_SAMPLER;
    else
       res_class = DXIL_RESOURCE_CLASS_SRV;
@@ -4528,24 +4529,19 @@ emit_module(struct ntd_context *ctx, const struct nir_to_dxil_options *opts)
    /* Samplers */
    nir_foreach_variable_with_modes(var, ctx->shader, nir_var_uniform) {
       unsigned count = glsl_type_get_sampler_count(var->type);
-      const struct glsl_type *without_array = glsl_without_array(var->type);
-      if (var->data.mode == nir_var_uniform && glsl_type_is_sampler(without_array) &&
-          glsl_get_sampler_result_type(without_array) == GLSL_TYPE_VOID) {
-         if (!emit_sampler(ctx, var, count))
-            return false;
-      }
+      assert(count == 0 || glsl_type_is_bare_sampler(glsl_without_array(var->type)));
+      if (count > 0 && !emit_sampler(ctx, var, count))
+         return false;
    }
 
    /* SRVs */
    nir_foreach_variable_with_modes(var, ctx->shader, nir_var_uniform) {
-      unsigned count = glsl_type_get_sampler_count(var->type);
-      const struct glsl_type *without_array = glsl_without_array(var->type);
-      if (var->data.mode == nir_var_uniform && glsl_type_is_sampler(without_array) &&
-          glsl_get_sampler_result_type(without_array) != GLSL_TYPE_VOID) {
-         if (!emit_srv(ctx, var, count))
-            return false;
-      }
+      unsigned count = glsl_type_get_texture_count(var->type);
+      assert(count == 0 || glsl_type_is_texture(glsl_without_array(var->type)));
+      if (count > 0 && !emit_srv(ctx, var, count))
+         return false;
    }
+
    /* Handle read-only SSBOs as SRVs */
    nir_foreach_variable_with_modes(var, ctx->shader, nir_var_mem_ssbo) {
       if ((var->data.access & ACCESS_NON_WRITEABLE) != 0) {
diff --git a/src/microsoft/spirv_to_dxil/spirv_to_dxil.c b/src/microsoft/spirv_to_dxil/spirv_to_dxil.c
index b3649d01176..e45ca71f429 100644
--- a/src/microsoft/spirv_to_dxil/spirv_to_dxil.c
+++ b/src/microsoft/spirv_to_dxil/spirv_to_dxil.c
@@ -295,8 +295,10 @@ spirv_to_dxil(const uint32_t *words, size_t word_count,
 
    NIR_PASS_V(nir, dxil_nir_split_clip_cull_distance);
    NIR_PASS_V(nir, dxil_nir_lower_loads_stores_to_dxil);
-   NIR_PASS_V(nir, dxil_nir_create_bare_samplers);
+   NIR_PASS_V(nir, dxil_nir_split_typed_samplers);
    NIR_PASS_V(nir, dxil_nir_lower_bool_input);
+   NIR_PASS_V(nir, nir_opt_dce);
+   NIR_PASS_V(nir, nir_remove_dead_variables, nir_var_uniform, NULL);
 
    nir_shader_gather_info(nir, nir_shader_get_entrypoint(nir));
 



More information about the mesa-commit mailing list