From dd09f1d806bab62e2399d2fc7a5d0922c594eab3 Mon Sep 17 00:00:00 2001 From: Tapani Pälli Date: Fri, 3 Jan 2020 07:56:23 +0200 Subject: mesa/st/i965: add a ProgramResourceHash for quicker resource lookup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 Reviewed-by: Marek Olšák Tested-by: Marge Bot Part-of: --- src/mesa/drivers/dri/i965/brw_link.cpp | 2 + src/mesa/main/mtypes.h | 3 ++ src/mesa/main/shader_query.cpp | 83 ++++++++++++++++++++++++++++-- src/mesa/main/shaderapi.h | 3 ++ src/mesa/main/shaderobj.c | 5 ++ src/mesa/state_tracker/st_glsl_to_nir.cpp | 2 + src/mesa/state_tracker/st_glsl_to_tgsi.cpp | 2 + 7 files changed, 95 insertions(+), 5 deletions(-) diff --git a/src/mesa/drivers/dri/i965/brw_link.cpp b/src/mesa/drivers/dri/i965/brw_link.cpp index 2a844575c3d..8a62ffd760b 100644 --- a/src/mesa/drivers/dri/i965/brw_link.cpp +++ b/src/mesa/drivers/dri/i965/brw_link.cpp @@ -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) diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h index 3b3e7ddb8de..02766d3aced 100644 --- a/src/mesa/main/mtypes.h +++ b/src/mesa/main/mtypes.h @@ -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. */ diff --git a/src/mesa/main/shader_query.cpp b/src/mesa/main/shader_query.cpp index 000e2a16ea7..1a50abc31d0 100644 --- a/src/mesa/main/shader_query.cpp +++ b/src/mesa/main/shader_query.cpp @@ -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); + } + } +} diff --git a/src/mesa/main/shaderapi.h b/src/mesa/main/shaderapi.h index 66acb6a9694..bba737868ef 100644 --- a/src/mesa/main/shaderapi.h +++ b/src/mesa/main/shaderapi.h @@ -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); diff --git a/src/mesa/main/shaderobj.c b/src/mesa/main/shaderobj.c index 834e2a92ec4..a2478d96975 100644 --- a/src/mesa/main/shaderobj.c +++ b/src/mesa/main/shaderobj.c @@ -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); } diff --git a/src/mesa/state_tracker/st_glsl_to_nir.cpp b/src/mesa/state_tracker/st_glsl_to_nir.cpp index c92b1c365a7..b01cc3fd8d9 100644 --- a/src/mesa/state_tracker/st_glsl_to_nir.cpp +++ b/src/mesa/state_tracker/st_glsl_to_nir.cpp @@ -843,6 +843,8 @@ st_link_nir(struct gl_context *ctx, prev_info = info; } + _mesa_create_program_resource_hash(shader_program); + return true; } diff --git a/src/mesa/state_tracker/st_glsl_to_tgsi.cpp b/src/mesa/state_tracker/st_glsl_to_tgsi.cpp index b6c2c2deb77..cd77effebc4 100644 --- a/src/mesa/state_tracker/st_glsl_to_tgsi.cpp +++ b/src/mesa/state_tracker/st_glsl_to_tgsi.cpp @@ -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; } -- cgit v1.2.3