Revert "ir_to_mesa: Load all the STATE_VAR elements of a builtin uniform to a temp."
authorMarek Olšák <maraeo@gmail.com>
Fri, 3 Sep 2010 22:42:36 +0000 (00:42 +0200)
committerMarek Olšák <maraeo@gmail.com>
Sat, 4 Sep 2010 17:06:47 +0000 (19:06 +0200)
This reverts commit 5ad74779cea07cc6a19a52874cdaef8b018e2f1b.

Sorry, but I had to revert this.

Any commit which needlessly increases the number of temporaries is wrong.
More temporaries mean less shader performance because of reduced parallelism
and therefore less efficient latency hiding. In this case, there is possible
performance degradation of every shader which uses GL state variables.
I cannot accept this.

src/mesa/program/ir_to_mesa.cpp

index 839d6f0467379aef1bfe248bca8a6a1ab84de7f6..d61698b4e44b718dd7a64fd1214d98b712aad5c6 100644 (file)
@@ -577,239 +577,6 @@ ir_to_mesa_visitor::find_variable_storage(ir_variable *var)
    return NULL;
 }
 
-struct statevar_element {
-   const char *field;
-   int tokens[STATE_LENGTH];
-   int swizzle;
-   bool array_indexed;
-};
-
-static struct statevar_element gl_DepthRange_elements[] = {
-   {"near", {STATE_DEPTH_RANGE, 0, 0}, SWIZZLE_XXXX},
-   {"far", {STATE_DEPTH_RANGE, 0, 0}, SWIZZLE_YYYY},
-   {"diff", {STATE_DEPTH_RANGE, 0, 0}, SWIZZLE_ZZZZ},
-};
-
-static struct statevar_element gl_ClipPlane_elements[] = {
-   {NULL, {STATE_CLIPPLANE, 0, 0}, SWIZZLE_XYZW}
-};
-
-static struct statevar_element gl_Point_elements[] = {
-   {"size", {STATE_POINT_SIZE}, SWIZZLE_XXXX},
-   {"sizeMin", {STATE_POINT_SIZE}, SWIZZLE_YYYY},
-   {"sizeMax", {STATE_POINT_SIZE}, SWIZZLE_ZZZZ},
-   {"fadeThresholdSize", {STATE_POINT_SIZE}, SWIZZLE_WWWW},
-   {"distanceConstantAttenuation", {STATE_POINT_ATTENUATION}, SWIZZLE_XXXX},
-   {"distanceLinearAttenuation", {STATE_POINT_ATTENUATION}, SWIZZLE_YYYY},
-   {"distanceQuadraticAttenuation", {STATE_POINT_ATTENUATION}, SWIZZLE_ZZZZ},
-};
-
-static struct statevar_element gl_FrontMaterial_elements[] = {
-   {"emission", {STATE_MATERIAL, 0, STATE_EMISSION}, SWIZZLE_XYZW},
-   {"ambient", {STATE_MATERIAL, 0, STATE_AMBIENT}, SWIZZLE_XYZW},
-   {"diffuse", {STATE_MATERIAL, 0, STATE_DIFFUSE}, SWIZZLE_XYZW},
-   {"specular", {STATE_MATERIAL, 0, STATE_SPECULAR}, SWIZZLE_XYZW},
-   {"shininess", {STATE_MATERIAL, 0, STATE_SHININESS}, SWIZZLE_XXXX},
-};
-
-static struct statevar_element gl_BackMaterial_elements[] = {
-   {"emission", {STATE_MATERIAL, 1, STATE_EMISSION}, SWIZZLE_XYZW},
-   {"ambient", {STATE_MATERIAL, 1, STATE_AMBIENT}, SWIZZLE_XYZW},
-   {"diffuse", {STATE_MATERIAL, 1, STATE_DIFFUSE}, SWIZZLE_XYZW},
-   {"specular", {STATE_MATERIAL, 1, STATE_SPECULAR}, SWIZZLE_XYZW},
-   {"shininess", {STATE_MATERIAL, 1, STATE_SHININESS}, SWIZZLE_XXXX},
-};
-
-static struct statevar_element gl_LightSource_elements[] = {
-   {"ambient", {STATE_LIGHT, 0, STATE_AMBIENT}, SWIZZLE_XYZW},
-   {"diffuse", {STATE_LIGHT, 0, STATE_DIFFUSE}, SWIZZLE_XYZW},
-   {"specular", {STATE_LIGHT, 0, STATE_SPECULAR}, SWIZZLE_XYZW},
-   {"position", {STATE_LIGHT, 0, STATE_POSITION}, SWIZZLE_XYZW},
-   {"halfVector", {STATE_LIGHT, 0, STATE_HALF_VECTOR}, SWIZZLE_XYZW},
-   {"spotDirection", {STATE_LIGHT, 0, STATE_SPOT_DIRECTION}, SWIZZLE_XYZW},
-   {"spotCosCutoff", {STATE_LIGHT, 0, STATE_SPOT_DIRECTION}, SWIZZLE_WWWW},
-   {"spotCutoff", {STATE_LIGHT, 0, STATE_SPOT_CUTOFF}, SWIZZLE_XXXX},
-   {"spotExponent", {STATE_LIGHT, 0, STATE_ATTENUATION}, SWIZZLE_WWWW},
-   {"constantAttenuation", {STATE_LIGHT, 0, STATE_ATTENUATION}, SWIZZLE_XXXX},
-   {"linearAttenuation", {STATE_LIGHT, 0, STATE_ATTENUATION}, SWIZZLE_YYYY},
-   {"quadraticAttenuation", {STATE_LIGHT, 0, STATE_ATTENUATION}, SWIZZLE_ZZZZ},
-};
-
-static struct statevar_element gl_LightModel_elements[] = {
-   {"ambient", {STATE_LIGHTMODEL_AMBIENT, 0}, SWIZZLE_XYZW},
-};
-
-static struct statevar_element gl_FrontLightModelProduct_elements[] = {
-   {"sceneColor", {STATE_LIGHTMODEL_SCENECOLOR, 0}, SWIZZLE_XYZW},
-};
-
-static struct statevar_element gl_BackLightModelProduct_elements[] = {
-   {"sceneColor", {STATE_LIGHTMODEL_SCENECOLOR, 1}, SWIZZLE_XYZW},
-};
-
-static struct statevar_element gl_FrontLightProduct_elements[] = {
-   {"ambient", {STATE_LIGHTPROD, 0, 0, STATE_AMBIENT}, SWIZZLE_XYZW},
-   {"diffuse", {STATE_LIGHTPROD, 0, 0, STATE_DIFFUSE}, SWIZZLE_XYZW},
-   {"specular", {STATE_LIGHTPROD, 0, 0, STATE_SPECULAR}, SWIZZLE_XYZW},
-};
-
-static struct statevar_element gl_BackLightProduct_elements[] = {
-   {"ambient", {STATE_LIGHTPROD, 0, 1, STATE_AMBIENT}, SWIZZLE_XYZW},
-   {"diffuse", {STATE_LIGHTPROD, 0, 1, STATE_DIFFUSE}, SWIZZLE_XYZW},
-   {"specular", {STATE_LIGHTPROD, 0, 1, STATE_SPECULAR}, SWIZZLE_XYZW},
-};
-
-static struct statevar_element gl_TextureEnvColor_elements[] = {
-   {NULL, {STATE_TEXENV_COLOR, 0}, SWIZZLE_XYZW},
-};
-
-static struct statevar_element gl_EyePlaneS_elements[] = {
-   {NULL, {STATE_TEXGEN, 0, STATE_TEXGEN_EYE_S}, SWIZZLE_XYZW},
-};
-
-static struct statevar_element gl_EyePlaneT_elements[] = {
-   {NULL, {STATE_TEXGEN, 0, STATE_TEXGEN_EYE_T}, SWIZZLE_XYZW},
-};
-
-static struct statevar_element gl_EyePlaneR_elements[] = {
-   {NULL, {STATE_TEXGEN, 0, STATE_TEXGEN_EYE_R}, SWIZZLE_XYZW},
-};
-
-static struct statevar_element gl_EyePlaneQ_elements[] = {
-   {NULL, {STATE_TEXGEN, 0, STATE_TEXGEN_EYE_Q}, SWIZZLE_XYZW},
-};
-
-static struct statevar_element gl_ObjectPlaneS_elements[] = {
-   {NULL, {STATE_TEXGEN, 0, STATE_TEXGEN_OBJECT_S}, SWIZZLE_XYZW},
-};
-
-static struct statevar_element gl_ObjectPlaneT_elements[] = {
-   {NULL, {STATE_TEXGEN, 0, STATE_TEXGEN_OBJECT_T}, SWIZZLE_XYZW},
-};
-
-static struct statevar_element gl_ObjectPlaneR_elements[] = {
-   {NULL, {STATE_TEXGEN, 0, STATE_TEXGEN_OBJECT_R}, SWIZZLE_XYZW},
-};
-
-static struct statevar_element gl_ObjectPlaneQ_elements[] = {
-   {NULL, {STATE_TEXGEN, 0, STATE_TEXGEN_OBJECT_Q}, SWIZZLE_XYZW},
-};
-
-static struct statevar_element gl_Fog_elements[] = {
-   {"color", {STATE_FOG_COLOR}, SWIZZLE_XYZW},
-   {"density", {STATE_FOG_PARAMS}, SWIZZLE_XXXX},
-   {"start", {STATE_FOG_PARAMS}, SWIZZLE_YYYY},
-   {"end", {STATE_FOG_PARAMS}, SWIZZLE_ZZZZ},
-   {"scale", {STATE_FOG_PARAMS}, SWIZZLE_WWWW},
-};
-
-#define MATRIX(name, statevar, modifier)                       \
-   static struct statevar_element name ## _elements[] = {              \
-      { NULL, { statevar, 0, 0, 0, modifier}, SWIZZLE_XYZW },          \
-      { NULL, { statevar, 0, 1, 1, modifier}, SWIZZLE_XYZW },          \
-      { NULL, { statevar, 0, 2, 2, modifier}, SWIZZLE_XYZW },          \
-      { NULL, { statevar, 0, 3, 3, modifier}, SWIZZLE_XYZW },          \
-   }
-
-MATRIX(gl_ModelViewMatrix,
-       STATE_MODELVIEW_MATRIX, STATE_MATRIX_TRANSPOSE);
-MATRIX(gl_ModelViewMatrixInverse,
-       STATE_MODELVIEW_MATRIX, STATE_MATRIX_INVTRANS);
-MATRIX(gl_ModelViewMatrixTranspose,
-       STATE_MODELVIEW_MATRIX, 0);
-MATRIX(gl_ModelViewMatrixInverseTranspose,
-       STATE_MODELVIEW_MATRIX, STATE_MATRIX_INVERSE);
-
-MATRIX(gl_ProjectionMatrix,
-       STATE_PROJECTION_MATRIX, STATE_MATRIX_TRANSPOSE);
-MATRIX(gl_ProjectionMatrixInverse,
-       STATE_PROJECTION_MATRIX, STATE_MATRIX_INVTRANS);
-MATRIX(gl_ProjectionMatrixTranspose,
-       STATE_PROJECTION_MATRIX, 0);
-MATRIX(gl_ProjectionMatrixInverseTranspose,
-       STATE_PROJECTION_MATRIX, STATE_MATRIX_INVERSE);
-
-MATRIX(gl_ModelViewProjectionMatrix,
-       STATE_MVP_MATRIX, STATE_MATRIX_TRANSPOSE);
-MATRIX(gl_ModelViewProjectionMatrixInverse,
-       STATE_MVP_MATRIX, STATE_MATRIX_INVTRANS);
-MATRIX(gl_ModelViewProjectionMatrixTranspose,
-       STATE_MVP_MATRIX, 0);
-MATRIX(gl_ModelViewProjectionMatrixInverseTranspose,
-       STATE_MVP_MATRIX, STATE_MATRIX_INVERSE);
-
-MATRIX(gl_TextureMatrix,
-       STATE_TEXTURE_MATRIX, STATE_MATRIX_TRANSPOSE);
-MATRIX(gl_TextureMatrixInverse,
-       STATE_TEXTURE_MATRIX, STATE_MATRIX_INVTRANS);
-MATRIX(gl_TextureMatrixTranspose,
-       STATE_TEXTURE_MATRIX, 0);
-MATRIX(gl_TextureMatrixInverseTranspose,
-       STATE_TEXTURE_MATRIX, STATE_MATRIX_INVERSE);
-
-static struct statevar_element gl_NormalMatrix_elements[] = {
-   { NULL, { STATE_MODELVIEW_MATRIX, 0, 0, 0, STATE_MATRIX_INVERSE},
-     SWIZZLE_XYZW },
-   { NULL, { STATE_MODELVIEW_MATRIX, 0, 1, 1, STATE_MATRIX_INVERSE},
-     SWIZZLE_XYZW },
-   { NULL, { STATE_MODELVIEW_MATRIX, 0, 2, 2, STATE_MATRIX_INVERSE},
-     SWIZZLE_XYZW },
-};
-
-#undef MATRIX
-
-#define STATEVAR(name) {#name, name ## _elements, Elements(name ## _elements)}
-
-static struct {
-   const char *name;
-   struct statevar_element *elements;
-   int num_elements;
-} statevars[] = {
-   STATEVAR(gl_DepthRange),
-   STATEVAR(gl_ClipPlane),
-   STATEVAR(gl_Point),
-   STATEVAR(gl_FrontMaterial),
-   STATEVAR(gl_BackMaterial),
-   STATEVAR(gl_LightSource),
-   STATEVAR(gl_LightModel),
-   STATEVAR(gl_FrontLightModelProduct),
-   STATEVAR(gl_BackLightModelProduct),
-   STATEVAR(gl_FrontLightProduct),
-   STATEVAR(gl_BackLightProduct),
-   STATEVAR(gl_TextureEnvColor),
-   STATEVAR(gl_EyePlaneS),
-   STATEVAR(gl_EyePlaneT),
-   STATEVAR(gl_EyePlaneR),
-   STATEVAR(gl_EyePlaneQ),
-   STATEVAR(gl_ObjectPlaneS),
-   STATEVAR(gl_ObjectPlaneT),
-   STATEVAR(gl_ObjectPlaneR),
-   STATEVAR(gl_ObjectPlaneQ),
-   STATEVAR(gl_Fog),
-
-   STATEVAR(gl_ModelViewMatrix),
-   STATEVAR(gl_ModelViewMatrixInverse),
-   STATEVAR(gl_ModelViewMatrixTranspose),
-   STATEVAR(gl_ModelViewMatrixInverseTranspose),
-
-   STATEVAR(gl_ProjectionMatrix),
-   STATEVAR(gl_ProjectionMatrixInverse),
-   STATEVAR(gl_ProjectionMatrixTranspose),
-   STATEVAR(gl_ProjectionMatrixInverseTranspose),
-
-   STATEVAR(gl_ModelViewProjectionMatrix),
-   STATEVAR(gl_ModelViewProjectionMatrixInverse),
-   STATEVAR(gl_ModelViewProjectionMatrixTranspose),
-   STATEVAR(gl_ModelViewProjectionMatrixInverseTranspose),
-
-   STATEVAR(gl_TextureMatrix),
-   STATEVAR(gl_TextureMatrixInverse),
-   STATEVAR(gl_TextureMatrixTranspose),
-   STATEVAR(gl_TextureMatrixInverseTranspose),
-
-   STATEVAR(gl_NormalMatrix),
-};
-
 void
 ir_to_mesa_visitor::visit(ir_variable *ir)
 {
@@ -819,64 +586,6 @@ ir_to_mesa_visitor::visit(ir_variable *ir)
       fp->OriginUpperLeft = ir->origin_upper_left;
       fp->PixelCenterInteger = ir->pixel_center_integer;
    }
-
-   if (ir->mode == ir_var_uniform && strncmp(ir->name, "gl_", 3) == 0) {
-      unsigned int i;
-
-      struct variable_storage *entry;
-      entry = new(mem_ctx) variable_storage(ir, PROGRAM_TEMPORARY,
-                                           this->next_temp);
-      this->variables.push_tail(entry);
-      this->next_temp += type_size(ir->type);
-
-      for (i = 0; i < Elements(statevars); i++) {
-        if (strcmp(ir->name, statevars[i].name) == 0)
-           break;
-      }
-
-      if (i == Elements(statevars)) {
-        fail_link(this->shader_program,
-                  "Failed to find builtin uniform `%s'\n", ir->name);
-        return;
-      }
-
-      ir_to_mesa_dst_reg dst =
-        ir_to_mesa_dst_reg_from_src(ir_to_mesa_src_reg(PROGRAM_TEMPORARY,
-                                                       entry->index, NULL));
-
-      int array_count;
-      if (ir->type->is_array()) {
-        array_count = ir->type->length;
-      } else {
-        array_count = 1;
-      }
-
-      for (int a = 0; a < array_count; a++) {
-        for (int j = 0; j < statevars[i].num_elements; j++) {
-           struct statevar_element *element = &statevars[i].elements[j];
-           int tokens[STATE_LENGTH];
-
-           memcpy(tokens, element->tokens, sizeof(element->tokens));
-           if (ir->type->is_array()) {
-              tokens[1] = a;
-           }
-
-           int index = _mesa_add_state_reference(this->prog->Parameters,
-                                                 (gl_state_index *)tokens);
-           ir_to_mesa_src_reg src(PROGRAM_STATE_VAR, index, NULL);
-           src.swizzle = element->swizzle;
-           ir_to_mesa_emit_op1(ir, OPCODE_MOV, dst, src);
-           /* even a float takes up a whole vec4 reg in a struct/array. */
-           dst.index++;
-        }
-      }
-      if (dst.index != entry->index + type_size(ir->type)) {
-        fail_link(this->shader_program,
-                  "failed to load builtin uniform `%s'  (%d/%d regs loaded)\n",
-                  ir->name, dst.index - entry->index,
-                  type_size(ir->type));
-      }
-   }
 }
 
 void
@@ -1348,6 +1057,289 @@ ir_to_mesa_visitor::visit(ir_swizzle *ir)
    this->result = src_reg;
 }
 
+static const struct {
+   const char *name;
+   const char *field;
+   int tokens[STATE_LENGTH];
+   int swizzle;
+   bool array_indexed;
+} statevars[] = {
+   {"gl_DepthRange", "near",
+    {STATE_DEPTH_RANGE, 0, 0}, SWIZZLE_XXXX, false},
+   {"gl_DepthRange", "far",
+    {STATE_DEPTH_RANGE, 0, 0}, SWIZZLE_YYYY, false},
+   {"gl_DepthRange", "diff",
+    {STATE_DEPTH_RANGE, 0, 0}, SWIZZLE_ZZZZ, false},
+
+   {"gl_ClipPlane", NULL,
+    {STATE_CLIPPLANE, 0, 0}, SWIZZLE_XYZW, true}
+,
+   {"gl_Point", "size",
+    {STATE_POINT_SIZE}, SWIZZLE_XXXX, false},
+   {"gl_Point", "sizeMin",
+    {STATE_POINT_SIZE}, SWIZZLE_YYYY, false},
+   {"gl_Point", "sizeMax",
+    {STATE_POINT_SIZE}, SWIZZLE_ZZZZ, false},
+   {"gl_Point", "fadeThresholdSize",
+    {STATE_POINT_SIZE}, SWIZZLE_WWWW, false},
+   {"gl_Point", "distanceConstantAttenuation",
+    {STATE_POINT_ATTENUATION}, SWIZZLE_XXXX, false},
+   {"gl_Point", "distanceLinearAttenuation",
+    {STATE_POINT_ATTENUATION}, SWIZZLE_YYYY, false},
+   {"gl_Point", "distanceQuadraticAttenuation",
+    {STATE_POINT_ATTENUATION}, SWIZZLE_ZZZZ, false},
+
+   {"gl_FrontMaterial", "emission",
+    {STATE_MATERIAL, 0, STATE_EMISSION}, SWIZZLE_XYZW, false},
+   {"gl_FrontMaterial", "ambient",
+    {STATE_MATERIAL, 0, STATE_AMBIENT}, SWIZZLE_XYZW, false},
+   {"gl_FrontMaterial", "diffuse",
+    {STATE_MATERIAL, 0, STATE_DIFFUSE}, SWIZZLE_XYZW, false},
+   {"gl_FrontMaterial", "specular",
+    {STATE_MATERIAL, 0, STATE_SPECULAR}, SWIZZLE_XYZW, false},
+   {"gl_FrontMaterial", "shininess",
+    {STATE_MATERIAL, 0, STATE_SHININESS}, SWIZZLE_XXXX, false},
+
+   {"gl_BackMaterial", "emission",
+    {STATE_MATERIAL, 1, STATE_EMISSION}, SWIZZLE_XYZW, false},
+   {"gl_BackMaterial", "ambient",
+    {STATE_MATERIAL, 1, STATE_AMBIENT}, SWIZZLE_XYZW, false},
+   {"gl_BackMaterial", "diffuse",
+    {STATE_MATERIAL, 1, STATE_DIFFUSE}, SWIZZLE_XYZW, false},
+   {"gl_BackMaterial", "specular",
+    {STATE_MATERIAL, 1, STATE_SPECULAR}, SWIZZLE_XYZW, false},
+   {"gl_BackMaterial", "shininess",
+    {STATE_MATERIAL, 1, STATE_SHININESS}, SWIZZLE_XXXX, false},
+
+   {"gl_LightSource", "ambient",
+    {STATE_LIGHT, 0, STATE_AMBIENT}, SWIZZLE_XYZW, true},
+   {"gl_LightSource", "diffuse",
+    {STATE_LIGHT, 0, STATE_DIFFUSE}, SWIZZLE_XYZW, true},
+   {"gl_LightSource", "specular",
+    {STATE_LIGHT, 0, STATE_SPECULAR}, SWIZZLE_XYZW, true},
+   {"gl_LightSource", "position",
+    {STATE_LIGHT, 0, STATE_POSITION}, SWIZZLE_XYZW, true},
+   {"gl_LightSource", "halfVector",
+    {STATE_LIGHT, 0, STATE_HALF_VECTOR}, SWIZZLE_XYZW, true},
+   {"gl_LightSource", "spotDirection",
+    {STATE_LIGHT, 0, STATE_SPOT_DIRECTION}, SWIZZLE_XYZW, true},
+   {"gl_LightSource", "spotCosCutoff",
+    {STATE_LIGHT, 0, STATE_SPOT_DIRECTION}, SWIZZLE_WWWW, true},
+   {"gl_LightSource", "spotCutoff",
+    {STATE_LIGHT, 0, STATE_SPOT_CUTOFF}, SWIZZLE_XXXX, true},
+   {"gl_LightSource", "spotExponent",
+    {STATE_LIGHT, 0, STATE_ATTENUATION}, SWIZZLE_WWWW, true},
+   {"gl_LightSource", "constantAttenuation",
+    {STATE_LIGHT, 0, STATE_ATTENUATION}, SWIZZLE_XXXX, true},
+   {"gl_LightSource", "linearAttenuation",
+    {STATE_LIGHT, 0, STATE_ATTENUATION}, SWIZZLE_YYYY, true},
+   {"gl_LightSource", "quadraticAttenuation",
+    {STATE_LIGHT, 0, STATE_ATTENUATION}, SWIZZLE_ZZZZ, true},
+
+   {"gl_LightModel", "ambient",
+    {STATE_LIGHTMODEL_AMBIENT, 0}, SWIZZLE_XYZW, false},
+
+   {"gl_FrontLightModelProduct", "sceneColor",
+    {STATE_LIGHTMODEL_SCENECOLOR, 0}, SWIZZLE_XYZW, false},
+   {"gl_BackLightModelProduct", "sceneColor",
+    {STATE_LIGHTMODEL_SCENECOLOR, 1}, SWIZZLE_XYZW, false},
+
+   {"gl_FrontLightProduct", "ambient",
+    {STATE_LIGHTPROD, 0, 0, STATE_AMBIENT}, SWIZZLE_XYZW, true},
+   {"gl_FrontLightProduct", "diffuse",
+    {STATE_LIGHTPROD, 0, 0, STATE_DIFFUSE}, SWIZZLE_XYZW, true},
+   {"gl_FrontLightProduct", "specular",
+    {STATE_LIGHTPROD, 0, 0, STATE_SPECULAR}, SWIZZLE_XYZW, true},
+
+   {"gl_BackLightProduct", "ambient",
+    {STATE_LIGHTPROD, 0, 1, STATE_AMBIENT}, SWIZZLE_XYZW, true},
+   {"gl_BackLightProduct", "diffuse",
+    {STATE_LIGHTPROD, 0, 1, STATE_DIFFUSE}, SWIZZLE_XYZW, true},
+   {"gl_BackLightProduct", "specular",
+    {STATE_LIGHTPROD, 0, 1, STATE_SPECULAR}, SWIZZLE_XYZW, true},
+
+   {"gl_TextureEnvColor", NULL,
+    {STATE_TEXENV_COLOR, 0}, SWIZZLE_XYZW, true},
+
+   {"gl_EyePlaneS", NULL,
+    {STATE_TEXGEN, 0, STATE_TEXGEN_EYE_S}, SWIZZLE_XYZW, true},
+   {"gl_EyePlaneT", NULL,
+    {STATE_TEXGEN, 0, STATE_TEXGEN_EYE_T}, SWIZZLE_XYZW, true},
+   {"gl_EyePlaneR", NULL,
+    {STATE_TEXGEN, 0, STATE_TEXGEN_EYE_R}, SWIZZLE_XYZW, true},
+   {"gl_EyePlaneQ", NULL,
+    {STATE_TEXGEN, 0, STATE_TEXGEN_EYE_Q}, SWIZZLE_XYZW, true},
+
+   {"gl_ObjectPlaneS", NULL,
+    {STATE_TEXGEN, 0, STATE_TEXGEN_OBJECT_S}, SWIZZLE_XYZW, true},
+   {"gl_ObjectPlaneT", NULL,
+    {STATE_TEXGEN, 0, STATE_TEXGEN_OBJECT_T}, SWIZZLE_XYZW, true},
+   {"gl_ObjectPlaneR", NULL,
+    {STATE_TEXGEN, 0, STATE_TEXGEN_OBJECT_R}, SWIZZLE_XYZW, true},
+   {"gl_ObjectPlaneQ", NULL,
+    {STATE_TEXGEN, 0, STATE_TEXGEN_OBJECT_Q}, SWIZZLE_XYZW, true},
+
+   {"gl_Fog", "color",
+    {STATE_FOG_COLOR}, SWIZZLE_XYZW, false},
+   {"gl_Fog", "density",
+    {STATE_FOG_PARAMS}, SWIZZLE_XXXX, false},
+   {"gl_Fog", "start",
+    {STATE_FOG_PARAMS}, SWIZZLE_YYYY, false},
+   {"gl_Fog", "end",
+    {STATE_FOG_PARAMS}, SWIZZLE_ZZZZ, false},
+   {"gl_Fog", "scale",
+    {STATE_FOG_PARAMS}, SWIZZLE_WWWW, false},
+};
+
+static ir_to_mesa_src_reg
+get_builtin_uniform_reg(struct gl_program *prog,
+                       const char *name, int array_index, const char *field)
+{
+   unsigned int i;
+   ir_to_mesa_src_reg src_reg;
+   int tokens[STATE_LENGTH];
+
+   for (i = 0; i < Elements(statevars); i++) {
+      if (strcmp(statevars[i].name, name) != 0)
+        continue;
+      if (!field && statevars[i].field) {
+        assert(!"FINISHME: whole-structure state var dereference");
+      }
+      if (field && (!statevars[i].field || strcmp(statevars[i].field, field) != 0))
+        continue;
+      break;
+   }
+
+   if (i ==  Elements(statevars)) {
+      printf("builtin uniform %s%s%s not found\n",
+            name,
+            field ? "." : "",
+            field ? field : "");
+      abort();
+   }
+
+   memcpy(&tokens, statevars[i].tokens, sizeof(tokens));
+   if (statevars[i].array_indexed)
+      tokens[1] = array_index;
+
+   src_reg.file = PROGRAM_STATE_VAR;
+   src_reg.index = _mesa_add_state_reference(prog->Parameters,
+                                            (gl_state_index *)tokens);
+   src_reg.swizzle = statevars[i].swizzle;
+   src_reg.negate = 0;
+   src_reg.reladdr = false;
+
+   return src_reg;
+}
+
+static int
+add_matrix_ref(struct gl_program *prog, int *tokens)
+{
+   int base_pos = -1;
+   int i;
+
+   /* Add a ref for each column.  It looks like the reason we do
+    * it this way is that _mesa_add_state_reference doesn't work
+    * for things that aren't vec4s, so the tokens[2]/tokens[3]
+    * range has to be equal.
+    */
+   for (i = 0; i < 4; i++) {
+      tokens[2] = i;
+      tokens[3] = i;
+      int pos = _mesa_add_state_reference(prog->Parameters,
+                                         (gl_state_index *)tokens);
+      if (base_pos == -1)
+        base_pos = pos;
+      else
+        assert(base_pos + i == pos);
+   }
+
+   return base_pos;
+}
+
+static variable_storage *
+get_builtin_matrix_ref(void *mem_ctx, struct gl_program *prog, ir_variable *var,
+                      ir_rvalue *array_index)
+{
+   /*
+    * NOTE: The ARB_vertex_program extension specified that matrices get
+    * loaded in registers in row-major order.  With GLSL, we want column-
+    * major order.  So, we need to transpose all matrices here...
+    */
+   static const struct {
+      const char *name;
+      int matrix;
+      int modifier;
+   } matrices[] = {
+      { "gl_ModelViewMatrix", STATE_MODELVIEW_MATRIX, STATE_MATRIX_TRANSPOSE },
+      { "gl_ModelViewMatrixInverse", STATE_MODELVIEW_MATRIX, STATE_MATRIX_INVTRANS },
+      { "gl_ModelViewMatrixTranspose", STATE_MODELVIEW_MATRIX, 0 },
+      { "gl_ModelViewMatrixInverseTranspose", STATE_MODELVIEW_MATRIX, STATE_MATRIX_INVERSE },
+
+      { "gl_ProjectionMatrix", STATE_PROJECTION_MATRIX, STATE_MATRIX_TRANSPOSE },
+      { "gl_ProjectionMatrixInverse", STATE_PROJECTION_MATRIX, STATE_MATRIX_INVTRANS },
+      { "gl_ProjectionMatrixTranspose", STATE_PROJECTION_MATRIX, 0 },
+      { "gl_ProjectionMatrixInverseTranspose", STATE_PROJECTION_MATRIX, STATE_MATRIX_INVERSE },
+
+      { "gl_ModelViewProjectionMatrix", STATE_MVP_MATRIX, STATE_MATRIX_TRANSPOSE },
+      { "gl_ModelViewProjectionMatrixInverse", STATE_MVP_MATRIX, STATE_MATRIX_INVTRANS },
+      { "gl_ModelViewProjectionMatrixTranspose", STATE_MVP_MATRIX, 0 },
+      { "gl_ModelViewProjectionMatrixInverseTranspose", STATE_MVP_MATRIX, STATE_MATRIX_INVERSE },
+
+      { "gl_TextureMatrix", STATE_TEXTURE_MATRIX, STATE_MATRIX_TRANSPOSE },
+      { "gl_TextureMatrixInverse", STATE_TEXTURE_MATRIX, STATE_MATRIX_INVTRANS },
+      { "gl_TextureMatrixTranspose", STATE_TEXTURE_MATRIX, 0 },
+      { "gl_TextureMatrixInverseTranspose", STATE_TEXTURE_MATRIX, STATE_MATRIX_INVERSE },
+
+      { "gl_NormalMatrix", STATE_MODELVIEW_MATRIX, STATE_MATRIX_INVERSE },
+
+   };
+   unsigned int i;
+   variable_storage *entry;
+
+   /* C++ gets angry when we try to use an int as a gl_state_index, so we use
+    * ints for gl_state_index.  Make sure they're compatible.
+    */
+   assert(sizeof(gl_state_index) == sizeof(int));
+
+   for (i = 0; i < Elements(matrices); i++) {
+      if (strcmp(var->name, matrices[i].name) == 0) {
+        int tokens[STATE_LENGTH];
+        int base_pos = -1;
+
+        tokens[0] = matrices[i].matrix;
+        tokens[4] = matrices[i].modifier;
+        if (matrices[i].matrix == STATE_TEXTURE_MATRIX) {
+           ir_constant *index = array_index->constant_expression_value();
+           if (index) {
+              tokens[1] = index->value.i[0];
+              base_pos = add_matrix_ref(prog, tokens);
+           } else {
+              for (i = 0; i < var->type->length; i++) {
+                 tokens[1] = i;
+                 int pos = add_matrix_ref(prog, tokens);
+                 if (base_pos == -1)
+                    base_pos = pos;
+                 else
+                    assert(base_pos + (int)i * 4 == pos);
+              }
+           }
+        } else {
+           tokens[1] = 0; /* unused array index */
+           base_pos = add_matrix_ref(prog, tokens);
+        }
+
+        entry = new(mem_ctx) variable_storage(var,
+                                              PROGRAM_STATE_VAR,
+                                              base_pos);
+
+        return entry;
+      }
+   }
+
+   return NULL;
+}
+
 void
 ir_to_mesa_visitor::visit(ir_dereference_variable *ir)
 {
@@ -1356,6 +1348,11 @@ ir_to_mesa_visitor::visit(ir_dereference_variable *ir)
    if (!entry) {
       switch (ir->var->mode) {
       case ir_var_uniform:
+        entry = get_builtin_matrix_ref(this->mem_ctx, this->prog, ir->var,
+                                       NULL);
+        if (entry)
+           break;
+
         entry = new(mem_ctx) variable_storage(ir->var, PROGRAM_UNIFORM,
                                               ir->var->location);
         this->variables.push_tail(entry);
@@ -1414,12 +1411,58 @@ ir_to_mesa_visitor::visit(ir_dereference_variable *ir)
 void
 ir_to_mesa_visitor::visit(ir_dereference_array *ir)
 {
+   ir_variable *var = ir->variable_referenced();
    ir_constant *index;
    ir_to_mesa_src_reg src_reg;
+   ir_dereference_variable *deref_var = ir->array->as_dereference_variable();
    int element_size = type_size(ir->type);
 
    index = ir->array_index->constant_expression_value();
 
+   if (deref_var && strncmp(deref_var->var->name,
+                           "gl_TextureMatrix",
+                           strlen("gl_TextureMatrix")) == 0) {
+      variable_storage *entry;
+
+      entry = get_builtin_matrix_ref(this->mem_ctx, this->prog, deref_var->var,
+                                    ir->array_index);
+      assert(entry);
+
+      ir_to_mesa_src_reg src_reg(entry->file, entry->index, ir->type);
+
+      if (index) {
+        src_reg.reladdr = NULL;
+      } else {
+        ir_to_mesa_src_reg index_reg = get_temp(glsl_type::float_type);
+
+        ir->array_index->accept(this);
+        ir_to_mesa_emit_op2(ir, OPCODE_MUL,
+                            ir_to_mesa_dst_reg_from_src(index_reg),
+                            this->result, src_reg_for_float(element_size));
+
+        src_reg.reladdr = talloc(mem_ctx, ir_to_mesa_src_reg);
+        memcpy(src_reg.reladdr, &index_reg, sizeof(index_reg));
+      }
+
+      this->result = src_reg;
+      return;
+   }
+
+   if (var &&
+       strncmp(var->name, "gl_", 3) == 0 && var->mode == ir_var_uniform &&
+       !var->type->is_matrix()) {
+      ir_dereference_record *record = NULL;
+      if (ir->array->ir_type == ir_type_dereference_record)
+        record = (ir_dereference_record *)ir->array;
+
+      assert(index || !"FINISHME: variable-indexed builtin uniform access");
+
+      this->result = get_builtin_uniform_reg(prog,
+                                            var->name,
+                                            index->value.i[0],
+                                            record ? record->field : NULL);
+   }
+
    ir->array->accept(this);
    src_reg = this->result;
 
@@ -1464,6 +1507,17 @@ ir_to_mesa_visitor::visit(ir_dereference_record *ir)
    unsigned int i;
    const glsl_type *struct_type = ir->record->type;
    int offset = 0;
+   ir_variable *var = ir->record->variable_referenced();
+
+   if (strncmp(var->name, "gl_", 3) == 0 && var->mode == ir_var_uniform) {
+      assert(var);
+
+      this->result = get_builtin_uniform_reg(prog,
+                                            var->name,
+                                            0,
+                                            ir->field);
+      return;
+   }
 
    ir->record->accept(this);