glsl: add bindless support to nir uniform linker
authorTimothy Arceri <tarceri@itsqueeze.com>
Tue, 24 Mar 2020 00:51:37 +0000 (11:51 +1100)
committerMarge Bot <eric+marge@anholt.net>
Tue, 21 Apr 2020 01:57:34 +0000 (01:57 +0000)
Reviewed-by: Alejandro PiƱeiro <apinheiro@igalia.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/4395>

src/compiler/glsl/gl_nir_link_uniforms.c

index 7ed484444606cacba97c1511fc0d6b045a34c2ab..175af7c7edb5cc6d0e2f99318874ffd4d6d88310 100644 (file)
@@ -469,6 +469,8 @@ struct nir_link_uniforms_state {
    unsigned next_subroutine;
 
    /* per-shader stage */
+   unsigned next_bindless_image_index;
+   unsigned next_bindless_sampler_index;
    unsigned next_image_index;
    unsigned next_sampler_index;
    unsigned num_shader_samplers;
@@ -500,7 +502,8 @@ add_parameter(struct gl_uniform_storage *uniform,
               const struct glsl_type *type,
               struct nir_link_uniforms_state *state)
 {
-   if (!state->params || uniform->is_shader_storage || glsl_contains_opaque(type))
+   if (!state->params || uniform->is_shader_storage ||
+       (glsl_contains_opaque(type) && !state->current_var->data.bindless))
       return;
 
    unsigned num_params = glsl_get_aoa_size(type);
@@ -662,45 +665,59 @@ find_and_update_named_uniform_storage(struct gl_context *ctx,
          unsigned values = glsl_get_component_slots(type);
          const struct glsl_type *type_no_array = glsl_without_array(type);
          if (glsl_type_is_sampler(type_no_array)) {
-            struct gl_linked_shader *sh = prog->_LinkedShaders[stage];
             bool init_idx;
-            unsigned sampler_index =
-               get_next_index(state, uniform, &state->next_sampler_index,
-                              &init_idx);
+            unsigned *next_index = state->current_var->data.bindless ?
+               &state->next_bindless_sampler_index :
+               &state->next_sampler_index;
+            int sampler_index =
+               get_next_index(state, uniform, next_index, &init_idx);
+            struct gl_linked_shader *sh = prog->_LinkedShaders[stage];
 
-            /* Samplers (bound or bindless) are counted as two components as
-             * specified by ARB_bindless_texture.
-             */
-            state->num_shader_samplers += values / 2;
+            if (state->current_var->data.bindless) {
+               if (init_idx) {
+                  sh->Program->sh.BindlessSamplers =
+                     rerzalloc(sh->Program, sh->Program->sh.BindlessSamplers,
+                               struct gl_bindless_sampler,
+                               sh->Program->sh.NumBindlessSamplers,
+                               state->next_bindless_sampler_index);
+
+                  for (unsigned j = sh->Program->sh.NumBindlessSamplers;
+                       j < state->next_bindless_sampler_index; j++) {
+                     sh->Program->sh.BindlessSamplers[j].target =
+                        glsl_get_sampler_target(type_no_array);
+                  }
 
-            uniform->opaque[stage].active = true;
-            uniform->opaque[stage].index = sampler_index;
+                  sh->Program->sh.NumBindlessSamplers =
+                     state->next_bindless_sampler_index;
+               }
 
-            if (init_idx) {
-               const unsigned shadow =
-                  glsl_sampler_type_is_shadow(type_no_array);
-               for (unsigned i = sampler_index;
-                    i < MIN2(state->next_sampler_index, MAX_SAMPLERS);
-                    i++) {
-                  sh->Program->sh.SamplerTargets[i] =
-                     glsl_get_sampler_target(type_no_array);
-                  state->shader_samplers_used |= 1U << i;
-                  state->shader_shadow_samplers |= shadow << i;
+               if (!state->var_is_in_block)
+                  state->num_shader_uniform_components += values;
+
+            } else {
+               /* Samplers (bound or bindless) are counted as two components
+                * as specified by ARB_bindless_texture.
+                */
+               state->num_shader_samplers += values / 2;
+
+               if (init_idx) {
+                  const unsigned shadow =
+                     glsl_sampler_type_is_shadow(type_no_array);
+                  for (unsigned i = sampler_index;
+                       i < MIN2(state->next_sampler_index, MAX_SAMPLERS);
+                       i++) {
+                     sh->Program->sh.SamplerTargets[i] =
+                        glsl_get_sampler_target(type_no_array);
+                     state->shader_samplers_used |= 1U << i;
+                     state->shader_shadow_samplers |= shadow << i;
+                  }
                }
             }
-         } else if (glsl_type_is_image(type_no_array)) {
-            struct gl_linked_shader *sh = prog->_LinkedShaders[stage];
-            int image_index = state->next_image_index;
-            /* TODO: handle structs when bindless support is added */
-            state->next_image_index += MAX2(1, uniform->array_elements);
-
-            /* Images (bound or bindless) are counted as two components as
-             * specified by ARB_bindless_texture.
-             */
-            state->num_shader_images += values / 2;
 
             uniform->opaque[stage].active = true;
-            uniform->opaque[stage].index = image_index;
+            uniform->opaque[stage].index = sampler_index;
+         } else if (glsl_type_is_image(type_no_array)) {
+            struct gl_linked_shader *sh = prog->_LinkedShaders[stage];
 
             /* Set image access qualifiers */
             enum gl_access_qualifier image_access =
@@ -711,11 +728,48 @@ find_and_update_named_uniform_storage(struct gl_context *ctx,
                                                        GL_READ_ONLY) :
                ((image_access & ACCESS_NON_READABLE) ? GL_WRITE_ONLY :
                                                        GL_READ_WRITE);
-            for (unsigned i = image_index;
-                 i < MIN2(state->next_image_index, MAX_IMAGE_UNIFORMS);
-                 i++) {
-               sh->Program->sh.ImageAccess[i] = access;
+
+            int image_index;
+            if (state->current_var->data.bindless) {
+               image_index = state->next_bindless_image_index;
+               state->next_bindless_image_index +=
+                  MAX2(1, uniform->array_elements);
+
+               sh->Program->sh.BindlessImages =
+                  rerzalloc(sh->Program, sh->Program->sh.BindlessImages,
+                            struct gl_bindless_image,
+                            sh->Program->sh.NumBindlessImages,
+                            state->next_bindless_image_index);
+
+               for (unsigned j = sh->Program->sh.NumBindlessImages;
+                    j < state->next_bindless_image_index; j++) {
+                  sh->Program->sh.BindlessImages[j].access = access;
+               }
+
+               sh->Program->sh.NumBindlessImages =
+                  state->next_bindless_image_index;
+
+            } else {
+               image_index = state->next_image_index;
+               state->next_image_index += MAX2(1, uniform->array_elements);
+
+               /* Images (bound or bindless) are counted as two components as
+                * specified by ARB_bindless_texture.
+                */
+               state->num_shader_images += values / 2;
+
+               for (unsigned i = image_index;
+                    i < MIN2(state->next_image_index, MAX_IMAGE_UNIFORMS);
+                    i++) {
+                  sh->Program->sh.ImageAccess[i] = access;
+               }
             }
+
+            uniform->opaque[stage].active = true;
+            uniform->opaque[stage].index = image_index;
+
+            if (!uniform->is_shader_storage)
+               state->num_shader_uniform_components += values;
          }
 
          struct hash_entry *entry =
@@ -1115,6 +1169,7 @@ nir_link_uniform(struct gl_context *ctx,
          state->num_hidden_uniforms++;
 
       uniform->is_shader_storage = nir_variable_is_in_ssbo(state->current_var);
+      uniform->is_bindless = state->current_var->data.bindless;
 
       /* Set fields whose default value depend on the variable being inside a
        * block.
@@ -1229,14 +1284,8 @@ nir_link_uniform(struct gl_context *ctx,
       }
 
       uniform->block_index = buffer_block_index;
-
-      /* @FIXME: the initialization of the following will be done as we
-       * implement support for their specific features, like SSBO, atomics,
-       * etc.
-       */
       uniform->builtin = is_gl_identifier(uniform->name);
       uniform->atomic_buffer_index = -1;
-      uniform->is_bindless = false;
 
       /* The following are not for features not supported by ARB_gl_spirv */
       uniform->num_compatible_subroutines = 0;
@@ -1246,45 +1295,56 @@ nir_link_uniform(struct gl_context *ctx,
 
       if (glsl_type_is_sampler(type_no_array)) {
          bool init_idx;
+         unsigned *next_index = state->current_var->data.bindless ?
+            &state->next_bindless_sampler_index : &state->next_sampler_index;
          int sampler_index =
-            get_next_index(state, uniform, &state->next_sampler_index,
-                           &init_idx);
+            get_next_index(state, uniform, next_index, &init_idx);
 
-         /* Samplers (bound or bindless) are counted as two components as
-          * specified by ARB_bindless_texture.
-          */
-         state->num_shader_samplers += values / 2;
+         if (state->current_var->data.bindless) {
 
-         uniform->opaque[stage].active = true;
-         uniform->opaque[stage].index = sampler_index;
+            if (init_idx) {
+               stage_program->sh.BindlessSamplers =
+                  rerzalloc(stage_program, stage_program->sh.BindlessSamplers,
+                            struct gl_bindless_sampler,
+                            stage_program->sh.NumBindlessSamplers,
+                            state->next_bindless_sampler_index);
+
+               for (unsigned j = stage_program->sh.NumBindlessSamplers;
+                    j < state->next_bindless_sampler_index; j++) {
+                  stage_program->sh.BindlessSamplers[j].target =
+                     glsl_get_sampler_target(type_no_array);
+               }
 
-         if (init_idx) {
-            const unsigned shadow = glsl_sampler_type_is_shadow(type_no_array);
-            for (unsigned i = sampler_index;
-                 i < MIN2(state->next_sampler_index, MAX_SAMPLERS);
-                 i++) {
-               stage_program->sh.SamplerTargets[i] =
-                  glsl_get_sampler_target(type_no_array);
-               state->shader_samplers_used |= 1U << i;
-               state->shader_shadow_samplers |= shadow << i;
+               stage_program->sh.NumBindlessSamplers =
+                  state->next_bindless_sampler_index;
             }
-         }
-      } else if (glsl_type_is_image(type_no_array)) {
-         /* @FIXME: image_index should match that of the same image
-          * uniform in other shaders. This means we need to match image
-          * uniforms by location (GLSL does it by variable name, but we
-          * want to avoid that).
-          */
-         int image_index = state->next_image_index;
-         state->next_image_index += entries;
 
-         /* Images (bound or bindless) are counted as two components as
-          * specified by ARB_bindless_texture.
-          */
-         state->num_shader_images += values / 2;
+            if (!state->var_is_in_block)
+               state->num_shader_uniform_components += values;
+
+         } else {
+            /* Samplers (bound or bindless) are counted as two components as
+             * specified by ARB_bindless_texture.
+             */
+            state->num_shader_samplers += values / 2;
+
+            if (init_idx) {
+               const unsigned shadow =
+                  glsl_sampler_type_is_shadow(type_no_array);
+               for (unsigned i = sampler_index;
+                    i < MIN2(state->next_sampler_index, MAX_SAMPLERS);
+                    i++) {
+                  stage_program->sh.SamplerTargets[i] =
+                     glsl_get_sampler_target(type_no_array);
+                  state->shader_samplers_used |= 1U << i;
+                  state->shader_shadow_samplers |= shadow << i;
+               }
+            }
+         }
 
          uniform->opaque[stage].active = true;
-         uniform->opaque[stage].index = image_index;
+         uniform->opaque[stage].index = sampler_index;
+      } else if (glsl_type_is_image(type_no_array)) {
 
          /* Set image access qualifiers */
          enum gl_access_qualifier image_access =
@@ -1295,12 +1355,45 @@ nir_link_uniform(struct gl_context *ctx,
                                                     GL_READ_ONLY) :
             ((image_access & ACCESS_NON_READABLE) ? GL_WRITE_ONLY :
                                                     GL_READ_WRITE);
-         for (unsigned i = image_index;
-              i < MIN2(state->next_image_index, MAX_IMAGE_UNIFORMS);
-              i++) {
-            stage_program->sh.ImageAccess[i] = access;
+
+         int image_index;
+         if (state->current_var->data.bindless) {
+            image_index = state->next_bindless_image_index;
+            state->next_bindless_image_index += entries;
+
+            stage_program->sh.BindlessImages =
+               rerzalloc(stage_program, stage_program->sh.BindlessImages,
+                         struct gl_bindless_image,
+                         stage_program->sh.NumBindlessImages,
+                         state->next_bindless_image_index);
+
+            for (unsigned j = stage_program->sh.NumBindlessImages;
+                 j < state->next_bindless_image_index; j++) {
+               stage_program->sh.BindlessImages[j].access = access;
+            }
+
+            stage_program->sh.NumBindlessImages =
+               state->next_bindless_image_index;
+
+         } else {
+            image_index = state->next_image_index;
+            state->next_image_index += entries;
+
+            /* Images (bound or bindless) are counted as two components as
+             * specified by ARB_bindless_texture.
+             */
+            state->num_shader_images += values / 2;
+
+            for (unsigned i = image_index;
+                  i < MIN2(state->next_image_index, MAX_IMAGE_UNIFORMS);
+                 i++) {
+               stage_program->sh.ImageAccess[i] = access;
+            }
          }
 
+         uniform->opaque[stage].active = true;
+         uniform->opaque[stage].index = image_index;
+
          if (!uniform->is_shader_storage)
             state->num_shader_uniform_components += values;
       } else {
@@ -1367,6 +1460,8 @@ gl_nir_link_uniforms(struct gl_context *ctx,
       state.referenced_uniforms =
          _mesa_hash_table_create(NULL, _mesa_hash_pointer,
                                  _mesa_key_pointer_equal);
+      state.next_bindless_image_index = 0;
+      state.next_bindless_sampler_index = 0;
       state.next_image_index = 0;
       state.next_sampler_index = 0;
       state.num_shader_samplers = 0;