summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrian Paul <brian.paul@tungstengraphics.com>2008-12-12 18:00:47 -0700
committerBrian Paul <brian.paul@tungstengraphics.com>2008-12-12 18:00:47 -0700
commit3b61e9c6e699690aa2ce61ad746170ea6d5597f4 (patch)
tree717030b903f020426f35fcfdefc8061770b94a1c
parent0da44c62cc91c60d392f6e57aa047473b67ffb9b (diff)
mesa: place glsl constant arrays in constant memory
For example, a declaration like const float[3] xxx = float[3](1.1, 2.2, 3.3); will place the array in the constant buffer whereas a regular, non-const array would be placed in the temporary register file. Next up: do the same thing for uniform arrays.
-rw-r--r--src/mesa/shader/slang/slang_codegen.c100
1 files changed, 93 insertions, 7 deletions
diff --git a/src/mesa/shader/slang/slang_codegen.c b/src/mesa/shader/slang/slang_codegen.c
index 840add105d..b807d2cc18 100644
--- a/src/mesa/shader/slang/slang_codegen.c
+++ b/src/mesa/shader/slang/slang_codegen.c
@@ -2641,6 +2641,75 @@ _slang_gen_temporary(GLint size)
/**
+ * Generate program constants for an array.
+ * Ex: const vec2[3] v = vec2[3](vec2(1,1), vec2(2,2), vec2(3,3));
+ * This will allocate and initialize three vector constants, storing
+ * the array in constant memory, not temporaries like a non-const array.
+ * This can also be used for uniform array initializers.
+ * \return GL_TRUE for success, GL_FALSE if failure (semantic error, etc).
+ */
+static GLboolean
+make_constant_array(slang_assemble_ctx *A,
+ slang_variable *var,
+ slang_operation *initializer)
+{
+ struct gl_program *prog = A->program;
+ const GLenum datatype = _slang_gltype_from_specifier(&var->type.specifier);
+ const char *varName = (char *) var->a_name;
+ const GLuint numElements = initializer->num_children;
+ GLint size;
+ GLuint i, j;
+ GLfloat *values;
+
+ if (!var->store) {
+ var->store = _slang_new_ir_storage(PROGRAM_UNDEFINED, -6, -6);
+ }
+ size = var->store->Size;
+
+ assert(var->type.qualifier == SLANG_QUAL_CONST ||
+ var->type.qualifier == SLANG_QUAL_UNIFORM);
+ assert(initializer->type == SLANG_OPER_CALL);
+ assert(initializer->array_constructor);
+
+ values = (GLfloat *) _mesa_malloc(numElements * 4 * sizeof(GLfloat));
+
+ /* convert constructor params into ordinary floats */
+ for (i = 0; i < numElements; i++) {
+ const slang_operation *op = &initializer->children[i];
+ if (op->type != SLANG_OPER_LITERAL_FLOAT) {
+ /* unsupported type for this optimization */
+ free(values);
+ return GL_FALSE;
+ }
+ for (j = 0; j < op->literal_size; j++) {
+ values[i * 4 + j] = op->literal[j];
+ }
+ for ( ; j < 4; j++) {
+ values[i * 4 + j] = 0.0f;
+ }
+ }
+
+ /* slightly different paths for constants vs. uniforms */
+ if (var->type.qualifier == SLANG_QUAL_UNIFORM) {
+ var->store->File = PROGRAM_UNIFORM;
+ var->store->Index = _mesa_add_uniform(prog->Parameters, varName,
+ size, datatype, values);
+ }
+ else {
+ var->store->File = PROGRAM_CONSTANT;
+ var->store->Index = _mesa_add_named_constant(prog->Parameters, varName,
+ values, size);
+ }
+ assert(var->store->Size == size);
+
+ _mesa_free(values);
+
+ return GL_TRUE;
+}
+
+
+
+/**
* Generate IR node for allocating/declaring a variable.
* \param initializer Optional initializer expression for the variable.
*/
@@ -2725,21 +2794,31 @@ _slang_gen_var_decl(slang_assemble_ctx *A, slang_variable *var,
#endif
}
+ /* IR for the variable we're initializing */
+ varRef = new_var(A, var);
+ if (!varRef) {
+ slang_info_log_error(A->log, "undefined variable '%s'", varName);
+ return NULL;
+ }
+
/* constant-folding, etc here */
_slang_simplify(initializer, &A->space, A->atoms);
+ if ((var->type.qualifier == SLANG_QUAL_CONST ||
+ var->type.qualifier == SLANG_QUAL_UNIFORM) &&
+ initializer->type == SLANG_OPER_CALL &&
+ initializer->array_constructor) {
+ printf("Constant array initializer\n");
+ make_constant_array(A, var, initializer);
+ n = varRef;
+ return n;
+ }
+
/* IR for initializer */
init = _slang_gen_operation(A, initializer);
if (!init)
return NULL;
- /* IR for the variable we're initializing */
- varRef = new_var(A, var);
- if (!varRef) {
- slang_info_log_error(A->log, "undefined variable '%s'", varName);
- return NULL;
- }
-
/* XXX remove this when type checking is added above */
if (init->Store && varRef->Store->Size != init->Store->Size) {
slang_info_log_error(A->log, "invalid assignment (wrong types)");
@@ -3947,6 +4026,13 @@ _slang_codegen_global_variable(slang_assemble_ctx *A, slang_variable *var,
else {
GLint uniformLoc;
const GLfloat *initialValues = NULL;
+#if 0
+ /* this code needs some work yet */
+ if (make_constant_array(A, var, var->initializer)) {
+ /* OK */
+ }
+ else
+#endif
if (var->initializer) {
_slang_simplify(var->initializer, &A->space, A->atoms);
if (var->initializer->type == SLANG_OPER_LITERAL_FLOAT ||