From ddf33754742954b42cb5d964f10b17abecd88d04 Mon Sep 17 00:00:00 2001 From: Nicolai Hähnle Date: Sat, 24 Jun 2017 10:14:07 +0200 Subject: mesa: store uniform location in gl_program_parameter This avoids name-based lookups after the initial linking, which should help with SPIR-V shaders where names are optional. --- src/compiler/glsl/shader_cache.cpp | 20 ++++++++--- src/mesa/program/ir_to_mesa.cpp | 19 +++++++---- src/mesa/program/prog_parameter.c | 9 +++-- src/mesa/program/prog_parameter.h | 14 +++++--- src/mesa/program/prog_parameter_layout.c | 17 ++++----- src/mesa/program/prog_print.c | 2 +- src/mesa/program/prog_statevars.c | 2 +- src/mesa/state_tracker/st_glsl_to_nir.cpp | 57 +++++++++---------------------- 8 files changed, 71 insertions(+), 69 deletions(-) diff --git a/src/compiler/glsl/shader_cache.cpp b/src/compiler/glsl/shader_cache.cpp index cc4d24482d..2989408dd2 100644 --- a/src/compiler/glsl/shader_cache.cpp +++ b/src/compiler/glsl/shader_cache.cpp @@ -1085,8 +1085,12 @@ write_shader_parameters(struct blob *metadata, blob_write_string(metadata, param->Name); blob_write_uint32(metadata, param->Size); blob_write_uint32(metadata, param->DataType); - blob_write_bytes(metadata, param->StateIndexes, - sizeof(param->StateIndexes)); + if (param->Type == PROGRAM_STATE_VAR) { + blob_write_bytes(metadata, param->u.StateIndexes, + sizeof(param->u.StateIndexes)); + } else { + blob_write_uint32(metadata, param->u.Location); + } i += (param->Size + 3) / 4; } @@ -1111,11 +1115,17 @@ read_shader_parameters(struct blob_reader *metadata, const char *name = blob_read_string(metadata); unsigned size = blob_read_uint32(metadata); unsigned data_type = blob_read_uint32(metadata); - blob_copy_bytes(metadata, (uint8_t *) state_indexes, - sizeof(state_indexes)); + + if (type == PROGRAM_STATE_VAR) { + blob_copy_bytes(metadata, (uint8_t *) state_indexes, + sizeof(state_indexes)); + } _mesa_add_parameter(params, type, name, size, data_type, - NULL, state_indexes); + NULL, type == PROGRAM_STATE_VAR ? state_indexes : NULL); + + if (type != PROGRAM_STATE_VAR) + params->Parameters[i].u.Location = blob_read_uint32(metadata); i += (size + 3) / 4; } diff --git a/src/mesa/program/ir_to_mesa.cpp b/src/mesa/program/ir_to_mesa.cpp index 1dfa9fe657..8839ec108e 100644 --- a/src/mesa/program/ir_to_mesa.cpp +++ b/src/mesa/program/ir_to_mesa.cpp @@ -2457,6 +2457,17 @@ add_uniform_to_shader::visit_field(const glsl_type *type, const char *name, int index = _mesa_add_parameter(params, PROGRAM_UNIFORM, name, size, type->gl_type, NULL, NULL); + unsigned location; + const bool found = + this->shader_program->UniformHash->get(location, name); + + assert(found); + if (!found) + return; + + for (unsigned int j = 0; j < size / 4; j++) + params->Parameters[index + j].u.Location = location; + /* The first part of the uniform that's processed determines the base * location of the whole uniform (for structures). */ @@ -2510,13 +2521,7 @@ _mesa_associate_uniform_storage(struct gl_context *ctx, if (params->Parameters[i].Type != PROGRAM_UNIFORM) continue; - unsigned location; - const bool found = - shader_program->UniformHash->get(location, params->Parameters[i].Name); - assert(found); - - if (!found) - continue; + unsigned location = params->Parameters[i].u.Location; struct gl_uniform_storage *storage = &shader_program->data->UniformStorage[location]; diff --git a/src/mesa/program/prog_parameter.c b/src/mesa/program/prog_parameter.c index 40bc47de35..5c50101863 100644 --- a/src/mesa/program/prog_parameter.c +++ b/src/mesa/program/prog_parameter.c @@ -286,8 +286,10 @@ _mesa_add_parameter(struct gl_program_parameter_list *paramList, } if (state) { + assert(type == PROGRAM_STATE_VAR); + for (i = 0; i < STATE_LENGTH; i++) - paramList->Parameters[oldNum].StateIndexes[i] = state[i]; + paramList->Parameters[oldNum].u.StateIndexes[i] = state[i]; } return (GLint) oldNum; @@ -371,7 +373,10 @@ _mesa_add_state_reference(struct gl_program_parameter_list *paramList, /* Check if the state reference is already in the list */ for (index = 0; index < (GLint) paramList->NumParameters; index++) { - if (!memcmp(paramList->Parameters[index].StateIndexes, + if (paramList->Parameters[index].Type != PROGRAM_STATE_VAR) + continue; + + if (!memcmp(paramList->Parameters[index].u.StateIndexes, stateTokens, STATE_LENGTH * sizeof(gl_state_index))) { return index; } diff --git a/src/mesa/program/prog_parameter.h b/src/mesa/program/prog_parameter.h index f50e99c8ab..23a06bd06a 100644 --- a/src/mesa/program/prog_parameter.h +++ b/src/mesa/program/prog_parameter.h @@ -69,10 +69,16 @@ struct gl_program_parameter * The next program parameter's Size will be Size-4 of this parameter. */ GLuint Size; - /** - * A sequence of STATE_* tokens and integers to identify GL state. - */ - gl_state_index StateIndexes[STATE_LENGTH]; + + union { + /** + * A sequence of STATE_* tokens and integers to identify GL state. + */ + gl_state_index StateIndexes[STATE_LENGTH]; + + /** Location of the corresponding uniform */ + GLuint Location; + } u; }; diff --git a/src/mesa/program/prog_parameter_layout.c b/src/mesa/program/prog_parameter_layout.c index 282a367ad0..052aceeda0 100644 --- a/src/mesa/program/prog_parameter_layout.c +++ b/src/mesa/program/prog_parameter_layout.c @@ -80,13 +80,14 @@ copy_indirect_accessed_array(struct gl_program_parameter_list *src, if (curr->Type == PROGRAM_CONSTANT) { j = dst->NumParameters; - } else { - for (j = 0; j < dst->NumParameters; j++) { - if (memcmp(dst->Parameters[j].StateIndexes, curr->StateIndexes, - sizeof(curr->StateIndexes)) == 0) { - return -1; - } - } + } else if (curr->Type == PROGRAM_STATE_VAR) { + for (j = 0; j < dst->NumParameters; j++) { + if (dst->Parameters[j].Type == PROGRAM_STATE_VAR && + memcmp(dst->Parameters[j].u.StateIndexes, curr->u.StateIndexes, + sizeof(curr->u.StateIndexes)) == 0) { + return -1; + } + } } assert(j == dst->NumParameters); @@ -196,7 +197,7 @@ _mesa_layout_parameters(struct asm_parser_state *state) case PROGRAM_STATE_VAR: inst->Base.SrcReg[i].Index = - _mesa_add_state_reference(layout, p->StateIndexes); + _mesa_add_state_reference(layout, p->u.StateIndexes); break; default: diff --git a/src/mesa/program/prog_print.c b/src/mesa/program/prog_print.c index 4f85d14c41..24ea4ca6e7 100644 --- a/src/mesa/program/prog_print.c +++ b/src/mesa/program/prog_print.c @@ -401,7 +401,7 @@ reg_string(gl_register_file f, GLint index, gl_prog_print_mode mode, { struct gl_program_parameter *param = prog->Parameters->Parameters + index; - char *state = _mesa_program_state_string(param->StateIndexes); + char *state = _mesa_program_state_string(param->u.StateIndexes); sprintf(str, "%s", state); free(state); } diff --git a/src/mesa/program/prog_statevars.c b/src/mesa/program/prog_statevars.c index 91178e395c..b24c473637 100644 --- a/src/mesa/program/prog_statevars.c +++ b/src/mesa/program/prog_statevars.c @@ -1076,7 +1076,7 @@ _mesa_load_state_parameters(struct gl_context *ctx, for (i = 0; i < paramList->NumParameters; i++) { if (paramList->Parameters[i].Type == PROGRAM_STATE_VAR) { _mesa_fetch_state(ctx, - paramList->Parameters[i].StateIndexes, + paramList->Parameters[i].u.StateIndexes, ¶mList->ParameterValues[i][0]); } } diff --git a/src/mesa/state_tracker/st_glsl_to_nir.cpp b/src/mesa/state_tracker/st_glsl_to_nir.cpp index 8d29aa93d6..56e5694b60 100644 --- a/src/mesa/state_tracker/st_glsl_to_nir.cpp +++ b/src/mesa/state_tracker/st_glsl_to_nir.cpp @@ -123,50 +123,25 @@ st_nir_assign_vs_in_locations(struct gl_program *prog, nir_shader *nir) static int st_nir_lookup_parameter_index(const struct gl_program_parameter_list *params, - const char *name) + nir_variable *uniform) { - int loc = _mesa_lookup_parameter_index(params, name); - - /* is there a better way to do this? If we have something like: - * - * struct S { - * float f; - * vec4 v; - * }; - * uniform S color; - * - * Then what we get in prog->Parameters looks like: - * - * 0: Name=color.f, Type=6, DataType=1406, Size=1 - * 1: Name=color.v, Type=6, DataType=8b52, Size=4 - * - * So the name doesn't match up and _mesa_lookup_parameter_index() - * fails. In this case just find the first matching "color.*".. - * - * Note for arrays you could end up w/ color[n].f, for example. - * - * glsl_to_tgsi works slightly differently in this regard. It is - * emitting something more low level, so it just translates the - * params list 1:1 to CONST[] regs. Going from GLSL IR to TGSI, - * it just calculates the additional offset of struct field members - * in glsl_to_tgsi_visitor::visit(ir_dereference_record *ir) or - * glsl_to_tgsi_visitor::visit(ir_dereference_array *ir). It never - * needs to work backwards to get base var loc from the param-list - * which already has them separated out. - */ - if (loc < 0) { - int namelen = strlen(name); - for (unsigned i = 0; i < params->NumParameters; i++) { - struct gl_program_parameter *p = ¶ms->Parameters[i]; - if ((strncmp(p->Name, name, namelen) == 0) && - ((p->Name[namelen] == '.') || (p->Name[namelen] == '['))) { - loc = i; - break; - } + assert(uniform->data.mode == nir_var_uniform); + assert(uniform->data.location >= 0 || strncmp(uniform->name, "state.", 6) == 0); + + for (unsigned int i = 0; i < params->NumParameters; ++i) { + const struct gl_program_parameter *param = ¶ms->Parameters[i]; + + if (uniform->data.location >= 0) { + if ((param->Type == PROGRAM_SAMPLER || param->Type == PROGRAM_UNIFORM) && + param->u.Location == (unsigned)uniform->data.location) + return i; + } else if (param->Type == PROGRAM_STATE_VAR && + strcmp(uniform->name, param->Name) == 0) { + return i; } } - return loc; + return -1; } static void @@ -205,7 +180,7 @@ st_nir_assign_uniform_locations(struct gl_program *prog, */ loc = _mesa_add_state_reference(prog->Parameters, stateTokens); } else { - loc = st_nir_lookup_parameter_index(prog->Parameters, uniform->name); + loc = st_nir_lookup_parameter_index(prog->Parameters, uniform); } uniform->data.driver_location = loc; -- cgit v1.2.3