aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric Anholt <[email protected]>2010-08-02 14:32:52 -0700
committerEric Anholt <[email protected]>2010-08-02 17:47:35 -0700
commit26675e37bc5a086c6df77946d2dada34dc9129f0 (patch)
treec6f7378f3b204ae6bfcbb9b7a8f7a17730a05237
parent9c02412cdc0270f2b0dc64afe709721e049fd5b0 (diff)
ir_to_mesa: Support for struct uniforms.
Fixes glsl-uniform-struct.
-rw-r--r--src/mesa/program/ir_to_mesa.cpp78
1 files changed, 78 insertions, 0 deletions
diff --git a/src/mesa/program/ir_to_mesa.cpp b/src/mesa/program/ir_to_mesa.cpp
index 5510440475d..7d5761f6996 100644
--- a/src/mesa/program/ir_to_mesa.cpp
+++ b/src/mesa/program/ir_to_mesa.cpp
@@ -252,6 +252,11 @@ public:
GLboolean try_emit_mad(ir_expression *ir,
int mul_operand);
+ void add_aggregate_uniform(ir_instruction *ir,
+ const char *name,
+ const struct glsl_type *type,
+ struct ir_to_mesa_dst_reg temp);
+
int *sampler_map;
int sampler_map_size;
@@ -1241,6 +1246,62 @@ get_builtin_matrix_ref(void *mem_ctx, struct gl_program *prog, ir_variable *var,
return NULL;
}
+/* Recursively add all the members of the aggregate uniform as uniform names
+ * to Mesa, moving those uniforms to our structured temporary.
+ */
+void
+ir_to_mesa_visitor::add_aggregate_uniform(ir_instruction *ir,
+ const char *name,
+ const struct glsl_type *type,
+ struct ir_to_mesa_dst_reg temp)
+{
+ int loc;
+
+ if (type->is_record()) {
+ void *mem_ctx = talloc_new(NULL);
+
+ for (unsigned int i = 0; i < type->length; i++) {
+ const glsl_type *field_type = type->fields.structure[i].type;
+ add_aggregate_uniform(ir,
+ talloc_asprintf(mem_ctx, "%s.%s", name,
+ type->fields.structure[i].name),
+ field_type, temp);
+ temp.index += type_size(field_type);
+ }
+
+ talloc_free(mem_ctx);
+
+ return;
+ }
+
+ assert(type->is_vector() || type->is_scalar() || !"FINISHME: other types");
+
+ int len;
+
+ if (type->is_vector() ||
+ type->is_scalar()) {
+ len = type->vector_elements;
+ } else {
+ len = type_size(type) * 4;
+ }
+
+ loc = _mesa_add_uniform(this->prog->Parameters,
+ name,
+ len,
+ type->gl_type,
+ NULL);
+
+
+ ir_to_mesa_src_reg uniform(PROGRAM_UNIFORM, loc, type);
+
+ for (int i = 0; i < type_size(type); i++) {
+ ir_to_mesa_emit_op1(ir, OPCODE_MOV, temp, uniform);
+ temp.index++;
+ uniform.index++;
+ }
+}
+
+
void
ir_to_mesa_visitor::visit(ir_dereference_variable *ir)
{
@@ -1276,6 +1337,23 @@ ir_to_mesa_visitor::visit(ir_dereference_variable *ir)
assert(ir->var->type->gl_type != 0 &&
ir->var->type->gl_type != GL_INVALID_ENUM);
+ /* Oh, the joy of aggregate types in Mesa. Like constants,
+ * we can only really do vec4s. So, make a temp, chop the
+ * aggregate up into vec4s, and move those vec4s to the temp.
+ */
+ if (ir->var->type->is_record()) {
+ ir_to_mesa_src_reg temp = get_temp(ir->var->type);
+
+ entry = new(mem_ctx) variable_storage(ir->var,
+ temp.file,
+ temp.index);
+ this->variables.push_tail(entry);
+
+ add_aggregate_uniform(ir->var, ir->var->name, ir->var->type,
+ ir_to_mesa_dst_reg_from_src(temp));
+ break;
+ }
+
if (ir->var->type->is_vector() ||
ir->var->type->is_scalar()) {
len = ir->var->type->vector_elements;