summaryrefslogtreecommitdiffstats
path: root/src/glsl
diff options
context:
space:
mode:
Diffstat (limited to 'src/glsl')
-rw-r--r--src/glsl/ir.h26
-rw-r--r--src/glsl/ir_clone.cpp12
-rw-r--r--src/glsl/ir_variable.cpp46
-rw-r--r--src/glsl/linker.cpp13
4 files changed, 94 insertions, 3 deletions
diff --git a/src/glsl/ir.h b/src/glsl/ir.h
index 39d4ebc7107..a41984310b3 100644
--- a/src/glsl/ir.h
+++ b/src/glsl/ir.h
@@ -253,6 +253,16 @@ enum ir_depth_layout {
const char*
depth_layout_string(ir_depth_layout layout);
+/**
+ * Description of built-in state associated with a uniform
+ *
+ * \sa ir_variable::state_slots
+ */
+struct ir_state_slot {
+ int tokens[5];
+ int swizzle;
+};
+
class ir_variable : public ir_instruction {
public:
ir_variable(const struct glsl_type *, const char *, ir_variable_mode);
@@ -386,6 +396,22 @@ public:
int location;
/**
+ * Built-in state that backs this uniform
+ *
+ * Once set at variable creation, \c state_slots must remain invariant.
+ * This is because, ideally, this array would be shared by all clones of
+ * this variable in the IR tree. In other words, we'd really like for it
+ * to be a fly-weight.
+ *
+ * If the variable is not a uniform, \c num_state_slots will be zero and
+ * \c state_slots will be \c NULL.
+ */
+ /*@{*/
+ unsigned num_state_slots; /**< Number of state slots used */
+ ir_state_slot *state_slots; /**< State descriptors. */
+ /*@}*/
+
+ /**
* Emit a warning if this variable is accessed.
*/
const char *warn_extension;
diff --git a/src/glsl/ir_clone.cpp b/src/glsl/ir_clone.cpp
index 2c0574dc6bf..069bb85e8de 100644
--- a/src/glsl/ir_clone.cpp
+++ b/src/glsl/ir_clone.cpp
@@ -53,6 +53,18 @@ ir_variable::clone(void *mem_ctx, struct hash_table *ht) const
var->origin_upper_left = this->origin_upper_left;
var->pixel_center_integer = this->pixel_center_integer;
var->explicit_location = this->explicit_location;
+
+ var->num_state_slots = this->num_state_slots;
+ if (this->state_slots) {
+ /* FINISHME: This really wants to use something like talloc_reference, but
+ * FINISHME: ralloc doesn't have any similar function.
+ */
+ var->state_slots = ralloc_array(var, ir_state_slot,
+ this->num_state_slots);
+ memcpy(var->state_slots, this->state_slots,
+ sizeof(this->state_slots[0]) * var->num_state_slots);
+ }
+
if (this->explicit_location)
var->location = this->location;
diff --git a/src/glsl/ir_variable.cpp b/src/glsl/ir_variable.cpp
index c2715254a59..f3577175691 100644
--- a/src/glsl/ir_variable.cpp
+++ b/src/glsl/ir_variable.cpp
@@ -327,7 +327,43 @@ static ir_variable *
add_uniform(exec_list *instructions, glsl_symbol_table *symtab,
const char *name, const glsl_type *type)
{
- return add_variable(instructions, symtab, name, type, ir_var_uniform, -1);
+ ir_variable *const uni =
+ add_variable(instructions, symtab, name, type, ir_var_uniform, -1);
+
+ unsigned i;
+ for (i = 0; _mesa_builtin_uniform_desc[i].name != NULL; i++) {
+ if (strcmp(_mesa_builtin_uniform_desc[i].name, name) == 0) {
+ break;
+ }
+ }
+
+ assert(_mesa_builtin_uniform_desc[i].name != NULL);
+ const struct gl_builtin_uniform_desc* const statevar =
+ &_mesa_builtin_uniform_desc[i];
+
+ const unsigned array_count = type->is_array() ? type->length : 1;
+ uni->num_state_slots = array_count * statevar->num_elements;
+
+ ir_state_slot *slots =
+ ralloc_array(uni, ir_state_slot, uni->num_state_slots);
+
+ uni->state_slots = slots;
+
+ for (unsigned a = 0; a < array_count; a++) {
+ for (unsigned j = 0; j < statevar->num_elements; j++) {
+ struct gl_builtin_uniform_element *element = &statevar->elements[j];
+
+ memcpy(slots->tokens, element->tokens, sizeof(element->tokens));
+ if (type->is_array()) {
+ slots->tokens[1] = a;
+ }
+
+ slots->swizzle = element->swizzle;
+ slots++;
+ }
+ }
+
+ return uni;
}
static void
@@ -341,8 +377,12 @@ add_builtin_variable(exec_list *instructions, glsl_symbol_table *symtab,
assert(type != NULL);
- add_variable(instructions, symtab, proto->name, type, proto->mode,
- proto->slot);
+ if (proto->mode == ir_var_uniform) {
+ add_uniform(instructions, symtab, proto->name, type);
+ } else {
+ add_variable(instructions, symtab, proto->name, type, proto->mode,
+ proto->slot);
+ }
}
static void
diff --git a/src/glsl/linker.cpp b/src/glsl/linker.cpp
index 7db5c5e8d53..17492357f2d 100644
--- a/src/glsl/linker.cpp
+++ b/src/glsl/linker.cpp
@@ -994,6 +994,19 @@ update_array_sizes(struct gl_shader_program *prog)
}
if (size + 1 != var->type->fields.array->length) {
+ /* If this is a built-in uniform (i.e., it's backed by some
+ * fixed-function state), adjust the number of state slots to
+ * match the new array size. The number of slots per array entry
+ * is not known. It seems saft to assume that the total number of
+ * slots is an integer multiple of the number of array elements.
+ * Determine the number of slots per array element by dividing by
+ * the old (total) size.
+ */
+ if (var->num_state_slots > 0) {
+ var->num_state_slots = (size + 1)
+ * (var->num_state_slots / var->type->length);
+ }
+
var->type = glsl_type::get_array_instance(var->type->fields.array,
size + 1);
/* FINISHME: We should update the types of array