summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric Anholt <eric@anholt.net>2010-09-28 09:31:56 -0700
committerEric Anholt <eric@anholt.net>2010-09-28 09:33:31 -0700
commit6bf12c8b7366a9db8c88b9cacaa06266b41a73b5 (patch)
tree0ce71a69e498e39ffd2a5ebad9c326d15c9eb14c
parentba481f2046e6427c8bd7fc5f8cb8ef3059a7881a (diff)
i965: Add support for struct, array, and matrix uniforms to FS backend.
Fixes 16 piglit cases.
-rw-r--r--src/mesa/drivers/dri/i965/brw_fs.cpp75
1 files changed, 60 insertions, 15 deletions
diff --git a/src/mesa/drivers/dri/i965/brw_fs.cpp b/src/mesa/drivers/dri/i965/brw_fs.cpp
index 4f88ca10c19..4a63fc61aaa 100644
--- a/src/mesa/drivers/dri/i965/brw_fs.cpp
+++ b/src/mesa/drivers/dri/i965/brw_fs.cpp
@@ -453,6 +453,7 @@ public:
void emit_fb_writes();
struct brw_reg interp_reg(int location, int channel);
+ int setup_uniform_values(int loc, const glsl_type *type);
struct brw_context *brw;
struct intel_context *intel;
@@ -541,6 +542,64 @@ fs_visitor::variable_storage(ir_variable *var)
return (fs_reg *)hash_table_find(this->variable_ht, var);
}
+/* Our support for uniforms is piggy-backed on the struct
+ * gl_fragment_program, because that's where the values actually
+ * get stored, rather than in some global gl_shader_program uniform
+ * store.
+ */
+int
+fs_visitor::setup_uniform_values(int loc, const glsl_type *type)
+{
+ const struct gl_program *fp = &this->brw->fragment_program->Base;
+ unsigned int offset = 0;
+ float *vec_values;
+
+ if (type->is_matrix()) {
+ const glsl_type *column = glsl_type::get_instance(GLSL_TYPE_FLOAT,
+ type->vector_elements,
+ 1);
+
+ for (unsigned int i = 0; i < type->matrix_columns; i++) {
+ offset += setup_uniform_values(loc + offset, column);
+ }
+
+ return offset;
+ }
+
+ switch (type->base_type) {
+ case GLSL_TYPE_FLOAT:
+ case GLSL_TYPE_UINT:
+ case GLSL_TYPE_INT:
+ case GLSL_TYPE_BOOL:
+ vec_values = fp->Parameters->ParameterValues[loc];
+ for (unsigned int i = 0; i < type->vector_elements; i++) {
+ c->prog_data.param[c->prog_data.nr_params++] = &vec_values[i];
+ }
+ return 1;
+
+ case GLSL_TYPE_STRUCT:
+ for (unsigned int i = 0; i < type->length; i++) {
+ offset += setup_uniform_values(loc + offset,
+ type->fields.structure[i].type);
+ }
+ return offset;
+
+ case GLSL_TYPE_ARRAY:
+ for (unsigned int i = 0; i < type->length; i++) {
+ offset += setup_uniform_values(loc + offset, type->fields.array);
+ }
+ return offset;
+
+ case GLSL_TYPE_SAMPLER:
+ /* The sampler takes up a slot, but we don't use any values from it. */
+ return 1;
+
+ default:
+ assert(!"not reached");
+ return 0;
+ }
+}
+
void
fs_visitor::visit(ir_variable *ir)
{
@@ -560,23 +619,9 @@ fs_visitor::visit(ir_variable *ir)
}
if (ir->mode == ir_var_uniform) {
- const float *vec_values;
int param_index = c->prog_data.nr_params;
- /* FINISHME: This is wildly incomplete. */
- assert(ir->type->is_scalar() || ir->type->is_vector() ||
- ir->type->is_sampler());
-
- const struct gl_program *fp = &this->brw->fragment_program->Base;
- /* Our support for uniforms is piggy-backed on the struct
- * gl_fragment_program, because that's where the values actually
- * get stored, rather than in some global gl_shader_program uniform
- * store.
- */
- vec_values = fp->Parameters->ParameterValues[ir->location];
- for (unsigned int i = 0; i < ir->type->vector_elements; i++) {
- c->prog_data.param[c->prog_data.nr_params++] = &vec_values[i];
- }
+ setup_uniform_values(ir->location, ir->type);
reg = new(this->mem_ctx) fs_reg(UNIFORM, param_index);
}