From 368df1615ef65afed96a44e1f43ade8cc703696f Mon Sep 17 00:00:00 2001 From: Brian Paul Date: Tue, 16 Dec 2008 14:29:52 -0700 Subject: [PATCH] mesa: fix some GLSL array regressions array.length() wasn't working. Swizzle mask for accessing elements of float arrays was incorrect. --- src/mesa/shader/slang/slang_codegen.c | 113 ++++++++++++-------------- src/mesa/shader/slang/slang_compile.c | 9 +- src/mesa/shader/slang/slang_emit.c | 25 +++++- src/mesa/shader/slang/slang_emit.h | 4 + 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 @@ -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) { 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"), @@ -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 */ } 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, -- 2.30.2