ir_to_mesa: Generate gl_program_parameter list by walking the GLSL IR.
Generate the program parameters list by walking the IR instead of by walking the list of linked uniforms. This simplifies the code quite a bit, and is probably a bit more correct. The list of linked uniforms should really only be used by the GL API to interact with the application. Signed-off-by: Ian Romanick <ian.d.romanick@intel.com> Reviewed-by: Kenneth Graunke <kenneth@whitecape.org> Cc: Bryan Cain <bryancain3@gmail.com> Cc: Eric Anholt <eric@anholt.net>
This commit is contained in:
@@ -2588,78 +2588,15 @@ check_resources(const struct gl_context *ctx,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
struct uniform_sort {
|
|
||||||
struct gl_uniform *u;
|
|
||||||
int pos;
|
|
||||||
};
|
|
||||||
|
|
||||||
/* The shader_program->Uniforms list is almost sorted in increasing
|
|
||||||
* uniform->{Frag,Vert}Pos locations, but not quite when there are
|
|
||||||
* uniforms shared between targets. We need to add parameters in
|
|
||||||
* increasing order for the targets.
|
|
||||||
*/
|
|
||||||
static int
|
static int
|
||||||
sort_uniforms(const void *a, const void *b)
|
add_uniform_to_shader(ir_variable *var,
|
||||||
|
struct gl_program_parameter_list *params,
|
||||||
|
unsigned int &next_sampler)
|
||||||
{
|
{
|
||||||
struct uniform_sort *u1 = (struct uniform_sort *)a;
|
const glsl_type *type = var->type;
|
||||||
struct uniform_sort *u2 = (struct uniform_sort *)b;
|
|
||||||
|
|
||||||
return u1->pos - u2->pos;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Add the uniforms to the parameters. The linker chose locations
|
|
||||||
* in our parameters lists (which weren't created yet), which the
|
|
||||||
* uniforms code will use to poke values into our parameters list
|
|
||||||
* when uniforms are updated.
|
|
||||||
*/
|
|
||||||
static void
|
|
||||||
add_uniforms_to_parameters_list(struct gl_shader_program *shader_program,
|
|
||||||
struct gl_shader *shader,
|
|
||||||
struct gl_program *prog)
|
|
||||||
{
|
|
||||||
unsigned int i;
|
|
||||||
unsigned int next_sampler = 0, num_uniforms = 0;
|
|
||||||
struct uniform_sort *sorted_uniforms;
|
|
||||||
|
|
||||||
sorted_uniforms = ralloc_array(NULL, struct uniform_sort,
|
|
||||||
shader_program->Uniforms->NumUniforms);
|
|
||||||
|
|
||||||
for (i = 0; i < shader_program->Uniforms->NumUniforms; i++) {
|
|
||||||
struct gl_uniform *uniform = shader_program->Uniforms->Uniforms + i;
|
|
||||||
int parameter_index = -1;
|
|
||||||
|
|
||||||
switch (shader->Type) {
|
|
||||||
case GL_VERTEX_SHADER:
|
|
||||||
parameter_index = uniform->VertPos;
|
|
||||||
break;
|
|
||||||
case GL_FRAGMENT_SHADER:
|
|
||||||
parameter_index = uniform->FragPos;
|
|
||||||
break;
|
|
||||||
case GL_GEOMETRY_SHADER:
|
|
||||||
parameter_index = uniform->GeomPos;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Only add uniforms used in our target. */
|
|
||||||
if (parameter_index != -1) {
|
|
||||||
sorted_uniforms[num_uniforms].pos = parameter_index;
|
|
||||||
sorted_uniforms[num_uniforms].u = uniform;
|
|
||||||
num_uniforms++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
qsort(sorted_uniforms, num_uniforms, sizeof(struct uniform_sort),
|
|
||||||
sort_uniforms);
|
|
||||||
|
|
||||||
for (i = 0; i < num_uniforms; i++) {
|
|
||||||
struct gl_uniform *uniform = sorted_uniforms[i].u;
|
|
||||||
int parameter_index = sorted_uniforms[i].pos;
|
|
||||||
const glsl_type *type = uniform->Type;
|
|
||||||
unsigned int size;
|
unsigned int size;
|
||||||
|
|
||||||
if (type->is_vector() ||
|
if (type->is_vector() || type->is_scalar()) {
|
||||||
type->is_scalar()) {
|
|
||||||
size = type->vector_elements;
|
size = type->vector_elements;
|
||||||
} else {
|
} else {
|
||||||
size = type_size(type) * 4;
|
size = type_size(type) * 4;
|
||||||
@@ -2673,12 +2610,10 @@ add_uniforms_to_parameters_list(struct gl_shader_program *shader_program,
|
|||||||
file = PROGRAM_UNIFORM;
|
file = PROGRAM_UNIFORM;
|
||||||
}
|
}
|
||||||
|
|
||||||
GLint index = _mesa_lookup_parameter_index(prog->Parameters, -1,
|
int index = _mesa_lookup_parameter_index(params, -1, var->name);
|
||||||
uniform->Name);
|
|
||||||
|
|
||||||
if (index < 0) {
|
if (index < 0) {
|
||||||
index = _mesa_add_parameter(prog->Parameters, file,
|
index = _mesa_add_parameter(params, file,
|
||||||
uniform->Name, size, type->gl_type,
|
var->name, size, type->gl_type,
|
||||||
NULL, NULL, 0x0);
|
NULL, NULL, 0x0);
|
||||||
|
|
||||||
/* Sampler uniform values are stored in prog->SamplerUnits,
|
/* Sampler uniform values are stored in prog->SamplerUnits,
|
||||||
@@ -2687,22 +2622,49 @@ add_uniforms_to_parameters_list(struct gl_shader_program *shader_program,
|
|||||||
*/
|
*/
|
||||||
if (file == PROGRAM_SAMPLER) {
|
if (file == PROGRAM_SAMPLER) {
|
||||||
for (unsigned int j = 0; j < size / 4; j++)
|
for (unsigned int j = 0; j < size / 4; j++)
|
||||||
prog->Parameters->ParameterValues[index + j][0].f = next_sampler++;
|
params->ParameterValues[index + j][0].f = next_sampler++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The location chosen in the Parameters list here (returned
|
return index;
|
||||||
* from _mesa_add_uniform) has to match what the linker chose.
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate the program parameters list for the user uniforms in a shader
|
||||||
|
*
|
||||||
|
* \param shader_program Linked shader program. This is only used to
|
||||||
|
* emit possible link errors to the info log.
|
||||||
|
* \param sh Shader whose uniforms are to be processed.
|
||||||
|
* \param params Parameter list to be filled in.
|
||||||
*/
|
*/
|
||||||
if (index != parameter_index) {
|
void
|
||||||
|
_mesa_generate_parameters_list_for_uniforms(struct gl_shader_program
|
||||||
|
*shader_program,
|
||||||
|
struct gl_shader *sh,
|
||||||
|
struct gl_program_parameter_list
|
||||||
|
*params)
|
||||||
|
{
|
||||||
|
unsigned int next_sampler = 0;
|
||||||
|
|
||||||
|
foreach_list(node, sh->ir) {
|
||||||
|
ir_variable *var = ((ir_instruction *) node)->as_variable();
|
||||||
|
|
||||||
|
if ((var == NULL) || (var->mode != ir_var_uniform)
|
||||||
|
|| (strncmp(var->name, "gl_", 3) == 0))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
int loc = add_uniform_to_shader(var, params, next_sampler);
|
||||||
|
|
||||||
|
/* The location chosen in the Parameters list here (returned from
|
||||||
|
* _mesa_add_parameter) has to match what the linker chose.
|
||||||
|
*/
|
||||||
|
if (var->location != loc) {
|
||||||
linker_error(shader_program,
|
linker_error(shader_program,
|
||||||
"Allocation of uniform `%s' to target failed "
|
"Allocation of uniform `%s' to target failed "
|
||||||
"(%d vs %d)\n",
|
"(%d vs %d)\n",
|
||||||
uniform->Name, index, parameter_index);
|
var->name, loc, var->location);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
ralloc_free(sorted_uniforms);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -3046,7 +3008,8 @@ get_mesa_program(struct gl_context *ctx,
|
|||||||
v.shader_program = shader_program;
|
v.shader_program = shader_program;
|
||||||
v.options = options;
|
v.options = options;
|
||||||
|
|
||||||
add_uniforms_to_parameters_list(shader_program, shader, prog);
|
_mesa_generate_parameters_list_for_uniforms(shader_program, shader,
|
||||||
|
prog->Parameters);
|
||||||
|
|
||||||
/* Emit Mesa IR for main(). */
|
/* Emit Mesa IR for main(). */
|
||||||
visit_exec_list(shader->ir, &v);
|
visit_exec_list(shader->ir, &v);
|
||||||
|
@@ -38,4 +38,11 @@ GLboolean _mesa_ir_link_shader(struct gl_context *ctx, struct gl_shader_program
|
|||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
_mesa_generate_parameters_list_for_uniforms(struct gl_shader_program
|
||||||
|
*shader_program,
|
||||||
|
struct gl_shader *sh,
|
||||||
|
struct gl_program_parameter_list
|
||||||
|
*params);
|
||||||
#endif
|
#endif
|
||||||
|
Reference in New Issue
Block a user