checkpoint overhaul of pre-defined uniform code
authorBrian <brian@yutani.localnet.net>
Wed, 21 Feb 2007 16:15:39 +0000 (09:15 -0700)
committerBrian <brian@yutani.localnet.net>
Wed, 21 Feb 2007 16:15:39 +0000 (09:15 -0700)
src/mesa/shader/slang/slang_builtin.c
src/mesa/shader/slang/slang_builtin.h
src/mesa/shader/slang/slang_codegen.c
src/mesa/shader/slang/slang_emit.c

index a92efa8..b4aecdb 100644 (file)
@@ -152,6 +152,10 @@ _slang_lookup_statevar(const char *name, GLint index,
       { "gl_BackLightModelProduct.sceneColor", 1, SWIZZLE_NOOP,
         { STATE_LIGHTMODEL_SCENECOLOR, 1, 0, 0, 0, 0 } },
 
+      { "gl_FrontLightProduct", 1, SWIZZLE_NOOP,
+        { STATE_LIGHTPROD, 0, STATE_AMBIENT, 0, 0, 0 } },
+
+
       { "gl_Fog", 1, SWIZZLE_NOOP,
         { STATE_FOG_COLOR, 0, 0, 0, 0, 0 } },
       { "gl_Fog.color", 1, SWIZZLE_NOOP,
@@ -165,6 +169,8 @@ _slang_lookup_statevar(const char *name, GLint index,
       { "gl_Fog.scale", 1, SWIZZLE_WWWW,
         { STATE_FOG_PARAMS, 0, 0, 0, 0, 0 } },
 
+      { "gl_ClipPlane", 1, SWIZZLE_NOOP,
+        { STATE_CLIPPLANE, 0, 0, 0, 0, 0 } },
 
       { NULL, 0, 0, {0, 0, 0, 0, 0, 0} }
    };
@@ -230,3 +236,189 @@ _slang_lookup_statevar_field(const char *base, const char *field,
 }
 
 
+struct field_info {
+   const char *Name;
+   gl_state_index Token;
+   GLint TokenPos;
+   GLuint Swizzle;
+};
+
+#define MT_FIELD { NULL, 0, -1, 0 }
+#define MAX_FIELDS 5
+#define INDEX_POS 1000
+
+struct state_uniform_info {
+   const char *Name;
+   gl_state_index StateTokens[2];
+   struct field_info Fields[MAX_FIELDS];
+};
+
+
+
+static const struct state_uniform_info Uniforms[] = {
+   { "gl_ModelViewMatrix", { STATE_MATRIX, STATE_MODELVIEW },
+     { MT_FIELD, MT_FIELD, MT_FIELD, MT_FIELD, MT_FIELD}
+   },
+   { "gl_ProjectionMatrix", { STATE_MATRIX, STATE_PROJECTION },
+     { MT_FIELD, MT_FIELD, MT_FIELD, MT_FIELD, MT_FIELD}
+   },
+   { "gl_ModelViewProjectionMatrix", { STATE_MATRIX, STATE_MVP },
+     { MT_FIELD, MT_FIELD, MT_FIELD, MT_FIELD, MT_FIELD}
+   },
+   { "gl_NormalMatrix", { STATE_MATRIX, STATE_MODELVIEW },
+     { MT_FIELD, MT_FIELD, MT_FIELD, MT_FIELD, MT_FIELD}
+   },
+   { "gl_TextureMatrix", { STATE_MATRIX, STATE_TEXTURE },
+     { MT_FIELD, MT_FIELD, MT_FIELD, MT_FIELD, MT_FIELD}
+   },
+
+   { "gl_ClipPlane", { STATE_CLIPPLANE, INDEX_POS },
+     { MT_FIELD, MT_FIELD, MT_FIELD, MT_FIELD, MT_FIELD}
+   },
+
+   { "gl_DepthRange", { STATE_DEPTH_RANGE, 0 },
+     {
+        { "near", 0, -1, SWIZZLE_XXXX },
+        { "far", 0, -1, SWIZZLE_YYYY },
+        { "diff", 0, -1, SWIZZLE_ZZZZ },
+        MT_FIELD,
+        MT_FIELD
+     }
+   },
+
+   { "gl_Fog", { 0, 0 },
+     {
+        { "color", STATE_FOG_COLOR, 0, SWIZZLE_NOOP },
+        { "density", STATE_FOG_PARAMS, 0, SWIZZLE_XXXX },
+        { "start", STATE_FOG_PARAMS, 0, SWIZZLE_YYYY },
+        { "end", STATE_FOG_PARAMS, 0, SWIZZLE_ZZZZ },
+        { "scale", STATE_FOG_PARAMS, 0, SWIZZLE_WWWW }
+     }
+   },
+
+   { NULL, { 0, 0 },
+     { MT_FIELD, MT_FIELD, MT_FIELD, MT_FIELD, MT_FIELD }
+   }
+};
+
+
+static GLint
+lookup_statevar(const char *var, GLint index, const char *field,
+                GLuint *swizzleOut,
+                struct gl_program_parameter_list *paramList)
+{
+   gl_state_index tokens[STATE_LENGTH];
+   GLuint i, j;
+   GLint pos;
+
+   for (i = 0; i < STATE_LENGTH; i++) {
+      tokens[i] = 0;
+   }
+
+   for (i = 0; Uniforms[i].Name; i++) {
+      if (strcmp(var, Uniforms[i].Name) == 0) {
+         /* found the uniform */
+
+         for (j = 0; j < 2; j++) {
+            tokens[j] = Uniforms[i].StateTokens[j];
+            if (tokens[j] == INDEX_POS) {
+               /* replace INDEX_POS with actual array index */
+               assert(index >= 0);
+               tokens[j] = index;
+            }
+         }
+
+         if (field) {
+            /* extra work for var.field */
+            for (j = 0; j < MAX_FIELDS; j++) {
+               if (!Uniforms[i].Fields[j].Name) {
+                  /* field not found! */
+                  _mesa_problem(NULL, "field not found");
+                  return -1;
+               }
+               else if (strcmp(field, Uniforms[i].Fields[j].Name) == 0) {
+                  /* found the field */
+                  GLint tokenPos = Uniforms[i].Fields[j].TokenPos;
+                  if (tokenPos>= 0) {
+                     tokens[tokenPos] = Uniforms[i].Fields[j].Token;
+                  }
+                  *swizzleOut = Uniforms[i].Fields[j].Swizzle;
+                  break;
+               }
+
+            }
+         }
+
+         if (tokens[0] == STATE_MATRIX) {
+            /* a matrix */
+            GLuint j;
+            GLint pos[4];
+            gl_state_index indexesCopy[STATE_LENGTH];
+            /* make copy of state tokens */
+            for (j = 0; j < STATE_LENGTH; j++)
+               indexesCopy[j] = tokens[j];
+            /* load rows */
+            for (j = 0; j < 4/*state[i].NumRows*/; j++) {
+               indexesCopy[3] = indexesCopy[4] = j; /* jth row of matrix */
+               pos[j] = _mesa_add_state_reference(paramList, (GLint*) indexesCopy);
+               assert(pos[j] >= 0);
+            }
+            return pos[0] + index;
+         }
+
+         pos = _mesa_add_state_reference(paramList, (GLint *) tokens);
+         assert(pos >= 0);
+         return pos;
+      }
+   }
+   return -1;
+}
+
+
+
+/**
+ * Allocate storage for a pre-defined uniform (a GL state variable).
+ * As a memory-saving optimization, we try to only allocate storage for
+ * state vars that are actually used.
+ * For example, the "gl_LightSource" uniform is huge.  If we only use
+ * a handful of gl_LightSource fields, we don't want to allocate storage
+ * for all of gl_LightSource.
+ *
+ * Currently, all pre-defined uniforms are in one of these forms:
+ *   var
+ *   var[index]
+ *   var.field
+ *   var[index].field
+ */
+GLint
+_slang_alloc_statevar(slang_ir_node *n,
+                      struct gl_program_parameter_list *paramList)
+{
+   const char *field = NULL, *var;
+   GLint index = -1, pos;
+   GLuint swizzle;
+
+   if (n->Opcode == IR_FIELD) {
+      field = n->Target;
+      n = n->Children[0];
+   }
+
+   if (n->Opcode == IR_ELEMENT) {
+      /* XXX can only handle constant indexes for now */
+      assert(n->Children[1]->Opcode == IR_FLOAT);
+      index = (GLint) n->Children[1]->Value[0];
+      n = n->Children[0];
+   }
+
+   assert(n->Opcode == IR_VAR);
+   var = (char *) n->Var->a_name;
+
+   pos = lookup_statevar(var, index, field, &swizzle, paramList);
+   assert(pos >= 0);
+   if (pos >= 0) {
+      n->Store->Index = pos;
+      n->Store->Swizzle = swizzle;
+   }
+   return pos;
+}
+
index a521e73..368a16b 100644 (file)
@@ -28,6 +28,7 @@
 
 #include "prog_parameter.h"
 #include "slang_utility.h"
+#include "slang_ir.h"
 
 
 extern GLint
@@ -41,5 +42,9 @@ _slang_lookup_statevar_field(const char *base, const char *field,
                              struct gl_program_parameter_list *paramList,
                              GLuint *swizzleOut);
 
+extern GLint
+_slang_alloc_statevar(slang_ir_node *n,
+                      struct gl_program_parameter_list *paramList);
+
 
 #endif /* SLANG_BUILTIN_H */
index 789ab8a..d78f45a 100644 (file)
@@ -205,18 +205,7 @@ slang_allocate_storage(slang_assemble_ctx *A, slang_ir_node *n)
          struct gl_program *prog = A->program;
          assert(prog);
 
-         /* determine storage location for this var.
-          * This is probably a pre-defined uniform or constant.
-          * We don't allocate storage for these until they're actually
-          * used to avoid wasting registers.
-          */
-         if (n->Store->File == PROGRAM_STATE_VAR) {
-            GLint i = _slang_lookup_statevar(varName, 0, prog->Parameters,
-                                             &n->Store->Swizzle);
-            assert(i >= 0);
-            n->Store->Index = i;
-         }
-         else if (n->Store->File == PROGRAM_CONSTANT) {
+         if (n->Store->File == PROGRAM_CONSTANT) {
             /* XXX compile-time constants should be converted to literals */
             GLint i = slang_lookup_constant(varName, prog->Parameters,
                                             &n->Store->Swizzle);
@@ -2262,6 +2251,7 @@ _slang_gen_subscript(slang_assemble_ctx * A, slang_operation *oper)
          elem->Store = _slang_new_ir_storage(array->Store->File,
                                              array->Store->Index,
                                              elemSize);
+         /* XXX try to do some array bounds checking here */
          return elem;
       }
       else {
index d993fbd..7584857 100644 (file)
@@ -1319,6 +1319,13 @@ emit_array_element(slang_var_table *vt, slang_ir_node *n,
    assert(n->Store);
    assert(n->Store->File != PROGRAM_UNDEFINED);
    assert(n->Store->Size > 0);
+
+   if (n->Store->File == PROGRAM_STATE_VAR) {
+      n->Store->Index = _slang_alloc_statevar(n, prog->Parameters);
+      return NULL;
+   }
+
+
    if (n->Children[1]->Opcode == IR_FLOAT) {
       /* Constant index */
       const GLint arrayAddr = n->Children[0]->Store->Index;
@@ -1343,6 +1350,11 @@ static struct prog_instruction *
 emit_struct_field(slang_var_table *vt, slang_ir_node *n,
                   struct gl_program *prog)
 {
+   if (n->Store->File == PROGRAM_STATE_VAR) {
+      n->Store->Index = _slang_alloc_statevar(n, prog->Parameters);
+      return NULL;
+   }
+
    if (n->Children[0]->Store->File == PROGRAM_STATE_VAR) {
       /* state variable sub-field */
       GLint pos;
@@ -1421,6 +1433,12 @@ emit(slang_var_table *vt, slang_ir_node *n, struct gl_program *prog)
        */
       assert(n->Store);
       assert(n->Store->File != PROGRAM_UNDEFINED);
+
+      if (n->Store->File == PROGRAM_STATE_VAR &&
+          n->Store->Index < 0) {
+         n->Store->Index = _slang_alloc_statevar(n, prog->Parameters);
+      }
+
       if (n->Store->Index < 0) {
          printf("#### VAR %s not allocated!\n", (char*)n->Var->a_name);
       }