Mesa (master): microsoft/compiler: Better support UBO/SSBO references to descriptors

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Fri Apr 16 17:16:32 UTC 2021


Module: Mesa
Branch: master
Commit: 50d7e97c1d67b38157654824b16599fce83eb407
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=50d7e97c1d67b38157654824b16599fce83eb407

Author: Jesse Natalie <jenatali at microsoft.com>
Date:   Tue Apr 13 09:56:05 2021 -0700

microsoft/compiler: Better support UBO/SSBO references to descriptors

Previously UBOs only supported static indices, and SSBOs only
supported dynamic indices. UBO support for descriptors was added
as an alternative to static indices, but the logic for detecting
descriptors to SSBOs couldn't just differentiate on constants vs not.

Add a helper which can differentiate cleanly across the board and
handle pre-created handles from descriptors, or static/dynamic raw
indices.

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

---

 src/microsoft/compiler/nir_to_dxil.c | 156 ++++++++++++++++++++---------------
 1 file changed, 90 insertions(+), 66 deletions(-)

diff --git a/src/microsoft/compiler/nir_to_dxil.c b/src/microsoft/compiler/nir_to_dxil.c
index b7404423204..58dc11ecc48 100644
--- a/src/microsoft/compiler/nir_to_dxil.c
+++ b/src/microsoft/compiler/nir_to_dxil.c
@@ -749,6 +749,43 @@ add_resource(struct ntd_context *ctx, enum dxil_resource_type type,
    ctx->num_resources++;
 }
 
+static unsigned
+get_resource_id(struct ntd_context *ctx, enum dxil_resource_class class,
+                unsigned space, unsigned binding)
+{
+   unsigned offset = 0;
+   unsigned count = 0;
+   switch (class) {
+   case DXIL_RESOURCE_CLASS_UAV:
+      offset = ctx->num_srv_arrays + ctx->num_sampler_arrays + ctx->num_cbv_arrays;
+      count = ctx->num_uav_arrays;
+      break;
+   case DXIL_RESOURCE_CLASS_SRV:
+      offset = ctx->num_sampler_arrays + ctx->num_cbv_arrays;
+      count = ctx->num_srv_arrays;
+      break;
+   case DXIL_RESOURCE_CLASS_SAMPLER:
+      offset = ctx->num_cbv_arrays;
+      count = ctx->num_sampler_arrays;
+      break;
+   case DXIL_RESOURCE_CLASS_CBV:
+      offset = 0;
+      count = ctx->num_cbv_arrays;
+      break;
+   }
+   assert(offset + count <= ctx->num_resources);
+   for (unsigned i = offset; i < offset + count; ++i) {
+      if (ctx->resources[i].space == space &&
+          ctx->resources[i].lower_bound <= binding &&
+          ctx->resources[i].upper_bound >= binding) {
+         return i - offset;
+      }
+   }
+
+   unreachable("Resource access for undeclared range");
+   return 0;
+}
+
 static bool
 emit_srv(struct ntd_context *ctx, nir_variable *var, unsigned binding, unsigned count)
 {
@@ -2282,26 +2319,57 @@ emit_gep_for_index(struct ntd_context *ctx, const nir_variable *var,
    return dxil_emit_gep_inbounds(&ctx->mod, ops, ARRAY_SIZE(ops));
 }
 
+static const struct dxil_value *
+get_ubo_ssbo_handle(struct ntd_context *ctx, nir_src *src, enum dxil_resource_class class, unsigned base_binding)
+{
+   assume(class == DXIL_RESOURCE_CLASS_CBV || class == DXIL_RESOURCE_CLASS_UAV);
+
+   /* This source might be one of:
+    * 1. Constant resource index - just look it up in precomputed handle arrays
+    *    If it's null in that array, create a handle, and store the result
+    * 2. A handle from load_vulkan_descriptor - just get the stored SSA value
+    * 3. Dynamic resource index - create a handle for it here
+    */
+   assert(src->ssa->num_components == 1 && src->ssa->bit_size == 32);
+   nir_const_value *const_block_index = nir_src_as_const_value(*src);
+   const struct dxil_value **handle_entry = NULL;
+   if (const_block_index) {
+      if (class == DXIL_RESOURCE_CLASS_CBV)
+         handle_entry = &ctx->cbv_handles[const_block_index->u32];
+      else
+         handle_entry = &ctx->uav_handles[const_block_index->u32];
+   }
+
+   if (handle_entry && *handle_entry)
+      return *handle_entry;
+
+   const struct dxil_value *value = get_src_ssa(ctx, src->ssa, 0);
+   if (ctx->opts->vulkan_environment) {
+      return value;
+   }
+
+   const struct dxil_value *handle = emit_createhandle_call(ctx, class, 
+      get_resource_id(ctx, class, 0, base_binding), value, !const_block_index);
+   if (handle_entry)
+      *handle_entry = handle;
+
+   return handle;
+}
+
 static bool
 emit_load_ssbo(struct ntd_context *ctx, nir_intrinsic_instr *intr)
 {
    const struct dxil_value *int32_undef = get_int32_undef(&ctx->mod);
-   const struct dxil_value *buffer =
-      get_src(ctx, &intr->src[0], 0, nir_type_uint);
+
+   const struct dxil_value *handle = get_ubo_ssbo_handle(ctx, &intr->src[0], DXIL_RESOURCE_CLASS_UAV, 0);
    const struct dxil_value *offset =
       get_src(ctx, &intr->src[1], 0, nir_type_uint);
-   if (!int32_undef || !buffer || !offset)
+   if (!int32_undef || !handle || !offset)
       return false;
 
    assert(nir_src_bit_size(intr->src[0]) == 32);
    assert(nir_intrinsic_dest_components(intr) <= 4);
 
-   const struct dxil_value *handle =
-      emit_createhandle_call(ctx, DXIL_RESOURCE_CLASS_UAV, 0, buffer,
-                             nir_src_is_const(intr->src[0]));
-   if (!handle)
-      return false;
-
    const struct dxil_value *coord[2] = {
       offset,
       int32_undef
@@ -2324,17 +2392,10 @@ emit_load_ssbo(struct ntd_context *ctx, nir_intrinsic_instr *intr)
 static bool
 emit_store_ssbo(struct ntd_context *ctx, nir_intrinsic_instr *intr)
 {
-   const struct dxil_value *buffer =
-      get_src(ctx, &intr->src[1], 0, nir_type_uint);
+   const struct dxil_value* handle = get_ubo_ssbo_handle(ctx, &intr->src[1], DXIL_RESOURCE_CLASS_UAV, 0);
    const struct dxil_value *offset =
       get_src(ctx, &intr->src[2], 0, nir_type_uint);
-   if (!buffer || !offset)
-      return false;
-
-   const struct dxil_value *handle =
-      emit_createhandle_call(ctx, DXIL_RESOURCE_CLASS_UAV, 0, buffer,
-                             nir_src_is_const(intr->src[1]));
-   if (!handle)
+   if (!handle || !offset)
       return false;
 
    assert(nir_src_bit_size(intr->src[0]) == 32);
@@ -2374,17 +2435,10 @@ emit_store_ssbo_masked(struct ntd_context *ctx, nir_intrinsic_instr *intr)
       get_src(ctx, &intr->src[0], 0, nir_type_uint);
    const struct dxil_value *mask =
       get_src(ctx, &intr->src[1], 0, nir_type_uint);
-   const struct dxil_value *buffer =
-      get_src(ctx, &intr->src[2], 0, nir_type_uint);
+   const struct dxil_value* handle = get_ubo_ssbo_handle(ctx, &intr->src[2], DXIL_RESOURCE_CLASS_UAV, 0);
    const struct dxil_value *offset =
       get_src(ctx, &intr->src[3], 0, nir_type_uint);
-   if (!value || !mask || !buffer || !offset)
-      return false;
-
-   const struct dxil_value *handle =
-      emit_createhandle_call(ctx, DXIL_RESOURCE_CLASS_UAV, 0, buffer,
-                             nir_src_is_const(intr->src[2]));
-   if (!handle)
+   if (!value || !mask || !handle || !offset)
       return false;
 
    const struct dxil_value *int32_undef = get_int32_undef(&ctx->mod);
@@ -2482,16 +2536,10 @@ emit_store_scratch(struct ntd_context *ctx, nir_intrinsic_instr *intr)
 static bool
 emit_load_ubo(struct ntd_context *ctx, nir_intrinsic_instr *intr)
 {
-   const struct dxil_value* handle = NULL;
-   nir_const_value* const_block_index = nir_src_as_const_value(intr->src[0]);
-   if (const_block_index) {
-      handle = ctx->cbv_handles[const_block_index->u32];
-   } else {
-      assert(nir_src_num_components(intr->src[0]) == 1);
-      handle = get_src_ssa(ctx, intr->src[0].ssa, 0);
-   }
+   const struct dxil_value* handle = get_ubo_ssbo_handle(ctx, &intr->src[0], DXIL_RESOURCE_CLASS_CBV, 0);
+   if (!handle)
+      return false;
 
-   assert(handle);
    const struct dxil_value *offset;
    nir_const_value *const_offset = nir_src_as_const_value(intr->src[1]);
    if (const_offset) {
@@ -2521,17 +2569,7 @@ emit_load_ubo_dxil(struct ntd_context *ctx, nir_intrinsic_instr *intr)
    assert(nir_dest_num_components(intr->dest) <= 4);
    assert(nir_dest_bit_size(intr->dest) == 32);
 
-   nir_const_value *index = nir_src_as_const_value(intr->src[0]);
-
-   const struct dxil_value* handle = NULL;
-   if (index) {
-      assert(index && index->u32 < ARRAY_SIZE(ctx->cbv_handles));
-      handle = ctx->cbv_handles[index->u32];
-   } else {
-      assert(nir_src_num_components(intr->src[0]) == 1);
-      handle = get_src_ssa(ctx, intr->src[0].ssa, 0);
-   }
-
+   const struct dxil_value* handle = get_ubo_ssbo_handle(ctx, &intr->src[0], DXIL_RESOURCE_CLASS_CBV, 0);
    const struct dxil_value *offset =
       get_src(ctx, &intr->src[1], 0, nir_type_uint);
 
@@ -3065,20 +3103,13 @@ static bool
 emit_ssbo_atomic(struct ntd_context *ctx, nir_intrinsic_instr *intr,
                    enum dxil_atomic_op op, nir_alu_type type)
 {
-   const struct dxil_value *buffer =
-      get_src(ctx, &intr->src[0], 0, nir_type_uint);
+   const struct dxil_value* handle = get_ubo_ssbo_handle(ctx, &intr->src[0], DXIL_RESOURCE_CLASS_UAV, 0);
    const struct dxil_value *offset =
       get_src(ctx, &intr->src[1], 0, nir_type_uint);
    const struct dxil_value *value =
       get_src(ctx, &intr->src[2], 0, type);
 
-   if (!value || !buffer || !offset)
-      return false;
-
-   const struct dxil_value *handle =
-      emit_createhandle_call(ctx, DXIL_RESOURCE_CLASS_UAV, 0, buffer,
-                             nir_src_is_const(intr->src[0]));
-   if (!handle)
+   if (!value || !handle || !offset)
       return false;
 
    const struct dxil_value *int32_undef = get_int32_undef(&ctx->mod);
@@ -3102,8 +3133,7 @@ emit_ssbo_atomic(struct ntd_context *ctx, nir_intrinsic_instr *intr,
 static bool
 emit_ssbo_atomic_comp_swap(struct ntd_context *ctx, nir_intrinsic_instr *intr)
 {
-   const struct dxil_value *buffer =
-      get_src(ctx, &intr->src[0], 0, nir_type_uint);
+   const struct dxil_value* handle = get_ubo_ssbo_handle(ctx, &intr->src[0], DXIL_RESOURCE_CLASS_UAV, 0);
    const struct dxil_value *offset =
       get_src(ctx, &intr->src[1], 0, nir_type_uint);
    const struct dxil_value *cmpval =
@@ -3111,13 +3141,7 @@ emit_ssbo_atomic_comp_swap(struct ntd_context *ctx, nir_intrinsic_instr *intr)
    const struct dxil_value *newval =
       get_src(ctx, &intr->src[3], 0, nir_type_int);
 
-   if (!cmpval || !newval || !buffer || !offset)
-      return false;
-
-   const struct dxil_value *handle =
-      emit_createhandle_call(ctx, DXIL_RESOURCE_CLASS_UAV, 0, buffer,
-                             nir_src_is_const(intr->src[0]));
-   if (!handle)
+   if (!cmpval || !newval || !handle || !offset)
       return false;
 
    const struct dxil_value *int32_undef = get_int32_undef(&ctx->mod);
@@ -3269,7 +3293,7 @@ emit_load_vulkan_descriptor(struct ntd_context *ctx, nir_intrinsic_instr *intr)
    handle = *handle_entry;
    if (!handle || !const_index) {
       handle = emit_createhandle_call(ctx, resource_class,
-         0,
+         get_resource_id(ctx, resource_class, 0, binding),
          get_src(ctx, &intr->src[0], 0, nir_type_uint32), false);
       if (const_index)
          *handle_entry = handle;



More information about the mesa-commit mailing list