glsl: Add a "ubo_load" expression type for fetches from UBOs.
authorEric Anholt <eric@anholt.net>
Mon, 9 Jul 2012 22:52:53 +0000 (15:52 -0700)
committerEric Anholt <eric@anholt.net>
Tue, 7 Aug 2012 18:47:49 +0000 (11:47 -0700)
Drivers will probably want to be able to take UBO references in a
shader like:

        uniform ubo1 {
                float a;
                float b;
                float c;
                float d;
        }

        void main() {
             gl_FragColor = vec4(a, b, c, d);
        }

and generate a single aligned vec4 load out of the UBO.  For intel,
this involves recognizing the shared offset of the aligned loads and
CSEing them out.  Obviously that involves breaking things down to
loads from an offset from a particular UBO first.  Thus, the driver
doesn't want to see

variable_ref(ir_variable("a")),

and even more so does it not want to see

array_ref(record_ref(variable_ref(ir_variable("a")),
          "field1"), variable_ref(ir_variable("i"))).

where a.field1[i] is a row_major matrix.

Instead, we're going to make a lowering pass to break UBO references
down to expressions that are obvious to codegen, and amenable to
merging through CSE.

v2: Fix some partial thoughts in the ir_binop comment (review by Kenneth)

Reviewed-by: Ian Romanick <ian.d.romanick@intel.com>
Reviewed-by: Kenneth Graunke <kenneth@whitecape.org>
src/glsl/ir.cpp
src/glsl/ir.h
src/glsl/ir_validate.cpp
src/mesa/drivers/dri/i965/brw_fs_channel_expressions.cpp
src/mesa/drivers/dri/i965/brw_fs_visitor.cpp
src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp
src/mesa/program/ir_to_mesa.cpp
src/mesa/state_tracker/st_glsl_to_tgsi.cpp

index b0e38d820e6b9dd6bb721a3a831ec7551fb0142e..f59cdd29ab8a98722cbf8054e39a03765207bd10 100644 (file)
@@ -480,6 +480,7 @@ static const char *const operator_strs[] = {
    "min",
    "max",
    "pow",
+   "ubo_load",
    "vector",
 };
 
index f019837d5f7f14cf5e728e9f3251ce2df09d28b6..89c516c877d166ebac04fd594e028717b9ca5ff6 100644 (file)
@@ -1017,10 +1017,18 @@ enum ir_expression_operation {
 
    ir_binop_pow,
 
+   /**
+    * Load a value the size of a given GLSL type from a uniform block.
+    *
+    * operand0 is the ir_constant uniform block index in the linked shader.
+    * operand1 is a byte offset within the uniform block.
+    */
+   ir_binop_ubo_load,
+
    /**
     * A sentinel marking the last of the binary operations.
     */
-   ir_last_binop = ir_binop_pow,
+   ir_last_binop = ir_binop_ubo_load,
 
    ir_quadop_vector,
 
index 191d398310978f0eb0999d7a4c2b2cbd8afbf655..af0b5768ac08a465a5f55d3bf4060935bb5cc5b7 100644 (file)
@@ -423,6 +423,13 @@ ir_validate::visit_leave(ir_expression *ir)
       assert(ir->operands[0]->type == ir->operands[1]->type);
       break;
 
+   case ir_binop_ubo_load:
+      assert(ir->operands[0]->as_constant());
+      assert(ir->operands[0]->type == glsl_type::uint_type);
+
+      assert(ir->operands[1]->type == glsl_type::uint_type);
+      break;
+
    case ir_quadop_vector:
       /* The vector operator collects some number of scalars and generates a
        * vector from them.
index 983d92e971db24cb30708c6b4b407b2dc1462283..58521ee6e6d3c3856e09ad3baedd96371b78ccc1 100644 (file)
@@ -337,6 +337,11 @@ ir_channel_expressions_visitor::visit_leave(ir_assignment *ir)
    case ir_unop_noise:
       assert(!"noise should have been broken down to function call");
       break;
+
+   case ir_binop_ubo_load:
+      assert(!"not yet supported");
+      break;
+
    case ir_quadop_vector:
       assert(!"should have been lowered");
       break;
index f5090fae3c1e59376cc48ed530c69596c75930d8..1e18e92de54ad294849775d1926a5d1272e32c83 100644 (file)
@@ -571,6 +571,10 @@ fs_visitor::visit(ir_expression *ir)
       else
         inst = emit(BRW_OPCODE_SHR, this->result, op[0], op[1]);
       break;
+
+   case ir_binop_ubo_load:
+      assert(!"not yet supported");
+      break;
    }
 }
 
index 9ae99b4b3acf8b0348d7c9f944bfb7a70b42c045..8a4a1b0721ee7fcbf7148e3318697451aeb8ec3c 100644 (file)
@@ -1314,6 +1314,10 @@ vec4_visitor::visit(ir_expression *ir)
         inst = emit(BRW_OPCODE_SHR, result_dst, op[0], op[1]);
       break;
 
+   case ir_binop_ubo_load:
+      assert(!"not yet supported");
+      break;
+
    case ir_quadop_vector:
       assert(!"not reached: should be handled by lower_quadop_vector");
       break;
index 255a8a76a0f007786eafd836ed5069047ecb5bcf..70c4cc8aec154c34d55e7e2cd94892ee796412d3 100644 (file)
@@ -1456,6 +1456,10 @@ ir_to_mesa_visitor::visit(ir_expression *ir)
       emit(ir, OPCODE_MOV, result_dst, op[0]);
       break;
 
+   case ir_binop_ubo_load:
+      assert(!"not supported");
+      break;
+
    case ir_quadop_vector:
       /* This operation should have already been handled.
        */
index 66627acb6fc27024d2df478720939c120eaa2d00..43c80be13e2066cbe105384147fc47d45d90080c 100644 (file)
@@ -1867,6 +1867,10 @@ glsl_to_tgsi_visitor::visit(ir_expression *ir)
       assert(!"GLSL 1.30 features unsupported");
       break;
 
+   case ir_binop_ubo_load:
+      assert(!"not yet supported");
+      break;
+
    case ir_quadop_vector:
       /* This operation should have already been handled.
        */