[Mesa-dev] [PATCH 03/17] mesa: rework ParameterList to allow packing
Nicolai Hähnle
nhaehnle at gmail.com
Mon Jun 26 09:17:34 UTC 2017
On 25.06.2017 03:31, Timothy Arceri wrote:
> Currently everything is padded to 4 elements. Making the list
> more flexible will allow us to do uniform packing.
>
> This change requires us to remove the existing packing in
> _mesa_add_typed_unnamed_constant() in order to avoid regressions.
> This packing will no longer be required once we add full packing
> support in the folling patches anyway.
> ---
> src/compiler/glsl/shader_cache.cpp | 14 ++++++--
> src/mesa/drivers/dri/i915/i915_fragprog.c | 9 +++---
> src/mesa/drivers/dri/i965/brw_nir_uniforms.cpp | 6 ++--
> src/mesa/drivers/dri/r200/r200_vertprog.c | 10 +++---
> src/mesa/main/uniform_query.cpp | 14 ++++----
> src/mesa/program/ir_to_mesa.cpp | 11 ++++---
> src/mesa/program/prog_execute.c | 6 ++--
> src/mesa/program/prog_opt_constant_fold.c | 3 +-
> src/mesa/program/prog_parameter.c | 44 ++++++++++++++++++--------
> src/mesa/program/prog_parameter.h | 9 ++++--
> src/mesa/program/prog_parameter_layout.c | 21 +++++++++---
> src/mesa/program/prog_print.c | 4 ++-
> src/mesa/program/prog_statevars.c | 3 +-
> src/mesa/program/prog_to_nir.c | 3 +-
> src/mesa/program/program_parse.y | 2 +-
> src/mesa/state_tracker/st_atifs_to_tgsi.c | 6 ++--
> src/mesa/state_tracker/st_atom_constbuf.c | 5 +--
> src/mesa/state_tracker/st_glsl_to_tgsi.cpp | 4 ++-
> src/mesa/state_tracker/st_mesa_to_tgsi.c | 8 +++--
> 19 files changed, 121 insertions(+), 61 deletions(-)
>
> diff --git a/src/compiler/glsl/shader_cache.cpp b/src/compiler/glsl/shader_cache.cpp
> index 1293246..ff81de1 100644
> --- a/src/compiler/glsl/shader_cache.cpp
> +++ b/src/compiler/glsl/shader_cache.cpp
> @@ -1069,66 +1069,74 @@ read_program_resource_list(struct blob_reader *metadata,
> (uint8_t *) &prog->data->ProgramResourceList[i].StageReferences,
> sizeof(prog->data->ProgramResourceList[i].StageReferences));
> }
> }
>
> static void
> write_shader_parameters(struct blob *metadata,
> struct gl_program_parameter_list *params)
> {
> blob_write_uint32(metadata, params->NumParameters);
> + blob_write_uint32(metadata, params->NumParameterValues);
> uint32_t i = 0;
>
> while (i < params->NumParameters) {
> struct gl_program_parameter *param = ¶ms->Parameters[i];
>
> blob_write_uint32(metadata, param->Type);
> 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));
>
> i++;
> }
>
> blob_write_bytes(metadata, params->ParameterValues,
> - sizeof(gl_constant_value) * 4 * params->NumParameters);
> + sizeof(gl_constant_value) * params->NumParameterValues);
> +
> + blob_write_bytes(metadata, params->ParameterValueOffset,
> + sizeof(uint32_t) * params->NumParameters);
>
> blob_write_uint32(metadata, params->StateFlags);
> }
>
> static void
> read_shader_parameters(struct blob_reader *metadata,
> struct gl_program_parameter_list *params)
> {
> gl_state_index state_indexes[STATE_LENGTH];
> uint32_t i = 0;
> uint32_t num_parameters = blob_read_uint32(metadata);
> + uint32_t num_parameters_values = blob_read_uint32(metadata);
>
> _mesa_reserve_parameter_storage(params, num_parameters);
> while (i < num_parameters) {
> gl_register_file type = (gl_register_file) blob_read_uint32(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));
>
> _mesa_add_parameter(params, type, name, size, data_type,
> - NULL, state_indexes);
> + NULL, state_indexes, false);
>
> i++;
> }
>
> blob_copy_bytes(metadata, (uint8_t *) params->ParameterValues,
> - sizeof(gl_constant_value) * 4 * params->NumParameters);
> + sizeof(gl_constant_value) * num_parameters_values);
> +
> + blob_copy_bytes(metadata, (uint8_t *) params->ParameterValueOffset,
> + sizeof(uint32_t) * num_parameters);
>
> params->StateFlags = blob_read_uint32(metadata);
> }
>
> static void
> write_shader_metadata(struct blob *metadata, gl_linked_shader *shader)
> {
> assert(shader->Program);
> struct gl_program *glprog = shader->Program;
> unsigned i;
> diff --git a/src/mesa/drivers/dri/i915/i915_fragprog.c b/src/mesa/drivers/dri/i915/i915_fragprog.c
> index 2e04319..6493ab9 100644
> --- a/src/mesa/drivers/dri/i915/i915_fragprog.c
> +++ b/src/mesa/drivers/dri/i915/i915_fragprog.c
> @@ -177,25 +177,26 @@ src_vector(struct i915_fragment_program *p,
> i915_program_error(p, "Bad source->Index: %d", source->Index);
> return 0;
> }
> break;
>
> /* Various paramters and env values. All emitted to
> * hardware as program constants.
> */
> case PROGRAM_CONSTANT:
> case PROGRAM_STATE_VAR:
> - case PROGRAM_UNIFORM:
> - src = i915_emit_param4fv(p,
> - &program->Parameters->ParameterValues[source->Index][0].f);
> + case PROGRAM_UNIFORM: {
> + struct gl_program_parameter_list *params = program->Parameters;
> + unsigned offset = params->ParameterValueOffset[source->Index];
> + src = i915_emit_param4fv(p, ¶ms->ParameterValues[offset].f);
> break;
> -
> + }
> default:
> i915_program_error(p, "Bad source->File: %d", source->File);
> return 0;
> }
>
> src = swizzle(src,
> GET_SWZ(source->Swizzle, 0),
> GET_SWZ(source->Swizzle, 1),
> GET_SWZ(source->Swizzle, 2), GET_SWZ(source->Swizzle, 3));
>
> diff --git a/src/mesa/drivers/dri/i965/brw_nir_uniforms.cpp b/src/mesa/drivers/dri/i965/brw_nir_uniforms.cpp
> index f0bccac..c23c961 100644
> --- a/src/mesa/drivers/dri/i965/brw_nir_uniforms.cpp
> +++ b/src/mesa/drivers/dri/i965/brw_nir_uniforms.cpp
> @@ -39,35 +39,36 @@ brw_nir_setup_glsl_builtin_uniform(nir_variable *var,
> * get the same index back here.
> */
> int index = _mesa_add_state_reference(prog->Parameters,
> (gl_state_index *)slots[i].tokens);
>
> /* Add each of the unique swizzles of the element as a parameter.
> * This'll end up matching the expected layout of the
> * array/matrix/structure we're trying to fill in.
> */
> int last_swiz = -1;
> + unsigned offset = prog->Parameters->ParameterValueOffset[index];
> for (unsigned j = 0; j < 4; j++) {
> int swiz = GET_SWZ(slots[i].swizzle, j);
>
> /* If we hit a pair of identical swizzles, this means we've hit the
> * end of the builtin variable. In scalar mode, we should just quit
> * and move on to the next one. In vec4, we need to continue and pad
> * it out to 4 components.
> */
> if (swiz == last_swiz && is_scalar)
> break;
>
> last_swiz = swiz;
>
> stage_prog_data->param[uniform_index++] =
> - &prog->Parameters->ParameterValues[index][swiz];
> + &prog->Parameters->ParameterValues[offset + swiz];
> }
> }
> }
>
> static void
> setup_vec4_uniform_value(const gl_constant_value **params,
> const gl_constant_value *values,
> unsigned n)
> {
> static const gl_constant_value zero = { 0 };
> @@ -216,19 +217,20 @@ brw_nir_setup_arb_uniforms(nir_shader *shader, struct gl_program *prog,
> assert(shader->uniforms.length() <= 2);
>
> for (unsigned p = 0; p < plist->NumParameters; p++) {
> /* Parameters should be either vec4 uniforms or single component
> * constants; matrices and other larger types should have been broken
> * down earlier.
> */
> assert(plist->Parameters[p].Size <= 4);
>
> unsigned i;
> + unsigned o = plist->ParameterValueOffset[p];
> for (i = 0; i < plist->Parameters[p].Size; i++) {
> - stage_prog_data->param[4 * p + i] = &plist->ParameterValues[p][i];
> + stage_prog_data->param[4 * p + i] = &plist->ParameterValues[o + i];
> }
> for (; i < 4; i++) {
> static const gl_constant_value zero = { 0.0 };
> stage_prog_data->param[4 * p + i] = &zero;
> }
> }
> }
> diff --git a/src/mesa/drivers/dri/r200/r200_vertprog.c b/src/mesa/drivers/dri/r200/r200_vertprog.c
> index bb85503..5385b19 100644
> --- a/src/mesa/drivers/dri/r200/r200_vertprog.c
> +++ b/src/mesa/drivers/dri/r200/r200_vertprog.c
> @@ -113,28 +113,30 @@ static GLboolean r200VertexProgUpdateParams(struct gl_context *ctx, struct r200_
> assert(mesa_vp->Parameters);
> _mesa_load_state_parameters(ctx, mesa_vp->Parameters);
> paramList = mesa_vp->Parameters;
>
> if(paramList->NumParameters > R200_VSF_MAX_PARAM){
> fprintf(stderr, "%s:Params exhausted\n", __func__);
> return GL_FALSE;
> }
>
> for(pi = 0; pi < paramList->NumParameters; pi++) {
> + unsigned pvo = paramList->ParameterValueOffset[pi];
> +
> switch(paramList->Parameters[pi].Type) {
> case PROGRAM_STATE_VAR:
> //fprintf(stderr, "%s", vp->Parameters->Parameters[pi].Name);
> case PROGRAM_CONSTANT:
> - *fcmd++ = paramList->ParameterValues[pi][0].f;
> - *fcmd++ = paramList->ParameterValues[pi][1].f;
> - *fcmd++ = paramList->ParameterValues[pi][2].f;
> - *fcmd++ = paramList->ParameterValues[pi][3].f;
> + *fcmd++ = paramList->ParameterValues[pvo + 0].f;
> + *fcmd++ = paramList->ParameterValues[pvo + 1].f;
> + *fcmd++ = paramList->ParameterValues[pvo + 2].f;
> + *fcmd++ = paramList->ParameterValues[pvo + 3].f;
> break;
> default:
> _mesa_problem(NULL, "Bad param type in %s", __func__);
> break;
> }
> if (pi == 95) {
> fcmd = (GLfloat *)&rmesa->hw.vpp[1].cmd[VPP_CMD_0 + 1];
> }
> }
> /* hack up the cmd_size so not the whole state atom is emitted always. */
> diff --git a/src/mesa/main/uniform_query.cpp b/src/mesa/main/uniform_query.cpp
> index 9683fa8..5755b40 100644
> --- a/src/mesa/main/uniform_query.cpp
> +++ b/src/mesa/main/uniform_query.cpp
> @@ -715,27 +715,29 @@ log_program_parameters(const struct gl_shader_program *shProg)
> {
> for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) {
> if (shProg->_LinkedShaders[i] == NULL)
> continue;
>
> const struct gl_program *const prog = shProg->_LinkedShaders[i]->Program;
>
> printf("Program %d %s shader parameters:\n",
> shProg->Name, _mesa_shader_stage_to_string(i));
> for (unsigned j = 0; j < prog->Parameters->NumParameters; j++) {
> - printf("%s: %p %f %f %f %f\n",
> + unsigned pvo = prog->Parameters->ParameterValueOffset[j];
> + printf("%s: %u %p %f %f %f %f\n",
> prog->Parameters->Parameters[j].Name,
> - prog->Parameters->ParameterValues[j],
> - prog->Parameters->ParameterValues[j][0].f,
> - prog->Parameters->ParameterValues[j][1].f,
> - prog->Parameters->ParameterValues[j][2].f,
> - prog->Parameters->ParameterValues[j][3].f);
> + pvo,
> + prog->Parameters->ParameterValues + pvo,
> + prog->Parameters->ParameterValues[pvo].f,
> + prog->Parameters->ParameterValues[pvo + 1].f,
> + prog->Parameters->ParameterValues[pvo + 2].f,
> + prog->Parameters->ParameterValues[pvo + 3].f);
> }
> }
> fflush(stdout);
> }
> #endif
>
> /**
> * Propagate some values from uniform backing storage to driver storage
> *
> * Values propagated from uniform backing storage to driver storage
> diff --git a/src/mesa/program/ir_to_mesa.cpp b/src/mesa/program/ir_to_mesa.cpp
> index dd757c6..3fb5a24 100644
> --- a/src/mesa/program/ir_to_mesa.cpp
> +++ b/src/mesa/program/ir_to_mesa.cpp
> @@ -2461,21 +2461,21 @@ add_uniform_to_shader::visit_field(const glsl_type *type, const char *name,
>
> bool is_dual_slot = type->without_array()->is_dual_slot();
> if (is_dual_slot)
> num_params *= 2;
>
> _mesa_reserve_parameter_storage(params, num_params);
> index = params->NumParameters;
> for (unsigned i = 0; i < num_params; i++) {
> unsigned comps = 4;
> _mesa_add_parameter(params, PROGRAM_UNIFORM, name, comps,
> - type->gl_type, NULL, NULL);
> + type->gl_type, NULL, NULL, false);
> }
> }
>
> /* The first part of the uniform that's processed determines the base
> * location of the whole uniform (for structures).
> */
> if (this->idx < 0)
> this->idx = index;
> }
>
> @@ -2586,44 +2586,45 @@ _mesa_associate_uniform_storage(struct gl_context *ctx,
> case GLSL_TYPE_ARRAY:
> case GLSL_TYPE_VOID:
> case GLSL_TYPE_STRUCT:
> case GLSL_TYPE_ERROR:
> case GLSL_TYPE_INTERFACE:
> case GLSL_TYPE_FUNCTION:
> assert(!"Should not get here.");
> break;
> }
>
> - _mesa_uniform_attach_driver_storage(storage, dmul * columns, dmul,
> + unsigned pvo = params->ParameterValueOffset[i];
> + _mesa_uniform_attach_driver_storage(storage, dmul * columns, dmul,
Spurious whitespace change.
> format,
> - ¶ms->ParameterValues[i]);
> + ¶ms->ParameterValues[pvo]);
>
> /* When a bindless sampler/image is bound to a texture/image unit, we
> * have to overwrite the constant value by the resident handle
> * directly in the constant buffer before the next draw. One solution
> * is to keep track a pointer to the base of the data.
> */
> if (storage->is_bindless && (prog->sh.NumBindlessSamplers ||
> prog->sh.NumBindlessImages)) {
> unsigned array_elements = MAX2(1, storage->array_elements);
>
> for (unsigned j = 0; j < array_elements; ++j) {
> unsigned unit = storage->opaque[shader_type].index + j;
>
> if (storage->type->without_array()->is_sampler()) {
> assert(unit >= 0 && unit < prog->sh.NumBindlessSamplers);
> prog->sh.BindlessSamplers[unit].data =
> - ¶ms->ParameterValues[i] + j;
> + ¶ms->ParameterValues[pvo] + j;
Should this be 4 * j?
> } else if (storage->type->without_array()->is_image()) {
> assert(unit >= 0 && unit < prog->sh.NumBindlessImages);
> prog->sh.BindlessImages[unit].data =
> - ¶ms->ParameterValues[i] + j;
> + ¶ms->ParameterValues[pvo] + j;
Dito.
> }
> }
> }
>
> /* After attaching the driver's storage to the uniform, propagate any
> * data from the linker's backing store. This will cause values from
> * initializers in the source code to be copied over.
> */
> if (propagate_to_storage) {
> unsigned array_elements = MAX2(1, storage->array_elements);
> diff --git a/src/mesa/program/prog_execute.c b/src/mesa/program/prog_execute.c
> index 1268476..5cea484 100644
> --- a/src/mesa/program/prog_execute.c
> +++ b/src/mesa/program/prog_execute.c
> @@ -110,25 +110,27 @@ get_src_register_pointer(const struct prog_src_register *source,
>
> case PROGRAM_OUTPUT:
> if (reg >= MAX_PROGRAM_OUTPUTS)
> return ZeroVec;
> return machine->Outputs[reg];
>
> case PROGRAM_STATE_VAR:
> /* Fallthrough */
> case PROGRAM_CONSTANT:
> /* Fallthrough */
> - case PROGRAM_UNIFORM:
> + case PROGRAM_UNIFORM: {
> if (reg >= (GLint) prog->Parameters->NumParameters)
> return ZeroVec;
> - return (GLfloat *) prog->Parameters->ParameterValues[reg];
>
> + unsigned pvo = prog->Parameters->ParameterValueOffset[reg];
> + return (GLfloat *) prog->Parameters->ParameterValues + pvo;
> + }
> case PROGRAM_SYSTEM_VALUE:
> assert(reg < (GLint) ARRAY_SIZE(machine->SystemValues));
> return machine->SystemValues[reg];
>
> default:
> _mesa_problem(NULL,
> "Invalid src register file %d in get_src_register_pointer()",
> source->File);
> return ZeroVec;
> }
> diff --git a/src/mesa/program/prog_opt_constant_fold.c b/src/mesa/program/prog_opt_constant_fold.c
> index ba4a954..638bdbd 100644
> --- a/src/mesa/program/prog_opt_constant_fold.c
> +++ b/src/mesa/program/prog_opt_constant_fold.c
> @@ -83,22 +83,23 @@ src_regs_are_same(const struct prog_src_register *a,
> && (a->Index == b->Index)
> && (a->Swizzle == b->Swizzle)
> && (a->Negate == b->Negate)
> && (a->RelAddr == 0)
> && (b->RelAddr == 0);
> }
>
> static void
> get_value(struct gl_program *prog, struct prog_src_register *r, float *data)
> {
> + unsigned pvo = prog->Parameters->ParameterValueOffset[r->Index];
> const gl_constant_value *const value =
> - prog->Parameters->ParameterValues[r->Index];
> + prog->Parameters->ParameterValues + pvo;
>
> data[0] = value[GET_SWZ(r->Swizzle, 0)].f;
> data[1] = value[GET_SWZ(r->Swizzle, 1)].f;
> data[2] = value[GET_SWZ(r->Swizzle, 2)].f;
> data[3] = value[GET_SWZ(r->Swizzle, 3)].f;
>
> if (r->Negate & 0x01) {
> data[0] = -data[0];
> }
>
> diff --git a/src/mesa/program/prog_parameter.c b/src/mesa/program/prog_parameter.c
> index 81609f5..a677493 100644
> --- a/src/mesa/program/prog_parameter.c
> +++ b/src/mesa/program/prog_parameter.c
> @@ -59,58 +59,60 @@ lookup_parameter_constant(const struct gl_program_parameter_list *list,
> assert(vSize >= 1);
> assert(vSize <= 4);
>
> if (!list) {
> *posOut = -1;
> return GL_FALSE;
> }
>
> for (i = 0; i < list->NumParameters; i++) {
> if (list->Parameters[i].Type == PROGRAM_CONSTANT) {
> + unsigned offset = list->ParameterValueOffset[i];
> +
> if (!swizzleOut) {
> /* swizzle not allowed */
> GLuint j, match = 0;
> for (j = 0; j < vSize; j++) {
> - if (v[j].u == list->ParameterValues[i][j].u)
> + if (v[j].u == list->ParameterValues[offset + j].u)
> match++;
> }
> if (match == vSize) {
> *posOut = i;
> return GL_TRUE;
> }
> }
> else {
> /* try matching w/ swizzle */
> if (vSize == 1) {
> /* look for v[0] anywhere within float[4] value */
> GLuint j;
> for (j = 0; j < list->Parameters[i].Size; j++) {
> - if (list->ParameterValues[i][j].u == v[0].u) {
> + if (list->ParameterValues[offset + j].u == v[0].u) {
> /* found it */
> *posOut = i;
> *swizzleOut = MAKE_SWIZZLE4(j, j, j, j);
> return GL_TRUE;
> }
> }
> }
> else if (vSize <= list->Parameters[i].Size) {
> /* see if we can match this constant (with a swizzle) */
> GLuint swz[4];
> GLuint match = 0, j, k;
> for (j = 0; j < vSize; j++) {
> - if (v[j].u == list->ParameterValues[i][j].u) {
> + if (v[j].u == list->ParameterValues[offset + j].u) {
> swz[j] = j;
> match++;
> }
> else {
> for (k = 0; k < list->Parameters[i].Size; k++) {
> - if (v[j].u == list->ParameterValues[i][k].u) {
> + if (v[j].u == list->ParameterValues[offset + k].u) {
> swz[j] = k;
> match++;
> break;
> }
> }
> }
> }
> /* smear last value to remaining positions */
> for (; j < 4; j++)
> swz[j] = swz[j-1];
> @@ -142,21 +144,23 @@ _mesa_new_parameter_list_sized(unsigned size)
> {
> struct gl_program_parameter_list *p = _mesa_new_parameter_list();
>
> if ((p != NULL) && (size != 0)) {
> p->Size = size;
>
> /* alloc arrays */
> p->Parameters = (struct gl_program_parameter *)
> calloc(size, sizeof(struct gl_program_parameter));
>
> - p->ParameterValues = (gl_constant_value (*)[4])
> + p->ParameterValueOffset = (unsigned *) calloc(size, sizeof(unsigned));
> +
> + p->ParameterValues = (gl_constant_value *)
> _mesa_align_malloc(size * 4 *sizeof(gl_constant_value), 16);
>
>
> if ((p->Parameters == NULL) || (p->ParameterValues == NULL)) {
> free(p->Parameters);
> _mesa_align_free(p->ParameterValues);
> free(p);
> p = NULL;
> }
> }
> @@ -196,21 +200,25 @@ _mesa_reserve_parameter_storage(struct gl_program_parameter_list *paramList,
>
> if (oldNum + reserve_slots > paramList->Size) {
> /* Need to grow the parameter list array (alloc some extra) */
> paramList->Size = paramList->Size + 4 * reserve_slots;
>
> /* realloc arrays */
> paramList->Parameters =
> realloc(paramList->Parameters,
> paramList->Size * sizeof(struct gl_program_parameter));
>
> - paramList->ParameterValues = (gl_constant_value (*)[4])
> + paramList->ParameterValueOffset =
> + realloc(paramList->ParameterValueOffset,
> + paramList->Size * sizeof(unsigned));
> +
> + paramList->ParameterValues = (gl_constant_value *)
> _mesa_align_realloc(paramList->ParameterValues, /* old buf */
> oldNum * 4 * sizeof(gl_constant_value),/* old sz */
> paramList->Size*4*sizeof(gl_constant_value),/*new*/
> 16);
> }
> }
>
>
> /**
> * Add a new parameter to a parameter list.
> @@ -225,59 +233,66 @@ _mesa_reserve_parameter_storage(struct gl_program_parameter_list *paramList,
> * \param datatype GL_FLOAT, GL_FLOAT_VECx, GL_INT, GL_INT_VECx or GL_NONE.
> * \param values initial parameter value, up to 4 gl_constant_values, or NULL
> * \param state state indexes, or NULL
> * \return index of new parameter in the list, or -1 if error (out of mem)
> */
> GLint
> _mesa_add_parameter(struct gl_program_parameter_list *paramList,
> gl_register_file type, const char *name,
> GLuint size, GLenum datatype,
> const gl_constant_value *values,
> - const gl_state_index state[STATE_LENGTH])
> + const gl_state_index state[STATE_LENGTH],
> + bool pad_and_align)
> {
> assert(0 < size && size <=4);
> const GLuint oldNum = paramList->NumParameters;
> + unsigned oldValNum = pad_and_align ?
> + align(paramList->NumParameterValues, 4) : paramList->NumParameterValues;
>
> _mesa_reserve_parameter_storage(paramList, 1);
>
> - if (!paramList->Parameters ||
> + if (!paramList->Parameters || !paramList->ParameterValueOffset ||
> !paramList->ParameterValues) {
> /* out of memory */
> paramList->NumParameters = 0;
> paramList->Size = 0;
> return -1;
> }
>
> paramList->NumParameters = oldNum + 1;
>
> + unsigned pad = pad_and_align && size < 4 ? align(size, 4) : size;
Simplify to just pad_and_align ? align(size, 4) : size.
> + paramList->NumParameterValues = oldValNum + pad;
> +
> memset(¶mList->Parameters[oldNum], 0,
> sizeof(struct gl_program_parameter));
>
> struct gl_program_parameter *p = paramList->Parameters + oldNum;
> p->Name = strdup(name ? name : "");
> p->Type = type;
> p->Size = size;
> p->DataType = datatype;
>
> + paramList->ParameterValueOffset[oldNum] = oldValNum;
> if (values) {
> if (size >= 4) {
> - COPY_4V(paramList->ParameterValues[oldNum], values);
> + COPY_4V(paramList->ParameterValues + oldValNum, values);
> } else {
> /* copy 1, 2 or 3 values */
> assert(size < 4);
> for (unsigned j = 0; j < size; j++) {
> - paramList->ParameterValues[oldNum][j].f = values[j].f;
> + paramList->ParameterValues[oldValNum + j].f = values[j].f;
I think you may want to 0-initialize the padding space here (when it
exists) -- otherwise you may get valgrind errors in the disk cache.
> }
> }
> } else {
> for (unsigned j = 0; j < 4; j++) {
> - paramList->ParameterValues[oldNum][j].f = 0;
> + paramList->ParameterValues[oldValNum + j].f = 0;
> }
> }
>
> if (state) {
> for (unsigned i = 0; i < STATE_LENGTH; i++)
> paramList->Parameters[oldNum].StateIndexes[i] = state[i];
> }
>
> return (GLint) oldNum;
> }
> @@ -309,35 +324,36 @@ _mesa_add_typed_unnamed_constant(struct gl_program_parameter_list *paramList,
> return pos;
> }
>
> /* Look for empty space in an already unnamed constant parameter
> * to add this constant. This will only work for single-element
> * constants because we rely on smearing (i.e. .yyyy or .zzzz).
> */
> if (size == 1 && swizzleOut) {
> for (pos = 0; pos < (GLint) paramList->NumParameters; pos++) {
> struct gl_program_parameter *p = paramList->Parameters + pos;
> + unsigned offset = paramList->ParameterValueOffset[pos];
> if (p->Type == PROGRAM_CONSTANT && p->Size + size <= 4) {
> /* ok, found room */
> - gl_constant_value *pVal = paramList->ParameterValues[pos];
> + gl_constant_value *pVal = paramList->ParameterValues + offset;
> GLuint swz = p->Size; /* 1, 2 or 3 for Y, Z, W */
> pVal[p->Size] = values[0];
> p->Size++;
> *swizzleOut = MAKE_SWIZZLE4(swz, swz, swz, swz);
> return pos;
> }
> }
> }
>
> /* add a new parameter to store this constant */
> pos = _mesa_add_parameter(paramList, PROGRAM_CONSTANT, NULL,
> - size, datatype, values, NULL);
> + size, datatype, values, NULL, size < 4);
Why not just "true" as the pad_and_align parameter?
> if (pos >= 0 && swizzleOut) {
> if (size == 1)
> *swizzleOut = SWIZZLE_XXXX;
> else
> *swizzleOut = SWIZZLE_NOOP;
> }
> return pos;
> }
>
>
> @@ -362,18 +378,18 @@ _mesa_add_state_reference(struct gl_program_parameter_list *paramList,
> for (index = 0; index < (GLint) paramList->NumParameters; index++) {
> if (!memcmp(paramList->Parameters[index].StateIndexes,
> stateTokens, STATE_LENGTH * sizeof(gl_state_index))) {
> return index;
> }
> }
>
> name = _mesa_program_state_string(stateTokens);
> index = _mesa_add_parameter(paramList, PROGRAM_STATE_VAR, name,
> size, GL_NONE,
> - NULL, (gl_state_index *) stateTokens);
> + NULL, (gl_state_index *) stateTokens, false);
I'd prefer a "true" here as the pad_and_align parameter. It doesn't
really matter since size == 4 is hardcoded, but it makes the
compatibility requirement with non-packing drivers more obvious.
Actually, I'd like this to be changed at all call sites of
_mesa_add_parameter, except perhaps in the disk cache where the offsets
are overwritten anyway.
Cheers,
Nicolai
> paramList->StateFlags |= _mesa_program_state_flags(stateTokens);
>
> /* free name string here since we duplicated it in add_parameter() */
> free(name);
>
> return index;
> }
> diff --git a/src/mesa/program/prog_parameter.h b/src/mesa/program/prog_parameter.h
> index f50e99c..e5f3b39 100644
> --- a/src/mesa/program/prog_parameter.h
> +++ b/src/mesa/program/prog_parameter.h
> @@ -75,23 +75,25 @@ struct gl_program_parameter
> gl_state_index StateIndexes[STATE_LENGTH];
> };
>
>
> /**
> * List of gl_program_parameter instances.
> */
> struct gl_program_parameter_list
> {
> GLuint Size; /**< allocated size of Parameters, ParameterValues */
> - GLuint NumParameters; /**< number of parameters in arrays */
> + GLuint NumParameters; /**< number of used parameters in array */
> + unsigned NumParameterValues; /**< number of used parameter values array */
> struct gl_program_parameter *Parameters; /**< Array [Size] */
> - gl_constant_value (*ParameterValues)[4]; /**< Array [Size] of constant[4] */
> + unsigned *ParameterValueOffset;
> + gl_constant_value *ParameterValues; /**< Array [Size] of gl_constant_value */
> GLbitfield StateFlags; /**< _NEW_* flags indicating which state changes
> might invalidate ParameterValues[] */
> };
>
>
> extern struct gl_program_parameter_list *
> _mesa_new_parameter_list(void);
>
> extern struct gl_program_parameter_list *
> _mesa_new_parameter_list_sized(unsigned size);
> @@ -101,21 +103,22 @@ _mesa_free_parameter_list(struct gl_program_parameter_list *paramList);
>
> extern void
> _mesa_reserve_parameter_storage(struct gl_program_parameter_list *paramList,
> unsigned reserve_slots);
>
> extern GLint
> _mesa_add_parameter(struct gl_program_parameter_list *paramList,
> gl_register_file type, const char *name,
> GLuint size, GLenum datatype,
> const gl_constant_value *values,
> - const gl_state_index state[STATE_LENGTH]);
> + const gl_state_index state[STATE_LENGTH],
> + bool pad_and_align);
>
> extern GLint
> _mesa_add_typed_unnamed_constant(struct gl_program_parameter_list *paramList,
> const gl_constant_value values[4], GLuint size,
> GLenum datatype, GLuint *swizzleOut);
>
> static inline GLint
> _mesa_add_unnamed_constant(struct gl_program_parameter_list *paramList,
> const gl_constant_value values[4], GLuint size,
> GLuint *swizzleOut)
> diff --git a/src/mesa/program/prog_parameter_layout.c b/src/mesa/program/prog_parameter_layout.c
> index 282a367..d28a667 100644
> --- a/src/mesa/program/prog_parameter_layout.c
> +++ b/src/mesa/program/prog_parameter_layout.c
> @@ -85,24 +85,34 @@ copy_indirect_accessed_array(struct gl_program_parameter_list *src,
> if (memcmp(dst->Parameters[j].StateIndexes, curr->StateIndexes,
> sizeof(curr->StateIndexes)) == 0) {
> return -1;
> }
> }
> }
>
> assert(j == dst->NumParameters);
>
> /* copy src parameter [i] to dest parameter [j] */
> - memcpy(& dst->Parameters[j], curr,
> + memcpy(&dst->Parameters[j], curr,
> sizeof(dst->Parameters[j]));
> - memcpy(dst->ParameterValues[j], src->ParameterValues[i],
> - sizeof(GLfloat) * 4);
> +
> + dst->ParameterValueOffset[j] = dst->NumParameterValues;
> +
> + gl_constant_value *pv_dst =
> + dst->ParameterValues + dst->ParameterValueOffset[j];
> + gl_constant_value *pv_src =
> + src->ParameterValues + src->ParameterValueOffset[i];
> +
> + memcpy(pv_dst, pv_src, MIN2(src->Parameters[i].Size, 4) *
> + sizeof(GLfloat));
> + dst->NumParameterValues += MIN2(dst->Parameters[j].Size, 4);
> +
>
> /* Pointer to the string name was copied. Null-out src param name
> * to prevent double free later.
> */
> curr->Name = NULL;
>
> dst->NumParameters++;
> }
>
> return base;
> @@ -176,22 +186,23 @@ _mesa_layout_parameters(struct asm_parser_state *state)
> if ((inst->SrcReg[i].Base.File <= PROGRAM_OUTPUT)
> || (inst->SrcReg[i].Base.File >= PROGRAM_WRITE_ONLY)) {
> continue;
> }
>
> inst->Base.SrcReg[i] = inst->SrcReg[i].Base;
> p = & state->prog->Parameters->Parameters[idx];
>
> switch (p->Type) {
> case PROGRAM_CONSTANT: {
> - const gl_constant_value *const v =
> - state->prog->Parameters->ParameterValues[idx];
> + unsigned pvo = state->prog->Parameters->ParameterValueOffset[idx];
> + const gl_constant_value *const v =
> + state->prog->Parameters->ParameterValues + pvo;
>
> inst->Base.SrcReg[i].Index =
> _mesa_add_unnamed_constant(layout, v, p->Size, & swizzle);
>
> inst->Base.SrcReg[i].Swizzle =
> _mesa_combine_swizzles(swizzle, inst->Base.SrcReg[i].Swizzle);
> break;
> }
>
> case PROGRAM_STATE_VAR:
> diff --git a/src/mesa/program/prog_print.c b/src/mesa/program/prog_print.c
> index 4f85d14..3bc69fd 100644
> --- a/src/mesa/program/prog_print.c
> +++ b/src/mesa/program/prog_print.c
> @@ -913,21 +913,23 @@ _mesa_fprint_parameter_list(FILE *f,
> GLuint i;
>
> if (!list)
> return;
>
> if (0)
> fprintf(f, "param list %p\n", (void *) list);
> fprintf(f, "dirty state flags: 0x%x\n", list->StateFlags);
> for (i = 0; i < list->NumParameters; i++){
> struct gl_program_parameter *param = list->Parameters + i;
> - const GLfloat *v = (GLfloat *) list->ParameterValues[i];
> + unsigned pvo = list->ParameterValueOffset[i];
> + const GLfloat *v = (GLfloat *) list->ParameterValues + pvo;
> +
> fprintf(f, "param[%d] sz=%d %s %s = {%.3g, %.3g, %.3g, %.3g}",
> i, param->Size,
> _mesa_register_file_name(list->Parameters[i].Type),
> param->Name, v[0], v[1], v[2], v[3]);
> fprintf(f, "\n");
> }
> }
>
>
> /**
> diff --git a/src/mesa/program/prog_statevars.c b/src/mesa/program/prog_statevars.c
> index 91178e3..db370fe 100644
> --- a/src/mesa/program/prog_statevars.c
> +++ b/src/mesa/program/prog_statevars.c
> @@ -1068,16 +1068,17 @@ void
> _mesa_load_state_parameters(struct gl_context *ctx,
> struct gl_program_parameter_list *paramList)
> {
> GLuint i;
>
> if (!paramList)
> return;
>
> for (i = 0; i < paramList->NumParameters; i++) {
> if (paramList->Parameters[i].Type == PROGRAM_STATE_VAR) {
> + unsigned pvo = paramList->ParameterValueOffset[i];
> _mesa_fetch_state(ctx,
> paramList->Parameters[i].StateIndexes,
> - ¶mList->ParameterValues[i][0]);
> + paramList->ParameterValues + pvo);
> }
> }
> }
> diff --git a/src/mesa/program/prog_to_nir.c b/src/mesa/program/prog_to_nir.c
> index 851b3f2..b49616c 100644
> --- a/src/mesa/program/prog_to_nir.c
> +++ b/src/mesa/program/prog_to_nir.c
> @@ -154,21 +154,22 @@ ptn_get_src(struct ptn_compile *c, const struct prog_src_register *prog_src)
> * constants.
> */
> struct gl_program_parameter_list *plist = c->prog->Parameters;
> gl_register_file file = prog_src->RelAddr ? prog_src->File :
> plist->Parameters[prog_src->Index].Type;
>
> switch (file) {
> case PROGRAM_CONSTANT:
> if ((c->prog->arb.IndirectRegisterFiles &
> (1 << PROGRAM_CONSTANT)) == 0) {
> - float *v = (float *) plist->ParameterValues[prog_src->Index];
> + unsigned pvo = plist->ParameterValueOffset[prog_src->Index];
> + float *v = (float *) plist->ParameterValues + pvo;
> src.src = nir_src_for_ssa(nir_imm_vec4(b, v[0], v[1], v[2], v[3]));
> break;
> }
> /* FALLTHROUGH */
> case PROGRAM_STATE_VAR: {
> assert(c->parameters != NULL);
>
> nir_intrinsic_instr *load =
> nir_intrinsic_instr_create(b->shader, nir_intrinsic_load_var);
> nir_ssa_dest_init(&load->instr, &load->dest, 4, 32, NULL);
> diff --git a/src/mesa/program/program_parse.y b/src/mesa/program/program_parse.y
> index f3adea6..e18637d 100644
> --- a/src/mesa/program/program_parse.y
> +++ b/src/mesa/program/program_parse.y
> @@ -2285,21 +2285,21 @@ declare_variable(struct asm_parser_state *state, char *name, enum asm_type t,
>
> int add_state_reference(struct gl_program_parameter_list *param_list,
> const gl_state_index tokens[STATE_LENGTH])
> {
> const GLuint size = 4; /* XXX fix */
> char *name;
> GLint index;
>
> name = _mesa_program_state_string(tokens);
> index = _mesa_add_parameter(param_list, PROGRAM_STATE_VAR, name,
> - size, GL_NONE, NULL, tokens);
> + size, GL_NONE, NULL, tokens, false);
> param_list->StateFlags |= _mesa_program_state_flags(tokens);
>
> /* free name string here since we duplicated it in add_parameter() */
> free(name);
>
> return index;
> }
>
>
> int
> diff --git a/src/mesa/state_tracker/st_atifs_to_tgsi.c b/src/mesa/state_tracker/st_atifs_to_tgsi.c
> index 338ced5..34d4378 100644
> --- a/src/mesa/state_tracker/st_atifs_to_tgsi.c
> +++ b/src/mesa/state_tracker/st_atifs_to_tgsi.c
> @@ -470,29 +470,31 @@ st_translate_atifs_program(
> */
> if (program->Parameters) {
> t->constants = calloc(program->Parameters->NumParameters,
> sizeof t->constants[0]);
> if (t->constants == NULL) {
> ret = PIPE_ERROR_OUT_OF_MEMORY;
> goto out;
> }
>
> for (i = 0; i < program->Parameters->NumParameters; i++) {
> + unsigned pvo = program->Parameters->ParameterValueOffset[i];
> +
> switch (program->Parameters->Parameters[i].Type) {
> case PROGRAM_STATE_VAR:
> case PROGRAM_UNIFORM:
> t->constants[i] = ureg_DECL_constant(ureg, i);
> break;
> case PROGRAM_CONSTANT:
> t->constants[i] =
> ureg_DECL_immediate(ureg,
> - (const float*)program->Parameters->ParameterValues[i],
> + (const float*)program->Parameters->ParameterValues + pvo,
> 4);
> break;
> default:
> break;
> }
> }
> }
>
> /* texture samplers */
> for (i = 0; i < MAX_NUM_FRAGMENT_REGISTERS_ATI; i++) {
> @@ -595,21 +597,21 @@ st_init_atifs_prog(struct gl_context *ctx, struct gl_program *prog)
> }
> }
> }
> }
> /* we may need fog */
> prog->info.inputs_read |= BITFIELD64_BIT(VARYING_SLOT_FOGC);
>
> /* we always have the ATI_fs constants, and the fog params */
> for (i = 0; i < MAX_NUM_FRAGMENT_CONSTANTS_ATI; i++) {
> _mesa_add_parameter(prog->Parameters, PROGRAM_UNIFORM,
> - NULL, 4, GL_FLOAT, NULL, NULL);
> + NULL, 4, GL_FLOAT, NULL, NULL, false);
> }
> _mesa_add_state_reference(prog->Parameters, fog_params_state);
> _mesa_add_state_reference(prog->Parameters, fog_color);
>
> prog->arb.NumInstructions = 0;
> prog->arb.NumTemporaries = MAX_NUM_FRAGMENT_REGISTERS_ATI + 3; /* 3 input temps for arith ops */
> prog->arb.NumParameters = MAX_NUM_FRAGMENT_CONSTANTS_ATI + 2; /* 2 state variables for fog */
> }
>
>
> diff --git a/src/mesa/state_tracker/st_atom_constbuf.c b/src/mesa/state_tracker/st_atom_constbuf.c
> index e4b5851..7f17546 100644
> --- a/src/mesa/state_tracker/st_atom_constbuf.c
> +++ b/src/mesa/state_tracker/st_atom_constbuf.c
> @@ -64,25 +64,26 @@ void st_upload_constants(struct st_context *st, struct gl_program *prog)
> shader_type == PIPE_SHADER_TESS_CTRL ||
> shader_type == PIPE_SHADER_TESS_EVAL ||
> shader_type == PIPE_SHADER_COMPUTE);
>
> /* update the ATI constants before rendering */
> if (shader_type == PIPE_SHADER_FRAGMENT && st->fp->ati_fs) {
> struct ati_fragment_shader *ati_fs = st->fp->ati_fs;
> unsigned c;
>
> for (c = 0; c < MAX_NUM_FRAGMENT_CONSTANTS_ATI; c++) {
> + unsigned offset = params->ParameterValueOffset[c];
> if (ati_fs->LocalConstDef & (1 << c))
> - memcpy(params->ParameterValues[c],
> + memcpy(params->ParameterValues + offset,
> ati_fs->Constants[c], sizeof(GLfloat) * 4);
> else
> - memcpy(params->ParameterValues[c],
> + memcpy(params->ParameterValues + offset,
> st->ctx->ATIFragmentShader.GlobalConstants[c], sizeof(GLfloat) * 4);
> }
> }
>
> /* Make all bindless samplers/images bound texture/image units resident in
> * the context.
> */
> st_make_bound_samplers_resident(st, prog);
> st_make_bound_images_resident(st, prog);
>
> diff --git a/src/mesa/state_tracker/st_glsl_to_tgsi.cpp b/src/mesa/state_tracker/st_glsl_to_tgsi.cpp
> index 7852941..1998852 100644
> --- a/src/mesa/state_tracker/st_glsl_to_tgsi.cpp
> +++ b/src/mesa/state_tracker/st_glsl_to_tgsi.cpp
> @@ -6631,38 +6631,40 @@ st_translate_program(
> if (proginfo->Parameters) {
> t->constants = (struct ureg_src *)
> calloc(proginfo->Parameters->NumParameters, sizeof(t->constants[0]));
> if (t->constants == NULL) {
> ret = PIPE_ERROR_OUT_OF_MEMORY;
> goto out;
> }
> t->num_constants = proginfo->Parameters->NumParameters;
>
> for (i = 0; i < proginfo->Parameters->NumParameters; i++) {
> + unsigned pvo = proginfo->Parameters->ParameterValueOffset[i];
> +
> switch (proginfo->Parameters->Parameters[i].Type) {
> case PROGRAM_STATE_VAR:
> case PROGRAM_UNIFORM:
> t->constants[i] = ureg_DECL_constant(ureg, i);
> break;
>
> /* Emit immediates for PROGRAM_CONSTANT only when there's no indirect
> * addressing of the const buffer.
> * FIXME: Be smarter and recognize param arrays:
> * indirect addressing is only valid within the referenced
> * array.
> */
> case PROGRAM_CONSTANT:
> if (program->indirect_addr_consts)
> t->constants[i] = ureg_DECL_constant(ureg, i);
> else
> t->constants[i] = emit_immediate(t,
> - proginfo->Parameters->ParameterValues[i],
> + proginfo->Parameters->ParameterValues + pvo,
> proginfo->Parameters->Parameters[i].DataType,
> 4);
> break;
> default:
> break;
> }
> }
> }
>
> for (i = 0; i < proginfo->info.num_ubos; i++) {
> diff --git a/src/mesa/state_tracker/st_mesa_to_tgsi.c b/src/mesa/state_tracker/st_mesa_to_tgsi.c
> index 984ff92..640e175 100644
> --- a/src/mesa/state_tracker/st_mesa_to_tgsi.c
> +++ b/src/mesa/state_tracker/st_mesa_to_tgsi.c
> @@ -991,40 +991,42 @@ st_translate_mesa_program(
> */
> if (program->Parameters) {
> t->constants = calloc( program->Parameters->NumParameters,
> sizeof t->constants[0] );
> if (t->constants == NULL) {
> ret = PIPE_ERROR_OUT_OF_MEMORY;
> goto out;
> }
>
> for (i = 0; i < program->Parameters->NumParameters; i++) {
> + unsigned pvo = program->Parameters->ParameterValueOffset[i];
> +
> switch (program->Parameters->Parameters[i].Type) {
> case PROGRAM_STATE_VAR:
> case PROGRAM_UNIFORM:
> t->constants[i] = ureg_DECL_constant( ureg, i );
> break;
>
> /* Emit immediates only when there's no indirect addressing of
> * the const buffer.
> * FIXME: Be smarter and recognize param arrays:
> * indirect addressing is only valid within the referenced
> * array.
> */
> case PROGRAM_CONSTANT:
> if (program->arb.IndirectRegisterFiles & PROGRAM_ANY_CONST)
> t->constants[i] = ureg_DECL_constant( ureg, i );
> else
> t->constants[i] =
> - ureg_DECL_immediate( ureg,
> - (const float*) program->Parameters->ParameterValues[i],
> - 4 );
> + ureg_DECL_immediate(ureg,
> + (const float*) program->Parameters->ParameterValues + pvo,
> + 4);
> break;
> default:
> break;
> }
> }
> }
>
> /* texture samplers */
> for (i = 0; i < ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxTextureImageUnits; i++) {
> if (program->SamplersUsed & (1u << i)) {
>
--
Lerne, wie die Welt wirklich ist,
Aber vergiss niemals, wie sie sein sollte.
More information about the mesa-dev
mailing list