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

Author: Mike Blumenkrantz <[email protected]>
Date:   Wed Jul 29 20:33:50 2020 -0400

zink: handle arrays of ubos

with the nir pass removing all dynamic indexing, all that's needed here
is generating extra binding points for each array member, as everything else
is already handled

Reviewed-by: Erik Faye-Lund <[email protected]>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/8314>

---

 .../drivers/zink/nir_to_spirv/nir_to_spirv.c       | 39 ++++++++++++++--------
 src/gallium/drivers/zink/zink_compiler.c           | 33 ++++++++++++------
 2 files changed, 48 insertions(+), 24 deletions(-)

diff --git a/src/gallium/drivers/zink/nir_to_spirv/nir_to_spirv.c 
b/src/gallium/drivers/zink/nir_to_spirv/nir_to_spirv.c
index e003ce2c992..6108bda4ea8 100644
--- a/src/gallium/drivers/zink/nir_to_spirv/nir_to_spirv.c
+++ b/src/gallium/drivers/zink/nir_to_spirv/nir_to_spirv.c
@@ -618,10 +618,11 @@ emit_sampler(struct ntv_context *ctx, struct nir_variable 
*var)
 static void
 emit_ubo(struct ntv_context *ctx, struct nir_variable *var)
 {
+   bool is_ubo_array = glsl_type_is_array(var->type) && 
glsl_type_is_interface(glsl_without_array(var->type));
    /* variables accessed inside a uniform block will get merged into a big
     * memory blob and accessed by offset
     */
-   if (var->data.location)
+   if (var->data.location && !is_ubo_array)
       return;
 
    uint32_t size = glsl_count_attribute_slots(var->interface_type, false);
@@ -643,24 +644,36 @@ emit_ubo(struct ntv_context *ctx, struct nir_variable 
*var)
                                  SpvDecorationBlock);
    spirv_builder_emit_member_offset(&ctx->builder, struct_type, 0, 0);
 
-
    SpvId pointer_type = spirv_builder_type_pointer(&ctx->builder,
                                                    SpvStorageClassUniform,
                                                    struct_type);
 
-   SpvId var_id = spirv_builder_emit_var(&ctx->builder, pointer_type,
-                                         SpvStorageClassUniform);
-   if (var->name)
-      spirv_builder_emit_name(&ctx->builder, var_id, var->name);
+   /* if this is a ubo array, create a binding point for each array member:
+    * 
+      "For uniform blocks declared as arrays, each individual array element
+       corresponds to a separate buffer object backing one instance of the 
block."
+       - ARB_gpu_shader5
 
-   assert(ctx->num_ubos < ARRAY_SIZE(ctx->ubos));
-   ctx->ubos[ctx->num_ubos++] = var_id;
+      (also it's just easier)
+    */
+   for (unsigned i = 0; i < (is_ubo_array ? glsl_get_aoa_size(var->type) : 1); 
i++) {
+      SpvId var_id = spirv_builder_emit_var(&ctx->builder, pointer_type,
+                                            SpvStorageClassUniform);
+      if (var->name) {
+         char struct_name[100];
+         snprintf(struct_name, sizeof(struct_name), "%s[%u]", var->name, i);
+         spirv_builder_emit_name(&ctx->builder, var_id, var->name);
+      }
 
-   spirv_builder_emit_descriptor_set(&ctx->builder, var_id, 0);
-   int binding = zink_binding(ctx->stage,
-                              VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
-                              var->data.binding);
-   spirv_builder_emit_binding(&ctx->builder, var_id, binding);
+      assert(ctx->num_ubos < ARRAY_SIZE(ctx->ubos));
+      ctx->ubos[ctx->num_ubos++] = var_id;
+
+      spirv_builder_emit_descriptor_set(&ctx->builder, var_id, 0);
+      int binding = zink_binding(ctx->stage,
+                                 VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
+                                 var->data.binding + i);
+      spirv_builder_emit_binding(&ctx->builder, var_id, binding);
+   }
 }
 
 static void
diff --git a/src/gallium/drivers/zink/zink_compiler.c 
b/src/gallium/drivers/zink/zink_compiler.c
index 13413e89176..d070f607fa1 100644
--- a/src/gallium/drivers/zink/zink_compiler.c
+++ b/src/gallium/drivers/zink/zink_compiler.c
@@ -476,18 +476,29 @@ zink_shader_create(struct zink_screen *screen, struct 
nir_shader *nir,
                                         nir_var_mem_ssbo)) {
          if (var->data.mode == nir_var_mem_ubo) {
             /* ignore variables being accessed if they aren't the base of the 
UBO */
-            if (var->data.location)
+            bool ubo_array = glsl_type_is_array(var->type) && 
glsl_type_is_interface(glsl_without_array(var->type));
+            if (var->data.location && !ubo_array)
                continue;
-            var->data.binding = cur_ubo++;
-
-            int binding = zink_binding(nir->info.stage,
-                                       VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
-                                       var->data.binding);
-            ret->bindings[ret->num_bindings].index = ubo_index++;
-            ret->bindings[ret->num_bindings].binding = binding;
-            ret->bindings[ret->num_bindings].type = 
VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
-            ret->bindings[ret->num_bindings].size = 1;
-            ret->num_bindings++;
+            var->data.binding = cur_ubo;
+            /* if this is a ubo array, create a binding point for each array 
member:
+             * 
+               "For uniform blocks declared as arrays, each individual array 
element
+                corresponds to a separate buffer object backing one instance 
of the block."
+                - ARB_gpu_shader5
+
+               (also it's just easier)
+             */
+            for (unsigned i = 0; i < (ubo_array ? glsl_get_aoa_size(var->type) 
: 1); i++) {
+
+               int binding = zink_binding(nir->info.stage,
+                                          VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
+                                          cur_ubo++);
+               ret->bindings[ret->num_bindings].index = ubo_index++;
+               ret->bindings[ret->num_bindings].binding = binding;
+               ret->bindings[ret->num_bindings].type = 
VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
+               ret->bindings[ret->num_bindings].size = 1;
+               ret->num_bindings++;
+            }
          } else {
             assert(var->data.mode == nir_var_uniform);
             const struct glsl_type *type = glsl_without_array(var->type);

_______________________________________________
mesa-commit mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/mesa-commit

Reply via email to