summaryrefslogtreecommitdiffstats
path: root/src/mesa/shader
diff options
context:
space:
mode:
authorBrian Paul <[email protected]>2008-12-16 14:29:52 -0700
committerBrian Paul <[email protected]>2008-12-16 14:29:52 -0700
commit368df1615ef65afed96a44e1f43ade8cc703696f (patch)
treec45fe7f9e6d6d59ef1669e573955f19c2c97a220 /src/mesa/shader
parent702b5b076b7591560e7e701e0c9ff2eeb30fa966 (diff)
mesa: fix some GLSL array regressions
array.length() wasn't working. Swizzle mask for accessing elements of float arrays was incorrect.
Diffstat (limited to 'src/mesa/shader')
-rw-r--r--src/mesa/shader/slang/slang_codegen.c113
-rw-r--r--src/mesa/shader/slang/slang_compile.c9
-rw-r--r--src/mesa/shader/slang/slang_emit.c25
-rw-r--r--src/mesa/shader/slang/slang_emit.h4
4 files changed, 85 insertions, 66 deletions
diff --git a/src/mesa/shader/slang/slang_codegen.c b/src/mesa/shader/slang/slang_codegen.c
index 5b022a34cd0..7d764cb5c1d 100644
--- a/src/mesa/shader/slang/slang_codegen.c
+++ b/src/mesa/shader/slang/slang_codegen.c
@@ -234,6 +234,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.
* The IR node must be a IR_VAR or IR_VAR_DECL node.
@@ -1416,27 +1458,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:
* vec3 v;
@@ -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 {
@@ -3961,24 +3967,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
* storage will be used.
@@ -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) {
diff --git a/src/mesa/shader/slang/slang_compile.c b/src/mesa/shader/slang/slang_compile.c
index cc6d214c727..9ffffc3b496 100644
--- a/src/mesa/shader/slang/slang_compile.c
+++ b/src/mesa/shader/slang/slang_compile.c
@@ -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;
}
diff --git a/src/mesa/shader/slang/slang_emit.c b/src/mesa/shader/slang/slang_emit.c
index e3cb252a3d7..6587f9cf276 100644
--- a/src/mesa/shader/slang/slang_emit.c
+++ b/src/mesa/shader/slang/slang_emit.c
@@ -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"),
@@ -155,6 +155,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).
*
* Typically this is temporary storage for an intermediate result (such as
@@ -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 */
}
diff --git a/src/mesa/shader/slang/slang_emit.h b/src/mesa/shader/slang/slang_emit.h
index 4db4bbe5621..59fb2fa890d 100644
--- a/src/mesa/shader/slang/slang_emit.h
+++ b/src/mesa/shader/slang/slang_emit.h
@@ -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,