[Mesa-dev] [PATCH] mesa/glsl: introduce a remap table for uniform locations
Ian Romanick
idr at freedesktop.org
Fri Mar 7 06:05:19 PST 2014
On 03/07/2014 12:55 PM, Tapani Pälli wrote:
> Patch adds a remap table for uniforms that is used to provide a mapping
> from application specified uniform location to actual location in the
> UniformStorage. Existing UniformLocationBaseScale usage is removed as
> table can be used to set sequential values for array uniform elements.
>
> This mapping helps to implement GL_ARB_explicit_uniform_location so that
> uniforms locations can be reorganized and handled in a more easy manner.
>
> Signed-off-by: Tapani Pälli <tapani.palli at intel.com>
A couple minor comments below. With those fixed, this patch is
Reviewed-by: Ian Romanick <ian.d.romanick at intel.com>
Might give others a day or two to review too...
I look forward to seeing the patches to implement
GL_ARB_explicit_uniform_location. That will be a nice addition for our
next major release. :)
> ---
> src/glsl/ir_uniform.h | 6 ++++++
> src/glsl/link_uniforms.cpp | 38 +++++++++++++++++++++++++++-----------
> src/mesa/main/mtypes.h | 22 +++++++---------------
> src/mesa/main/shaderobj.c | 7 ++++++-
> src/mesa/main/uniform_query.cpp | 7 +++++++
> src/mesa/main/uniforms.h | 31 ++++++++++++++++++-------------
> 6 files changed, 71 insertions(+), 40 deletions(-)
>
> diff --git a/src/glsl/ir_uniform.h b/src/glsl/ir_uniform.h
> index 7508f79..3508509 100644
> --- a/src/glsl/ir_uniform.h
> +++ b/src/glsl/ir_uniform.h
> @@ -178,6 +178,12 @@ struct gl_uniform_storage {
> * an atomic counter.
> */
> int atomic_buffer_index;
> +
> + /**
> + * The 'base location' for this uniform in the uniform remap table. For
> + * arrays this is the first element in the array.
> + */
> + unsigned remap_location;
> };
>
> #ifdef __cplusplus
> diff --git a/src/glsl/link_uniforms.cpp b/src/glsl/link_uniforms.cpp
> index 1c451e7..1607555 100644
> --- a/src/glsl/link_uniforms.cpp
> +++ b/src/glsl/link_uniforms.cpp
> @@ -799,6 +799,10 @@ link_assign_uniform_locations(struct gl_shader_program *prog)
> prog->UniformStorage = NULL;
> prog->NumUserUniformStorage = 0;
>
> + ralloc_free(prog->UniformRemapTable);
> + prog->UniformRemapTable = NULL;
> + prog->NumUniformRemapTable = 0;
> +
> if (prog->UniformHash != NULL) {
> prog->UniformHash->clear();
> } else {
> @@ -911,19 +915,31 @@ link_assign_uniform_locations(struct gl_shader_program *prog)
> sizeof(prog->_LinkedShaders[i]->SamplerTargets));
> }
>
> - /* Determine the size of the largest uniform array queryable via
> - * glGetUniformLocation. Using this as the location scale guarantees that
> - * there is enough "room" for the array index to be stored in the low order
> - * part of the uniform location. It also makes the locations be more
> - * tightly packed.
> - */
> - unsigned max_array_size = 1;
> + /* Build the uniform remap table that is used to set/get uniform locations */
> for (unsigned i = 0; i < num_user_uniforms; i++) {
> - if (uniforms[i].array_elements > max_array_size)
> - max_array_size = uniforms[i].array_elements;
> - }
>
> - prog->UniformLocationBaseScale = max_array_size;
> + /* how many new entries for this uniform? */
> + unsigned entries = 1;
> +
> + if (uniforms[i].array_elements > 0)
> + entries = uniforms[i].array_elements;
I'd do this as
const unsigned entries = MAX2(1, uniforms[i].array_elements);
> +
> + /* resize remap table to fit new entries */
> + prog->UniformRemapTable =
> + reralloc(prog,
> + prog->UniformRemapTable,
> + gl_uniform_storage *,
> + prog->NumUniformRemapTable + entries);
> +
> + /* set pointers for this uniform */
> + for (unsigned j = 0; j < entries; j++)
> + prog->UniformRemapTable[prog->NumUniformRemapTable+j] = &uniforms[i];
> +
> + /* set the base location in remap table for the uniform */
> + uniforms[i].remap_location = prog->NumUniformRemapTable;
> +
> + prog->NumUniformRemapTable += entries;
> + }
>
> #ifndef NDEBUG
> for (unsigned i = 0; i < num_user_uniforms; i++) {
> diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h
> index d05649c..3133ea5 100644
> --- a/src/mesa/main/mtypes.h
> +++ b/src/mesa/main/mtypes.h
> @@ -2702,6 +2702,13 @@ struct gl_shader_program
> struct gl_uniform_storage *UniformStorage;
>
> /**
> + * This table is used to generate locations of uniforms
> + * (returned by \c glGetUniformLocation).
> + */
> + unsigned NumUniformRemapTable;
> + struct gl_uniform_storage **UniformRemapTable;
> +
> + /**
> * Size of the gl_ClipDistance array that is output from the last pipeline
> * stage before the fragment shader.
> */
> @@ -2711,21 +2718,6 @@ struct gl_shader_program
> unsigned NumUniformBlocks;
>
> /**
> - * Scale factor for the uniform base location
> - *
> - * This is used to generate locations (returned by \c glGetUniformLocation)
> - * of uniforms. The base location of the uniform is multiplied by this
> - * value, and the array index is added.
> - *
> - * \note
> - * Must be >= 1.
> - *
> - * \sa
> - * _mesa_uniform_merge_location_offset, _mesa_uniform_split_location_offset
> - */
> - unsigned UniformLocationBaseScale;
> -
> - /**
> * Indices into the _LinkedShaders's UniformBlocks[] array for each stage
> * they're used in, or -1.
> *
> diff --git a/src/mesa/main/shaderobj.c b/src/mesa/main/shaderobj.c
> index d5c3d80..b0f0bfa 100644
> --- a/src/mesa/main/shaderobj.c
> +++ b/src/mesa/main/shaderobj.c
> @@ -285,7 +285,12 @@ _mesa_clear_shader_program_data(struct gl_context *ctx,
> ralloc_free(shProg->UniformStorage);
> shProg->NumUserUniformStorage = 0;
> shProg->UniformStorage = NULL;
> - shProg->UniformLocationBaseScale = 0;
> + }
> +
> + if (shProg->UniformRemapTable) {
> + ralloc_free(shProg->UniformRemapTable);
> + shProg->NumUniformRemapTable = 0;
> + shProg->UniformRemapTable = NULL;
> }
>
> if (shProg->UniformHash) {
> diff --git a/src/mesa/main/uniform_query.cpp b/src/mesa/main/uniform_query.cpp
> index 8cc5da7..700a333 100644
> --- a/src/mesa/main/uniform_query.cpp
> +++ b/src/mesa/main/uniform_query.cpp
> @@ -246,6 +246,13 @@ validate_uniform_parameters(struct gl_context *ctx,
> return false;
> }
>
> + /* Check that the given location is in bounds of uniform remap table. */
> + if (location >= (GLint) shProg->NumUniformRemapTable) {
> + _mesa_error(ctx, GL_INVALID_OPERATION, "%s(location=%d)",
> + caller, location);
> + return false;
> + }
> +
> _mesa_uniform_split_location_offset(shProg, location, loc, array_index);
>
> if (*loc >= shProg->NumUserUniformStorage) {
> diff --git a/src/mesa/main/uniforms.h b/src/mesa/main/uniforms.h
> index bd50fd9..d493d2d 100644
> --- a/src/mesa/main/uniforms.h
> +++ b/src/mesa/main/uniforms.h
> @@ -340,15 +340,14 @@ struct gl_builtin_uniform_desc {
> * element. We could insert dummy entries in the list for each array
> * element after [0] but that causes complications elsewhere.
> *
> - * We solve this problem by encoding two values in the location that's
> - * returned by glGetUniformLocation():
> - * a) index into gl_uniform_list::Uniforms[] for the uniform
> - * b) an array/field offset (0 for simple types)
> + * We solve this problem by creating multiple entries for uniform arrays
> + * in the UniformRemapTable so that their elements get sequential locations.
> + *
> + * Utility functions below offer functionality to split UniformRemapTable
> + * location in to location of the uniform in UniformStorage + offset to the
> + * array element (0 if not an array) and also merge it back again as the
> + * UniformRemapTable location.
> *
> - * These two values are encoded in the high and low halves of a GLint.
> - * By putting the uniform number in the high part and the offset in the
> - * low part, we can support the unofficial ability to index into arrays
> - * by adding offsets to the location value.
> */
> /*@{*/
> /**
> @@ -358,9 +357,8 @@ static inline GLint
> _mesa_uniform_merge_location_offset(const struct gl_shader_program *prog,
> unsigned base_location, unsigned offset)
^^^^^^
At least this parameter (and the offset parameter in
_mesa_uniform_split_location_offset) should be changed. It was a bad
name when I came up with it. :) Maybe uniform_array_index? We should
probably also change base_location too. Maybe storage_index?
> {
> - assert(prog->UniformLocationBaseScale >= 1);
> - assert(offset < prog->UniformLocationBaseScale);
> - return (base_location * prog->UniformLocationBaseScale) + offset;
> + /* location in remap table + array element offset */
> + return prog->UniformStorage[base_location].remap_location + offset;
> }
>
> /**
> @@ -371,8 +369,15 @@ _mesa_uniform_split_location_offset(const struct gl_shader_program *prog,
> GLint location, unsigned *base_location,
> unsigned *offset)
> {
> - *offset = location % prog->UniformLocationBaseScale;
> - *base_location = location / prog->UniformLocationBaseScale;
> + *base_location = prog->UniformRemapTable[location] - prog->UniformStorage;
> + *offset = location - prog->UniformRemapTable[location]->remap_location;
> +
> + /**
Don't need the Doxygen markup here. :)
> + * gl_uniform_storage in in UniformStorage with the calculated base_location
> + * must match with the entry in remap table
> + */
> + assert(&prog->UniformStorage[*base_location] ==
> + prog->UniformRemapTable[location]);
> }
> /*@}*/
>
>
More information about the mesa-dev
mailing list