summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBrian Paul <[email protected]>2009-01-07 08:54:09 -0700
committerBrian Paul <[email protected]>2009-01-07 08:54:09 -0700
commita8542200b306f06d40d3944c42bc9634f425c8b0 (patch)
tree0ddec831d704bdce6257579a2b42c359e1ec9c6f
parentcea7f7b76365dc41ba0e577d992193997b4f246f (diff)
glsl: also unroll loops with variable declarations such as "for (int i = 0; ..."
-rw-r--r--src/mesa/shader/slang/slang_codegen.c82
1 files changed, 58 insertions, 24 deletions
diff --git a/src/mesa/shader/slang/slang_codegen.c b/src/mesa/shader/slang/slang_codegen.c
index 64d72b5bfa3..7917566c3ed 100644
--- a/src/mesa/shader/slang/slang_codegen.c
+++ b/src/mesa/shader/slang/slang_codegen.c
@@ -58,7 +58,7 @@
/** Max iterations to unroll */
-const GLuint MAX_FOR_LOOP_UNROLL_ITERATIONS = 20;
+const GLuint MAX_FOR_LOOP_UNROLL_ITERATIONS = 32;
/** Max for-loop body size (in slang operations) to unroll */
const GLuint MAX_FOR_LOOP_UNROLL_BODY_SIZE = 50;
@@ -2487,19 +2487,45 @@ _slang_can_unroll_for_loop(slang_assemble_ctx * A, const slang_operation *oper)
GLuint bodySize;
GLint start, end;
const char *varName;
+ slang_atom varId;
assert(oper->type == SLANG_OPER_FOR);
assert(oper->num_children == 4);
- /* children[0] must be "i=constant" */
- if (oper->children[0].type != SLANG_OPER_EXPRESSION)
- return GL_FALSE;
- if (oper->children[0].children[0].type != SLANG_OPER_ASSIGN)
- return GL_FALSE;
- if (oper->children[0].children[0].children[0].type != SLANG_OPER_IDENTIFIER)
- return GL_FALSE;
- if (oper->children[0].children[0].children[1].type != SLANG_OPER_LITERAL_INT)
+ /* children[0] must be either "int i=constant" or "i=constant" */
+ if (oper->children[0].type == SLANG_OPER_BLOCK_NO_NEW_SCOPE) {
+ slang_variable *var;
+
+ if (oper->children[0].children[0].type != SLANG_OPER_VARIABLE_DECL)
+ return GL_FALSE;
+
+ varId = oper->children[0].children[0].a_id;
+
+ var = _slang_variable_locate(oper->children[0].children[0].locals,
+ varId, GL_TRUE);
+ if (!var)
+ return GL_FALSE;
+ if (!var->initializer)
+ return GL_FALSE;
+ if (var->initializer->type != SLANG_OPER_LITERAL_INT)
+ return GL_FALSE;
+ start = (GLint) var->initializer->literal[0];
+ }
+ else if (oper->children[0].type == SLANG_OPER_EXPRESSION) {
+ if (oper->children[0].children[0].type != SLANG_OPER_ASSIGN)
+ return GL_FALSE;
+ if (oper->children[0].children[0].children[0].type != SLANG_OPER_IDENTIFIER)
+ return GL_FALSE;
+ if (oper->children[0].children[0].children[1].type != SLANG_OPER_LITERAL_INT)
+ return GL_FALSE;
+
+ varId = oper->children[0].children[0].children[0].a_id;
+
+ start = (GLint) oper->children[0].children[0].children[1].literal[0];
+ }
+ else {
return GL_FALSE;
+ }
/* children[1] must be "i<constant" */
if (oper->children[1].type != SLANG_OPER_EXPRESSION)
@@ -2511,6 +2537,8 @@ _slang_can_unroll_for_loop(slang_assemble_ctx * A, const slang_operation *oper)
if (oper->children[1].children[0].children[1].type != SLANG_OPER_LITERAL_INT)
return GL_FALSE;
+ end = (GLint) oper->children[1].children[0].children[1].literal[0];
+
/* children[2] must be "i++" or "++i" */
if (oper->children[2].type != SLANG_OPER_POSTINCREMENT &&
oper->children[2].type != SLANG_OPER_PREINCREMENT)
@@ -2519,13 +2547,11 @@ _slang_can_unroll_for_loop(slang_assemble_ctx * A, const slang_operation *oper)
return GL_FALSE;
/* make sure the same variable name is used in all places */
- if ((oper->children[0].children[0].children[0].a_id !=
- oper->children[1].children[0].children[0].a_id) ||
- (oper->children[0].children[0].children[0].a_id !=
- oper->children[2].children[0].a_id))
+ if ((oper->children[1].children[0].children[0].a_id != varId) ||
+ (oper->children[2].children[0].a_id != varId))
return GL_FALSE;
- varName = (const char *) oper->children[0].children[0].children[0].a_id;
+ varName = (const char *) varId;
/* children[3], the loop body, can't be too large */
bodySize = sizeof_operation(&oper->children[3]);
@@ -2537,10 +2563,6 @@ _slang_can_unroll_for_loop(slang_assemble_ctx * A, const slang_operation *oper)
return GL_FALSE;
}
- /* get/check loop iteration limits */
- start = (GLint) oper->children[0].children[0].children[1].literal[0];
- end = (GLint) oper->children[1].children[0].children[1].literal[0];
-
if (start >= end)
return GL_FALSE; /* degenerate case */
@@ -2578,13 +2600,27 @@ _slang_unroll_for_loop(slang_assemble_ctx * A, const slang_operation *oper)
{
GLint start, end, iter;
slang_ir_node *n, *root = NULL;
+ slang_atom varId;
+
+ if (oper->children[0].type == SLANG_OPER_BLOCK_NO_NEW_SCOPE) {
+ /* for (int i=0; ... */
+ slang_variable *var;
+
+ varId = oper->children[0].children[0].a_id;
+ var = _slang_variable_locate(oper->children[0].children[0].locals,
+ varId, GL_TRUE);
+ start = (GLint) var->initializer->literal[0];
+ }
+ else {
+ /* for (i=0; ... */
+ varId = oper->children[0].children[0].children[0].a_id;
+ start = (GLint) oper->children[0].children[0].children[1].literal[0];
+ }
- start = (GLint) oper->children[0].children[0].children[1].literal[0];
end = (GLint) oper->children[1].children[0].children[1].literal[0];
for (iter = start; iter < end; iter++) {
slang_operation *body;
- slang_atom id;
/* make a copy of the loop body */
body = slang_operation_new(1);
@@ -2594,14 +2630,12 @@ _slang_unroll_for_loop(slang_assemble_ctx * A, const slang_operation *oper)
if (!slang_operation_copy(body, &oper->children[3]))
return NULL;
- id = oper->children[0].children[0].children[0].a_id;
-
- /* in body, replace instances of 'id' with literal 'iter' */
+ /* in body, replace instances of 'varId' with literal 'iter' */
{
slang_variable *oldVar;
slang_operation *newOper;
- oldVar = _slang_variable_locate(oper->locals, id, GL_TRUE);
+ oldVar = _slang_variable_locate(oper->locals, varId, GL_TRUE);
if (!oldVar) {
/* undeclared loop variable */
slang_operation_delete(body);