From 29285882676388aacff123e8bdf025904abf8ea9 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Thu, 24 Jun 2010 15:32:15 -0700 Subject: glsl2: Move the compiler to the subdirectory it will live in in Mesa. --- src/glsl/ir.cpp | 818 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 818 insertions(+) create mode 100644 src/glsl/ir.cpp (limited to 'src/glsl/ir.cpp') diff --git a/src/glsl/ir.cpp b/src/glsl/ir.cpp new file mode 100644 index 0000000000..2756752ba4 --- /dev/null +++ b/src/glsl/ir.cpp @@ -0,0 +1,818 @@ +/* + * Copyright © 2010 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ +#include +#include "main/imports.h" +#include "ir.h" +#include "ir_visitor.h" +#include "glsl_types.h" + +ir_assignment::ir_assignment(ir_rvalue *lhs, ir_rvalue *rhs, + ir_rvalue *condition) +{ + this->lhs = lhs; + this->rhs = rhs; + this->condition = condition; +} + + +ir_expression::ir_expression(int op, const struct glsl_type *type, + ir_rvalue *op0, ir_rvalue *op1) +{ + this->type = type; + this->operation = ir_expression_operation(op); + this->operands[0] = op0; + this->operands[1] = op1; +} + +unsigned int +ir_expression::get_num_operands(ir_expression_operation op) +{ +/* Update ir_print_visitor.cpp when updating this list. */ + const int num_operands[] = { + 1, /* ir_unop_bit_not */ + 1, /* ir_unop_logic_not */ + 1, /* ir_unop_neg */ + 1, /* ir_unop_abs */ + 1, /* ir_unop_sign */ + 1, /* ir_unop_rcp */ + 1, /* ir_unop_rsq */ + 1, /* ir_unop_sqrt */ + 1, /* ir_unop_exp */ + 1, /* ir_unop_log */ + 1, /* ir_unop_exp2 */ + 1, /* ir_unop_log2 */ + 1, /* ir_unop_f2i */ + 1, /* ir_unop_i2f */ + 1, /* ir_unop_f2b */ + 1, /* ir_unop_b2f */ + 1, /* ir_unop_i2b */ + 1, /* ir_unop_b2i */ + 1, /* ir_unop_u2f */ + + 1, /* ir_unop_trunc */ + 1, /* ir_unop_ceil */ + 1, /* ir_unop_floor */ + + 1, /* ir_unop_sin */ + 1, /* ir_unop_cos */ + + 1, /* ir_unop_dFdx */ + 1, /* ir_unop_dFdy */ + + 2, /* ir_binop_add */ + 2, /* ir_binop_sub */ + 2, /* ir_binop_mul */ + 2, /* ir_binop_div */ + 2, /* ir_binop_mod */ + + 2, /* ir_binop_less */ + 2, /* ir_binop_greater */ + 2, /* ir_binop_lequal */ + 2, /* ir_binop_gequal */ + 2, /* ir_binop_equal */ + 2, /* ir_binop_nequal */ + + 2, /* ir_binop_lshift */ + 2, /* ir_binop_rshift */ + 2, /* ir_binop_bit_and */ + 2, /* ir_binop_bit_xor */ + 2, /* ir_binop_bit_or */ + + 2, /* ir_binop_logic_and */ + 2, /* ir_binop_logic_xor */ + 2, /* ir_binop_logic_or */ + + 2, /* ir_binop_dot */ + 2, /* ir_binop_min */ + 2, /* ir_binop_max */ + + 2, /* ir_binop_pow */ + }; + + assert(sizeof(num_operands) / sizeof(num_operands[0]) == ir_binop_pow + 1); + + return num_operands[op]; +} + +static const char *const operator_strs[] = { + "~", + "!", + "neg", + "abs", + "sign", + "rcp", + "rsq", + "sqrt", + "exp", + "log", + "exp2", + "log2", + "f2i", + "i2f", + "f2b", + "b2f", + "i2b", + "b2i", + "u2f", + "trunc", + "ceil", + "floor", + "sin", + "cos", + "dFdx", + "dFdy", + "+", + "-", + "*", + "/", + "%", + "<", + ">", + "<=", + ">=", + "==", + "!=", + "<<", + ">>", + "&", + "^", + "|", + "&&", + "^^", + "||", + "dot", + "min", + "max", + "pow", +}; + +const char *ir_expression::operator_string() +{ + assert((unsigned int) operation <= + sizeof(operator_strs) / sizeof(operator_strs[0])); + return operator_strs[operation]; +} + +ir_expression_operation +ir_expression::get_operator(const char *str) +{ + const int operator_count = sizeof(operator_strs) / sizeof(operator_strs[0]); + for (int op = 0; op < operator_count; op++) { + if (strcmp(str, operator_strs[op]) == 0) + return (ir_expression_operation) op; + } + return (ir_expression_operation) -1; +} + +ir_constant::ir_constant() +{ + /* empty */ +} + +ir_constant::ir_constant(const struct glsl_type *type, + const ir_constant_data *data) +{ + assert((type->base_type >= GLSL_TYPE_UINT) + && (type->base_type <= GLSL_TYPE_BOOL)); + + this->type = type; + memcpy(& this->value, data, sizeof(this->value)); +} + +ir_constant::ir_constant(float f) +{ + this->type = glsl_type::float_type; + this->value.f[0] = f; +} + +ir_constant::ir_constant(unsigned int u) +{ + this->type = glsl_type::uint_type; + this->value.u[0] = u; +} + +ir_constant::ir_constant(int i) +{ + this->type = glsl_type::int_type; + this->value.i[0] = i; +} + +ir_constant::ir_constant(bool b) +{ + this->type = glsl_type::bool_type; + this->value.b[0] = b; +} + +ir_constant::ir_constant(const ir_constant *c, unsigned i) +{ + this->type = c->type->get_base_type(); + + switch (this->type->base_type) { + case GLSL_TYPE_UINT: this->value.u[0] = c->value.u[i]; break; + case GLSL_TYPE_INT: this->value.i[0] = c->value.i[i]; break; + case GLSL_TYPE_FLOAT: this->value.f[0] = c->value.f[i]; break; + case GLSL_TYPE_BOOL: this->value.b[0] = c->value.b[i]; break; + default: assert(!"Should not get here."); break; + } +} + +ir_constant::ir_constant(const struct glsl_type *type, exec_list *value_list) +{ + this->type = type; + + /* FINISHME: Support array types. */ + assert(type->is_scalar() || type->is_vector() || type->is_matrix() + || type->is_record()); + + /* If the constant is a record, the types of each of the entries in + * value_list must be a 1-for-1 match with the structure components. Each + * entry must also be a constant. Just move the nodes from the value_list + * to the list in the ir_constant. + */ + /* FINISHME: Should there be some type checking and / or assertions here? */ + /* FINISHME: Should the new constant take ownership of the nodes from + * FINISHME: value_list, or should it make copies? + */ + if (type->is_record()) { + value_list->move_nodes_to(& this->components); + return; + } + + + ir_constant *value = (ir_constant *) (value_list->head); + + /* Use each component from each entry in the value_list to initialize one + * component of the constant being constructed. + */ + for (unsigned i = 0; i < type->components(); /* empty */) { + assert(value->as_constant() != NULL); + assert(!value->is_tail_sentinal()); + + for (unsigned j = 0; j < value->type->components(); j++) { + switch (type->base_type) { + case GLSL_TYPE_UINT: + this->value.u[i] = value->get_uint_component(j); + break; + case GLSL_TYPE_INT: + this->value.i[i] = value->get_int_component(j); + break; + case GLSL_TYPE_FLOAT: + this->value.f[i] = value->get_float_component(j); + break; + case GLSL_TYPE_BOOL: + this->value.b[i] = value->get_bool_component(j); + break; + default: + /* FINISHME: What to do? Exceptions are not the answer. + */ + break; + } + + i++; + if (i >= type->components()) + break; + } + + value = (ir_constant *) value->next; + } +} + +bool +ir_constant::get_bool_component(unsigned i) const +{ + switch (this->type->base_type) { + case GLSL_TYPE_UINT: return this->value.u[i] != 0; + case GLSL_TYPE_INT: return this->value.i[i] != 0; + case GLSL_TYPE_FLOAT: return ((int)this->value.f[i]) != 0; + case GLSL_TYPE_BOOL: return this->value.b[i]; + default: assert(!"Should not get here."); break; + } + + /* Must return something to make the compiler happy. This is clearly an + * error case. + */ + return false; +} + +float +ir_constant::get_float_component(unsigned i) const +{ + switch (this->type->base_type) { + case GLSL_TYPE_UINT: return (float) this->value.u[i]; + case GLSL_TYPE_INT: return (float) this->value.i[i]; + case GLSL_TYPE_FLOAT: return this->value.f[i]; + case GLSL_TYPE_BOOL: return this->value.b[i] ? 1.0 : 0.0; + default: assert(!"Should not get here."); break; + } + + /* Must return something to make the compiler happy. This is clearly an + * error case. + */ + return 0.0; +} + +int +ir_constant::get_int_component(unsigned i) const +{ + switch (this->type->base_type) { + case GLSL_TYPE_UINT: return this->value.u[i]; + case GLSL_TYPE_INT: return this->value.i[i]; + case GLSL_TYPE_FLOAT: return (int) this->value.f[i]; + case GLSL_TYPE_BOOL: return this->value.b[i] ? 1 : 0; + default: assert(!"Should not get here."); break; + } + + /* Must return something to make the compiler happy. This is clearly an + * error case. + */ + return 0; +} + +unsigned +ir_constant::get_uint_component(unsigned i) const +{ + switch (this->type->base_type) { + case GLSL_TYPE_UINT: return this->value.u[i]; + case GLSL_TYPE_INT: return this->value.i[i]; + case GLSL_TYPE_FLOAT: return (unsigned) this->value.f[i]; + case GLSL_TYPE_BOOL: return this->value.b[i] ? 1 : 0; + default: assert(!"Should not get here."); break; + } + + /* Must return something to make the compiler happy. This is clearly an + * error case. + */ + return 0; +} + + +ir_constant * +ir_constant::get_record_field(const char *name) +{ + int idx = this->type->field_index(name); + + if (idx < 0) + return NULL; + + if (this->components.is_empty()) + return NULL; + + exec_node *node = this->components.head; + for (int i = 0; i < idx; i++) { + node = node->next; + + /* If the end of the list is encountered before the element matching the + * requested field is found, return NULL. + */ + if (node->is_tail_sentinal()) + return NULL; + } + + return (ir_constant *) node; +} + + +bool +ir_constant::has_value(const ir_constant *c) const +{ + if (this->type != c->type) + return false; + + /* FINISHME: This will probably also handle constant arrays as soon as those + * FINISHME: are supported. + */ + if (this->type->base_type == GLSL_TYPE_STRUCT) { + const exec_node *a_node = this->components.head; + const exec_node *b_node = c->components.head; + + while (!a_node->is_tail_sentinal()) { + assert(!b_node->is_tail_sentinal()); + + const ir_constant *const a_field = (ir_constant *) a_node; + const ir_constant *const b_field = (ir_constant *) b_node; + + if (!a_field->has_value(b_field)) + return false; + + a_node = a_node->next; + b_node = b_node->next; + } + + return true; + } + + for (unsigned i = 0; i < this->type->components(); i++) { + switch (this->type->base_type) { + case GLSL_TYPE_UINT: + if (this->value.u[i] != c->value.u[i]) + return false; + break; + case GLSL_TYPE_INT: + if (this->value.i[i] != c->value.i[i]) + return false; + break; + case GLSL_TYPE_FLOAT: + if (this->value.f[i] != c->value.f[i]) + return false; + break; + case GLSL_TYPE_BOOL: + if (this->value.b[i] != c->value.b[i]) + return false; + break; + default: + assert(!"Should not get here."); + return false; + } + } + + return true; +} + +ir_dereference_variable::ir_dereference_variable(ir_variable *var) +{ + this->var = var; + this->type = (var != NULL) ? var->type : glsl_type::error_type; +} + + +ir_dereference_array::ir_dereference_array(ir_rvalue *value, + ir_rvalue *array_index) +{ + this->array_index = array_index; + this->set_array(value); +} + + +ir_dereference_array::ir_dereference_array(ir_variable *var, + ir_rvalue *array_index) +{ + void *ctx = talloc_parent(var); + + this->array_index = array_index; + this->set_array(new(ctx) ir_dereference_variable(var)); +} + + +void +ir_dereference_array::set_array(ir_rvalue *value) +{ + this->array = value; + this->type = glsl_type::error_type; + + if (this->array != NULL) { + const glsl_type *const vt = this->array->type; + + if (vt->is_array()) { + type = vt->element_type(); + } else if (vt->is_matrix()) { + type = vt->column_type(); + } else if (vt->is_vector()) { + type = vt->get_base_type(); + } + } +} + + +ir_dereference_record::ir_dereference_record(ir_rvalue *value, + const char *field) +{ + this->record = value; + this->field = field; + this->type = (this->record != NULL) + ? this->record->type->field_type(field) : glsl_type::error_type; +} + + +ir_dereference_record::ir_dereference_record(ir_variable *var, + const char *field) +{ + void *ctx = talloc_parent(var); + + this->record = new(ctx) ir_dereference_variable(var); + this->field = field; + this->type = (this->record != NULL) + ? this->record->type->field_type(field) : glsl_type::error_type; +} + + +bool +ir_dereference::is_lvalue() +{ + ir_variable *var = this->variable_referenced(); + + /* Every l-value derference chain eventually ends in a variable. + */ + if ((var == NULL) || var->read_only) + return false; + + if (this->type->is_array() && !var->array_lvalue) + return false; + + return true; +} + + +const char *tex_opcode_strs[] = { "tex", "txb", "txl", "txd", "txf" }; + +const char *ir_texture::opcode_string() +{ + assert((unsigned int) op <= + sizeof(tex_opcode_strs) / sizeof(tex_opcode_strs[0])); + return tex_opcode_strs[op]; +} + +ir_texture_opcode +ir_texture::get_opcode(const char *str) +{ + const int count = sizeof(tex_opcode_strs) / sizeof(tex_opcode_strs[0]); + for (int op = 0; op < count; op++) { + if (strcmp(str, tex_opcode_strs[op]) == 0) + return (ir_texture_opcode) op; + } + return (ir_texture_opcode) -1; +} + + +void +ir_texture::set_sampler(ir_dereference *sampler) +{ + assert(sampler != NULL); + this->sampler = sampler; + + switch (sampler->type->sampler_type) { + case GLSL_TYPE_FLOAT: + this->type = glsl_type::vec4_type; + break; + case GLSL_TYPE_INT: + this->type = glsl_type::ivec4_type; + break; + case GLSL_TYPE_UINT: + this->type = glsl_type::uvec4_type; + break; + } +} + + +ir_swizzle::ir_swizzle(ir_rvalue *val, unsigned x, unsigned y, unsigned z, + unsigned w, unsigned count) + : val(val) +{ + assert((count >= 1) && (count <= 4)); + + const unsigned dup_mask = 0 + | ((count > 1) ? ((1U << y) & ((1U << x) )) : 0) + | ((count > 2) ? ((1U << z) & ((1U << x) | (1U << y) )) : 0) + | ((count > 3) ? ((1U << w) & ((1U << x) | (1U << y) | (1U << z))) : 0); + + assert(x <= 3); + assert(y <= 3); + assert(z <= 3); + assert(w <= 3); + + mask.x = x; + mask.y = y; + mask.z = z; + mask.w = w; + mask.num_components = count; + mask.has_duplicates = dup_mask != 0; + + /* Based on the number of elements in the swizzle and the base type + * (i.e., float, int, unsigned, or bool) of the vector being swizzled, + * generate the type of the resulting value. + */ + type = glsl_type::get_instance(val->type->base_type, mask.num_components, 1); +} + +ir_swizzle::ir_swizzle(ir_rvalue *val, ir_swizzle_mask mask) +{ + this->val = val; + this->mask = mask; + this->type = glsl_type::get_instance(val->type->base_type, + mask.num_components, 1); +} + +#define X 1 +#define R 5 +#define S 9 +#define I 13 + +ir_swizzle * +ir_swizzle::create(ir_rvalue *val, const char *str, unsigned vector_length) +{ + void *ctx = talloc_parent(val); + + /* For each possible swizzle character, this table encodes the value in + * \c idx_map that represents the 0th element of the vector. For invalid + * swizzle characters (e.g., 'k'), a special value is used that will allow + * detection of errors. + */ + static const unsigned char base_idx[26] = { + /* a b c d e f g h i j k l m */ + R, R, I, I, I, I, R, I, I, I, I, I, I, + /* n o p q r s t u v w x y z */ + I, I, S, S, R, S, S, I, I, X, X, X, X + }; + + /* Each valid swizzle character has an entry in the previous table. This + * table encodes the base index encoded in the previous table plus the actual + * index of the swizzle character. When processing swizzles, the first + * character in the string is indexed in the previous table. Each character + * in the string is indexed in this table, and the value found there has the + * value form the first table subtracted. The result must be on the range + * [0,3]. + * + * For example, the string "wzyx" will get X from the first table. Each of + * the charcaters will get X+3, X+2, X+1, and X+0 from this table. After + * subtraction, the swizzle values are { 3, 2, 1, 0 }. + * + * The string "wzrg" will get X from the first table. Each of the characters + * will get X+3, X+2, R+0, and R+1 from this table. After subtraction, the + * swizzle values are { 3, 2, 4, 5 }. Since 4 and 5 are outside the range + * [0,3], the error is detected. + */ + static const unsigned char idx_map[26] = { + /* a b c d e f g h i j k l m */ + R+3, R+2, 0, 0, 0, 0, R+1, 0, 0, 0, 0, 0, 0, + /* n o p q r s t u v w x y z */ + 0, 0, S+2, S+3, R+0, S+0, S+1, 0, 0, X+3, X+0, X+1, X+2 + }; + + int swiz_idx[4] = { 0, 0, 0, 0 }; + unsigned i; + + + /* Validate the first character in the swizzle string and look up the base + * index value as described above. + */ + if ((str[0] < 'a') || (str[0] > 'z')) + return NULL; + + const unsigned base = base_idx[str[0] - 'a']; + + + for (i = 0; (i < 4) && (str[i] != '\0'); i++) { + /* Validate the next character, and, as described above, convert it to a + * swizzle index. + */ + if ((str[i] < 'a') || (str[i] > 'z')) + return NULL; + + swiz_idx[i] = idx_map[str[i] - 'a'] - base; + if ((swiz_idx[i] < 0) || (swiz_idx[i] >= (int) vector_length)) + return NULL; + } + + if (str[i] != '\0') + return NULL; + + return new(ctx) ir_swizzle(val, swiz_idx[0], swiz_idx[1], swiz_idx[2], + swiz_idx[3], i); +} + +#undef X +#undef R +#undef S +#undef I + +ir_variable * +ir_swizzle::variable_referenced() +{ + return this->val->variable_referenced(); +} + +ir_variable::ir_variable(const struct glsl_type *type, const char *name) + : max_array_access(0), read_only(false), centroid(false), invariant(false), + shader_in(false), shader_out(false), + mode(ir_var_auto), interpolation(ir_var_smooth), array_lvalue(false) +{ + this->type = type; + this->name = name; + this->location = -1; + this->warn_extension = NULL; + this->constant_value = NULL; + + if (type && type->base_type == GLSL_TYPE_SAMPLER) + this->read_only = true; +} + + +const char * +ir_variable::interpolation_string() const +{ + if (!this->shader_in && !this->shader_out) + return ""; + + switch (this->interpolation) { + case ir_var_smooth: return "smooth"; + case ir_var_flat: return "flat"; + case ir_var_noperspective: return "noperspective"; + } + + assert(!"Should not get here."); + return ""; +} + + +unsigned +ir_variable::component_slots() const +{ + /* FINISHME: Sparsely accessed arrays require fewer slots. */ + return this->type->component_slots(); +} + + +ir_function_signature::ir_function_signature(const glsl_type *return_type) + : return_type(return_type), is_defined(false) +{ + /* empty */ +} + + +const char * +ir_function_signature::qualifiers_match(exec_list *params) +{ + exec_list_iterator iter_a = parameters.iterator(); + exec_list_iterator iter_b = params->iterator(); + + /* check that the qualifiers match. */ + while (iter_a.has_next()) { + ir_variable *a = (ir_variable *)iter_a.get(); + ir_variable *b = (ir_variable *)iter_b.get(); + + if (a->read_only != b->read_only || + a->mode != b->mode || + a->interpolation != b->interpolation || + a->centroid != b->centroid) { + + /* parameter a's qualifiers don't match */ + return a->name; + } + + iter_a.next(); + iter_b.next(); + } + return NULL; +} + + +void +ir_function_signature::replace_parameters(exec_list *new_params) +{ + /* Destroy all of the previous parameter information. If the previous + * parameter information comes from the function prototype, it may either + * specify incorrect parameter names or not have names at all. + */ + foreach_iter(exec_list_iterator, iter, parameters) { + assert(((ir_instruction *) iter.get())->as_variable() != NULL); + + iter.remove(); + } + + new_params->move_nodes_to(¶meters); +} + + +ir_function::ir_function(const char *name) + : name(name) +{ + /* empty */ +} + + +ir_call * +ir_call::get_error_instruction(void *ctx) +{ + ir_call *call = new(ctx) ir_call; + + call->type = glsl_type::error_type; + return call; +} + +void +visit_exec_list(exec_list *list, ir_visitor *visitor) +{ + foreach_iter(exec_list_iterator, iter, *list) { + ((ir_instruction *)iter.get())->accept(visitor); + } +} + -- cgit v1.2.3 From 6315b68f5fbe529bce3497b67c42af1eaa62b8c1 Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Fri, 25 Jun 2010 15:25:27 -0700 Subject: ir_swizzle: Add new constructor, refactor constructors Adds a new constructor that takes an array of component values. Refactors the meat of the two constructors to an init_mask method. --- src/glsl/ir.cpp | 63 ++++++++++++++++++++++++++++++++++++++++----------------- src/glsl/ir.h | 11 ++++++++++ 2 files changed, 56 insertions(+), 18 deletions(-) (limited to 'src/glsl/ir.cpp') diff --git a/src/glsl/ir.cpp b/src/glsl/ir.cpp index 2756752ba4..4eb0e9e33e 100644 --- a/src/glsl/ir.cpp +++ b/src/glsl/ir.cpp @@ -573,28 +573,40 @@ ir_texture::set_sampler(ir_dereference *sampler) } -ir_swizzle::ir_swizzle(ir_rvalue *val, unsigned x, unsigned y, unsigned z, - unsigned w, unsigned count) - : val(val) +void +ir_swizzle::init_mask(const unsigned *comp, unsigned count) { assert((count >= 1) && (count <= 4)); - const unsigned dup_mask = 0 - | ((count > 1) ? ((1U << y) & ((1U << x) )) : 0) - | ((count > 2) ? ((1U << z) & ((1U << x) | (1U << y) )) : 0) - | ((count > 3) ? ((1U << w) & ((1U << x) | (1U << y) | (1U << z))) : 0); - - assert(x <= 3); - assert(y <= 3); - assert(z <= 3); - assert(w <= 3); + memset(&this->mask, 0, sizeof(this->mask)); + this->mask.num_components = count; + + unsigned dup_mask = 0; + switch (count) { + case 4: + assert(comp[3] <= 3); + dup_mask |= (1U << comp[3]) + & ((1U << comp[0]) | (1U << comp[1]) | (1U << comp[2])); + this->mask.w = comp[3]; + + case 3: + assert(comp[2] <= 3); + dup_mask |= (1U << comp[2]) + & ((1U << comp[0]) | (1U << comp[1])); + this->mask.z = comp[2]; + + case 2: + assert(comp[1] <= 3); + dup_mask |= (1U << comp[1]) + & ((1U << comp[0])); + this->mask.y = comp[1]; + + case 1: + assert(comp[0] <= 3); + this->mask.x = comp[0]; + } - mask.x = x; - mask.y = y; - mask.z = z; - mask.w = w; - mask.num_components = count; - mask.has_duplicates = dup_mask != 0; + this->mask.has_duplicates = dup_mask != 0; /* Based on the number of elements in the swizzle and the base type * (i.e., float, int, unsigned, or bool) of the vector being swizzled, @@ -603,6 +615,21 @@ ir_swizzle::ir_swizzle(ir_rvalue *val, unsigned x, unsigned y, unsigned z, type = glsl_type::get_instance(val->type->base_type, mask.num_components, 1); } +ir_swizzle::ir_swizzle(ir_rvalue *val, unsigned x, unsigned y, unsigned z, + unsigned w, unsigned count) + : val(val) +{ + const unsigned components[4] = { x, y, z, w }; + this->init_mask(components, count); +} + +ir_swizzle::ir_swizzle(ir_rvalue *val, const unsigned *comp, + unsigned count) + : val(val) +{ + this->init_mask(comp, count); +} + ir_swizzle::ir_swizzle(ir_rvalue *val, ir_swizzle_mask mask) { this->val = val; diff --git a/src/glsl/ir.h b/src/glsl/ir.h index 3d2c7ff5cf..de1124975d 100644 --- a/src/glsl/ir.h +++ b/src/glsl/ir.h @@ -918,6 +918,9 @@ class ir_swizzle : public ir_rvalue { public: ir_swizzle(ir_rvalue *, unsigned x, unsigned y, unsigned z, unsigned w, unsigned count); + + ir_swizzle(ir_rvalue *val, const unsigned *components, unsigned count); + ir_swizzle(ir_rvalue *val, ir_swizzle_mask mask); virtual ir_instruction *clone(struct hash_table *) const; @@ -951,6 +954,14 @@ public: ir_rvalue *val; ir_swizzle_mask mask; + +private: + /** + * Initialize the mask component of a swizzle + * + * This is used by the \c ir_swizzle constructors. + */ + void init_mask(const unsigned *components, unsigned count); }; -- cgit v1.2.3 From 0eda9ae0a6bcd6a7e014df046c87fac5caee0e9e Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Wed, 30 Jun 2010 11:51:54 -0700 Subject: glsl2: Make function names and variable names be children of the node. This avoids losing their memory when the parser state is freed. --- src/glsl/ir.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'src/glsl/ir.cpp') diff --git a/src/glsl/ir.cpp b/src/glsl/ir.cpp index 4eb0e9e33e..60ee36d17c 100644 --- a/src/glsl/ir.cpp +++ b/src/glsl/ir.cpp @@ -733,7 +733,7 @@ ir_variable::ir_variable(const struct glsl_type *type, const char *name) mode(ir_var_auto), interpolation(ir_var_smooth), array_lvalue(false) { this->type = type; - this->name = name; + this->name = talloc_strdup(this, name); this->location = -1; this->warn_extension = NULL; this->constant_value = NULL; @@ -820,9 +820,8 @@ ir_function_signature::replace_parameters(exec_list *new_params) ir_function::ir_function(const char *name) - : name(name) { - /* empty */ + this->name = talloc_strdup(this, name); } -- cgit v1.2.3 From d925c9173009e9e5d48df30b30aaef22753183aa Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Thu, 1 Jul 2010 10:37:11 -0700 Subject: glsl2: Add ir_unop_fract as an expression type. Most backends will prefer seeing this to seeing (a - floor(a)), so represent it explicitly. --- src/glsl/builtin_function.cpp | 8 ++++---- src/glsl/builtins/110/fract | 8 ++++---- src/glsl/ir.cpp | 2 ++ src/glsl/ir.h | 1 + src/glsl/ir_constant_expression.cpp | 18 ++++++++++++++++++ src/mesa/shader/ir_to_mesa.cpp | 4 ++++ 6 files changed, 33 insertions(+), 8 deletions(-) (limited to 'src/glsl/ir.cpp') diff --git a/src/glsl/builtin_function.cpp b/src/glsl/builtin_function.cpp index b7dbc6b34f..30ba6a5267 100644 --- a/src/glsl/builtin_function.cpp +++ b/src/glsl/builtin_function.cpp @@ -781,22 +781,22 @@ static const char *builtins_110_fract = { " (signature float\n" " (parameters\n" " (declare (in) float x))\n" - " ((return (expression float - (var_ref x) (expression float floor (var_ref x))))))\n" + " ((return (expression float fract (var_ref x)))))\n" "\n" " (signature vec2\n" " (parameters\n" " (declare (in) vec2 x))\n" - " ((return (expression vec2 - (var_ref x) (expression vec2 floor (var_ref x))))))\n" + " ((return (expression vec2 fract (var_ref x)))))\n" "\n" " (signature vec3\n" " (parameters\n" " (declare (in) vec3 x))\n" - " ((return (expression vec3 - (var_ref x) (expression vec3 floor (var_ref x))))))\n" + " ((return (expression vec3 fract (var_ref x)))))\n" "\n" " (signature vec4\n" " (parameters\n" " (declare (in) vec4 x))\n" - " ((return (expression vec4 - (var_ref x) (expression vec4 floor (var_ref x))))))\n" + " ((return (expression vec4 fract (var_ref x)))))\n" "))\n" "\n" }; diff --git a/src/glsl/builtins/110/fract b/src/glsl/builtins/110/fract index 46741bb3cb..3f0763d1b3 100644 --- a/src/glsl/builtins/110/fract +++ b/src/glsl/builtins/110/fract @@ -2,21 +2,21 @@ (signature float (parameters (declare (in) float x)) - ((return (expression float - (var_ref x) (expression float floor (var_ref x)))))) + ((return (expression float fract (var_ref x))))) (signature vec2 (parameters (declare (in) vec2 x)) - ((return (expression vec2 - (var_ref x) (expression vec2 floor (var_ref x)))))) + ((return (expression vec2 fract (var_ref x))))) (signature vec3 (parameters (declare (in) vec3 x)) - ((return (expression vec3 - (var_ref x) (expression vec3 floor (var_ref x)))))) + ((return (expression vec3 fract (var_ref x))))) (signature vec4 (parameters (declare (in) vec4 x)) - ((return (expression vec4 - (var_ref x) (expression vec4 floor (var_ref x)))))) + ((return (expression vec4 fract (var_ref x))))) )) diff --git a/src/glsl/ir.cpp b/src/glsl/ir.cpp index 60ee36d17c..4257842583 100644 --- a/src/glsl/ir.cpp +++ b/src/glsl/ir.cpp @@ -72,6 +72,7 @@ ir_expression::get_num_operands(ir_expression_operation op) 1, /* ir_unop_trunc */ 1, /* ir_unop_ceil */ 1, /* ir_unop_floor */ + 1, /* ir_unop_fract */ 1, /* ir_unop_sin */ 1, /* ir_unop_cos */ @@ -137,6 +138,7 @@ static const char *const operator_strs[] = { "trunc", "ceil", "floor", + "fract", "sin", "cos", "dFdx", diff --git a/src/glsl/ir.h b/src/glsl/ir.h index 00b0076c17..f47813786b 100644 --- a/src/glsl/ir.h +++ b/src/glsl/ir.h @@ -528,6 +528,7 @@ enum ir_expression_operation { ir_unop_trunc, ir_unop_ceil, ir_unop_floor, + ir_unop_fract, /*@}*/ /** diff --git a/src/glsl/ir_constant_expression.cpp b/src/glsl/ir_constant_expression.cpp index c6348ac434..548217cddd 100644 --- a/src/glsl/ir_constant_expression.cpp +++ b/src/glsl/ir_constant_expression.cpp @@ -187,6 +187,24 @@ ir_constant_visitor::visit(ir_expression *ir) } break; + case ir_unop_fract: + for (c = 0; c < ir->operands[0]->type->components(); c++) { + switch (ir->type->base_type) { + case GLSL_TYPE_UINT: + data.u[c] = 0; + break; + case GLSL_TYPE_INT: + data.i[c] = 0; + break; + case GLSL_TYPE_FLOAT: + data.f[c] = op[0]->value.f[c] - floor(op[0]->value.f[c]); + break; + default: + assert(0); + } + } + break; + case ir_unop_neg: for (c = 0; c < ir->operands[0]->type->components(); c++) { switch (ir->type->base_type) { diff --git a/src/mesa/shader/ir_to_mesa.cpp b/src/mesa/shader/ir_to_mesa.cpp index b270e2da41..2f2096ef97 100644 --- a/src/mesa/shader/ir_to_mesa.cpp +++ b/src/mesa/shader/ir_to_mesa.cpp @@ -782,6 +782,10 @@ ir_to_mesa_visitor::visit(ir_expression *ir) case ir_unop_floor: ir_to_mesa_emit_op1(ir, OPCODE_FLR, result_dst, op[0]); break; + case ir_unop_fract: + ir_to_mesa_emit_op1(ir, OPCODE_FRC, result_dst, op[0]); + break; + case ir_binop_min: ir_to_mesa_emit_op2(ir, OPCODE_MIN, result_dst, op[0], op[1]); break; -- cgit v1.2.3 From 792e01c1e259077eb339af3ce61905fd227ae4bd Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Wed, 7 Jul 2010 11:33:13 -0700 Subject: ir_call: Add method to set the function signature being called --- src/glsl/ir.cpp | 8 ++++++++ src/glsl/ir.h | 5 +++++ 2 files changed, 13 insertions(+) (limited to 'src/glsl/ir.cpp') diff --git a/src/glsl/ir.cpp b/src/glsl/ir.cpp index 4257842583..f3ee12ce81 100644 --- a/src/glsl/ir.cpp +++ b/src/glsl/ir.cpp @@ -836,6 +836,14 @@ ir_call::get_error_instruction(void *ctx) return call; } +void +ir_call::set_callee(const ir_function_signature *sig) +{ + assert((this->type == NULL) || (this->type == sig->return_type)); + + this->callee = sig; +} + void visit_exec_list(exec_list *list, ir_visitor *visitor) { diff --git a/src/glsl/ir.h b/src/glsl/ir.h index 0d5bbc20aa..89922c6bbc 100644 --- a/src/glsl/ir.h +++ b/src/glsl/ir.h @@ -694,6 +694,11 @@ public: return callee; } + /** + * Set the function call target + */ + void set_callee(const ir_function_signature *sig); + /** * Generates an inline version of the function before @ir, * returning the return value of the function. -- cgit v1.2.3 From df05ad4e1aa5512ce1dfd2e6661641e012c8b279 Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Fri, 2 Jul 2010 13:28:32 -0700 Subject: ir_function_signature: Add method to get the function owning a signature There is no setter function, the getter returns a constant pointer, and ir_function_signature::_function is private for a reason. The only way to make a connection between a function and function signature is via ir_function::add_signature. This helps ensure that certain invariants (i.e., a function signature is in the list of signatures for its _function) are met. --- src/glsl/ir.cpp | 2 +- src/glsl/ir.h | 25 +++++++++++++++++++++---- 2 files changed, 22 insertions(+), 5 deletions(-) (limited to 'src/glsl/ir.cpp') diff --git a/src/glsl/ir.cpp b/src/glsl/ir.cpp index f3ee12ce81..6d89913286 100644 --- a/src/glsl/ir.cpp +++ b/src/glsl/ir.cpp @@ -771,7 +771,7 @@ ir_variable::component_slots() const ir_function_signature::ir_function_signature(const glsl_type *return_type) - : return_type(return_type), is_defined(false) + : return_type(return_type), is_defined(false), _function(NULL) { /* empty */ } diff --git a/src/glsl/ir.h b/src/glsl/ir.h index 18294ebc31..fb94b5a560 100644 --- a/src/glsl/ir.h +++ b/src/glsl/ir.h @@ -275,6 +275,23 @@ public: */ const char *function_name() const; + /** + * Get a handle to the function for which this is a signature + * + * There is no setter function, this function returns a \c const pointer, + * and \c ir_function_signature::_function is private for a reason. The + * only way to make a connection between a function and function signature + * is via \c ir_function::add_signature. This helps ensure that certain + * invariants (i.e., a function signature is in the list of signatures for + * its \c _function) are met. + * + * \sa ir_function::add_signature + */ + inline const class ir_function *function() const + { + return this->_function; + } + /** * Check whether the qualifiers match between this signature's parameters * and the supplied parameter list. If not, returns the name of the first @@ -312,7 +329,7 @@ public: private: /** Function of which this signature is one overload. */ - class ir_function *function; + class ir_function *_function; friend class ir_function; }; @@ -343,8 +360,8 @@ public: void add_signature(ir_function_signature *sig) { - sig->function = this; - signatures.push_tail(sig); + sig->_function = this; + this->signatures.push_tail(sig); } /** @@ -381,7 +398,7 @@ private: inline const char *ir_function_signature::function_name() const { - return function->name; + return this->_function->name; } /*@}*/ -- cgit v1.2.3 From 9be7f638130f46a9df2bfbcd4a03b36de9e4f3aa Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Tue, 13 Jul 2010 15:37:57 -0700 Subject: glsl2: Make cross() be an expression operation. ARB_fp, ARB_vp, Mesa IR, and the 965 vertex shader all have instructions for cross. Shaves 12 Mesa instructions off of a 66-instruction shader I have. --- src/glsl/builtin_function.cpp | 12 +----------- src/glsl/builtins/110/cross | 12 +----------- src/glsl/ir.cpp | 2 ++ src/glsl/ir.h | 1 + src/glsl/ir_constant_expression.cpp | 11 +++++++++++ src/mesa/shader/ir_to_mesa.cpp | 5 +++++ 6 files changed, 21 insertions(+), 22 deletions(-) (limited to 'src/glsl/ir.cpp') diff --git a/src/glsl/builtin_function.cpp b/src/glsl/builtin_function.cpp index 1cf88ada16..b3a283306d 100644 --- a/src/glsl/builtin_function.cpp +++ b/src/glsl/builtin_function.cpp @@ -486,17 +486,7 @@ static const char *builtins_110_cross = { " (parameters\n" " (declare (in) vec3 arg0)\n" " (declare (in) vec3 arg1))\n" - " ((declare () vec3 t)\n" - " (assign (constant bool (1)) (swiz x (var_ref t))\n" - " (expression float - (expression float * (swiz y (var_ref arg0)) (swiz z (var_ref arg1)))\n" - " (expression float * (swiz y (var_ref arg1)) (swiz z (var_ref arg0)))))\n" - " (assign (constant bool (1)) (swiz y (var_ref t))\n" - " (expression float - (expression float * (swiz z (var_ref arg0)) (swiz x (var_ref arg1)))\n" - " (expression float * (swiz z (var_ref arg1)) (swiz x (var_ref arg0)))))\n" - " (assign (constant bool (1)) (swiz z (var_ref t))\n" - " (expression float - (expression float * (swiz x (var_ref arg0)) (swiz y (var_ref arg1)))\n" - " (expression float * (swiz x (var_ref arg1)) (swiz y (var_ref arg0)))))\n" - " (return (var_ref t))))\n" + " ((return (expression vec3 cross (var_ref arg0) (var_ref arg1)))))\n" "))\n" }; diff --git a/src/glsl/builtins/110/cross b/src/glsl/builtins/110/cross index deb2f952bf..24717a2183 100644 --- a/src/glsl/builtins/110/cross +++ b/src/glsl/builtins/110/cross @@ -3,15 +3,5 @@ (parameters (declare (in) vec3 arg0) (declare (in) vec3 arg1)) - ((declare () vec3 t) - (assign (constant bool (1)) (swiz x (var_ref t)) - (expression float - (expression float * (swiz y (var_ref arg0)) (swiz z (var_ref arg1))) - (expression float * (swiz y (var_ref arg1)) (swiz z (var_ref arg0))))) - (assign (constant bool (1)) (swiz y (var_ref t)) - (expression float - (expression float * (swiz z (var_ref arg0)) (swiz x (var_ref arg1))) - (expression float * (swiz z (var_ref arg1)) (swiz x (var_ref arg0))))) - (assign (constant bool (1)) (swiz z (var_ref t)) - (expression float - (expression float * (swiz x (var_ref arg0)) (swiz y (var_ref arg1))) - (expression float * (swiz x (var_ref arg1)) (swiz y (var_ref arg0))))) - (return (var_ref t)))) + ((return (expression vec3 cross (var_ref arg0) (var_ref arg1))))) )) diff --git a/src/glsl/ir.cpp b/src/glsl/ir.cpp index 6d89913286..fcf5deced8 100644 --- a/src/glsl/ir.cpp +++ b/src/glsl/ir.cpp @@ -104,6 +104,7 @@ ir_expression::get_num_operands(ir_expression_operation op) 2, /* ir_binop_logic_or */ 2, /* ir_binop_dot */ + 2, /* ir_binop_cross */ 2, /* ir_binop_min */ 2, /* ir_binop_max */ @@ -163,6 +164,7 @@ static const char *const operator_strs[] = { "^^", "||", "dot", + "cross", "min", "max", "pow", diff --git a/src/glsl/ir.h b/src/glsl/ir.h index 790173ed6b..9d7af2dcab 100644 --- a/src/glsl/ir.h +++ b/src/glsl/ir.h @@ -609,6 +609,7 @@ enum ir_expression_operation { ir_binop_logic_or, ir_binop_dot, + ir_binop_cross, ir_binop_min, ir_binop_max, diff --git a/src/glsl/ir_constant_expression.cpp b/src/glsl/ir_constant_expression.cpp index c0fe47067b..ca834978f4 100644 --- a/src/glsl/ir_constant_expression.cpp +++ b/src/glsl/ir_constant_expression.cpp @@ -459,8 +459,19 @@ ir_constant_visitor::visit(ir_expression *ir) assert(0); } } + break; + case ir_binop_cross: + assert(op[0]->type == glsl_type::vec3_type); + assert(op[1]->type == glsl_type::vec3_type); + data.f[0] = (op[0]->value.f[1] * op[1]->value.f[2] - + op[1]->value.f[1] * op[0]->value.f[2]); + data.f[1] = (op[0]->value.f[2] * op[1]->value.f[0] - + op[1]->value.f[2] * op[0]->value.f[0]); + data.f[2] = (op[0]->value.f[0] * op[1]->value.f[1] - + op[1]->value.f[0] * op[0]->value.f[1]); break; + case ir_binop_add: assert(op[0]->type == op[1]->type || op0_scalar || op1_scalar); for (unsigned c = 0, c0 = 0, c1 = 0; diff --git a/src/mesa/shader/ir_to_mesa.cpp b/src/mesa/shader/ir_to_mesa.cpp index 6ecc6d317c..f99a1fc450 100644 --- a/src/mesa/shader/ir_to_mesa.cpp +++ b/src/mesa/shader/ir_to_mesa.cpp @@ -781,6 +781,11 @@ ir_to_mesa_visitor::visit(ir_expression *ir) op[0], op[1]); } break; + + case ir_binop_cross: + ir_to_mesa_emit_op2(ir, OPCODE_XPD, result_dst, op[0], op[1]); + break; + case ir_unop_sqrt: ir_to_mesa_emit_scalar_op1(ir, OPCODE_RSQ, result_dst, op[0]); ir_to_mesa_emit_scalar_op1(ir, OPCODE_RCP, result_dst, result_src); -- cgit v1.2.3 From 1f47245bdda2c85bf0f0174e6c24a50486b413aa Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Sun, 18 Jul 2010 17:45:16 -0700 Subject: glsl2: Remove the const disease from function signature's callee. --- src/glsl/ast_function.cpp | 3 +-- src/glsl/ir.cpp | 2 +- src/glsl/ir.h | 8 ++++---- src/glsl/ir_clone.cpp | 2 +- src/glsl/ir_reader.cpp | 2 +- 5 files changed, 8 insertions(+), 9 deletions(-) (limited to 'src/glsl/ir.cpp') diff --git a/src/glsl/ast_function.cpp b/src/glsl/ast_function.cpp index 467722c868..aaf1e57ae2 100644 --- a/src/glsl/ast_function.cpp +++ b/src/glsl/ast_function.cpp @@ -64,8 +64,7 @@ process_call(exec_list *instructions, ir_function *f, { void *ctx = state; - const ir_function_signature *sig = - f->matching_signature(actual_parameters); + ir_function_signature *sig = f->matching_signature(actual_parameters); /* The instructions param will be used when the FINISHMEs below are done */ (void) instructions; diff --git a/src/glsl/ir.cpp b/src/glsl/ir.cpp index fcf5deced8..70905ddb80 100644 --- a/src/glsl/ir.cpp +++ b/src/glsl/ir.cpp @@ -839,7 +839,7 @@ ir_call::get_error_instruction(void *ctx) } void -ir_call::set_callee(const ir_function_signature *sig) +ir_call::set_callee(ir_function_signature *sig) { assert((this->type == NULL) || (this->type == sig->return_type)); diff --git a/src/glsl/ir.h b/src/glsl/ir.h index 9d7af2dcab..042da94d85 100644 --- a/src/glsl/ir.h +++ b/src/glsl/ir.h @@ -661,7 +661,7 @@ public: */ class ir_call : public ir_rvalue { public: - ir_call(const ir_function_signature *callee, exec_list *actual_parameters) + ir_call(ir_function_signature *callee, exec_list *actual_parameters) : callee(callee) { assert(callee->return_type != NULL); @@ -706,7 +706,7 @@ public: return callee->function_name(); } - const ir_function_signature *get_callee() + ir_function_signature *get_callee() { return callee; } @@ -714,7 +714,7 @@ public: /** * Set the function call target */ - void set_callee(const ir_function_signature *sig); + void set_callee(ir_function_signature *sig); /** * Generates an inline version of the function before @ir, @@ -729,7 +729,7 @@ private: /* empty */ } - const ir_function_signature *callee; + ir_function_signature *callee; /* List of ir_rvalue of paramaters passed in this call. */ exec_list actual_parameters; diff --git a/src/glsl/ir_clone.cpp b/src/glsl/ir_clone.cpp index c7b786f0c4..91d6977354 100644 --- a/src/glsl/ir_clone.cpp +++ b/src/glsl/ir_clone.cpp @@ -356,7 +356,7 @@ public: /* Try to find the function signature referenced by the ir_call in the * table. If it is found, replace it with the value from the table. */ - const ir_function_signature *const sig = + ir_function_signature *sig = (ir_function_signature *) hash_table_find(this->ht, ir->get_callee()); if (sig != NULL) ir->set_callee(sig); diff --git a/src/glsl/ir_reader.cpp b/src/glsl/ir_reader.cpp index c83f92ef57..a1e5a7ad74 100644 --- a/src/glsl/ir_reader.cpp +++ b/src/glsl/ir_reader.cpp @@ -632,7 +632,7 @@ read_call(_mesa_glsl_parse_state *st, s_list *list) return NULL; } - const ir_function_signature *callee = f->matching_signature(¶meters); + ir_function_signature *callee = f->matching_signature(¶meters); if (callee == NULL) { ir_read_error(st, list, "couldn't find matching signature for function " "%s", name->value()); -- cgit v1.2.3 From d16044ad4d6176fec6164f96450a25f76b7677f1 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 19 Jul 2010 09:05:42 -0700 Subject: glsl2: Give IR nodes a type field. This is a big deal for debugging if nothing else ("what class is this ir_instruction, really?"), but is also nice for avoiding building a whole visitor or an if (node->as_whatever() || node->as_other_thing()) chain. --- src/glsl/ir.cpp | 23 +++++++++++++++++++++-- src/glsl/ir.h | 42 ++++++++++++++++++++++++++++++++++-------- src/glsl/ir_validate.cpp | 15 +++++++++++++++ 3 files changed, 70 insertions(+), 10 deletions(-) (limited to 'src/glsl/ir.cpp') diff --git a/src/glsl/ir.cpp b/src/glsl/ir.cpp index 70905ddb80..1648848ecb 100644 --- a/src/glsl/ir.cpp +++ b/src/glsl/ir.cpp @@ -29,6 +29,7 @@ ir_assignment::ir_assignment(ir_rvalue *lhs, ir_rvalue *rhs, ir_rvalue *condition) { + this->ir_type = ir_type_assignment; this->lhs = lhs; this->rhs = rhs; this->condition = condition; @@ -38,6 +39,7 @@ ir_assignment::ir_assignment(ir_rvalue *lhs, ir_rvalue *rhs, ir_expression::ir_expression(int op, const struct glsl_type *type, ir_rvalue *op0, ir_rvalue *op1) { + this->ir_type = ir_type_expression; this->type = type; this->operation = ir_expression_operation(op); this->operands[0] = op0; @@ -190,7 +192,7 @@ ir_expression::get_operator(const char *str) ir_constant::ir_constant() { - /* empty */ + this->ir_type = ir_type_constant; } ir_constant::ir_constant(const struct glsl_type *type, @@ -199,36 +201,42 @@ ir_constant::ir_constant(const struct glsl_type *type, assert((type->base_type >= GLSL_TYPE_UINT) && (type->base_type <= GLSL_TYPE_BOOL)); + this->ir_type = ir_type_constant; this->type = type; memcpy(& this->value, data, sizeof(this->value)); } ir_constant::ir_constant(float f) { + this->ir_type = ir_type_constant; this->type = glsl_type::float_type; this->value.f[0] = f; } ir_constant::ir_constant(unsigned int u) { + this->ir_type = ir_type_constant; this->type = glsl_type::uint_type; this->value.u[0] = u; } ir_constant::ir_constant(int i) { + this->ir_type = ir_type_constant; this->type = glsl_type::int_type; this->value.i[0] = i; } ir_constant::ir_constant(bool b) { + this->ir_type = ir_type_constant; this->type = glsl_type::bool_type; this->value.b[0] = b; } ir_constant::ir_constant(const ir_constant *c, unsigned i) { + this->ir_type = ir_type_constant; this->type = c->type->get_base_type(); switch (this->type->base_type) { @@ -242,6 +250,7 @@ ir_constant::ir_constant(const ir_constant *c, unsigned i) ir_constant::ir_constant(const struct glsl_type *type, exec_list *value_list) { + this->ir_type = ir_type_constant; this->type = type; /* FINISHME: Support array types. */ @@ -454,6 +463,7 @@ ir_constant::has_value(const ir_constant *c) const ir_dereference_variable::ir_dereference_variable(ir_variable *var) { + this->ir_type = ir_type_dereference_variable; this->var = var; this->type = (var != NULL) ? var->type : glsl_type::error_type; } @@ -462,6 +472,7 @@ ir_dereference_variable::ir_dereference_variable(ir_variable *var) ir_dereference_array::ir_dereference_array(ir_rvalue *value, ir_rvalue *array_index) { + this->ir_type = ir_type_dereference_array; this->array_index = array_index; this->set_array(value); } @@ -472,6 +483,7 @@ ir_dereference_array::ir_dereference_array(ir_variable *var, { void *ctx = talloc_parent(var); + this->ir_type = ir_type_dereference_array; this->array_index = array_index; this->set_array(new(ctx) ir_dereference_variable(var)); } @@ -500,6 +512,7 @@ ir_dereference_array::set_array(ir_rvalue *value) ir_dereference_record::ir_dereference_record(ir_rvalue *value, const char *field) { + this->ir_type = ir_type_dereference_record; this->record = value; this->field = field; this->type = (this->record != NULL) @@ -512,6 +525,7 @@ ir_dereference_record::ir_dereference_record(ir_variable *var, { void *ctx = talloc_parent(var); + this->ir_type = ir_type_dereference_record; this->record = new(ctx) ir_dereference_variable(var); this->field = field; this->type = (this->record != NULL) @@ -624,6 +638,7 @@ ir_swizzle::ir_swizzle(ir_rvalue *val, unsigned x, unsigned y, unsigned z, : val(val) { const unsigned components[4] = { x, y, z, w }; + this->ir_type = ir_type_swizzle; this->init_mask(components, count); } @@ -631,11 +646,13 @@ ir_swizzle::ir_swizzle(ir_rvalue *val, const unsigned *comp, unsigned count) : val(val) { + this->ir_type = ir_type_swizzle; this->init_mask(comp, count); } ir_swizzle::ir_swizzle(ir_rvalue *val, ir_swizzle_mask mask) { + this->ir_type = ir_type_swizzle; this->val = val; this->mask = mask; this->type = glsl_type::get_instance(val->type->base_type, @@ -736,6 +753,7 @@ ir_variable::ir_variable(const struct glsl_type *type, const char *name) shader_in(false), shader_out(false), mode(ir_var_auto), interpolation(ir_var_smooth), array_lvalue(false) { + this->ir_type = ir_type_variable; this->type = type; this->name = talloc_strdup(this, name); this->location = -1; @@ -775,7 +793,7 @@ ir_variable::component_slots() const ir_function_signature::ir_function_signature(const glsl_type *return_type) : return_type(return_type), is_defined(false), _function(NULL) { - /* empty */ + this->ir_type = ir_type_function_signature; } @@ -825,6 +843,7 @@ ir_function_signature::replace_parameters(exec_list *new_params) ir_function::ir_function(const char *name) { + this->ir_type = ir_type_function; this->name = talloc_strdup(this, name); } diff --git a/src/glsl/ir.h b/src/glsl/ir.h index 042da94d85..389fe24326 100644 --- a/src/glsl/ir.h +++ b/src/glsl/ir.h @@ -41,11 +41,34 @@ extern "C" { #define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0])) #endif +enum ir_node_type { + ir_type_unset, + ir_type_variable, + ir_type_assignment, + ir_type_call, + ir_type_constant, + ir_type_dereference_array, + ir_type_dereference_record, + ir_type_dereference_variable, + ir_type_discard, + ir_type_expression, + ir_type_function, + ir_type_function_signature, + ir_type_if, + ir_type_loop, + ir_type_loop_jump, + ir_type_return, + ir_type_swizzle, + ir_type_texture, + ir_type_max, /**< maximum ir_type enum number, for validation */ +}; + /** * Base class of all IR instructions */ class ir_instruction : public exec_node { public: + enum ir_node_type ir_type; const struct glsl_type *type; class ir_constant *constant_expression_value(); @@ -84,7 +107,7 @@ public: protected: ir_instruction() { - /* empty */ + ir_type = ir_type_unset; } }; @@ -410,7 +433,7 @@ public: ir_if(ir_rvalue *condition) : condition(condition) { - /* empty */ + ir_type = ir_type_if; } virtual ir_if *clone(struct hash_table *ht) const; @@ -442,7 +465,7 @@ class ir_loop : public ir_instruction { public: ir_loop() : from(NULL), to(NULL), increment(NULL), counter(NULL) { - /* empty */ + ir_type = ir_type_loop; } virtual ir_loop *clone(struct hash_table *ht) const; @@ -664,6 +687,7 @@ public: ir_call(ir_function_signature *callee, exec_list *actual_parameters) : callee(callee) { + ir_type = ir_type_call; assert(callee->return_type != NULL); type = callee->return_type; actual_parameters->move_nodes_to(& this->actual_parameters); @@ -726,7 +750,7 @@ private: ir_call() : callee(NULL) { - /* empty */ + this->ir_type = ir_type_call; } ir_function_signature *callee; @@ -746,7 +770,7 @@ class ir_jump : public ir_instruction { protected: ir_jump() { - /* empty */ + ir_type = ir_type_unset; } }; @@ -755,13 +779,13 @@ public: ir_return() : value(NULL) { - /* empty */ + this->ir_type = ir_type_return; } ir_return(ir_rvalue *value) : value(value) { - /* empty */ + this->ir_type = ir_type_return; } virtual ir_return *clone(struct hash_table *) const; @@ -804,6 +828,7 @@ public: ir_loop_jump(jump_mode mode) { + this->ir_type = ir_type_loop_jump; this->mode = mode; this->loop = loop; } @@ -841,6 +866,7 @@ class ir_discard : public ir_jump { public: ir_discard() { + this->ir_type = ir_type_discard; this->condition = NULL; } @@ -898,7 +924,7 @@ public: ir_texture(enum ir_texture_opcode op) : op(op), projector(NULL), shadow_comparitor(NULL) { - /* empty */ + this->ir_type = ir_type_texture; } virtual ir_texture *clone(struct hash_table *) const; diff --git a/src/glsl/ir_validate.cpp b/src/glsl/ir_validate.cpp index 4284f6b120..8a567954a1 100644 --- a/src/glsl/ir_validate.cpp +++ b/src/glsl/ir_validate.cpp @@ -172,10 +172,25 @@ ir_validate::validate_ir(ir_instruction *ir, void *data) hash_table_insert(ht, ir, ir); } +void +check_node_type(ir_instruction *ir, void *data) +{ + if (ir->ir_type <= ir_type_unset || ir->ir_type >= ir_type_max) { + printf("Instruction node with unset type\n"); + ir->print(); printf("\n"); + } +} + void validate_ir_tree(exec_list *instructions) { ir_validate v; v.run(instructions); + + foreach_iter(exec_list_iterator, iter, *instructions) { + ir_instruction *ir = (ir_instruction *)iter.get(); + + visit_tree(ir, check_node_type, NULL); + } } -- cgit v1.2.3 From fade78edcbff1e0ae24a1e2c455be2cc7932ee9c Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Tue, 20 Jul 2010 17:17:47 -0700 Subject: glsl2: strdup the field names used in dereference_record. Otherwise, after linking and freeing the old data, the pointer would dangle. Partial fix for glsl1-struct*. --- src/glsl/ir.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/glsl/ir.cpp') diff --git a/src/glsl/ir.cpp b/src/glsl/ir.cpp index 1648848ecb..ba8ee7b9ac 100644 --- a/src/glsl/ir.cpp +++ b/src/glsl/ir.cpp @@ -514,7 +514,7 @@ ir_dereference_record::ir_dereference_record(ir_rvalue *value, { this->ir_type = ir_type_dereference_record; this->record = value; - this->field = field; + this->field = talloc_strdup(this, field); this->type = (this->record != NULL) ? this->record->type->field_type(field) : glsl_type::error_type; } @@ -527,7 +527,7 @@ ir_dereference_record::ir_dereference_record(ir_variable *var, this->ir_type = ir_type_dereference_record; this->record = new(ctx) ir_dereference_variable(var); - this->field = field; + this->field = talloc_strdup(this, field); this->type = (this->record != NULL) ? this->record->type->field_type(field) : glsl_type::error_type; } -- cgit v1.2.3 From 7e2aa91507a5883e33473e0a94215ee3985baad1 Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Mon, 19 Jul 2010 17:12:42 -0700 Subject: glsl2: Add and use new variable mode ir_var_temporary This is quite a large patch because breaking it into smaller pieces would result in the tree being intermitently broken. The big changes are: * Add the ir_var_temporary variable mode * Change the ir_variable constructor to take the mode as a parameter and correctly specify the mode for all ir_varables. * Change the linker to not cross validate ir_var_temporary variables. * Change the linker to pull all ir_var_temporary variables from global scope into 'main'. --- src/glsl/ast_function.cpp | 21 +++++++++----- src/glsl/ast_to_hir.cpp | 26 ++++++++++------- src/glsl/glsl_types.cpp | 7 ++--- src/glsl/ir.cpp | 6 ++-- src/glsl/ir.h | 5 ++-- src/glsl/ir_clone.cpp | 4 +-- src/glsl/ir_expression_flattening.cpp | 2 +- src/glsl/ir_function.cpp | 1 + src/glsl/ir_function_inlining.cpp | 3 +- src/glsl/ir_if_return.cpp | 3 +- src/glsl/ir_if_to_cond_assign.cpp | 3 +- src/glsl/ir_mat_op_to_vec.cpp | 3 +- src/glsl/ir_mod_to_fract.cpp | 3 +- src/glsl/ir_reader.cpp | 3 +- src/glsl/ir_variable.cpp | 3 +- src/glsl/ir_vec_index_to_cond_assign.cpp | 12 +++++--- src/glsl/linker.cpp | 50 ++++++++++++++++++++++++++++---- src/mesa/shader/ir_to_mesa.cpp | 1 + 18 files changed, 109 insertions(+), 47 deletions(-) (limited to 'src/glsl/ir.cpp') diff --git a/src/glsl/ast_function.cpp b/src/glsl/ast_function.cpp index 643eb229a7..14c36af911 100644 --- a/src/glsl/ast_function.cpp +++ b/src/glsl/ast_function.cpp @@ -115,7 +115,8 @@ process_call(exec_list *instructions, ir_function *f, var = new(ctx) ir_variable(sig->return_type, talloc_asprintf(ctx, "%s_retval", - sig->function_name())); + sig->function_name()), + ir_var_temporary); instructions->push_tail(var); deref = new(ctx) ir_dereference_variable(var); @@ -509,7 +510,8 @@ emit_inline_vector_constructor(const glsl_type *type, assert(!parameters->is_empty()); ir_variable *var = new(ctx) ir_variable(type, - talloc_strdup(ctx, "vec_ctor")); + talloc_strdup(ctx, "vec_ctor"), + ir_var_temporary); instructions->push_tail(var); /* There are two kinds of vector constructors. @@ -621,7 +623,8 @@ emit_inline_matrix_constructor(const glsl_type *type, assert(!parameters->is_empty()); ir_variable *var = new(ctx) ir_variable(type, - talloc_strdup(ctx, "mat_ctor")); + talloc_strdup(ctx, "mat_ctor"), + ir_var_temporary); instructions->push_tail(var); /* There are three kinds of matrix constructors. @@ -645,7 +648,8 @@ emit_inline_matrix_constructor(const glsl_type *type, */ ir_variable *rhs_var = new(ctx) ir_variable(glsl_type::vec4_type, - talloc_strdup(ctx, "mat_ctor_vec")); + talloc_strdup(ctx, "mat_ctor_vec"), + ir_var_temporary); instructions->push_tail(rhs_var); ir_constant_data zero; @@ -759,7 +763,8 @@ emit_inline_matrix_constructor(const glsl_type *type, */ ir_variable *const rhs_var = new(ctx) ir_variable(first_param->type, - talloc_strdup(ctx, "mat_ctor_mat")); + talloc_strdup(ctx, "mat_ctor_mat"), + ir_var_temporary); instructions->push_tail(rhs_var); ir_dereference *const rhs_var_ref = @@ -825,7 +830,8 @@ emit_inline_matrix_constructor(const glsl_type *type, */ ir_variable *rhs_var = new(ctx) ir_variable(rhs->type, - talloc_strdup(ctx, "mat_ctor_vec")); + talloc_strdup(ctx, "mat_ctor_vec"), + ir_var_temporary); instructions->push_tail(rhs_var); ir_dereference *rhs_var_ref = @@ -1036,7 +1042,8 @@ ast_function_expression::hir(exec_list *instructions, continue; /* Create a temporary containing the matrix. */ - ir_variable *var = new(ctx) ir_variable(matrix->type, "matrix_tmp"); + ir_variable *var = new(ctx) ir_variable(matrix->type, "matrix_tmp", + ir_var_temporary); instructions->push_tail(var); instructions->push_tail(new(ctx) ir_assignment(new(ctx) ir_dereference_variable(var), matrix, NULL)); diff --git a/src/glsl/ast_to_hir.cpp b/src/glsl/ast_to_hir.cpp index f20c7ead33..c68e136256 100644 --- a/src/glsl/ast_to_hir.cpp +++ b/src/glsl/ast_to_hir.cpp @@ -527,7 +527,8 @@ do_assignment(exec_list *instructions, struct _mesa_glsl_parse_state *state, * temporary and return a deref of that temporary. If the rvalue * ends up not being used, the temp will get copy-propagated out. */ - ir_variable *var = new(ctx) ir_variable(rhs->type, "assignment_tmp"); + ir_variable *var = new(ctx) ir_variable(rhs->type, "assignment_tmp", + ir_var_temporary); ir_dereference_variable *deref_var = new(ctx) ir_dereference_variable(var); instructions->push_tail(var); instructions->push_tail(new(ctx) ir_assignment(deref_var, @@ -549,7 +550,8 @@ get_lvalue_copy(exec_list *instructions, ir_rvalue *lvalue) ir_variable *var; /* FINISHME: Give unique names to the temporaries. */ - var = new(ctx) ir_variable(lvalue->type, "_post_incdec_tmp"); + var = new(ctx) ir_variable(lvalue->type, "_post_incdec_tmp", + ir_var_temporary); instructions->push_tail(var); var->mode = ir_var_auto; @@ -806,7 +808,8 @@ ast_expression::hir(exec_list *instructions, type = glsl_type::bool_type; } else { ir_variable *const tmp = new(ctx) ir_variable(glsl_type::bool_type, - "and_tmp"); + "and_tmp", + ir_var_temporary); instructions->push_tail(tmp); ir_if *const stmt = new(ctx) ir_if(op[0]); @@ -870,7 +873,8 @@ ast_expression::hir(exec_list *instructions, type = glsl_type::bool_type; } else { ir_variable *const tmp = new(ctx) ir_variable(glsl_type::bool_type, - "or_tmp"); + "or_tmp", + ir_var_temporary); instructions->push_tail(tmp); ir_if *const stmt = new(ctx) ir_if(op[0]); @@ -1049,7 +1053,8 @@ ast_expression::hir(exec_list *instructions, && (cond_val != NULL) && (then_val != NULL) && (else_val != NULL)) { result = (cond_val->value.b[0]) ? then_val : else_val; } else { - ir_variable *const tmp = new(ctx) ir_variable(type, "conditional_tmp"); + ir_variable *const tmp = + new(ctx) ir_variable(type, "conditional_tmp", ir_var_temporary); instructions->push_tail(tmp); ir_if *const stmt = new(ctx) ir_if(op[0]); @@ -1474,6 +1479,9 @@ apply_type_qualifier_to_variable(const struct ast_type_qualifier *qual, } } + /* If there is no qualifier that changes the mode of the variable, leave + * the setting alone. + */ if (qual->in && qual->out) var->mode = ir_var_inout; else if (qual->attribute || qual->in @@ -1483,8 +1491,6 @@ apply_type_qualifier_to_variable(const struct ast_type_qualifier *qual, var->mode = ir_var_out; else if (qual->uniform) var->mode = ir_var_uniform; - else - var->mode = ir_var_auto; if (qual->uniform) var->shader_in = true; @@ -1633,7 +1639,7 @@ ast_declarator_list::hir(exec_list *instructions, var_type = decl_type; } - var = new(ctx) ir_variable(var_type, decl->identifier); + var = new(ctx) ir_variable(var_type, decl->identifier, ir_var_auto); /* From page 22 (page 28 of the PDF) of the GLSL 1.10 specification; * @@ -1993,7 +1999,7 @@ ast_parameter_declarator::hir(exec_list *instructions, } is_void = false; - ir_variable *var = new(ctx) ir_variable(type, this->identifier); + ir_variable *var = new(ctx) ir_variable(type, this->identifier, ir_var_in); /* FINISHME: Handle array declarations. Note that this requires * FINISHME: complete handling of constant expressions. @@ -2003,8 +2009,6 @@ ast_parameter_declarator::hir(exec_list *instructions, * for function parameters the default mode is 'in'. */ apply_type_qualifier_to_variable(& this->type->qualifier, var, state, & loc); - if (var->mode == ir_var_auto) - var->mode = ir_var_in; instructions->push_tail(var); diff --git a/src/glsl/glsl_types.cpp b/src/glsl/glsl_types.cpp index 77c591ed69..5cb327c89d 100644 --- a/src/glsl/glsl_types.cpp +++ b/src/glsl/glsl_types.cpp @@ -251,10 +251,9 @@ glsl_type::generate_constructor(glsl_symbol_table *symtab) const snprintf(param_name, 10, "p%08X", i); ir_variable *var = (this->base_type == GLSL_TYPE_ARRAY) - ? new(ctx) ir_variable(fields.array, param_name) - : new(ctx) ir_variable(fields.structure[i].type, param_name); + ? new(ctx) ir_variable(fields.array, param_name, ir_var_in) + : new(ctx) ir_variable(fields.structure[i].type, param_name, ir_var_in); - var->mode = ir_var_in; declarations[i] = var; sig->parameters.push_tail(var); } @@ -264,7 +263,7 @@ glsl_type::generate_constructor(glsl_symbol_table *symtab) const * the same type as the constructor. After initializing __retval, * __retval is returned. */ - ir_variable *retval = new(ctx) ir_variable(this, "__retval"); + ir_variable *retval = new(ctx) ir_variable(this, "__retval", ir_var_auto); sig->body.push_tail(retval); for (unsigned i = 0; i < length; i++) { diff --git a/src/glsl/ir.cpp b/src/glsl/ir.cpp index ba8ee7b9ac..146ff17af3 100644 --- a/src/glsl/ir.cpp +++ b/src/glsl/ir.cpp @@ -748,10 +748,12 @@ ir_swizzle::variable_referenced() return this->val->variable_referenced(); } -ir_variable::ir_variable(const struct glsl_type *type, const char *name) + +ir_variable::ir_variable(const struct glsl_type *type, const char *name, + ir_variable_mode mode) : max_array_access(0), read_only(false), centroid(false), invariant(false), shader_in(false), shader_out(false), - mode(ir_var_auto), interpolation(ir_var_smooth), array_lvalue(false) + mode(mode), interpolation(ir_var_smooth), array_lvalue(false) { this->ir_type = ir_type_variable; this->type = type; diff --git a/src/glsl/ir.h b/src/glsl/ir.h index 3be096270d..9fd9850391 100644 --- a/src/glsl/ir.h +++ b/src/glsl/ir.h @@ -162,7 +162,8 @@ enum ir_variable_mode { ir_var_uniform, ir_var_in, ir_var_out, - ir_var_inout + ir_var_inout, + ir_var_temporary /**< Temporary variable generated during compilation. */ }; enum ir_variable_interpolation { @@ -174,7 +175,7 @@ enum ir_variable_interpolation { class ir_variable : public ir_instruction { public: - ir_variable(const struct glsl_type *, const char *); + ir_variable(const struct glsl_type *, const char *, ir_variable_mode); virtual ir_variable *clone(struct hash_table *ht) const; diff --git a/src/glsl/ir_clone.cpp b/src/glsl/ir_clone.cpp index 91d6977354..f7e8794728 100644 --- a/src/glsl/ir_clone.cpp +++ b/src/glsl/ir_clone.cpp @@ -39,7 +39,8 @@ ir_variable * ir_variable::clone(struct hash_table *ht) const { void *ctx = talloc_parent(this); - ir_variable *var = new(ctx) ir_variable(type, name); + ir_variable *var = new(ctx) ir_variable(this->type, this->name, + (ir_variable_mode) this->mode); var->max_array_access = this->max_array_access; var->read_only = this->read_only; @@ -47,7 +48,6 @@ ir_variable::clone(struct hash_table *ht) const var->invariant = this->invariant; var->shader_in = this->shader_in; var->shader_out = this->shader_out; - var->mode = this->mode; var->interpolation = this->interpolation; var->array_lvalue = this->array_lvalue; var->location = this->location; diff --git a/src/glsl/ir_expression_flattening.cpp b/src/glsl/ir_expression_flattening.cpp index f18659342f..6dbebc6378 100644 --- a/src/glsl/ir_expression_flattening.cpp +++ b/src/glsl/ir_expression_flattening.cpp @@ -89,7 +89,7 @@ ir_expression_flattening_visitor::operand_to_temp(ir_rvalue *ir) if (!this->predicate(ir)) return ir; - var = new(ctx) ir_variable(ir->type, "flattening_tmp"); + var = new(ctx) ir_variable(ir->type, "flattening_tmp", ir_var_temporary); base_ir->insert_before(var); assign = new(ctx) ir_assignment(new(ctx) ir_dereference_variable(var), diff --git a/src/glsl/ir_function.cpp b/src/glsl/ir_function.cpp index e85b18ce02..28a5c399f1 100644 --- a/src/glsl/ir_function.cpp +++ b/src/glsl/ir_function.cpp @@ -116,6 +116,7 @@ parameter_lists_match(const exec_list *list_a, const exec_list *list_b) switch ((enum ir_variable_mode)(param->mode)) { case ir_var_auto: case ir_var_uniform: + case ir_var_temporary: /* These are all error conditions. It is invalid for a parameter to * a function to be declared as auto (not in, out, or inout) or * as uniform. diff --git a/src/glsl/ir_function_inlining.cpp b/src/glsl/ir_function_inlining.cpp index a3f7089cdc..05dd83f7ff 100644 --- a/src/glsl/ir_function_inlining.cpp +++ b/src/glsl/ir_function_inlining.cpp @@ -122,7 +122,8 @@ ir_call::generate_inline(ir_instruction *next_ir) /* Generate storage for the return value. */ if (this->callee->return_type) { - retval = new(ctx) ir_variable(this->callee->return_type, "__retval"); + retval = new(ctx) ir_variable(this->callee->return_type, "__retval", + ir_var_auto); next_ir->insert_before(retval); } diff --git a/src/glsl/ir_if_return.cpp b/src/glsl/ir_if_return.cpp index f68dcfb501..a9af7166b9 100644 --- a/src/glsl/ir_if_return.cpp +++ b/src/glsl/ir_if_return.cpp @@ -102,7 +102,8 @@ ir_if_return_visitor::visit_enter(ir_if *ir) } else { ir_assignment *assign; ir_variable *new_var = new(ir) ir_variable(then_return->value->type, - "if_return_tmp"); + "if_return_tmp", + ir_var_temporary); ir->insert_before(new_var); assign = new(ir) ir_assignment(new(ir) ir_dereference_variable(new_var), diff --git a/src/glsl/ir_if_to_cond_assign.cpp b/src/glsl/ir_if_to_cond_assign.cpp index 274874bbb7..0b87413941 100644 --- a/src/glsl/ir_if_to_cond_assign.cpp +++ b/src/glsl/ir_if_to_cond_assign.cpp @@ -145,7 +145,8 @@ ir_if_to_cond_assign_visitor::visit_leave(ir_if *ir) * simpler. */ cond_var = new(mem_ctx) ir_variable(glsl_type::bool_type, - "if_to_cond_assign_condition"); + "if_to_cond_assign_condition", + ir_var_temporary); ir->insert_before(cond_var); deref = new(mem_ctx) ir_dereference_variable(cond_var); diff --git a/src/glsl/ir_mat_op_to_vec.cpp b/src/glsl/ir_mat_op_to_vec.cpp index 7bdb9057d8..742fc2a295 100644 --- a/src/glsl/ir_mat_op_to_vec.cpp +++ b/src/glsl/ir_mat_op_to_vec.cpp @@ -298,7 +298,8 @@ ir_mat_op_to_vec_visitor::visit_leave(ir_assignment *assign) ir_assignment *assign; op_var[i] = new(base_ir) ir_variable(expr->operands[i]->type, - "mat_op_to_vec"); + "mat_op_to_vec", + ir_var_temporary); base_ir->insert_before(op_var[i]); lhs_deref = new(base_ir) ir_dereference_variable(op_var[i]); diff --git a/src/glsl/ir_mod_to_fract.cpp b/src/glsl/ir_mod_to_fract.cpp index ec1e65092d..71c9472b12 100644 --- a/src/glsl/ir_mod_to_fract.cpp +++ b/src/glsl/ir_mod_to_fract.cpp @@ -60,7 +60,8 @@ ir_mod_to_fract_visitor::visit_leave(ir_expression *ir) if (ir->operation != ir_binop_mod) return visit_continue; - ir_variable *temp = new(ir) ir_variable(ir->operands[1]->type, "mod_b"); + ir_variable *temp = new(ir) ir_variable(ir->operands[1]->type, "mod_b", + ir_var_temporary); this->base_ir->insert_before(temp); ir_assignment *assign; diff --git a/src/glsl/ir_reader.cpp b/src/glsl/ir_reader.cpp index a1e5a7ad74..ed68496587 100644 --- a/src/glsl/ir_reader.cpp +++ b/src/glsl/ir_reader.cpp @@ -401,7 +401,8 @@ read_declaration(_mesa_glsl_parse_state *st, s_list *list) return NULL; } - ir_variable *var = new(ctx) ir_variable(type, var_name->value()); + ir_variable *var = new(ctx) ir_variable(type, var_name->value(), + ir_var_auto); foreach_iter(exec_list_iterator, it, quals->subexpressions) { s_symbol *qualifier = SX_AS_SYMBOL(it.get()); diff --git a/src/glsl/ir_variable.cpp b/src/glsl/ir_variable.cpp index 4593c18112..700c5de648 100644 --- a/src/glsl/ir_variable.cpp +++ b/src/glsl/ir_variable.cpp @@ -39,9 +39,8 @@ add_variable(const char *name, enum ir_variable_mode mode, int slot, const glsl_type *type, exec_list *instructions, glsl_symbol_table *symtab) { - ir_variable *var = new(symtab) ir_variable(type, name); + ir_variable *var = new(symtab) ir_variable(type, name, mode); - var->mode = mode; switch (var->mode) { case ir_var_auto: var->read_only = true; diff --git a/src/glsl/ir_vec_index_to_cond_assign.cpp b/src/glsl/ir_vec_index_to_cond_assign.cpp index ac420454e8..7e04389b5f 100644 --- a/src/glsl/ir_vec_index_to_cond_assign.cpp +++ b/src/glsl/ir_vec_index_to_cond_assign.cpp @@ -86,14 +86,16 @@ ir_vec_index_to_cond_assign_visitor::convert_vec_index_to_cond_assign(ir_rvalue /* Store the index to a temporary to avoid reusing its tree. */ index = new(base_ir) ir_variable(glsl_type::int_type, - "vec_index_tmp_i"); + "vec_index_tmp_i", + ir_var_temporary); base_ir->insert_before(index); deref = new(base_ir) ir_dereference_variable(index); assign = new(base_ir) ir_assignment(deref, orig_deref->array_index, NULL); base_ir->insert_before(assign); /* Temporary where we store whichever value we swizzle out. */ - var = new(base_ir) ir_variable(ir->type, "vec_index_tmp_v"); + var = new(base_ir) ir_variable(ir->type, "vec_index_tmp_v", + ir_var_temporary); base_ir->insert_before(var); /* Generate a conditional move of each vector element to the temp. */ @@ -166,14 +168,16 @@ ir_vec_index_to_cond_assign_visitor::visit_leave(ir_assignment *ir) assert(orig_deref->array_index->type->base_type == GLSL_TYPE_INT); /* Store the index to a temporary to avoid reusing its tree. */ - index = new(ir) ir_variable(glsl_type::int_type, "vec_index_tmp_i"); + index = new(ir) ir_variable(glsl_type::int_type, "vec_index_tmp_i", + ir_var_temporary); ir->insert_before(index); deref = new(ir) ir_dereference_variable(index); assign = new(ir) ir_assignment(deref, orig_deref->array_index, NULL); ir->insert_before(assign); /* Store the RHS to a temporary to avoid reusing its tree. */ - var = new(ir) ir_variable(ir->rhs->type, "vec_index_tmp_v"); + var = new(ir) ir_variable(ir->rhs->type, "vec_index_tmp_v", + ir_var_temporary); ir->insert_before(var); deref = new(ir) ir_dereference_variable(var); assign = new(ir) ir_assignment(deref, ir->rhs, NULL); diff --git a/src/glsl/linker.cpp b/src/glsl/linker.cpp index 4869dbe1ca..eb4eb9d20e 100644 --- a/src/glsl/linker.cpp +++ b/src/glsl/linker.cpp @@ -246,6 +246,8 @@ mode_string(const ir_variable *var) case ir_var_in: return "shader input"; case ir_var_out: return "shader output"; case ir_var_inout: return "shader inout"; + + case ir_var_temporary: default: assert(!"Should not get here."); return "invalid variable"; @@ -276,6 +278,12 @@ cross_validate_globals(struct gl_shader_program *prog, if (uniforms_only && (var->mode != ir_var_uniform)) continue; + /* Don't cross validate temporaries that are at global scope. These + * will eventually get pulled into the shaders 'main'. + */ + if (var->mode == ir_var_temporary) + continue; + /* If a global with this name has already been seen, verify that the * new instance has the same type. In addition, if the globals have * initializers, the values of the initializers must be the same. @@ -480,18 +488,28 @@ populate_symbol_table(gl_shader *sh) */ void remap_variables(ir_instruction *inst, glsl_symbol_table *symbols, - exec_list *instructions) + exec_list *instructions, hash_table *temps) { class remap_visitor : public ir_hierarchical_visitor { public: - remap_visitor(glsl_symbol_table *symbols, exec_list *instructions) + remap_visitor(glsl_symbol_table *symbols, exec_list *instructions, + hash_table *temps) { this->symbols = symbols; this->instructions = instructions; + this->temps = temps; } virtual ir_visitor_status visit(ir_dereference_variable *ir) { + if (ir->var->mode == ir_var_temporary) { + ir_variable *var = (ir_variable *) hash_table_find(temps, ir->var); + + assert(var != NULL); + ir->var = var; + return visit_continue; + } + ir_variable *const existing = this->symbols->get_variable(ir->var->name); if (existing != NULL) @@ -501,6 +519,7 @@ remap_variables(ir_instruction *inst, glsl_symbol_table *symbols, this->symbols->add_variable(copy->name, copy); this->instructions->push_head(copy); + ir->var = copy; } return visit_continue; @@ -509,9 +528,10 @@ remap_variables(ir_instruction *inst, glsl_symbol_table *symbols, private: glsl_symbol_table *symbols; exec_list *instructions; + hash_table *temps; }; - remap_visitor v(symbols, instructions); + remap_visitor v(symbols, instructions, temps); inst->accept(&v); } @@ -542,17 +562,32 @@ exec_node * move_non_declarations(exec_list *instructions, exec_node *last, bool make_copies, gl_shader *target) { + hash_table *temps = NULL; + + if (make_copies) + temps = hash_table_ctor(0, hash_table_pointer_hash, + hash_table_pointer_compare); + foreach_list_safe(node, instructions) { ir_instruction *inst = (ir_instruction *) node; - if (inst->as_variable() || inst->as_function()) + if (inst->as_function()) + continue; + + ir_variable *var = inst->as_variable(); + if ((var != NULL) && (var->mode != ir_var_temporary)) continue; - assert(inst->as_assignment()); + assert(inst->as_assignment() + || ((var != NULL) && (var->mode == ir_var_temporary))); if (make_copies) { inst = inst->clone(NULL); - remap_variables(inst, target->symbols, target->ir); + + if (var != NULL) + hash_table_insert(temps, inst, var); + else + remap_variables(inst, target->symbols, target->ir, temps); } else { inst->remove(); } @@ -561,6 +596,9 @@ move_non_declarations(exec_list *instructions, exec_node *last, last = inst; } + if (make_copies) + hash_table_dtor(temps); + return last; } diff --git a/src/mesa/shader/ir_to_mesa.cpp b/src/mesa/shader/ir_to_mesa.cpp index 352b496625..7cc469f3a7 100644 --- a/src/mesa/shader/ir_to_mesa.cpp +++ b/src/mesa/shader/ir_to_mesa.cpp @@ -1133,6 +1133,7 @@ ir_to_mesa_visitor::visit(ir_dereference_variable *ir) break; case ir_var_auto: + case ir_var_temporary: entry = new(mem_ctx) variable_storage(ir->var, PROGRAM_TEMPORARY, this->next_temp); this->variables.push_tail(entry); -- cgit v1.2.3 From 60e2d06d1ccc66ad00cd7ab81c418853f21be291 Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Tue, 20 Jul 2010 11:27:38 -0700 Subject: glsl2: Implement utility routine to talloc reparent an IR tree --- src/glsl/ir.cpp | 15 +++++++++++++++ src/glsl/ir.h | 3 +++ src/glsl/main.cpp | 10 +--------- src/mesa/shader/ir_to_mesa.cpp | 10 +--------- 4 files changed, 20 insertions(+), 18 deletions(-) (limited to 'src/glsl/ir.cpp') diff --git a/src/glsl/ir.cpp b/src/glsl/ir.cpp index 146ff17af3..a2732962f0 100644 --- a/src/glsl/ir.cpp +++ b/src/glsl/ir.cpp @@ -875,3 +875,18 @@ visit_exec_list(exec_list *list, ir_visitor *visitor) } } + +static void +steal_memory(ir_instruction *ir, void *new_ctx) +{ + talloc_steal(new_ctx, ir); +} + + +void +reparent_ir(exec_list *list, void *mem_ctx) +{ + foreach_list(node, list) { + visit_tree((ir_instruction *) node, steal_memory, mem_ctx); + } +} diff --git a/src/glsl/ir.h b/src/glsl/ir.h index 9fd9850391..e4b0e9f082 100644 --- a/src/glsl/ir.h +++ b/src/glsl/ir.h @@ -1315,4 +1315,7 @@ extern void _mesa_glsl_initialize_functions(exec_list *instructions, struct _mesa_glsl_parse_state *state); +extern void +reparent_ir(exec_list *list, void *mem_ctx); + #endif /* IR_H */ diff --git a/src/glsl/main.cpp b/src/glsl/main.cpp index 6b1a01c704..cf9a515785 100644 --- a/src/glsl/main.cpp +++ b/src/glsl/main.cpp @@ -118,12 +118,6 @@ const struct option compiler_opts[] = { { NULL, 0, NULL, 0 } }; -static void -steal_memory(ir_instruction *ir, void *new_ctx) -{ - talloc_steal(new_ctx, ir); -} - void compile_shader(struct gl_shader *shader) { @@ -232,9 +226,7 @@ compile_shader(struct gl_shader *shader) shader->InfoLog = state->info_log; /* Retain any live IR, but trash the rest. */ - foreach_list(node, shader->ir) { - visit_tree((ir_instruction *) node, steal_memory, shader); - } + reparent_ir(shader->ir, shader); talloc_free(state); diff --git a/src/mesa/shader/ir_to_mesa.cpp b/src/mesa/shader/ir_to_mesa.cpp index 1a9b0e3948..d1c09febd6 100644 --- a/src/mesa/shader/ir_to_mesa.cpp +++ b/src/mesa/shader/ir_to_mesa.cpp @@ -2146,12 +2146,6 @@ get_mesa_program(GLcontext *ctx, struct gl_shader_program *shader_program, extern "C" { -static void -steal_memory(ir_instruction *ir, void *new_ctx) -{ - talloc_steal(new_ctx, ir); -} - void _mesa_glsl_compile_shader(GLcontext *ctx, struct gl_shader *shader) { @@ -2215,9 +2209,7 @@ _mesa_glsl_compile_shader(GLcontext *ctx, struct gl_shader *shader) shader->Version = state->language_version; /* Retain any live IR, but trash the rest. */ - foreach_list(node, shader->ir) { - visit_tree((ir_instruction *) node, steal_memory, shader); - } + reparent_ir(shader->ir, shader); talloc_free(state); } -- cgit v1.2.3 From 74e1802f5dd8921750851abc6128e4073602d405 Mon Sep 17 00:00:00 2001 From: Kenneth Graunke Date: Tue, 20 Jul 2010 01:06:33 -0700 Subject: glsl2: Extend ir_constant to store constant arrays, and generate them. Since GLSL permits arrays of structures, we need to store each element as an ir_constant*, not just ir_constant_data. Fixes parser tests const-array-01.frag, const-array-03.frag, const-array-04.frag, const-array-05.frag, though 03 and 04 generate the wrong code. --- src/glsl/ast_function.cpp | 5 ++--- src/glsl/ir.cpp | 23 +++++++++++++++++++++-- src/glsl/ir.h | 6 ++++++ src/glsl/ir_clone.cpp | 11 +++++++++++ 4 files changed, 40 insertions(+), 5 deletions(-) (limited to 'src/glsl/ir.cpp') diff --git a/src/glsl/ast_function.cpp b/src/glsl/ast_function.cpp index 1982c83a43..855f27f175 100644 --- a/src/glsl/ast_function.cpp +++ b/src/glsl/ast_function.cpp @@ -358,9 +358,8 @@ process_array_constructor(exec_list *instructions, ir->replace_with(result); } - if (all_parameters_are_constant) { - /* FINISHME: Add support for generating constant arrays. */ - } + if (all_parameters_are_constant) + return new(ctx) ir_constant(constructor_type, &actual_parameters); ir_variable *var = new(ctx) ir_variable(constructor_type, "array_ctor", ir_var_temporary); diff --git a/src/glsl/ir.cpp b/src/glsl/ir.cpp index a2732962f0..d3f7302b54 100644 --- a/src/glsl/ir.cpp +++ b/src/glsl/ir.cpp @@ -253,9 +253,20 @@ ir_constant::ir_constant(const struct glsl_type *type, exec_list *value_list) this->ir_type = ir_type_constant; this->type = type; - /* FINISHME: Support array types. */ assert(type->is_scalar() || type->is_vector() || type->is_matrix() - || type->is_record()); + || type->is_record() || type->is_array()); + + if (type->is_array()) { + this->array_elements = talloc_array(this, ir_constant *, type->length); + unsigned i = 0; + foreach_list(node, value_list) { + ir_constant *value = (ir_constant *) node; + assert(value->as_constant() != NULL); + + this->array_elements[i++] = value; + } + return; + } /* If the constant is a record, the types of each of the entries in * value_list must be a 1-for-1 match with the structure components. Each @@ -378,6 +389,14 @@ ir_constant::get_uint_component(unsigned i) const return 0; } +ir_constant * +ir_constant::get_array_element(unsigned i) const +{ + assert(this->type->is_array()); + assert(i < this->type->length); + + return array_elements[i]; +} ir_constant * ir_constant::get_record_field(const char *name) diff --git a/src/glsl/ir.h b/src/glsl/ir.h index 3a643fc580..c73bf4ce8b 100644 --- a/src/glsl/ir.h +++ b/src/glsl/ir.h @@ -1268,6 +1268,8 @@ public: unsigned get_uint_component(unsigned i) const; /*@}*/ + ir_constant *get_array_element(unsigned i) const; + ir_constant *get_record_field(const char *name); /** @@ -1284,6 +1286,10 @@ public: */ union ir_constant_data value; + /* Array elements */ + ir_constant **array_elements; + + /* Structure fields */ exec_list components; private: diff --git a/src/glsl/ir_clone.cpp b/src/glsl/ir_clone.cpp index f7e8794728..a3e4a3ae31 100644 --- a/src/glsl/ir_clone.cpp +++ b/src/glsl/ir_clone.cpp @@ -337,6 +337,17 @@ ir_constant::clone(struct hash_table *ht) const return c; } + case GLSL_TYPE_ARRAY: { + ir_constant *c = new(ctx) ir_constant; + + c->type = this->type; + c->array_elements = talloc_array(c, ir_constant *, this->type->length); + for (unsigned i = 0; i < this->type->length; i++) { + c->array_elements[i] = this->array_elements[i]->clone(NULL); + } + return c; + } + default: assert(!"Should not get here."); break; return NULL; -- cgit v1.2.3 From 9a6d40fbfb679f01412c1fcc9d767c20a22246d8 Mon Sep 17 00:00:00 2001 From: Kenneth Graunke Date: Tue, 20 Jul 2010 03:08:32 -0700 Subject: ir_constant_expression: Add support for array == and !=. Piglit parser tests const-array-03.frag and const-array-04.frag now generate the correct code. --- src/glsl/ir.cpp | 11 ++++++++--- src/glsl/ir_constant_expression.cpp | 17 ++++++++++++++++- 2 files changed, 24 insertions(+), 4 deletions(-) (limited to 'src/glsl/ir.cpp') diff --git a/src/glsl/ir.cpp b/src/glsl/ir.cpp index d3f7302b54..5054ec725c 100644 --- a/src/glsl/ir.cpp +++ b/src/glsl/ir.cpp @@ -430,9 +430,14 @@ ir_constant::has_value(const ir_constant *c) const if (this->type != c->type) return false; - /* FINISHME: This will probably also handle constant arrays as soon as those - * FINISHME: are supported. - */ + if (this->type->is_array()) { + for (unsigned i = 0; i < this->type->length; i++) { + if (this->array_elements[i]->has_value(c->array_elements[i])) + return false; + } + return true; + } + if (this->type->base_type == GLSL_TYPE_STRUCT) { const exec_node *a_node = this->components.head; const exec_node *b_node = c->components.head; diff --git a/src/glsl/ir_constant_expression.cpp b/src/glsl/ir_constant_expression.cpp index d72a57c66a..5bef17c755 100644 --- a/src/glsl/ir_constant_expression.cpp +++ b/src/glsl/ir_constant_expression.cpp @@ -73,6 +73,22 @@ ir_expression::constant_expression_value() components = op[1]->type->components(); } + void *ctx = talloc_parent(this); + + /* Handle array operations here, rather than below. */ + if (op[0]->type->is_array()) { + assert(op[1] != NULL && op[1]->type->is_array()); + switch (this->operation) { + case ir_binop_equal: + return new(ctx) ir_constant(op[0]->has_value(op[1])); + case ir_binop_nequal: + return new(ctx) ir_constant(!op[0]->has_value(op[1])); + default: + break; + } + return NULL; + } + switch (this->operation) { case ir_unop_logic_not: assert(op[0]->type->base_type == GLSL_TYPE_BOOL); @@ -616,7 +632,6 @@ ir_expression::constant_expression_value() return NULL; } - void *ctx = talloc_parent(this); return new(ctx) ir_constant(this->type, &data); } -- cgit v1.2.3 From 0a89175a35ba3ac2a94d0ba9bcc9926edc8927e3 Mon Sep 17 00:00:00 2001 From: Kenneth Graunke Date: Thu, 22 Jul 2010 16:45:37 -0700 Subject: glsl2: Initialize ir_instruction::type and ir_rvalue::type. Top-level instructions now get NULL as their default type (since type is irrelevant for things like ir_function), while ir_rvalues get error_type by default. This should make it easier to tell if we've forgotten to set a type. It also fixes some "Conditional jump or move depends on uninitialized value" errors in valgrind caused by ir_validate examining the type of top level ir_instructions, which weren't set. --- src/glsl/ir.cpp | 5 +++++ src/glsl/ir.h | 6 ++---- 2 files changed, 7 insertions(+), 4 deletions(-) (limited to 'src/glsl/ir.cpp') diff --git a/src/glsl/ir.cpp b/src/glsl/ir.cpp index 5054ec725c..8ebef7d95a 100644 --- a/src/glsl/ir.cpp +++ b/src/glsl/ir.cpp @@ -26,6 +26,11 @@ #include "ir_visitor.h" #include "glsl_types.h" +ir_rvalue::ir_rvalue() +{ + this->type = glsl_type::error_type; +} + ir_assignment::ir_assignment(ir_rvalue *lhs, ir_rvalue *rhs, ir_rvalue *condition) { diff --git a/src/glsl/ir.h b/src/glsl/ir.h index 3fd3a7660b..e0f3683a7a 100644 --- a/src/glsl/ir.h +++ b/src/glsl/ir.h @@ -106,6 +106,7 @@ protected: ir_instruction() { ir_type = ir_type_unset; + type = NULL; } }; @@ -150,10 +151,7 @@ public: } protected: - ir_rvalue() - { - /* empty */ - } + ir_rvalue(); }; -- cgit v1.2.3 From eb2cc4f1b1f5ac657c632aa41da5f23eb1cdbe10 Mon Sep 17 00:00:00 2001 From: Kenneth Graunke Date: Fri, 23 Jul 2010 12:49:17 -0700 Subject: glsl2: Steal ir_variable's constant_value field. Fixes a link-time crash in glsl-vs-cross-3. --- src/glsl/ir.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src/glsl/ir.cpp') diff --git a/src/glsl/ir.cpp b/src/glsl/ir.cpp index 8ebef7d95a..2fd654e9bf 100644 --- a/src/glsl/ir.cpp +++ b/src/glsl/ir.cpp @@ -908,6 +908,9 @@ visit_exec_list(exec_list *list, ir_visitor *visitor) static void steal_memory(ir_instruction *ir, void *new_ctx) { + ir_variable *var = ir->as_variable(); + if (var != NULL && var->constant_value != NULL) + talloc_steal(ir, var->constant_value); talloc_steal(new_ctx, ir); } -- cgit v1.2.3 From fbaca31352678ab7d7bf132f0c9a6aa29ca9fabf Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 26 Jul 2010 19:26:53 -0700 Subject: glsl2: Also steal the constant components of aggregate-typed ir_constants. --- src/glsl/ir.cpp | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'src/glsl/ir.cpp') diff --git a/src/glsl/ir.cpp b/src/glsl/ir.cpp index 2fd654e9bf..6dccbd806e 100644 --- a/src/glsl/ir.cpp +++ b/src/glsl/ir.cpp @@ -909,8 +909,26 @@ static void steal_memory(ir_instruction *ir, void *new_ctx) { ir_variable *var = ir->as_variable(); + ir_constant *constant = ir->as_constant(); if (var != NULL && var->constant_value != NULL) talloc_steal(ir, var->constant_value); + + /* The components of aggregate constants are not visited by the normal + * visitor, so steal their values by hand. + */ + if (constant != NULL) { + if (constant->type->is_record()) { + foreach_iter(exec_list_iterator, iter, constant->components) { + ir_constant *field = (ir_constant *)iter.get(); + steal_memory(field, ir); + } + } else if (constant->type->is_array()) { + for (unsigned int i = 0; i < constant->type->length; i++) { + steal_memory(constant->array_elements[i], ir); + } + } + } + talloc_steal(new_ctx, ir); } -- cgit v1.2.3 From f9b0e5e322a676cf778dc3785281040fcc0bd248 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Tue, 27 Jul 2010 15:25:07 -0700 Subject: glsl2: When stealing var->constant_value, steal its children as well. Fixes: glsl1-GLSL 1.20 uniform array constructor --- src/glsl/ir.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/glsl/ir.cpp') diff --git a/src/glsl/ir.cpp b/src/glsl/ir.cpp index 6dccbd806e..c75d560c48 100644 --- a/src/glsl/ir.cpp +++ b/src/glsl/ir.cpp @@ -911,7 +911,7 @@ steal_memory(ir_instruction *ir, void *new_ctx) ir_variable *var = ir->as_variable(); ir_constant *constant = ir->as_constant(); if (var != NULL && var->constant_value != NULL) - talloc_steal(ir, var->constant_value); + steal_memory(var->constant_value, ir); /* The components of aggregate constants are not visited by the normal * visitor, so steal their values by hand. -- cgit v1.2.3 From ee9a3a51b61f0afe75b4b8b0c3025310140437ec Mon Sep 17 00:00:00 2001 From: Kenneth Graunke Date: Wed, 21 Jul 2010 15:54:15 -0700 Subject: glsl2: Add new ir_constant::zero static method. This conveniently creates a zero value of whatever type you want. --- src/glsl/ir.cpp | 12 ++++++++++++ src/glsl/ir.h | 5 +++++ 2 files changed, 17 insertions(+) (limited to 'src/glsl/ir.cpp') diff --git a/src/glsl/ir.cpp b/src/glsl/ir.cpp index c75d560c48..bb58d95624 100644 --- a/src/glsl/ir.cpp +++ b/src/glsl/ir.cpp @@ -326,6 +326,18 @@ ir_constant::ir_constant(const struct glsl_type *type, exec_list *value_list) } } +ir_constant * +ir_constant::zero(void *mem_ctx, const glsl_type *type) +{ + assert(type->is_numeric()); + + ir_constant *c = new(mem_ctx) ir_constant; + c->type = type; + memset(&c->value, 0, sizeof(c->value)); + + return c; +} + bool ir_constant::get_bool_component(unsigned i) const { diff --git a/src/glsl/ir.h b/src/glsl/ir.h index 202685d145..bee9f6a2de 100644 --- a/src/glsl/ir.h +++ b/src/glsl/ir.h @@ -1248,6 +1248,11 @@ public: */ ir_constant(const ir_constant *c, unsigned i); + /** + * Return a new ir_constant of the specified type containing all zeros. + */ + static ir_constant *zero(void *mem_ctx, const glsl_type *type); + virtual ir_constant *clone(struct hash_table *) const; virtual ir_constant *constant_expression_value(); -- cgit v1.2.3 From 62c4763b707e2227409f81b09dd5cf6e4410ea6a Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Thu, 29 Jul 2010 13:52:25 -0700 Subject: glsl2: Fix spelling of "sentinel." --- src/glsl/ast_function.cpp | 6 +++--- src/glsl/ir.cpp | 8 ++++---- src/glsl/ir_clone.cpp | 2 +- src/glsl/ir_function.cpp | 10 +++++----- src/glsl/ir_function_inlining.cpp | 2 +- src/glsl/linker.cpp | 2 +- src/glsl/list.h | 32 ++++++++++++++++---------------- 7 files changed, 31 insertions(+), 31 deletions(-) (limited to 'src/glsl/ir.cpp') diff --git a/src/glsl/ast_function.cpp b/src/glsl/ast_function.cpp index bb45e2530d..bbc3bc1a59 100644 --- a/src/glsl/ast_function.cpp +++ b/src/glsl/ast_function.cpp @@ -398,7 +398,7 @@ constant_record_constructor(const glsl_type *constructor_type, for (unsigned i = 0; i < constructor_type->length; i++) { ir_instruction *ir = (ir_instruction *) node; - if (node->is_tail_sentinal()) { + if (node->is_tail_sentinel()) { _mesa_glsl_error(loc, state, "insufficient parameters to constructor for `%s'", constructor_type->name); @@ -531,7 +531,7 @@ single_scalar_parameter(exec_list *parameters) const ir_rvalue *const p = (ir_rvalue *) parameters->head; assert(((ir_rvalue *)p)->as_rvalue() != NULL); - return (p->type->is_scalar() && p->next->is_tail_sentinal()); + return (p->type->is_scalar() && p->next->is_tail_sentinel()); } @@ -763,7 +763,7 @@ emit_inline_matrix_constructor(const glsl_type *type, * identity matrix. If a matrix argument is given to a matrix * constructor, it is an error to have any other arguments." */ - assert(first_param->next->is_tail_sentinal()); + assert(first_param->next->is_tail_sentinel()); ir_rvalue *const src_matrix = first_param; /* If the source matrix is smaller, pre-initialize the relavent parts of diff --git a/src/glsl/ir.cpp b/src/glsl/ir.cpp index bb58d95624..7178c68e6b 100644 --- a/src/glsl/ir.cpp +++ b/src/glsl/ir.cpp @@ -295,7 +295,7 @@ ir_constant::ir_constant(const struct glsl_type *type, exec_list *value_list) */ for (unsigned i = 0; i < type->components(); /* empty */) { assert(value->as_constant() != NULL); - assert(!value->is_tail_sentinal()); + assert(!value->is_tail_sentinel()); for (unsigned j = 0; j < value->type->components(); j++) { switch (type->base_type) { @@ -433,7 +433,7 @@ ir_constant::get_record_field(const char *name) /* If the end of the list is encountered before the element matching the * requested field is found, return NULL. */ - if (node->is_tail_sentinal()) + if (node->is_tail_sentinel()) return NULL; } @@ -459,8 +459,8 @@ ir_constant::has_value(const ir_constant *c) const const exec_node *a_node = this->components.head; const exec_node *b_node = c->components.head; - while (!a_node->is_tail_sentinal()) { - assert(!b_node->is_tail_sentinal()); + while (!a_node->is_tail_sentinel()) { + assert(!b_node->is_tail_sentinel()); const ir_constant *const a_field = (ir_constant *) a_node; const ir_constant *const b_field = (ir_constant *) b_node; diff --git a/src/glsl/ir_clone.cpp b/src/glsl/ir_clone.cpp index f97080d205..6be3e59a95 100644 --- a/src/glsl/ir_clone.cpp +++ b/src/glsl/ir_clone.cpp @@ -330,7 +330,7 @@ ir_constant::clone(struct hash_table *ht) const c->type = this->type; for (exec_node *node = this->components.head - ; !node->is_tail_sentinal() + ; !node->is_tail_sentinel() ; node = node->next) { ir_constant *const orig = (ir_constant *) node; diff --git a/src/glsl/ir_function.cpp b/src/glsl/ir_function.cpp index 28a5c399f1..0a97e01424 100644 --- a/src/glsl/ir_function.cpp +++ b/src/glsl/ir_function.cpp @@ -94,13 +94,13 @@ parameter_lists_match(const exec_list *list_a, const exec_list *list_b) int total_score = 0; for (/* empty */ - ; !node_a->is_tail_sentinal() + ; !node_a->is_tail_sentinel() ; node_a = node_a->next, node_b = node_b->next) { /* If all of the parameters from the other parameter list have been * exhausted, the lists have different length and, by definition, * do not match. */ - if (node_b->is_tail_sentinal()) + if (node_b->is_tail_sentinel()) return -1; @@ -151,7 +151,7 @@ parameter_lists_match(const exec_list *list_a, const exec_list *list_b) * exhausted, the lists have different length and, by definition, do not * match. */ - if (!node_b->is_tail_sentinal()) + if (!node_b->is_tail_sentinel()) return -1; return total_score; @@ -192,7 +192,7 @@ parameter_lists_match_exact(const exec_list *list_a, const exec_list *list_b) const exec_node *node_b = list_b->head; for (/* empty */ - ; !node_a->is_tail_sentinal() && !node_b->is_tail_sentinal() + ; !node_a->is_tail_sentinel() && !node_b->is_tail_sentinel() ; node_a = node_a->next, node_b = node_b->next) { ir_variable *a = (ir_variable *) node_a; ir_variable *b = (ir_variable *) node_b; @@ -207,7 +207,7 @@ parameter_lists_match_exact(const exec_list *list_a, const exec_list *list_b) /* Unless both lists are exhausted, they differ in length and, by * definition, do not match. */ - return (node_a->is_tail_sentinal() == node_b->is_tail_sentinal()); + return (node_a->is_tail_sentinel() == node_b->is_tail_sentinel()); } ir_function_signature * diff --git a/src/glsl/ir_function_inlining.cpp b/src/glsl/ir_function_inlining.cpp index 9daffeb017..77c264f288 100644 --- a/src/glsl/ir_function_inlining.cpp +++ b/src/glsl/ir_function_inlining.cpp @@ -96,7 +96,7 @@ replace_return_with_assignment(ir_instruction *ir, void *data) /* un-valued return has to be the last return, or we shouldn't * have reached here. (see can_inline()). */ - assert(!ret->next->is_tail_sentinal()); + assert(!ret->next->is_tail_sentinel()); ret->remove(); } } diff --git a/src/glsl/linker.cpp b/src/glsl/linker.cpp index fa4fb493f2..e9daad28ec 100644 --- a/src/glsl/linker.cpp +++ b/src/glsl/linker.cpp @@ -542,7 +542,7 @@ remap_variables(ir_instruction *inst, glsl_symbol_table *symbols, * Move non-declarations from one instruction stream to another * * The intended usage pattern of this function is to pass the pointer to the - * head sentinal of a list (i.e., a pointer to the list cast to an \c exec_node + * head sentinel of a list (i.e., a pointer to the list cast to an \c exec_node * pointer) for \c last and \c false for \c make_copies on the first * call. Successive calls pass the return value of the previous call for * \c last and \c true for \c make_copies. diff --git a/src/glsl/list.h b/src/glsl/list.h index 7348e323c1..a70b79d571 100644 --- a/src/glsl/list.h +++ b/src/glsl/list.h @@ -25,28 +25,28 @@ * \file list.h * \brief Doubly-linked list abstract container type. * - * Each doubly-linked list has a sentinal head and tail node. These nodes - * contain no data. The head sentinal can be identified by its \c prev - * pointer being \c NULL. The tail sentinal can be identified by its + * Each doubly-linked list has a sentinel head and tail node. These nodes + * contain no data. The head sentinel can be identified by its \c prev + * pointer being \c NULL. The tail sentinel can be identified by its * \c next pointer being \c NULL. * - * A list is empty if either the head sentinal's \c next pointer points to the - * tail sentinal or the tail sentinal's \c prev poiner points to the head - * sentinal. + * A list is empty if either the head sentinel's \c next pointer points to the + * tail sentinel or the tail sentinel's \c prev poiner points to the head + * sentinel. * * Instead of tracking two separate \c node structures and a \c list structure - * that points to them, the sentinal nodes are in a single structure. Noting - * that each sentinal node always has one \c NULL pointer, the \c NULL + * that points to them, the sentinel nodes are in a single structure. Noting + * that each sentinel node always has one \c NULL pointer, the \c NULL * pointers occupy the same memory location. In the \c list structure * contains a the following: * * - A \c head pointer that represents the \c next pointer of the - * head sentinal node. + * head sentinel node. * - A \c tail pointer that represents the \c prev pointer of the head - * sentinal node and the \c next pointer of the tail sentinal node. This + * sentinel node and the \c next pointer of the tail sentinel node. This * pointer is \b always \c NULL. * - A \c tail_prev pointer that represents the \c prev pointer of the - * tail sentinal node. + * tail sentinel node. * * Therefore, if \c head->next is \c NULL or \c tail_prev->prev is \c NULL, * the list is empty. @@ -178,17 +178,17 @@ struct exec_node { } /** - * Is this the sentinal at the tail of the list? + * Is this the sentinel at the tail of the list? */ - bool is_tail_sentinal() const + bool is_tail_sentinel() const { return this->next == NULL; } /** - * Is this the sentinal at the head of the list? + * Is this the sentinel at the head of the list? */ - bool is_head_sentinal() const + bool is_head_sentinel() const { return this->prev == NULL; } @@ -320,7 +320,7 @@ struct exec_list { * * - Check to see if the \c head points to the \c tail. * - Check to see if the \c tail_pred points to the \c head. - * - Check to see if the \c head is the sentinal node by test whether its + * - Check to see if the \c head is the sentinel node by test whether its * \c next pointer is \c NULL. * * The first two methods tend to generate better code on modern systems -- cgit v1.2.3 From 939a1807fe5a70db25725335ba0acccce8b01db3 Mon Sep 17 00:00:00 2001 From: Kenneth Graunke Date: Fri, 30 Jul 2010 13:30:11 -0700 Subject: glsl2: Initialize ir_function_signature::is_built_in. Fixes a valgrind error. --- src/glsl/ir.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'src/glsl/ir.cpp') diff --git a/src/glsl/ir.cpp b/src/glsl/ir.cpp index 7178c68e6b..2b5f441ddd 100644 --- a/src/glsl/ir.cpp +++ b/src/glsl/ir.cpp @@ -837,6 +837,7 @@ ir_function_signature::ir_function_signature(const glsl_type *return_type) : return_type(return_type), is_defined(false), _function(NULL) { this->ir_type = ir_type_function_signature; + this->is_built_in = false; } -- cgit v1.2.3 From 960ba0014af7009f8543c55f455271cf3cb45cd6 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 2 Aug 2010 11:20:32 -0700 Subject: glsl2: Initialize the ARB_fcc fields of ir_variable. Fixes intermittent failure in glsl-arb-fragment-coord-conventions. --- src/glsl/ir.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/glsl/ir.cpp') diff --git a/src/glsl/ir.cpp b/src/glsl/ir.cpp index 2b5f441ddd..79cbaa9ea0 100644 --- a/src/glsl/ir.cpp +++ b/src/glsl/ir.cpp @@ -802,6 +802,8 @@ ir_variable::ir_variable(const struct glsl_type *type, const char *name, this->location = -1; this->warn_extension = NULL; this->constant_value = NULL; + this->origin_upper_left = false; + this->pixel_center_integer = false; if (type && type->base_type == GLSL_TYPE_SAMPLER) this->read_only = true; -- cgit v1.2.3 From 5a7758efbe14dee026245a4f4f4fb3ccf7b2c23b Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Mon, 2 Aug 2010 18:48:25 -0700 Subject: glsl2: Add ir_assignment::write_mask and associated methods Replace swizzles on the LHS with additional swizzles on the RHS and a write mask in the assignment instruction. As part of this add ir_assignment::set_lhs. Ideally we'd make ir_assignment::lhs private to prevent erroneous writes, but that would require a lot of code butchery at this point. Add ir_assignment constructor that takes an explicit write mask. This is required for ir_assignment::clone, but it can also be used in other places. Without this, ir_assignment clones lose their write masks, and incorrect IR is generated in optimization passes. Add ir_assignment::whole_variable_written method. This method gets the variable on the LHS if the whole variable is written or NULL otherwise. This is different from ir->lhs->whole_variable_referenced() because the latter has no knowledge of the write mask stored in the ir_assignment. Gut all code from ir_to_mesa that handled swizzles on the LHS of assignments. There is probably some other refactoring that could be done here, but that can be left for another day. --- src/glsl/ir.cpp | 113 ++++++++++++++++++++++++++++++++++- src/glsl/ir.h | 44 +++++++++++++- src/glsl/ir_clone.cpp | 3 +- src/glsl/ir_constant_variable.cpp | 2 +- src/glsl/ir_copy_propagation.cpp | 2 +- src/glsl/ir_dead_code_local.cpp | 2 +- src/glsl/ir_print_visitor.cpp | 14 ++++- src/glsl/ir_tree_grafting.cpp | 2 +- src/glsl/ir_vec_index_to_swizzle.cpp | 2 +- src/mesa/program/ir_to_mesa.cpp | 67 ++++++++------------- 10 files changed, 199 insertions(+), 52 deletions(-) (limited to 'src/glsl/ir.cpp') diff --git a/src/glsl/ir.cpp b/src/glsl/ir.cpp index 79cbaa9ea0..c3bade8d54 100644 --- a/src/glsl/ir.cpp +++ b/src/glsl/ir.cpp @@ -22,6 +22,7 @@ */ #include #include "main/imports.h" +#include "main/macros.h" #include "ir.h" #include "ir_visitor.h" #include "glsl_types.h" @@ -31,13 +32,121 @@ ir_rvalue::ir_rvalue() this->type = glsl_type::error_type; } +/** + * Modify the swizzle make to move one component to another + * + * \param m IR swizzle to be modified + * \param from Component in the RHS that is to be swizzled + * \param to Desired swizzle location of \c from + */ +static void +update_rhs_swizzle(ir_swizzle_mask &m, unsigned from, unsigned to) +{ + switch (to) { + case 0: m.x = from; break; + case 1: m.y = from; break; + case 2: m.z = from; break; + case 3: m.w = from; break; + default: assert(!"Should not get here."); + } + + m.num_components = MAX2(m.num_components, (to + 1)); +} + +void +ir_assignment::set_lhs(ir_rvalue *lhs) +{ + while (lhs != NULL) { + ir_swizzle *swiz = lhs->as_swizzle(); + + if (swiz == NULL) + break; + + unsigned write_mask = 0; + ir_swizzle_mask rhs_swiz = { 0, 0, 0, 0, 0, 0 }; + + for (unsigned i = 0; i < swiz->mask.num_components; i++) { + unsigned c = 0; + + switch (i) { + case 0: c = swiz->mask.x; break; + case 1: c = swiz->mask.y; break; + case 2: c = swiz->mask.z; break; + case 3: c = swiz->mask.w; break; + default: assert(!"Should not get here."); + } + + write_mask |= (((this->write_mask >> i) & 1) << c); + update_rhs_swizzle(rhs_swiz, i, c); + } + + this->write_mask = write_mask; + lhs = swiz->val; + + this->rhs = new(this) ir_swizzle(this->rhs, rhs_swiz); + } + + assert((lhs == NULL) || lhs->as_dereference()); + + this->lhs = (ir_dereference *) lhs; +} + +ir_variable * +ir_assignment::whole_variable_written() +{ + ir_variable *v = this->lhs->whole_variable_referenced(); + + if (v == NULL) + return NULL; + + if (v->type->is_scalar()) + return v; + + if (v->type->is_vector()) { + const unsigned mask = (1U << v->type->vector_elements) - 1; + + if (mask != this->write_mask) + return NULL; + } + + /* Either all the vector components are assigned or the variable is some + * composite type (and the whole thing is assigned. + */ + return v; +} + +ir_assignment::ir_assignment(ir_dereference *lhs, ir_rvalue *rhs, + ir_rvalue *condition, unsigned write_mask) +{ + this->ir_type = ir_type_assignment; + this->condition = condition; + this->rhs = rhs; + this->lhs = lhs; + this->write_mask = write_mask; +} + ir_assignment::ir_assignment(ir_rvalue *lhs, ir_rvalue *rhs, ir_rvalue *condition) { this->ir_type = ir_type_assignment; - this->lhs = lhs; - this->rhs = rhs; this->condition = condition; + this->rhs = rhs; + + /* If the RHS is a vector type, assume that all components of the vector + * type are being written to the LHS. The write mask comes from the RHS + * because we can have a case where the LHS is a vec4 and the RHS is a + * vec3. In that case, the assignment is: + * + * (assign (...) (xyz) (var_ref lhs) (var_ref rhs)) + */ + if (rhs->type->is_vector()) + this->write_mask = (1U << rhs->type->vector_elements) - 1; + else if (rhs->type->is_scalar()) + this->write_mask = 1; + else + this->write_mask = 0; + + this->set_lhs(lhs); } diff --git a/src/glsl/ir.h b/src/glsl/ir.h index f964b36083..98789503e0 100644 --- a/src/glsl/ir.h +++ b/src/glsl/ir.h @@ -514,6 +514,16 @@ class ir_assignment : public ir_instruction { public: ir_assignment(ir_rvalue *lhs, ir_rvalue *rhs, ir_rvalue *condition); + /** + * Construct an assignment with an explicit write mask + * + * \note + * Since a write mask is supplied, the LHS must already be a bare + * \c ir_dereference. The cannot be any swizzles in the LHS. + */ + ir_assignment(ir_dereference *lhs, ir_rvalue *rhs, ir_rvalue *condition, + unsigned write_mask); + virtual ir_assignment *clone(void *mem_ctx, struct hash_table *ht) const; virtual ir_constant *constant_expression_value(); @@ -530,10 +540,32 @@ public: return this; } + /** + * Get a whole variable written by an assignment + * + * If the LHS of the assignment writes a whole variable, the variable is + * returned. Otherwise \c NULL is returned. Examples of whole-variable + * assignment are: + * + * - Assigning to a scalar + * - Assigning to all components of a vector + * - Whole array (or matrix) assignment + * - Whole structure assignment + */ + ir_variable *whole_variable_written(); + + /** + * Set the LHS of an assignment + */ + void set_lhs(ir_rvalue *lhs); + /** * Left-hand side of the assignment. + * + * This should be treated as read only. If you need to set the LHS of an + * assignment, use \c ir_assignment::set_lhs. */ - ir_rvalue *lhs; + ir_dereference *lhs; /** * Value being assigned @@ -544,6 +576,16 @@ public: * Optional condition for the assignment. */ ir_rvalue *condition; + + + /** + * Component mask written + * + * For non-vector types in the LHS, this field will be zero. For vector + * types, a bit will be set for each component that is written. Note that + * for \c vec2 and \c vec3 types only the lower bits will ever be set. + */ + unsigned write_mask:4; }; /* Update ir_expression::num_operands() and operator_strs when diff --git a/src/glsl/ir_clone.cpp b/src/glsl/ir_clone.cpp index 59831834bd..0e202164b3 100644 --- a/src/glsl/ir_clone.cpp +++ b/src/glsl/ir_clone.cpp @@ -242,7 +242,8 @@ ir_assignment::clone(void *mem_ctx, struct hash_table *ht) const return new(mem_ctx) ir_assignment(this->lhs->clone(mem_ctx, ht), this->rhs->clone(mem_ctx, ht), - new_condition); + new_condition, + this->write_mask); } ir_function * diff --git a/src/glsl/ir_constant_variable.cpp b/src/glsl/ir_constant_variable.cpp index 749e2cf809..1fb73e765e 100644 --- a/src/glsl/ir_constant_variable.cpp +++ b/src/glsl/ir_constant_variable.cpp @@ -110,7 +110,7 @@ ir_constant_variable_visitor::visit_enter(ir_assignment *ir) return visit_continue; } - ir_variable *var = ir->lhs->whole_variable_referenced(); + ir_variable *var = ir->whole_variable_written(); if (!var) return visit_continue; diff --git a/src/glsl/ir_copy_propagation.cpp b/src/glsl/ir_copy_propagation.cpp index 5712398732..26588a352c 100644 --- a/src/glsl/ir_copy_propagation.cpp +++ b/src/glsl/ir_copy_propagation.cpp @@ -224,7 +224,7 @@ add_copy(void *ctx, ir_assignment *ir, exec_list *acp) return; } - ir_variable *lhs_var = ir->lhs->whole_variable_referenced(); + ir_variable *lhs_var = ir->whole_variable_written(); ir_variable *rhs_var = ir->rhs->whole_variable_referenced(); if ((lhs_var != NULL) && (rhs_var != NULL)) { diff --git a/src/glsl/ir_dead_code_local.cpp b/src/glsl/ir_dead_code_local.cpp index 7a44ec8a4a..b22cc558df 100644 --- a/src/glsl/ir_dead_code_local.cpp +++ b/src/glsl/ir_dead_code_local.cpp @@ -137,7 +137,7 @@ process_assignment(void *ctx, ir_assignment *ir, exec_list *assignments) } /* Now, check if we did a whole-variable assignment. */ - if (always_assign && (ir->lhs->whole_variable_referenced() != NULL)) { + if (always_assign && (ir->whole_variable_written() != NULL)) { /* We did a whole-variable assignment. So, any instruction in * the assignment list with the same LHS is dead. */ diff --git a/src/glsl/ir_print_visitor.cpp b/src/glsl/ir_print_visitor.cpp index 73476e7e9b..39b11bb32c 100644 --- a/src/glsl/ir_print_visitor.cpp +++ b/src/glsl/ir_print_visitor.cpp @@ -296,7 +296,19 @@ void ir_print_visitor::visit(ir_assignment *ir) else printf("(constant bool (1))"); - printf(" "); + + char mask[5]; + unsigned j = 0; + + for (unsigned i = 0; i < 4; i++) { + if ((ir->write_mask & (1 << i)) != 0) { + mask[j] = "xyzw"[i]; + j++; + } + } + mask[j] = '\0'; + + printf(" (%s) ", mask); ir->lhs->accept(this); diff --git a/src/glsl/ir_tree_grafting.cpp b/src/glsl/ir_tree_grafting.cpp index 6f62de758b..38034a6197 100644 --- a/src/glsl/ir_tree_grafting.cpp +++ b/src/glsl/ir_tree_grafting.cpp @@ -315,7 +315,7 @@ tree_grafting_basic_block(ir_instruction *bb_first, if (!assign) continue; - ir_variable *lhs_var = assign->lhs->whole_variable_referenced(); + ir_variable *lhs_var = assign->whole_variable_written(); if (!lhs_var) continue; diff --git a/src/glsl/ir_vec_index_to_swizzle.cpp b/src/glsl/ir_vec_index_to_swizzle.cpp index 1e170cbae6..b3de91f8ab 100644 --- a/src/glsl/ir_vec_index_to_swizzle.cpp +++ b/src/glsl/ir_vec_index_to_swizzle.cpp @@ -107,7 +107,7 @@ ir_vec_index_to_swizzle_visitor::visit_enter(ir_swizzle *ir) ir_visitor_status ir_vec_index_to_swizzle_visitor::visit_enter(ir_assignment *ir) { - ir->lhs = convert_vec_index_to_swizzle(ir->lhs); + ir->set_lhs(convert_vec_index_to_swizzle(ir->lhs)); ir->rhs = convert_vec_index_to_swizzle(ir->rhs); return visit_continue; diff --git a/src/mesa/program/ir_to_mesa.cpp b/src/mesa/program/ir_to_mesa.cpp index 777b4d91f4..1cec4aa621 100644 --- a/src/mesa/program/ir_to_mesa.cpp +++ b/src/mesa/program/ir_to_mesa.cpp @@ -356,6 +356,7 @@ ir_to_mesa_visitor::ir_to_mesa_emit_op1(ir_instruction *ir, ir_to_mesa_dst_reg dst, ir_to_mesa_src_reg src0) { + assert(dst.writemask != 0); return ir_to_mesa_emit_op3(ir, op, dst, src0, ir_to_mesa_undef, ir_to_mesa_undef); } @@ -1615,21 +1616,17 @@ ir_to_mesa_visitor::visit(ir_dereference_record *ir) * We want to be careful in assignment setup to hit the actual storage * instead of potentially using a temporary like we might with the * ir_dereference handler. - * - * Thanks to ir_swizzle_swizzle, and ir_vec_index_to_swizzle, we - * should only see potentially one variable array index of a vector, - * and one swizzle, before getting to actual vec4 storage. So handle - * those, then go use ir_dereference to handle the rest. */ static struct ir_to_mesa_dst_reg -get_assignment_lhs(ir_instruction *ir, ir_to_mesa_visitor *v, +get_assignment_lhs(ir_dereference *ir, ir_to_mesa_visitor *v, ir_to_mesa_src_reg *r) { - struct ir_to_mesa_dst_reg dst_reg; - ir_swizzle *swiz; - + /* The LHS must be a dereference. If the LHS is a variable indexed array + * access of a vector, it must be separated into a series conditional moves + * before reaching this point (see ir_vec_index_to_cond_assign). + */ + assert(ir->as_dereference()); ir_dereference_array *deref_array = ir->as_dereference_array(); - /* This should have been handled by ir_vec_index_to_cond_assign */ if (deref_array) { assert(!deref_array->array->type->is_vector()); } @@ -1638,38 +1635,7 @@ get_assignment_lhs(ir_instruction *ir, ir_to_mesa_visitor *v, * swizzles in it and write swizzles using writemask, though. */ ir->accept(v); - dst_reg = ir_to_mesa_dst_reg_from_src(v->result); - - if ((swiz = ir->as_swizzle())) { - int swizzles[4] = { - swiz->mask.x, - swiz->mask.y, - swiz->mask.z, - swiz->mask.w - }; - int new_r_swizzle[4]; - int orig_r_swizzle = r->swizzle; - int i; - - for (i = 0; i < 4; i++) { - new_r_swizzle[i] = GET_SWZ(orig_r_swizzle, 0); - } - - dst_reg.writemask = 0; - for (i = 0; i < 4; i++) { - if (i < swiz->mask.num_components) { - dst_reg.writemask |= 1 << swizzles[i]; - new_r_swizzle[swizzles[i]] = GET_SWZ(orig_r_swizzle, i); - } - } - - r->swizzle = MAKE_SWIZZLE4(new_r_swizzle[0], - new_r_swizzle[1], - new_r_swizzle[2], - new_r_swizzle[3]); - } - - return dst_reg; + return ir_to_mesa_dst_reg_from_src(v->result); } void @@ -1684,6 +1650,23 @@ ir_to_mesa_visitor::visit(ir_assignment *ir) l = get_assignment_lhs(ir->lhs, this, &r); + /* FINISHME: This should really set to the correct maximal writemask for each + * FINISHME: component written (in the loops below). This case can only + * FINISHME: occur for matrices, arrays, and structures. + */ + if (ir->write_mask == 0) { + assert(!ir->lhs->type->is_scalar() && !ir->lhs->type->is_vector()); + l.writemask = WRITEMASK_XYZW; + } else if (ir->lhs->type->is_scalar()) { + /* FINISHME: This hack makes writing to gl_FragData, which lives in the + * FINISHME: W component of fragment shader output zero, work correctly. + */ + l.writemask = WRITEMASK_XYZW; + } else { + assert(ir->lhs->type->is_vector()); + l.writemask = ir->write_mask; + } + assert(l.file != PROGRAM_UNDEFINED); assert(r.file != PROGRAM_UNDEFINED); -- cgit v1.2.3 From 046bef235744e891e4a48076e1a3ff9a61a63092 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Wed, 4 Aug 2010 20:33:57 -0700 Subject: glsl2: Remove the shader_in/shader_out tracking separate from var->mode. I introduced this for ir_dead_code to distinguish function parameter outvals from varying outputs. Only, since ast_to_hir's current_function is unset when setting up function parameters (they're needed for making the function signature in the first place), all function parameter outvals were marked as shader outputs anyway. This meant that an inlined function's cloned outval was marked as a shader output and couldn't be dead-code eliminated. Instead, since ir_dead_code doesn't even look at function parameters, just use var->mode. The longest Mesa IR coming out of ir_to_mesa for Yo Frankie drops from 725 instructions to 636. --- src/glsl/ast_to_hir.cpp | 37 ++++++++++--------------------------- src/glsl/ir.cpp | 4 ---- src/glsl/ir.h | 14 ++++---------- src/glsl/ir_clone.cpp | 2 -- src/glsl/ir_dead_code.cpp | 3 ++- src/glsl/ir_variable.cpp | 12 +----------- src/glsl/linker.cpp | 2 -- 7 files changed, 17 insertions(+), 57 deletions(-) (limited to 'src/glsl/ir.cpp') diff --git a/src/glsl/ast_to_hir.cpp b/src/glsl/ast_to_hir.cpp index 14c528075b..292c7be621 100644 --- a/src/glsl/ast_to_hir.cpp +++ b/src/glsl/ast_to_hir.cpp @@ -1510,31 +1510,6 @@ apply_type_qualifier_to_variable(const struct ast_type_qualifier *qual, else if (qual->uniform) var->mode = ir_var_uniform; - if (qual->uniform) - var->shader_in = true; - - /* Any 'in' or 'inout' variables at global scope must be marked as being - * shader inputs. Likewise, any 'out' or 'inout' variables at global scope - * must be marked as being shader outputs. - */ - if (state->current_function == NULL) { - switch (var->mode) { - case ir_var_in: - case ir_var_uniform: - var->shader_in = true; - break; - case ir_var_out: - var->shader_out = true; - break; - case ir_var_inout: - var->shader_in = true; - var->shader_out = true; - break; - default: - break; - } - } - if (qual->flat) var->interpolation = ir_var_flat; else if (qual->noperspective) @@ -1702,11 +1677,19 @@ ast_declarator_list::hir(exec_list *instructions, & loc); if (this->type->qualifier.invariant) { - if ((state->target == vertex_shader) && !var->shader_out) { + if ((state->target == vertex_shader) && !(var->mode == ir_var_out || + var->mode == ir_var_inout)) { + /* FINISHME: Note that this doesn't work for invariant on + * a function signature outval + */ _mesa_glsl_error(& loc, state, "`%s' cannot be marked invariant, vertex shader " "outputs only\n", var->name); - } else if ((state->target == fragment_shader) && !var->shader_in) { + } else if ((state->target == fragment_shader) && + !(var->mode == ir_var_in || var->mode == ir_var_inout)) { + /* FINISHME: Note that this doesn't work for invariant on + * a function signature inval + */ _mesa_glsl_error(& loc, state, "`%s' cannot be marked invariant, fragment shader " "inputs only\n", var->name); diff --git a/src/glsl/ir.cpp b/src/glsl/ir.cpp index c3bade8d54..dd059e470d 100644 --- a/src/glsl/ir.cpp +++ b/src/glsl/ir.cpp @@ -902,7 +902,6 @@ ir_swizzle::variable_referenced() ir_variable::ir_variable(const struct glsl_type *type, const char *name, ir_variable_mode mode) : max_array_access(0), read_only(false), centroid(false), invariant(false), - shader_in(false), shader_out(false), mode(mode), interpolation(ir_var_smooth), array_lvalue(false) { this->ir_type = ir_type_variable; @@ -922,9 +921,6 @@ ir_variable::ir_variable(const struct glsl_type *type, const char *name, const char * ir_variable::interpolation_string() const { - if (!this->shader_in && !this->shader_out) - return ""; - switch (this->interpolation) { case ir_var_smooth: return "smooth"; case ir_var_flat: return "flat"; diff --git a/src/glsl/ir.h b/src/glsl/ir.h index 98789503e0..e61485813d 100644 --- a/src/glsl/ir.h +++ b/src/glsl/ir.h @@ -194,10 +194,10 @@ public: /** * Get the string value for the interpolation qualifier * - * \return - * If none of \c shader_in or \c shader_out is set, an empty string will - * be returned. Otherwise the string that would be used in a shader to - * specify \c mode will be returned. + * \return The string that would be used in a shader to specify \c + * mode will be returned. + * + * This function should only be used on a shader input or output variable. */ const char *interpolation_string() const; @@ -221,12 +221,6 @@ public: unsigned read_only:1; unsigned centroid:1; unsigned invariant:1; - /** If the variable is initialized outside of the scope of the shader */ - unsigned shader_in:1; - /** - * If the variable value is later used outside of the scope of the shader. - */ - unsigned shader_out:1; unsigned mode:3; unsigned interpolation:2; diff --git a/src/glsl/ir_clone.cpp b/src/glsl/ir_clone.cpp index 0e202164b3..a72609601a 100644 --- a/src/glsl/ir_clone.cpp +++ b/src/glsl/ir_clone.cpp @@ -45,8 +45,6 @@ ir_variable::clone(void *mem_ctx, struct hash_table *ht) const var->read_only = this->read_only; var->centroid = this->centroid; var->invariant = this->invariant; - var->shader_in = this->shader_in; - var->shader_out = this->shader_out; var->interpolation = this->interpolation; var->array_lvalue = this->array_lvalue; var->location = this->location; diff --git a/src/glsl/ir_dead_code.cpp b/src/glsl/ir_dead_code.cpp index 2b971b7aaa..bf032f1dc2 100644 --- a/src/glsl/ir_dead_code.cpp +++ b/src/glsl/ir_dead_code.cpp @@ -68,7 +68,8 @@ do_dead_code(exec_list *instructions) /* Remove a single dead assignment to the variable we found. * Don't do so if it's a shader output, though. */ - if (!entry->var->shader_out) { + if (entry->var->mode != ir_var_out && + entry->var->mode != ir_var_inout) { entry->assign->remove(); progress = true; } diff --git a/src/glsl/ir_variable.cpp b/src/glsl/ir_variable.cpp index 478cefc5a6..d9a16d4287 100644 --- a/src/glsl/ir_variable.cpp +++ b/src/glsl/ir_variable.cpp @@ -43,22 +43,12 @@ add_variable(const char *name, enum ir_variable_mode mode, int slot, switch (var->mode) { case ir_var_auto: - var->read_only = true; - break; case ir_var_in: - var->shader_in = true; + case ir_var_uniform: var->read_only = true; break; case ir_var_inout: - var->shader_in = true; - var->shader_out = true; - break; case ir_var_out: - var->shader_out = true; - break; - case ir_var_uniform: - var->shader_in = true; - var->read_only = true; break; default: assert(0); diff --git a/src/glsl/linker.cpp b/src/glsl/linker.cpp index b2953c67d1..94db57d6a5 100644 --- a/src/glsl/linker.cpp +++ b/src/glsl/linker.cpp @@ -1124,7 +1124,6 @@ assign_varying_locations(struct gl_shader_program *prog, * by the following stage. */ if (var->location == -1) { - var->shader_out = false; var->mode = ir_var_auto; } } @@ -1158,7 +1157,6 @@ assign_varying_locations(struct gl_shader_program *prog, /* An 'in' variable is only really a shader input if its * value is written by the previous stage. */ - var->shader_in = false; var->mode = ir_var_auto; } } -- cgit v1.2.3 From 664364052f362af2789e6b0fa88b6a5ba66ba936 Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Tue, 17 Aug 2010 12:57:28 -0700 Subject: ir_constant: Don't assert on out-of-bounds array accesses Several optimization paths, including constant folding, can lead to accessing an ir_constant array with an out of bounds index. The GLSL spec lets us produce "undefined" results, but it does not let us crash. Fixes piglit test case glsl-array-bounds-01 and glsl-array-bounds-03. --- src/glsl/ir.cpp | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) (limited to 'src/glsl/ir.cpp') diff --git a/src/glsl/ir.cpp b/src/glsl/ir.cpp index dd059e470d..ebb592792b 100644 --- a/src/glsl/ir.cpp +++ b/src/glsl/ir.cpp @@ -519,7 +519,21 @@ ir_constant * ir_constant::get_array_element(unsigned i) const { assert(this->type->is_array()); - assert(i < this->type->length); + + /* From page 35 (page 41 of the PDF) of the GLSL 1.20 spec: + * + * "Behavior is undefined if a shader subscripts an array with an index + * less than 0 or greater than or equal to the size the array was + * declared with." + * + * Most out-of-bounds accesses are removed before things could get this far. + * There are cases where non-constant array index values can get constant + * folded. + */ + if (int(i) < 0) + i = 0; + else if (i >= this->type->length) + i = this->type->length - 1; return array_elements[i]; } -- cgit v1.2.3 From 5e9ac94cc44ef4f97063d7b696411b2a4be16f36 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 23 Aug 2010 12:21:33 -0700 Subject: mesa: Add new ir_unop_any() expression operation. The previous any() implementation would generate arg0.x || arg0.y || arg0.z. Having an expression operation for this makes it easy for the backend to generate something easier (DPn + SNE for 915 FS, .any predication on 965 VS) --- src/glsl/README | 1 + src/glsl/builtins/ir/any | 6 +++--- src/glsl/ir.cpp | 2 ++ src/glsl/ir.h | 1 + src/glsl/ir_constant_expression.cpp | 9 +++++++++ src/glsl/ir_validate.cpp | 5 +++++ src/mesa/program/ir_to_mesa.cpp | 20 ++++++++++++++++++++ 7 files changed, 41 insertions(+), 3 deletions(-) (limited to 'src/glsl/ir.cpp') diff --git a/src/glsl/README b/src/glsl/README index 74520321b2..2e501d6206 100644 --- a/src/glsl/README +++ b/src/glsl/README @@ -180,6 +180,7 @@ ir.h (new enum) ir.cpp:get_num_operands() (used for ir_reader) ir.cpp:operator_strs (used for ir_reader) ir_constant_expression.cpp (you probably want to be able to constant fold) +ir_validate.cpp (check users have the right types) You may also need to update the backends if they will see the new expr type: diff --git a/src/glsl/builtins/ir/any b/src/glsl/builtins/ir/any index f10e8a7b47..cc6038a315 100644 --- a/src/glsl/builtins/ir/any +++ b/src/glsl/builtins/ir/any @@ -2,15 +2,15 @@ (signature bool (parameters (declare (in) bvec2 arg0)) - ((return (expression bool || (swiz x (var_ref arg0))(swiz y (var_ref arg0)))))) + ((return (expression bool any (var_ref arg0))))) (signature bool (parameters (declare (in) bvec3 arg0)) - ((return (expression bool || (expression bool || (swiz x (var_ref arg0))(swiz y (var_ref arg0))) (swiz z (var_ref arg0)))))) + ((return (expression bool any (var_ref arg0))))) (signature bool (parameters (declare (in) bvec4 arg0)) - ((return (expression bool || (expression bool || (expression bool || (swiz x (var_ref arg0))(swiz y (var_ref arg0))) (swiz z (var_ref arg0))) (swiz w (var_ref arg0)))))) + ((return (expression bool any (var_ref arg0))))) )) diff --git a/src/glsl/ir.cpp b/src/glsl/ir.cpp index ebb592792b..4622a1f939 100644 --- a/src/glsl/ir.cpp +++ b/src/glsl/ir.cpp @@ -184,6 +184,7 @@ ir_expression::get_num_operands(ir_expression_operation op) 1, /* ir_unop_i2b */ 1, /* ir_unop_b2i */ 1, /* ir_unop_u2f */ + 1, /* ir_unop_any */ 1, /* ir_unop_trunc */ 1, /* ir_unop_ceil */ @@ -252,6 +253,7 @@ static const char *const operator_strs[] = { "i2b", "b2i", "u2f", + "any", "trunc", "ceil", "floor", diff --git a/src/glsl/ir.h b/src/glsl/ir.h index b04222893c..500b152408 100644 --- a/src/glsl/ir.h +++ b/src/glsl/ir.h @@ -604,6 +604,7 @@ enum ir_expression_operation { ir_unop_i2b, /**< int-to-boolean conversion */ ir_unop_b2i, /**< Boolean-to-int conversion */ ir_unop_u2f, /**< Unsigned-to-float conversion. */ + ir_unop_any, /** * \name Unary floating-point rounding operations. diff --git a/src/glsl/ir_constant_expression.cpp b/src/glsl/ir_constant_expression.cpp index 54f14d1a54..942f198360 100644 --- a/src/glsl/ir_constant_expression.cpp +++ b/src/glsl/ir_constant_expression.cpp @@ -149,6 +149,15 @@ ir_expression::constant_expression_value() } break; + case ir_unop_any: + assert(op[0]->type->is_boolean()); + data.b[0] = false; + for (unsigned c = 0; c < op[0]->type->components(); c++) { + if (op[0]->value.b[c]) + data.b[0] = true; + } + break; + case ir_unop_trunc: assert(op[0]->type->base_type == GLSL_TYPE_FLOAT); for (unsigned c = 0; c < op[0]->type->components(); c++) { diff --git a/src/glsl/ir_validate.cpp b/src/glsl/ir_validate.cpp index 6e08fa4025..9ea11dd400 100644 --- a/src/glsl/ir_validate.cpp +++ b/src/glsl/ir_validate.cpp @@ -223,6 +223,11 @@ ir_validate::visit_leave(ir_expression *ir) assert(ir->type->base_type == GLSL_TYPE_FLOAT); break; + case ir_unop_any: + assert(ir->operands[0]->type->base_type == GLSL_TYPE_BOOL); + assert(ir->type == glsl_type::bool_type); + break; + case ir_unop_trunc: case ir_unop_ceil: case ir_unop_floor: diff --git a/src/mesa/program/ir_to_mesa.cpp b/src/mesa/program/ir_to_mesa.cpp index 7a615f2d58..ea2560af3e 100644 --- a/src/mesa/program/ir_to_mesa.cpp +++ b/src/mesa/program/ir_to_mesa.cpp @@ -844,6 +844,26 @@ ir_to_mesa_visitor::visit(ir_expression *ir) ir_to_mesa_emit_op2(ir, OPCODE_SNE, result_dst, op[0], op[1]); } break; + + case ir_unop_any: + switch (ir->operands[0]->type->vector_elements) { + case 4: + ir_to_mesa_emit_op2(ir, OPCODE_DP4, result_dst, op[0], op[0]); + break; + case 3: + ir_to_mesa_emit_op2(ir, OPCODE_DP3, result_dst, op[0], op[0]); + break; + case 2: + ir_to_mesa_emit_op2(ir, OPCODE_DP2, result_dst, op[0], op[0]); + break; + default: + assert(!"unreached: ir_unop_any of non-bvec"); + break; + } + ir_to_mesa_emit_op2(ir, OPCODE_SNE, + result_dst, result_src, src_reg_for_float(0.0)); + break; + case ir_binop_logic_xor: ir_to_mesa_emit_op2(ir, OPCODE_SNE, result_dst, op[0], op[1]); break; -- cgit v1.2.3 From bfd7c9ac228c7ed8aec04c3b3aa33f40ee00b035 Mon Sep 17 00:00:00 2001 From: Chia-I Wu Date: Mon, 23 Aug 2010 17:51:42 +0800 Subject: glsl: Include main/core.h. Make glsl include only main/core.h from core mesa. --- src/glsl/ast_function.cpp | 2 +- src/glsl/ast_to_hir.cpp | 3 +-- src/glsl/builtin_function.cpp | 2 +- src/glsl/builtin_variables.h | 2 +- src/glsl/builtins/tools/generate_builtins.py | 2 +- src/glsl/glcpp/glcpp-parse.c | 2 +- src/glsl/glcpp/glcpp-parse.y | 2 +- src/glsl/glsl_parser_extras.cpp | 2 +- src/glsl/glsl_types.cpp | 3 +-- src/glsl/hir_field_selection.cpp | 1 - src/glsl/ir.cpp | 3 +-- src/glsl/ir_constant_expression.cpp | 2 +- src/glsl/ir_explog_to_explog2.cpp | 2 +- src/glsl/ir_set_program_inouts.cpp | 2 +- src/glsl/ir_variable.cpp | 1 - src/glsl/link_functions.cpp | 2 +- src/glsl/linker.cpp | 5 +---- src/glsl/program.h | 8 +------- 18 files changed, 16 insertions(+), 30 deletions(-) (limited to 'src/glsl/ir.cpp') diff --git a/src/glsl/ast_function.cpp b/src/glsl/ast_function.cpp index f85b308c1b..34b0f70d41 100644 --- a/src/glsl/ast_function.cpp +++ b/src/glsl/ast_function.cpp @@ -25,7 +25,7 @@ #include "ast.h" #include "glsl_types.h" #include "ir.h" -#include "main/macros.h" +#include "main/core.h" /* for MIN2 */ static ir_rvalue * convert_component(ir_rvalue *src, const glsl_type *desired_type); diff --git a/src/glsl/ast_to_hir.cpp b/src/glsl/ast_to_hir.cpp index 57e331742e..64b142fa35 100644 --- a/src/glsl/ast_to_hir.cpp +++ b/src/glsl/ast_to_hir.cpp @@ -49,8 +49,7 @@ * parser (and lexer) sources. */ -#include "main/imports.h" -#include "main/extensions.h" +#include "main/core.h" /* for struct gl_extensions */ #include "glsl_symbol_table.h" #include "glsl_parser_extras.h" #include "ast.h" diff --git a/src/glsl/builtin_function.cpp b/src/glsl/builtin_function.cpp index 5471ba6020..a277ed6e8d 100644 --- a/src/glsl/builtin_function.cpp +++ b/src/glsl/builtin_function.cpp @@ -23,7 +23,7 @@ */ #include -#include "main/compiler.h" +#include "main/core.h" /* for struct gl_shader */ #include "glsl_parser_extras.h" #include "ir_reader.h" #include "program.h" diff --git a/src/glsl/builtin_variables.h b/src/glsl/builtin_variables.h index 2ec7d621bb..a7dbe480e9 100644 --- a/src/glsl/builtin_variables.h +++ b/src/glsl/builtin_variables.h @@ -21,7 +21,7 @@ * DEALINGS IN THE SOFTWARE. */ -#include "main/mtypes.h" +#include "main/core.h" /* for slot numbers */ struct builtin_variable { enum ir_variable_mode mode; diff --git a/src/glsl/builtins/tools/generate_builtins.py b/src/glsl/builtins/tools/generate_builtins.py index 2a763d784b..c72b5b3bc1 100755 --- a/src/glsl/builtins/tools/generate_builtins.py +++ b/src/glsl/builtins/tools/generate_builtins.py @@ -116,7 +116,7 @@ if __name__ == "__main__": */ #include -#include "main/compiler.h" +#include "main/core.h" /* for struct gl_shader */ #include "glsl_parser_extras.h" #include "ir_reader.h" #include "program.h" diff --git a/src/glsl/glcpp/glcpp-parse.c b/src/glsl/glcpp/glcpp-parse.c index 2c04d7d71b..91eb0bf972 100644 --- a/src/glsl/glcpp/glcpp-parse.c +++ b/src/glsl/glcpp/glcpp-parse.c @@ -100,7 +100,7 @@ #include #include "glcpp.h" -#include "main/mtypes.h" +#include "main/core.h" /* for struct gl_extensions */ #define glcpp_print(stream, str) stream = talloc_strdup_append(stream, str) #define glcpp_printf(stream, fmt, args, ...) \ diff --git a/src/glsl/glcpp/glcpp-parse.y b/src/glsl/glcpp/glcpp-parse.y index 3275496d99..3c28edf688 100644 --- a/src/glsl/glcpp/glcpp-parse.y +++ b/src/glsl/glcpp/glcpp-parse.y @@ -29,7 +29,7 @@ #include #include "glcpp.h" -#include "main/mtypes.h" +#include "main/core.h" /* for struct gl_extensions */ #define glcpp_print(stream, str) stream = talloc_strdup_append(stream, str) #define glcpp_printf(stream, fmt, args, ...) \ diff --git a/src/glsl/glsl_parser_extras.cpp b/src/glsl/glsl_parser_extras.cpp index b864218d50..bc56e4fcaf 100644 --- a/src/glsl/glsl_parser_extras.cpp +++ b/src/glsl/glsl_parser_extras.cpp @@ -27,7 +27,7 @@ extern "C" { #include -#include "main/mtypes.h" +#include "main/core.h" /* for struct __GLcontextRec */ } #include "ast.h" diff --git a/src/glsl/glsl_types.cpp b/src/glsl/glsl_types.cpp index c488f5c271..1da2fd76de 100644 --- a/src/glsl/glsl_types.cpp +++ b/src/glsl/glsl_types.cpp @@ -23,13 +23,12 @@ #include #include -#include "main/compiler.h" +#include "main/core.h" /* for Elements */ #include "glsl_symbol_table.h" #include "glsl_parser_extras.h" #include "glsl_types.h" #include "builtin_types.h" extern "C" { -#include "main/imports.h" #include "program/hash_table.h" } diff --git a/src/glsl/hir_field_selection.cpp b/src/glsl/hir_field_selection.cpp index 23045ff182..3c33127b5f 100644 --- a/src/glsl/hir_field_selection.cpp +++ b/src/glsl/hir_field_selection.cpp @@ -22,7 +22,6 @@ */ #include "ir.h" -#include "main/imports.h" #include "program/symbol_table.h" #include "glsl_parser_extras.h" #include "ast.h" diff --git a/src/glsl/ir.cpp b/src/glsl/ir.cpp index 4622a1f939..e5ed10d3e4 100644 --- a/src/glsl/ir.cpp +++ b/src/glsl/ir.cpp @@ -21,8 +21,7 @@ * DEALINGS IN THE SOFTWARE. */ #include -#include "main/imports.h" -#include "main/macros.h" +#include "main/core.h" /* for MAX2 */ #include "ir.h" #include "ir_visitor.h" #include "glsl_types.h" diff --git a/src/glsl/ir_constant_expression.cpp b/src/glsl/ir_constant_expression.cpp index 942f198360..f1c175c97a 100644 --- a/src/glsl/ir_constant_expression.cpp +++ b/src/glsl/ir_constant_expression.cpp @@ -34,7 +34,7 @@ */ #include -#include "main/macros.h" +#include "main/core.h" /* for MAX2, MIN2, CLAMP */ #include "ir.h" #include "ir_visitor.h" #include "glsl_types.h" diff --git a/src/glsl/ir_explog_to_explog2.cpp b/src/glsl/ir_explog_to_explog2.cpp index 9bf8271081..78694a2029 100644 --- a/src/glsl/ir_explog_to_explog2.cpp +++ b/src/glsl/ir_explog_to_explog2.cpp @@ -29,7 +29,7 @@ * and log2 operations. */ -#include "main/imports.h" +#include "main/core.h" /* for log2f on MSVC */ #include "ir.h" #include "glsl_types.h" diff --git a/src/glsl/ir_set_program_inouts.cpp b/src/glsl/ir_set_program_inouts.cpp index 534f602128..b3f1cc0d8b 100644 --- a/src/glsl/ir_set_program_inouts.cpp +++ b/src/glsl/ir_set_program_inouts.cpp @@ -35,7 +35,7 @@ */ extern "C" { -#include "main/mtypes.h" +#include "main/core.h" /* for struct gl_program */ #include "program/hash_table.h" } #include "ir.h" diff --git a/src/glsl/ir_variable.cpp b/src/glsl/ir_variable.cpp index 917c06743b..e638c9602f 100644 --- a/src/glsl/ir_variable.cpp +++ b/src/glsl/ir_variable.cpp @@ -21,7 +21,6 @@ * DEALINGS IN THE SOFTWARE. */ -#include "main/compiler.h" #include "ir.h" #include "glsl_parser_extras.h" #include "glsl_symbol_table.h" diff --git a/src/glsl/link_functions.cpp b/src/glsl/link_functions.cpp index dfda05fcbe..6374573e61 100644 --- a/src/glsl/link_functions.cpp +++ b/src/glsl/link_functions.cpp @@ -29,7 +29,7 @@ extern "C" { #include } -#include "main/mtypes.h" +#include "main/core.h" #include "glsl_symbol_table.h" #include "glsl_parser_extras.h" #include "ir.h" diff --git a/src/glsl/linker.cpp b/src/glsl/linker.cpp index 38d19c4c71..c5c8c9cdd6 100644 --- a/src/glsl/linker.cpp +++ b/src/glsl/linker.cpp @@ -72,10 +72,7 @@ extern "C" { #include } -#include "main/compiler.h" -#include "main/mtypes.h" -#include "main/macros.h" -#include "main/shaderobj.h" +#include "main/core.h" #include "glsl_symbol_table.h" #include "ir.h" #include "program.h" diff --git a/src/glsl/program.h b/src/glsl/program.h index ea2c4ab0dd..893169b6cc 100644 --- a/src/glsl/program.h +++ b/src/glsl/program.h @@ -21,13 +21,7 @@ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#include -#include "main/mtypes.h" - -extern "C" { -#include "program/prog_parameter.h" -#include "program/prog_uniform.h" -} +#include "main/core.h" extern void link_shaders(GLcontext *ctx, struct gl_shader_program *prog); -- cgit v1.2.3 From c735d85395f8f0c0a71b04ebc728390970271fe2 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Wed, 25 Aug 2010 23:27:56 -0700 Subject: glsl: Don't consider things with a type containing a sampler as an lvalue. We had ad-hoc handled some common cases by flagging sampler-typed variables as read_only, and rejected initializers of samplers. However, people could sneak them in in all sorts of surprising ways, like using whole-array or structure assignment. Fixes: glslparsertest/glsl2/sampler-01.frag glslparsertest/glsl2/sampler-03.frag glslparsertest/glsl2/sampler-04.frag glslparsertest/glsl2/sampler-06.frag Bug #27403. --- src/glsl/ir.cpp | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) (limited to 'src/glsl/ir.cpp') diff --git a/src/glsl/ir.cpp b/src/glsl/ir.cpp index e5ed10d3e4..31e40cac8c 100644 --- a/src/glsl/ir.cpp +++ b/src/glsl/ir.cpp @@ -697,6 +697,20 @@ ir_dereference_record::ir_dereference_record(ir_variable *var, ? this->record->type->field_type(field) : glsl_type::error_type; } +bool type_contains_sampler(const glsl_type *type) +{ + if (type->is_array()) { + return type_contains_sampler(type->fields.array); + } else if (type->is_record()) { + for (unsigned int i = 0; i < type->length; i++) { + if (type_contains_sampler(type->fields.structure[i].type)) + return true; + } + return false; + } else { + return type->is_sampler(); + } +} bool ir_dereference::is_lvalue() @@ -711,6 +725,15 @@ ir_dereference::is_lvalue() if (this->type->is_array() && !var->array_lvalue) return false; + /* From page 17 (page 23 of the PDF) of the GLSL 1.20 spec: + * + * "Samplers cannot be treated as l-values; hence cannot be used + * as out or inout function parameters, nor can they be + * assigned into." + */ + if (type_contains_sampler(this->type)) + return false; + return true; } -- cgit v1.2.3 From b6f15869b324ae64a00d0fe46fa3c8c62c1edb6c Mon Sep 17 00:00:00 2001 From: Kenneth Graunke Date: Fri, 20 Aug 2010 20:04:39 -0700 Subject: glsl: Move is_built_in flag from ir_function_signature to ir_function. Also rename it to "is_builtin" for consistency. Signed-off-by: Ian Romanick --- src/glsl/ir.cpp | 2 +- src/glsl/ir.h | 6 +++--- src/glsl/ir_clone.cpp | 3 ++- src/glsl/ir_constant_expression.cpp | 2 +- src/glsl/ir_import_prototypes.cpp | 2 +- src/glsl/ir_print_visitor.cpp | 10 ++-------- src/glsl/ir_reader.cpp | 2 +- src/glsl/linker.cpp | 4 ++-- 8 files changed, 13 insertions(+), 18 deletions(-) (limited to 'src/glsl/ir.cpp') diff --git a/src/glsl/ir.cpp b/src/glsl/ir.cpp index 31e40cac8c..8779ec73c9 100644 --- a/src/glsl/ir.cpp +++ b/src/glsl/ir.cpp @@ -982,7 +982,6 @@ ir_function_signature::ir_function_signature(const glsl_type *return_type) : return_type(return_type), is_defined(false), _function(NULL) { this->ir_type = ir_type_function_signature; - this->is_built_in = false; } @@ -1034,6 +1033,7 @@ ir_function::ir_function(const char *name) { this->ir_type = ir_type_function; this->name = talloc_strdup(this, name); + this->is_builtin = false; } diff --git a/src/glsl/ir.h b/src/glsl/ir.h index 500b152408..0f887a9327 100644 --- a/src/glsl/ir.h +++ b/src/glsl/ir.h @@ -342,9 +342,6 @@ public: /** Whether or not this function has a body (which may be empty). */ unsigned is_defined:1; - /** Whether or not this function signature is a built-in. */ - unsigned is_built_in:1; - /** Body of instructions in the function. */ struct exec_list body; @@ -410,6 +407,9 @@ public: */ const char *name; + /** Whether or not this function is a built-in. */ + unsigned is_builtin:1; + /** * List of ir_function_signature for each overloaded function with this name. */ diff --git a/src/glsl/ir_clone.cpp b/src/glsl/ir_clone.cpp index 0a9e25a295..1d690a4da7 100644 --- a/src/glsl/ir_clone.cpp +++ b/src/glsl/ir_clone.cpp @@ -249,6 +249,8 @@ ir_function::clone(void *mem_ctx, struct hash_table *ht) const { ir_function *copy = new(mem_ctx) ir_function(this->name); + copy->is_builtin = this->is_builtin; + foreach_list_const(node, &this->signatures) { const ir_function_signature *const sig = (const ir_function_signature *const) node; @@ -271,7 +273,6 @@ ir_function_signature::clone(void *mem_ctx, struct hash_table *ht) const new(mem_ctx) ir_function_signature(this->return_type); copy->is_defined = this->is_defined; - copy->is_built_in = this->is_built_in; /* Clone the parameter list. */ diff --git a/src/glsl/ir_constant_expression.cpp b/src/glsl/ir_constant_expression.cpp index f1c175c97a..5ec60c522f 100644 --- a/src/glsl/ir_constant_expression.cpp +++ b/src/glsl/ir_constant_expression.cpp @@ -785,7 +785,7 @@ ir_call::constant_expression_value() * "Function calls to user-defined functions (non-built-in functions) * cannot be used to form constant expressions." */ - if (!this->callee->is_built_in) + if (!this->callee->function()->is_builtin) return NULL; unsigned num_parameters = 0; diff --git a/src/glsl/ir_import_prototypes.cpp b/src/glsl/ir_import_prototypes.cpp index e553e12a49..a39b384071 100644 --- a/src/glsl/ir_import_prototypes.cpp +++ b/src/glsl/ir_import_prototypes.cpp @@ -59,6 +59,7 @@ public: this->function = this->symbols->get_function(ir->name); if (!this->function) { this->function = new(this->mem_ctx) ir_function(ir->name); + this->function->is_builtin = ir->is_builtin; list->push_tail(this->function); @@ -86,7 +87,6 @@ public: new(mem_ctx) ir_function_signature(ir->return_type); copy->is_defined = false; - copy->is_built_in = ir->is_built_in; /* Clone the parameter list, but NOT the body. */ diff --git a/src/glsl/ir_print_visitor.cpp b/src/glsl/ir_print_visitor.cpp index 83e6403272..f47ad87550 100644 --- a/src/glsl/ir_print_visitor.cpp +++ b/src/glsl/ir_print_visitor.cpp @@ -153,14 +153,8 @@ void ir_print_visitor::visit(ir_function_signature *ir) void ir_print_visitor::visit(ir_function *ir) { - bool found_non_builtin_proto = false; - - foreach_iter(exec_list_iterator, iter, *ir) { - ir_function_signature *const sig = (ir_function_signature *) iter.get(); - if (sig->is_defined || !sig->is_built_in) - found_non_builtin_proto = true; - } - if (!found_non_builtin_proto) + /* Don't print built-in functions as part of the IR. */ + if (ir->is_builtin) return; printf("(function %s\n", ir->name); diff --git a/src/glsl/ir_reader.cpp b/src/glsl/ir_reader.cpp index 3e221c0e5f..366db32774 100644 --- a/src/glsl/ir_reader.cpp +++ b/src/glsl/ir_reader.cpp @@ -209,6 +209,7 @@ read_function(_mesa_glsl_parse_state *st, s_list *list, bool skip_body) ir_function *f = st->symbols->get_function(name->value()); if (f == NULL) { f = new(ctx) ir_function(name->value()); + f->is_builtin = true; added = st->symbols->add_function(f->name, f); assert(added); } @@ -281,7 +282,6 @@ read_function_sig(_mesa_glsl_parse_state *st, ir_function *f, s_list *list, if (sig == NULL && skip_body) { /* If scanning for prototypes, generate a new signature. */ sig = new(ctx) ir_function_signature(return_type); - sig->is_built_in = true; f->add_signature(sig); } else if (sig != NULL) { const char *badvar = sig->qualifiers_match(&hir_parameters); diff --git a/src/glsl/linker.cpp b/src/glsl/linker.cpp index 0348bd01e8..3de069b531 100644 --- a/src/glsl/linker.cpp +++ b/src/glsl/linker.cpp @@ -726,14 +726,14 @@ link_intrastage_shaders(GLcontext *ctx, ir_function_signature *sig = (ir_function_signature *) iter.get(); - if (!sig->is_defined || sig->is_built_in) + if (!sig->is_defined || f->is_builtin) continue; ir_function_signature *other_sig = other->exact_matching_signature(& sig->parameters); if ((other_sig != NULL) && other_sig->is_defined - && !other_sig->is_built_in) { + && !other_sig->function()->is_builtin) { linker_error_printf(prog, "function `%s' is multiply defined", f->name); -- cgit v1.2.3 From f67400d4671ce7776f71cafced6546dddecba42c Mon Sep 17 00:00:00 2001 From: Vinson Lee Date: Sat, 28 Aug 2010 23:55:51 -0700 Subject: glsl: Initialize the rest of values of ir_constant::value. Fixes valgrind uninitialized value errors in the piglit shader tests for softpipe and llvmpipe. --- src/glsl/ir.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'src/glsl/ir.cpp') diff --git a/src/glsl/ir.cpp b/src/glsl/ir.cpp index 8779ec73c9..d56b603116 100644 --- a/src/glsl/ir.cpp +++ b/src/glsl/ir.cpp @@ -326,6 +326,9 @@ ir_constant::ir_constant(float f) this->ir_type = ir_type_constant; this->type = glsl_type::float_type; this->value.f[0] = f; + for (int i = 1; i < 16; i++) { + this->value.f[i] = 0; + } } ir_constant::ir_constant(unsigned int u) @@ -333,6 +336,9 @@ ir_constant::ir_constant(unsigned int u) this->ir_type = ir_type_constant; this->type = glsl_type::uint_type; this->value.u[0] = u; + for (int i = 1; i < 16; i++) { + this->value.u[i] = 0; + } } ir_constant::ir_constant(int i) @@ -340,6 +346,9 @@ ir_constant::ir_constant(int i) this->ir_type = ir_type_constant; this->type = glsl_type::int_type; this->value.i[0] = i; + for (int i = 1; i < 16; i++) { + this->value.i[i] = 0; + } } ir_constant::ir_constant(bool b) @@ -347,6 +356,9 @@ ir_constant::ir_constant(bool b) this->ir_type = ir_type_constant; this->type = glsl_type::bool_type; this->value.b[0] = b; + for (int i = 1; i < 16; i++) { + this->value.b[i] = false; + } } ir_constant::ir_constant(const ir_constant *c, unsigned i) -- cgit v1.2.3 From 30a086552827b82738421ff2d562e3c8c1da2735 Mon Sep 17 00:00:00 2001 From: Vinson Lee Date: Sun, 29 Aug 2010 13:15:56 -0700 Subject: glsl: Completely initialize value member in ir_constant constructor. The ir_constant::ir_constant(const struct glsl_type *type, exec_list *value_list) did not completely initialize the entire value member. Fixes piglit glsl-fs-sampler-numbering-2 valgrind uninitialized value error in softpipe and llvmpipe. --- src/glsl/ir.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src/glsl/ir.cpp') diff --git a/src/glsl/ir.cpp b/src/glsl/ir.cpp index d56b603116..992853c046 100644 --- a/src/glsl/ir.cpp +++ b/src/glsl/ir.cpp @@ -409,6 +409,9 @@ ir_constant::ir_constant(const struct glsl_type *type, exec_list *value_list) return; } + for (unsigned i = 0; i < 16; i++) { + this->value.u[i] = 0; + } ir_constant *value = (ir_constant *) (value_list->head); -- cgit v1.2.3 From a4262874f84e25412cb9bc53b3f1771e4017e27c Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Wed, 1 Sep 2010 10:12:55 -0700 Subject: glsl2: Allow ir_constant::zero to create boolean constants --- src/glsl/ir.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/glsl/ir.cpp') diff --git a/src/glsl/ir.cpp b/src/glsl/ir.cpp index 992853c046..5bd023f499 100644 --- a/src/glsl/ir.cpp +++ b/src/glsl/ir.cpp @@ -454,7 +454,7 @@ ir_constant::ir_constant(const struct glsl_type *type, exec_list *value_list) ir_constant * ir_constant::zero(void *mem_ctx, const glsl_type *type) { - assert(type->is_numeric()); + assert(type->is_numeric() || type->is_boolean()); ir_constant *c = new(mem_ctx) ir_constant; c->type = type; -- cgit v1.2.3 From 1f7c7df40f830e164f96df4468a2b4fa365c4b84 Mon Sep 17 00:00:00 2001 From: Kenneth Graunke Date: Wed, 1 Sep 2010 15:31:06 -0700 Subject: glsl: Move generate_constructor_(matrix|vector) to ir_constant ctor. --- src/glsl/ast_function.cpp | 100 +--------------------------------------------- src/glsl/ir.cpp | 35 ++++++++++++++++ 2 files changed, 36 insertions(+), 99 deletions(-) (limited to 'src/glsl/ir.cpp') diff --git a/src/glsl/ast_function.cpp b/src/glsl/ast_function.cpp index 0c9f890038..f639b8a1ba 100644 --- a/src/glsl/ast_function.cpp +++ b/src/glsl/ast_function.cpp @@ -469,79 +469,6 @@ constant_record_constructor(const glsl_type *constructor_type, } -/** - * Generate data for a constant matrix constructor w/a single scalar parameter - * - * Matrix constructors in GLSL can be passed a single scalar of the - * approriate type. In these cases, the resulting matrix is the identity - * matrix multipled by the specified scalar. This function generates data for - * that matrix. - * - * \param type Type of the desired matrix. - * \param initializer Scalar value used to initialize the matrix diagonal. - * \param data Location to store the resulting matrix. - */ -void -generate_constructor_matrix(const glsl_type *type, ir_constant *initializer, - ir_constant_data *data) -{ - assert(type->base_type == GLSL_TYPE_FLOAT); - assert(initializer->type->is_scalar()); - - for (unsigned i = 0; i < type->components(); i++) - data->f[i] = 0; - - for (unsigned i = 0; i < type->matrix_columns; i++) { - /* The array offset of the ith row and column of the matrix. */ - const unsigned idx = (i * type->vector_elements) + i; - - data->f[idx] = initializer->value.f[0]; - } -} - - -/** - * Generate data for a constant vector constructor w/a single scalar parameter - * - * Vector constructors in GLSL can be passed a single scalar of the - * approriate type. In these cases, the resulting vector contains the specified - * value in all components. This function generates data for that vector. - * - * \param type Type of the desired vector. - * \param initializer Scalar value used to initialize the vector. - * \param data Location to store the resulting vector data. - */ -void -generate_constructor_vector(const glsl_type *type, ir_constant *initializer, - ir_constant_data *data) -{ - switch (type->base_type) { - case GLSL_TYPE_UINT: - case GLSL_TYPE_INT: - for (unsigned i = 0; i < type->components(); i++) - data->u[i] = initializer->value.u[0]; - - break; - - case GLSL_TYPE_FLOAT: - for (unsigned i = 0; i < type->components(); i++) - data->f[i] = initializer->value.f[0]; - - break; - - case GLSL_TYPE_BOOL: - for (unsigned i = 0; i < type->components(); i++) - data->b[i] = initializer->value.b[0]; - - break; - - default: - assert(!"Should not get here."); - break; - } -} - - /** * Determine if a list consists of a single scalar r-value */ @@ -1219,32 +1146,7 @@ ast_function_expression::hir(exec_list *instructions, * constant representing the complete collection of parameters. */ if (all_parameters_are_constant) { - if (components_used >= type_components) - return new(ctx) ir_constant(constructor_type, - & actual_parameters); - - /* The above case must handle all scalar constructors. - */ - assert(constructor_type->is_vector() - || constructor_type->is_matrix()); - - /* Constructors with exactly one component are special for - * vectors and matrices. For vectors it causes all elements of - * the vector to be filled with the value. For matrices it - * causes the matrix to be filled with 0 and the diagonal to be - * filled with the value. - */ - ir_constant_data data = { { 0 } }; - ir_constant *const initializer = - (ir_constant *) actual_parameters.head; - if (constructor_type->is_matrix()) - generate_constructor_matrix(constructor_type, initializer, - &data); - else - generate_constructor_vector(constructor_type, initializer, - &data); - - return new(ctx) ir_constant(constructor_type, &data); + return new(ctx) ir_constant(constructor_type, &actual_parameters); } else if (constructor_type->is_scalar()) { return dereference_component((ir_rvalue *) actual_parameters.head, 0); diff --git a/src/glsl/ir.cpp b/src/glsl/ir.cpp index 5bd023f499..aee44a77c9 100644 --- a/src/glsl/ir.cpp +++ b/src/glsl/ir.cpp @@ -415,6 +415,41 @@ ir_constant::ir_constant(const struct glsl_type *type, exec_list *value_list) ir_constant *value = (ir_constant *) (value_list->head); + /* Constructors with exactly one scalar argument are special for vectors + * and matrices. For vectors, the scalar value is replicated to fill all + * the components. For matrices, the scalar fills the components of the + * diagonal while the rest is filled with 0. + */ + if (value->type->is_scalar() && value->next->is_tail_sentinel()) { + if (type->is_matrix()) { + /* Matrix - fill diagonal (rest is already set to 0) */ + assert(type->base_type == GLSL_TYPE_FLOAT); + for (unsigned i = 0; i < type->matrix_columns; i++) + this->value.f[i * type->vector_elements + i] = value->value.f[0]; + } else { + /* Vector or scalar - fill all components */ + switch (type->base_type) { + case GLSL_TYPE_UINT: + case GLSL_TYPE_INT: + for (unsigned i = 0; i < type->components(); i++) + this->value.u[i] = value->value.u[0]; + break; + case GLSL_TYPE_FLOAT: + for (unsigned i = 0; i < type->components(); i++) + this->value.f[i] = value->value.f[0]; + break; + case GLSL_TYPE_BOOL: + for (unsigned i = 0; i < type->components(); i++) + this->value.b[i] = value->value.b[0]; + break; + default: + assert(!"Should not get here."); + break; + } + } + return; + } + /* Use each component from each entry in the value_list to initialize one * component of the constant being constructed. */ -- cgit v1.2.3 From 54b35e673596d767a13f06f4d7ec1089e18fd46e Mon Sep 17 00:00:00 2001 From: Kenneth Graunke Date: Wed, 1 Sep 2010 15:37:13 -0700 Subject: glsl: Add proper handling for constant matrix-from-matrix constructors. Fixes piglit test case constructor-21.vert and changes constructor-22.vert to give the correct output. --- src/glsl/ir.cpp | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) (limited to 'src/glsl/ir.cpp') diff --git a/src/glsl/ir.cpp b/src/glsl/ir.cpp index aee44a77c9..68ad512bf5 100644 --- a/src/glsl/ir.cpp +++ b/src/glsl/ir.cpp @@ -450,6 +450,31 @@ ir_constant::ir_constant(const struct glsl_type *type, exec_list *value_list) return; } + if (type->is_matrix() && value->type->is_matrix()) { + assert(value->next->is_tail_sentinel()); + + /* From section 5.4.2 of the GLSL 1.20 spec: + * "If a matrix is constructed from a matrix, then each component + * (column i, row j) in the result that has a corresponding component + * (column i, row j) in the argument will be initialized from there." + */ + unsigned cols = MIN2(type->matrix_columns, value->type->matrix_columns); + unsigned rows = MIN2(type->vector_elements, value->type->vector_elements); + for (unsigned i = 0; i < cols; i++) { + for (unsigned j = 0; j < rows; j++) { + const unsigned src = i * value->type->vector_elements + j; + const unsigned dst = i * type->vector_elements + j; + this->value.f[dst] = value->value.f[src]; + } + } + + /* "All other components will be initialized to the identity matrix." */ + for (unsigned i = cols; i < type->matrix_columns; i++) + this->value.f[i * type->vector_elements + i] = 1.0; + + return; + } + /* Use each component from each entry in the value_list to initialize one * component of the constant being constructed. */ -- cgit v1.2.3