mesa: fix some GLSL array regressions
authorBrian Paul <brian.paul@tungstengraphics.com>
Tue, 16 Dec 2008 21:29:52 +0000 (14:29 -0700)
committerBrian Paul <brian.paul@tungstengraphics.com>
Tue, 16 Dec 2008 21:29:52 +0000 (14:29 -0700)
array.length() wasn't working.
Swizzle mask for accessing elements of float arrays was incorrect.

src/mesa/shader/slang/slang_codegen.c
src/mesa/shader/slang/slang_compile.c
src/mesa/shader/slang/slang_emit.c
src/mesa/shader/slang/slang_emit.h

index 5b022a34cd0c90cd399c29c41370ad1c3866885e..7d764cb5c1d809f2b01edabd121974577ddfd723 100644 (file)
@@ -233,6 +233,48 @@ _slang_sizeof_type_specifier(const slang_type_specifier *spec)
 }
 
 
+/**
+ * Query variable/array length (number of elements).
+ * This is slightly non-trivial because there are two ways to express
+ * arrays: "float x[3]" vs. "float[3] x".
+ * \return the length of the array for the given variable, or 0 if not an array
+ */
+static GLint
+_slang_array_length(const slang_variable *var)
+{
+   if (var->type.array_len > 0) {
+      /* Ex: float[4] x; */
+      return var->type.array_len;
+   }
+   if (var->array_len > 0) {
+      /* Ex: float x[4]; */
+      return var->array_len;
+   }
+   return 0;
+}
+
+
+/**
+ * Compute total size of array give size of element, number of elements.
+ * \return size in floats
+ */
+static GLint
+_slang_array_size(GLint elemSize, GLint arrayLen)
+{
+   GLint total;
+   assert(elemSize > 0);
+   if (arrayLen > 1) {
+      /* round up base type to multiple of 4 */
+      total = ((elemSize + 3) & ~0x3) * MAX2(arrayLen, 1);
+   }
+   else {
+      total = elemSize;
+   }
+   return total;
+}
+
+
+
 /**
  * Establish the binding between a slang_ir_node and a slang_variable.
  * Then, allocate/attach a slang_ir_storage object to the IR node if needed.
@@ -1415,27 +1457,6 @@ slang_find_asm_info(const char *name)
 }
 
 
-/**
- * Return the default swizzle mask for accessing a variable of the
- * given size (in floats).  If size = 1, comp is used to identify
- * which component [0..3] of the register holds the variable.
- */
-static GLuint
-_slang_var_swizzle(GLint size, GLint comp)
-{
-   switch (size) {
-   case 1:
-      return MAKE_SWIZZLE4(comp, comp, comp, comp);
-   case 2:
-      return MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_NIL, SWIZZLE_NIL);
-   case 3:
-      return MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_NIL);
-   default:
-      return SWIZZLE_XYZW;
-   }
-}
-
-
 /**
  * Some write-masked assignments are simple, but others are hard.
  * Simple example:
@@ -2243,7 +2264,7 @@ _slang_gen_method_call(slang_assemble_ctx *A, slang_operation *oper)
    /* Create a float/literal IR node encoding the array length */
    n = new_node0(IR_FLOAT);
    if (n) {
-      n->Value[0] = (float) var->array_len;
+      n->Value[0] = (float) _slang_array_length(var);
       n->Store = _slang_new_ir_storage(PROGRAM_CONSTANT, -1, 1);
    }
    return n;
@@ -2720,7 +2741,7 @@ _slang_gen_var_decl(slang_assemble_ctx *A, slang_variable *var,
    const GLenum datatype = _slang_gltype_from_specifier(&var->type.specifier);
    slang_ir_node *varDecl, *n;
    slang_ir_storage *store;
-   GLint size, totalSize;  /* if array then totalSize > size */
+   GLint arrayLen, size, totalSize;  /* if array then totalSize > size */
    enum register_file file;
 
    /*assert(!var->declared);*/
@@ -2737,29 +2758,14 @@ _slang_gen_var_decl(slang_assemble_ctx *A, slang_variable *var,
       file = PROGRAM_TEMPORARY;
    }
 
-   size = _slang_sizeof_type_specifier(&var->type.specifier);
+   totalSize = size = _slang_sizeof_type_specifier(&var->type.specifier);
    if (size <= 0) {
       slang_info_log_error(A->log, "invalid declaration for '%s'", varName);
       return NULL;
    }
 
-   totalSize = size;
-   if (var->type.array_len > 0) {
-      /* the type is an array, ex: float[4] x; */
-      GLint sz = (totalSize + 3) & ~3;
-      /* total size = element size * array length */
-      sz *= var->type.array_len;
-      totalSize = sz;
-   }
-
-   if (var->array_len > 0) {
-      /* this is an array, ex: float x[4]; */
-      /* round up the element size to a multiple of 4 */
-      GLint sz = (totalSize + 3) & ~3;
-      /* total size = element size * array length */
-      sz *= var->array_len;
-      totalSize = sz;
-   }
+   arrayLen = _slang_array_length(var);
+   totalSize = _slang_array_size(size, arrayLen);
 
    /* Allocate IR node for the declaration */
    varDecl = new_node0(IR_VAR_DECL);
@@ -3603,7 +3609,7 @@ _slang_gen_array_element(slang_assemble_ctx * A, slang_operation *oper)
          elem->Store = _slang_new_ir_storage(array->Store->File,
                                              array->Store->Index,
                                              elemSize);
-
+         elem->Store->Swizzle = _slang_var_swizzle(elemSize, 0);
          return elem;
       }
       else {
@@ -3960,24 +3966,6 @@ _slang_gen_operation(slang_assemble_ctx * A, slang_operation *oper)
 }
 
 
-/**
- * Compute total size of array give size of element, number of elements.
- */
-static GLint
-array_size(GLint baseSize, GLint arrayLen)
-{
-   GLint total;
-   if (arrayLen > 1) {
-      /* round up base type to multiple of 4 */
-      total = ((baseSize + 3) & ~0x3) * MAX2(arrayLen, 1);
-   }
-   else {
-      total = baseSize;
-   }
-   return total;
-}
-
-
 /**
  * Called by compiler when a global variable has been parsed/compiled.
  * Here we examine the variable's type to determine what kind of register
@@ -4003,6 +3991,8 @@ _slang_codegen_global_variable(slang_assemble_ctx *A, slang_variable *var,
    const GLenum datatype = _slang_gltype_from_specifier(&var->type.specifier);
    const GLint texIndex = sampler_to_texture_index(var->type.specifier.type);
    const GLint size = _slang_sizeof_type_specifier(&var->type.specifier);
+   const GLint arrayLen = _slang_array_length(var);
+   const GLint totalSize = _slang_array_size(size, arrayLen);
 
    if (texIndex != -1) {
       /* This is a texture sampler variable...
@@ -4030,7 +4020,6 @@ _slang_codegen_global_variable(slang_assemble_ctx *A, slang_variable *var,
    }
    else if (var->type.qualifier == SLANG_QUAL_UNIFORM) {
       /* Uniform variable */
-      const GLint totalSize = array_size(size, var->array_len);
       const GLuint swizzle = _slang_var_swizzle(totalSize, 0);
 
       if (prog) {
@@ -4089,8 +4078,6 @@ _slang_codegen_global_variable(slang_assemble_ctx *A, slang_variable *var,
       if (dbg) printf("UNIFORM (sz %d) ", totalSize);
    }
    else if (var->type.qualifier == SLANG_QUAL_VARYING) {
-      const GLint totalSize = array_size(size, var->array_len);
-
       /* varyings must be float, vec or mat */
       if (!_slang_type_is_float_vec_mat(var->type.specifier.type) &&
           var->type.specifier.type != SLANG_SPEC_ARRAY) {
index cc6d214c72705bddffc5a4db84f1673a159e9f78..9ffffc3b496b9c2ab700be7d38a23ed4ed14dab2 100644 (file)
@@ -158,7 +158,7 @@ typedef struct slang_output_ctx_
 /* Debugging aid, print file/line where parsing error is detected */
 #define RETURN0 \
    do { \
-      if (0) \
+      if (1) \
          printf("slang error at %s:%d\n", __FILE__, __LINE__); \
       return 0; \
    } while (0)
@@ -1425,6 +1425,9 @@ parse_expression(slang_parse_ctx * C, slang_output_ctx * O,
          if (op->a_id == SLANG_ATOM_NULL)
             RETURN0;
 
+         assert(*C->I == OP_END);
+         C->I++;
+
          while (*C->I != OP_END)
             if (!parse_child_operation(C, O, op, 0))
                RETURN0;
@@ -1977,6 +1980,7 @@ parse_init_declarator(slang_parse_ctx * C, slang_output_ctx * O,
    var->type.centroid = type->centroid;
    var->type.precision = type->precision;
    var->type.variant = type->variant;
+   var->type.array_len = type->array_len;
    var->a_name = a_name;
    if (var->a_name == SLANG_ATOM_NULL)
       RETURN0;
@@ -1989,7 +1993,7 @@ parse_init_declarator(slang_parse_ctx * C, slang_output_ctx * O,
       break;
    case VARIABLE_INITIALIZER:
       /* initialized variable - copy the specifier and parse the expression */
-      if (type->array_len >= 0) {
+      if (0 && type->array_len >= 0) {
          /* The type was something like "float[4]" */
          convert_to_array(C, var, &type->specifier);
          var->array_len = type->array_len;
@@ -2026,6 +2030,7 @@ parse_init_declarator(slang_parse_ctx * C, slang_output_ctx * O,
       break;
    case VARIABLE_ARRAY_EXPLICIT:
       if (type->array_len >= 0) {
+         /* the user is trying to do something like: float[2] x[3]; */
          slang_info_log_error(C->L, "multi-dimensional arrays not allowed");
          RETURN0;
       }
index e3cb252a3d7f01de900ba55c31f9a3144317bfa3..6587f9cf27628f767cf232e0f5f5eb0d440cc65c 100644 (file)
@@ -1,8 +1,8 @@
 /*
  * Mesa 3-D graphics library
- * Version:  7.1
  *
  * Copyright (C) 2005-2008  Brian Paul   All Rights Reserved.
+ * Copyright (C) 2008 VMware, Inc.   All Rights Reserved.
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -154,6 +154,28 @@ _slang_swizzle_swizzle(GLuint swz1, GLuint swz2)
 }
 
 
+/**
+ * Return the default swizzle mask for accessing a variable of the
+ * given size (in floats).  If size = 1, comp is used to identify
+ * which component [0..3] of the register holds the variable.
+ */
+GLuint
+_slang_var_swizzle(GLint size, GLint comp)
+{
+   switch (size) {
+   case 1:
+      return MAKE_SWIZZLE4(comp, comp, comp, comp);
+   case 2:
+      return MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_NIL, SWIZZLE_NIL);
+   case 3:
+      return MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_NIL);
+   default:
+      return SWIZZLE_XYZW;
+   }
+}
+
+
+
 /**
  * Allocate storage for the given node (if it hasn't already been allocated).
  *
@@ -1917,6 +1939,7 @@ emit_array_element(slang_emit_info *emitInfo, slang_ir_node *n)
    }
 
    n->Store->Size = elemSize;
+   n->Store->Swizzle = _slang_var_swizzle(elemSize, 0);
 
    return NULL; /* no instruction */
 }
index 4db4bbe5621f6032c826eea4956e8846299ed1c0..59fb2fa890d8d148c1fa91e8c6252c36562a31bc 100644 (file)
@@ -40,6 +40,10 @@ extern GLuint
 _slang_swizzle_swizzle(GLuint swz1, GLuint swz2);
 
 
+extern GLuint
+_slang_var_swizzle(GLint size, GLint comp);
+
+
 extern GLboolean
 _slang_emit_code(slang_ir_node *n, slang_var_table *vartable,
                  struct gl_program *prog, GLboolean withEnd,