zink: fix sampler array collision in `nir_to_spirv`
authorantonino <antonino.maniscalco@collabora.com>
Fri, 7 Apr 2023 12:41:27 +0000 (14:41 +0200)
committerMarge Bot <emma+marge@anholt.net>
Fri, 7 Apr 2023 19:25:08 +0000 (19:25 +0000)
`nir_to_spirv` has flat arrays to map driver_location to sampler
variables.

Now when bindless textures are used together with non binless textures
the sampler vars are in different descriptor sets and the binding can be
the same between different descriptor sets, this causes a collision in
arrays.

This patches chamges `nir_to_spirv` to also index the array by whether
the texture is bindless.

Fixes: bc202553e9b ("zink: implement bindless textures")
Reviewed-by: Mike Blumenkrantz <michael.blumenkrantz@gmail.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/22358>

src/gallium/drivers/zink/nir_to_spirv/nir_to_spirv.c

index 7a97c8a..46f4ef4 100644 (file)
@@ -63,9 +63,12 @@ struct ntv_context {
    SpvId images[PIPE_MAX_SHADER_IMAGES];
    struct hash_table image_types;
    SpvId samplers[PIPE_MAX_SHADER_SAMPLER_VIEWS];
+   SpvId bindless_samplers[2];
    SpvId cl_samplers[PIPE_MAX_SAMPLERS];
    nir_variable *sampler_var[PIPE_MAX_SHADER_SAMPLER_VIEWS]; /* driver_location -> variable */
+   nir_variable *bindless_sampler_var[2];
    unsigned last_sampler;
+   unsigned bindless_set_idx;
    nir_variable *image_var[PIPE_MAX_SHADER_IMAGES]; /* driver_location -> variable */
 
    SpvId entry_ifaces[PIPE_MAX_SHADER_INPUTS * 4 + PIPE_MAX_SHADER_OUTPUTS * 4];
@@ -1059,7 +1062,10 @@ emit_image(struct ntv_context *ctx, struct nir_variable *var, SpvId image_type)
 
    _mesa_hash_table_insert(ctx->vars, var, (void *)(intptr_t)var_id);
    if (is_sampler) {
-      ctx->samplers[index] = var_id;
+      if (var->data.descriptor_set == ctx->bindless_set_idx)
+         ctx->bindless_samplers[index] = var_id;
+      else
+         ctx->samplers[index] = var_id;
    } else {
       ctx->images[index] = var_id;
       emit_access_decorations(ctx, var, var_id);
@@ -3723,19 +3729,20 @@ emit_tex(struct ntv_context *ctx, nir_tex_instr *tex)
 
    unsigned texture_index = tex->texture_index;
    nir_variable *var = bindless_var ? bindless_var : ctx->sampler_var[tex->texture_index];
+   nir_variable **sampler_var = bindless ? ctx->bindless_sampler_var : ctx->sampler_var;
    if (!bindless_var && (!tex_offset || !var)) {
-      if (ctx->sampler_var[texture_index]) {
-         if (glsl_type_is_array(ctx->sampler_var[texture_index]->type))
+      if (sampler_var[texture_index]) {
+         if (glsl_type_is_array(sampler_var[texture_index]->type))
             tex_offset = emit_uint_const(ctx, 32, 0);
          assert(var);
       } else {
          /* convert constant index back to base + offset */
          for (int i = texture_index; i >= 0; i--) {
-            if (ctx->sampler_var[i]) {
-               assert(glsl_type_is_array(ctx->sampler_var[i]->type));
+            if (sampler_var[i]) {
+               assert(glsl_type_is_array(sampler_var[i]->type));
                if (!tex_offset)
                   tex_offset = emit_uint_const(ctx, 32, texture_index - i);
-               var = ctx->sampler_var[i];
+               var = sampler_var[i];
                texture_index = i;
                break;
             }
@@ -4364,6 +4371,7 @@ nir_to_spirv(struct nir_shader *s, const struct zink_shader_info *sinfo, uint32_
    assert(spirv_version >= SPIRV_VERSION(1, 0));
    ctx.spirv_1_4_interfaces = spirv_version >= SPIRV_VERSION(1, 4);
 
+   ctx.bindless_set_idx = sinfo->bindless_set_idx;
    ctx.glsl_types = _mesa_pointer_hash_table_create(ctx.mem_ctx);
    ctx.bo_array_types = _mesa_pointer_hash_table_create(ctx.mem_ctx);
    ctx.bo_struct_types = _mesa_pointer_hash_table_create(ctx.mem_ctx);
@@ -4551,7 +4559,10 @@ nir_to_spirv(struct nir_shader *s, const struct zink_shader_info *sinfo, uint32_
       ctx.image_var[var->data.driver_location] = var;
    nir_foreach_variable_with_modes(var, s, nir_var_uniform) {
       if (glsl_type_is_sampler(glsl_without_array(var->type))) {
-         ctx.sampler_var[var->data.driver_location] = var;
+         if (var->data.descriptor_set == ctx.bindless_set_idx)
+            ctx.bindless_sampler_var[var->data.driver_location] = var;
+         else
+            ctx.sampler_var[var->data.driver_location] = var;
          ctx.last_sampler = MAX2(ctx.last_sampler, var->data.driver_location);
       }
    }