mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2025-12-22 09:10:11 +01:00
glsl: Refactor AST-to-HIR code handling variable initializers
This commit is contained in:
parent
8e6cb9fe51
commit
0292ffb85c
1 changed files with 125 additions and 108 deletions
|
|
@ -2187,6 +2187,129 @@ get_variable_being_redeclared(ir_variable *var, ast_declaration *decl,
|
|||
return earlier;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate the IR for an initializer in a variable declaration
|
||||
*/
|
||||
ir_rvalue *
|
||||
process_initializer(ir_variable *var, ast_declaration *decl,
|
||||
ast_fully_specified_type *type,
|
||||
exec_list *initializer_instructions,
|
||||
struct _mesa_glsl_parse_state *state)
|
||||
{
|
||||
ir_rvalue *result = NULL;
|
||||
|
||||
YYLTYPE initializer_loc = decl->initializer->get_location();
|
||||
|
||||
/* From page 24 (page 30 of the PDF) of the GLSL 1.10 spec:
|
||||
*
|
||||
* "All uniform variables are read-only and are initialized either
|
||||
* directly by an application via API commands, or indirectly by
|
||||
* OpenGL."
|
||||
*/
|
||||
if ((state->language_version <= 110)
|
||||
&& (var->mode == ir_var_uniform)) {
|
||||
_mesa_glsl_error(& initializer_loc, state,
|
||||
"cannot initialize uniforms in GLSL 1.10");
|
||||
}
|
||||
|
||||
if (var->type->is_sampler()) {
|
||||
_mesa_glsl_error(& initializer_loc, state,
|
||||
"cannot initialize samplers");
|
||||
}
|
||||
|
||||
if ((var->mode == ir_var_in) && (state->current_function == NULL)) {
|
||||
_mesa_glsl_error(& initializer_loc, state,
|
||||
"cannot initialize %s shader input / %s",
|
||||
_mesa_glsl_shader_target_name(state->target),
|
||||
(state->target == vertex_shader)
|
||||
? "attribute" : "varying");
|
||||
}
|
||||
|
||||
ir_dereference *const lhs = new(state) ir_dereference_variable(var);
|
||||
ir_rvalue *rhs = decl->initializer->hir(initializer_instructions,
|
||||
state);
|
||||
|
||||
/* Calculate the constant value if this is a const or uniform
|
||||
* declaration.
|
||||
*/
|
||||
if (type->qualifier.flags.q.constant
|
||||
|| type->qualifier.flags.q.uniform) {
|
||||
ir_rvalue *new_rhs = validate_assignment(state, var->type, rhs);
|
||||
if (new_rhs != NULL) {
|
||||
rhs = new_rhs;
|
||||
|
||||
ir_constant *constant_value = rhs->constant_expression_value();
|
||||
if (!constant_value) {
|
||||
_mesa_glsl_error(& initializer_loc, state,
|
||||
"initializer of %s variable `%s' must be a "
|
||||
"constant expression",
|
||||
(type->qualifier.flags.q.constant)
|
||||
? "const" : "uniform",
|
||||
decl->identifier);
|
||||
if (var->type->is_numeric()) {
|
||||
/* Reduce cascading errors. */
|
||||
var->constant_value = ir_constant::zero(state, var->type);
|
||||
}
|
||||
} else {
|
||||
rhs = constant_value;
|
||||
var->constant_value = constant_value;
|
||||
}
|
||||
} else {
|
||||
_mesa_glsl_error(&initializer_loc, state,
|
||||
"initializer of type %s cannot be assigned to "
|
||||
"variable of type %s",
|
||||
rhs->type->name, var->type->name);
|
||||
if (var->type->is_numeric()) {
|
||||
/* Reduce cascading errors. */
|
||||
var->constant_value = ir_constant::zero(state, var->type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (rhs && !rhs->type->is_error()) {
|
||||
bool temp = var->read_only;
|
||||
if (type->qualifier.flags.q.constant)
|
||||
var->read_only = false;
|
||||
|
||||
/* Never emit code to initialize a uniform.
|
||||
*/
|
||||
const glsl_type *initializer_type;
|
||||
if (!type->qualifier.flags.q.uniform) {
|
||||
result = do_assignment(initializer_instructions, state,
|
||||
lhs, rhs,
|
||||
type->get_location());
|
||||
initializer_type = result->type;
|
||||
} else
|
||||
initializer_type = rhs->type;
|
||||
|
||||
/* If the declared variable is an unsized array, it must inherrit
|
||||
* its full type from the initializer. A declaration such as
|
||||
*
|
||||
* uniform float a[] = float[](1.0, 2.0, 3.0, 3.0);
|
||||
*
|
||||
* becomes
|
||||
*
|
||||
* uniform float a[4] = float[](1.0, 2.0, 3.0, 3.0);
|
||||
*
|
||||
* The assignment generated in the if-statement (below) will also
|
||||
* automatically handle this case for non-uniforms.
|
||||
*
|
||||
* If the declared variable is not an array, the types must
|
||||
* already match exactly. As a result, the type assignment
|
||||
* here can be done unconditionally. For non-uniforms the call
|
||||
* to do_assignment can change the type of the initializer (via
|
||||
* the implicit conversion rules). For uniforms the initializer
|
||||
* must be a constant expression, and the type of that expression
|
||||
* was validated above.
|
||||
*/
|
||||
var->type = initializer_type;
|
||||
|
||||
var->read_only = temp;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
ir_rvalue *
|
||||
ast_declarator_list::hir(exec_list *instructions,
|
||||
struct _mesa_glsl_parse_state *state)
|
||||
|
|
@ -2571,114 +2694,8 @@ ast_declarator_list::hir(exec_list *instructions,
|
|||
*/
|
||||
exec_list initializer_instructions;
|
||||
if (decl->initializer != NULL) {
|
||||
YYLTYPE initializer_loc = decl->initializer->get_location();
|
||||
|
||||
/* From page 24 (page 30 of the PDF) of the GLSL 1.10 spec:
|
||||
*
|
||||
* "All uniform variables are read-only and are initialized either
|
||||
* directly by an application via API commands, or indirectly by
|
||||
* OpenGL."
|
||||
*/
|
||||
if ((state->language_version <= 110)
|
||||
&& (var->mode == ir_var_uniform)) {
|
||||
_mesa_glsl_error(& initializer_loc, state,
|
||||
"cannot initialize uniforms in GLSL 1.10");
|
||||
}
|
||||
|
||||
if (var->type->is_sampler()) {
|
||||
_mesa_glsl_error(& initializer_loc, state,
|
||||
"cannot initialize samplers");
|
||||
}
|
||||
|
||||
if ((var->mode == ir_var_in) && (state->current_function == NULL)) {
|
||||
_mesa_glsl_error(& initializer_loc, state,
|
||||
"cannot initialize %s shader input / %s",
|
||||
_mesa_glsl_shader_target_name(state->target),
|
||||
(state->target == vertex_shader)
|
||||
? "attribute" : "varying");
|
||||
}
|
||||
|
||||
ir_dereference *const lhs = new(ctx) ir_dereference_variable(var);
|
||||
ir_rvalue *rhs = decl->initializer->hir(&initializer_instructions,
|
||||
state);
|
||||
|
||||
/* Calculate the constant value if this is a const or uniform
|
||||
* declaration.
|
||||
*/
|
||||
if (this->type->qualifier.flags.q.constant
|
||||
|| this->type->qualifier.flags.q.uniform) {
|
||||
ir_rvalue *new_rhs = validate_assignment(state, var->type, rhs);
|
||||
if (new_rhs != NULL) {
|
||||
rhs = new_rhs;
|
||||
|
||||
ir_constant *constant_value = rhs->constant_expression_value();
|
||||
if (!constant_value) {
|
||||
_mesa_glsl_error(& initializer_loc, state,
|
||||
"initializer of %s variable `%s' must be a "
|
||||
"constant expression",
|
||||
(this->type->qualifier.flags.q.constant)
|
||||
? "const" : "uniform",
|
||||
decl->identifier);
|
||||
if (var->type->is_numeric()) {
|
||||
/* Reduce cascading errors. */
|
||||
var->constant_value = ir_constant::zero(ctx, var->type);
|
||||
}
|
||||
} else {
|
||||
rhs = constant_value;
|
||||
var->constant_value = constant_value;
|
||||
}
|
||||
} else {
|
||||
_mesa_glsl_error(&initializer_loc, state,
|
||||
"initializer of type %s cannot be assigned to "
|
||||
"variable of type %s",
|
||||
rhs->type->name, var->type->name);
|
||||
if (var->type->is_numeric()) {
|
||||
/* Reduce cascading errors. */
|
||||
var->constant_value = ir_constant::zero(ctx, var->type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (rhs && !rhs->type->is_error()) {
|
||||
bool temp = var->read_only;
|
||||
if (this->type->qualifier.flags.q.constant)
|
||||
var->read_only = false;
|
||||
|
||||
/* Never emit code to initialize a uniform.
|
||||
*/
|
||||
const glsl_type *initializer_type;
|
||||
if (!this->type->qualifier.flags.q.uniform) {
|
||||
result = do_assignment(&initializer_instructions, state,
|
||||
lhs, rhs,
|
||||
this->get_location());
|
||||
initializer_type = result->type;
|
||||
} else
|
||||
initializer_type = rhs->type;
|
||||
|
||||
/* If the declared variable is an unsized array, it must inherrit
|
||||
* its full type from the initializer. A declaration such as
|
||||
*
|
||||
* uniform float a[] = float[](1.0, 2.0, 3.0, 3.0);
|
||||
*
|
||||
* becomes
|
||||
*
|
||||
* uniform float a[4] = float[](1.0, 2.0, 3.0, 3.0);
|
||||
*
|
||||
* The assignment generated in the if-statement (below) will also
|
||||
* automatically handle this case for non-uniforms.
|
||||
*
|
||||
* If the declared variable is not an array, the types must
|
||||
* already match exactly. As a result, the type assignment
|
||||
* here can be done unconditionally. For non-uniforms the call
|
||||
* to do_assignment can change the type of the initializer (via
|
||||
* the implicit conversion rules). For uniforms the initializer
|
||||
* must be a constant expression, and the type of that expression
|
||||
* was validated above.
|
||||
*/
|
||||
var->type = initializer_type;
|
||||
|
||||
var->read_only = temp;
|
||||
}
|
||||
result = process_initializer(var, decl, this->type,
|
||||
&initializer_instructions, state);
|
||||
}
|
||||
|
||||
/* From page 23 (page 29 of the PDF) of the GLSL 1.10 spec:
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue