mesa/st/i965: add a ProgramResourceHash for quicker resource lookup
authorTapani Pälli <tapani.palli@intel.com>
Fri, 3 Jan 2020 05:56:23 +0000 (07:56 +0200)
committerMarge Bot <eric+marge@anholt.net>
Tue, 7 Jan 2020 10:48:41 +0000 (10:48 +0000)
Many resource APIs require searching by name, add a hash table to make
this faster. Currently we traverse the whole resource list for name
based queries, this change makes all these cases use the hash.

Closes: https://gitlab.freedesktop.org/mesa/mesa/issues/2203
Signed-off-by: Tapani Pälli <tapani.palli@intel.com>
Reviewed-by: Marek Olšák <marek.olsak@amd.com>
Tested-by: Marge Bot <https://gitlab.freedesktop.org/mesa/mesa/merge_requests/3254>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/merge_requests/3254>

src/mesa/drivers/dri/i965/brw_link.cpp
src/mesa/main/mtypes.h
src/mesa/main/shader_query.cpp
src/mesa/main/shaderapi.h
src/mesa/main/shaderobj.c
src/mesa/state_tracker/st_glsl_to_nir.cpp
src/mesa/state_tracker/st_glsl_to_tgsi.cpp

index 2a844575c3d2907e97bbc9a25600d9c7f1fbc6d5..8a62ffd760b88104e23b782a3e0dc08a3c9dd072 100644 (file)
@@ -388,6 +388,8 @@ brw_link_shader(struct gl_context *ctx, struct gl_shader_program *shProg)
    else
       nir_build_program_resource_list(ctx, shProg, true);
 
+   _mesa_create_program_resource_hash(shProg);
+
    for (stage = 0; stage < ARRAY_SIZE(shProg->_LinkedShaders); stage++) {
       struct gl_linked_shader *shader = shProg->_LinkedShaders[stage];
       if (!shader)
index 3b3e7ddb8de04f40e288c8dbe39a83c08948ed16..02766d3acede52d8b851e32d15e423b6f917cb36 100644 (file)
@@ -2917,6 +2917,9 @@ struct gl_shader_program_data
     */
    union gl_constant_value *UniformDataDefaults;
 
+   /** Hash for quick search by name. */
+   struct hash_table_u64 *ProgramResourceHash;
+
    GLboolean Validated;
 
    /** List of all active resources after linking. */
index 000e2a16ea7787f017410a3627a41d2304bf7edc..1a50abc31d037fee368248d4f64339e3a3e83d89 100644 (file)
@@ -37,7 +37,7 @@
 #include "compiler/glsl/ir.h"
 #include "compiler/glsl/program.h"
 #include "compiler/glsl/string_to_uint_map.h"
-
+#include "util/mesa-sha1.h"
 
 static GLint
 program_resource_location(struct gl_program_resource *res,
@@ -461,7 +461,7 @@ _mesa_program_resource_name(struct gl_program_resource *res)
    case GL_TESS_EVALUATION_SUBROUTINE:
       return RESOURCE_SUB(res)->name;
    default:
-      assert(!"support for resource type not implemented");
+      break;
    }
    return NULL;
 }
@@ -527,6 +527,51 @@ valid_array_index(const GLchar *name, unsigned *array_index)
    return true;
 }
 
+static uint32_t
+compute_resource_key(GLenum programInterface, const char *name)
+{
+   struct mesa_sha1 ctx;
+   unsigned char sha1[20];
+
+   _mesa_sha1_init(&ctx);
+   _mesa_sha1_update(&ctx, &programInterface, sizeof(programInterface));
+   _mesa_sha1_update(&ctx, name, strlen(name));
+   _mesa_sha1_final(&ctx, sha1);
+
+   return _mesa_hash_data(sha1, sizeof(sha1));
+}
+
+static struct gl_program_resource *
+search_resource_hash(struct gl_shader_program *shProg,
+                     GLenum programInterface, const char *name,
+                     unsigned *array_index)
+{
+   const char *base_name_end;
+   long index = parse_program_resource_name(name, &base_name_end);
+   char *name_copy;
+
+   /* If dealing with array, we need to get the basename. */
+   if (index >= 0) {
+      name_copy = (char *) malloc(base_name_end - name + 1);
+      memcpy(name_copy, name, base_name_end - name);
+      name_copy[base_name_end - name] = '\0';
+   } else {
+      name_copy = (char*) name;
+   }
+
+   uint32_t key = compute_resource_key(programInterface, name_copy);
+   struct gl_program_resource *res = (struct gl_program_resource *)
+      _mesa_hash_table_u64_search(shProg->data->ProgramResourceHash, key);
+
+   if (name_copy != name)
+      free(name_copy);
+
+   if (res && array_index)
+      *array_index = index >= 0 ? index : 0;
+
+   return res;
+}
+
 /* Find a program resource with specific name in given interface.
  */
 struct gl_program_resource *
@@ -534,9 +579,17 @@ _mesa_program_resource_find_name(struct gl_shader_program *shProg,
                                  GLenum programInterface, const char *name,
                                  unsigned *array_index)
 {
-   struct gl_program_resource *res = shProg->data->ProgramResourceList;
-   for (unsigned i = 0; i < shProg->data->NumProgramResourceList;
-        i++, res++) {
+   struct gl_program_resource *res = NULL;
+
+   /* If we have a name, try the ProgramResourceHash first. */
+   if (name && shProg->data->ProgramResourceHash)
+      res = search_resource_hash(shProg, programInterface, name, array_index);
+
+   if (res)
+      return res;
+
+   res = shProg->data->ProgramResourceList;
+   for (unsigned i = 0; i < shProg->data->NumProgramResourceList; i++, res++) {
       if (res->Type != programInterface)
          continue;
 
@@ -1850,3 +1903,23 @@ _mesa_validate_pipeline_io(struct gl_pipeline_object *pipeline)
    }
    return true;
 }
+
+extern "C" void
+_mesa_create_program_resource_hash(struct gl_shader_program *shProg)
+{
+   /* Rebuild resource hash. */
+   if (shProg->data->ProgramResourceHash)
+      _mesa_hash_table_u64_destroy(shProg->data->ProgramResourceHash, NULL);
+
+   shProg->data->ProgramResourceHash = _mesa_hash_table_u64_create(shProg);
+
+   struct gl_program_resource *res = shProg->data->ProgramResourceList;
+   for (unsigned i = 0; i < shProg->data->NumProgramResourceList; i++, res++) {
+      const char *name = _mesa_program_resource_name(res);
+      if (name) {
+         uint32_t key = compute_resource_key(res->Type, name);
+         _mesa_hash_table_u64_insert(shProg->data->ProgramResourceHash, key,
+                                     res);
+      }
+   }
+}
index 66acb6a9694db56a2e6163ccf07f697e5e0140d9..bba737868ef290b7eb81b8237fc7ababb9013dd5 100644 (file)
@@ -332,6 +332,9 @@ _mesa_get_program_resourceiv(struct gl_shader_program *shProg,
                              GLsizei bufSize, GLsizei *length,
                              GLint *params);
 
+extern void
+_mesa_create_program_resource_hash(struct gl_shader_program *shProg);
+
 /* GL_ARB_tessellation_shader */
 void GLAPIENTRY
 _mesa_PatchParameteri_no_error(GLenum pname, GLint value);
index 834e2a92ec4120bc87686c3335ad5e33d06a0a77..a2478d969759e5932600f839852c41882ed4e497 100644 (file)
@@ -344,6 +344,11 @@ _mesa_clear_shader_program_data(struct gl_context *ctx,
       shProg->UniformHash = NULL;
    }
 
+   if (shProg->data && shProg->data->ProgramResourceHash) {
+      _mesa_hash_table_u64_destroy(shProg->data->ProgramResourceHash, NULL);
+      shProg->data->ProgramResourceHash = NULL;
+   }
+
    _mesa_reference_shader_program_data(ctx, &shProg->data, NULL);
 }
 
index c92b1c365a7707aba1e78c9d07dc3d35e7046cd6..b01cc3fd8d9a0617cfd64629346e6f1a522250d4 100644 (file)
@@ -843,6 +843,8 @@ st_link_nir(struct gl_context *ctx,
       prev_info = info;
    }
 
+   _mesa_create_program_resource_hash(shader_program);
+
    return true;
 }
 
index b6c2c2deb776ab43d83d9a9a3230c128e075846b..cd77effebc4016fcfd1e734b5162233b7ddaa845 100644 (file)
@@ -7428,5 +7428,7 @@ st_link_tgsi(struct gl_context *ctx, struct gl_shader_program *prog)
       }
    }
 
+   _mesa_create_program_resource_hash(prog);
+
    return GL_TRUE;
 }