summaryrefslogtreecommitdiffstats
path: root/src/mesa/shader
diff options
context:
space:
mode:
authorBrian <[email protected]>2006-12-18 10:05:24 -0700
committerBrian <[email protected]>2006-12-18 10:05:24 -0700
commit1aee657b0f0fb34a0d6717e47f3bdfd67de8bfc2 (patch)
treea963e0a23653cb87240994c90cd7500e6e112e73 /src/mesa/shader
parent34ae99d6049b10115ca64daecdd1d879d3b5140d (diff)
Implement if-conditionals and while loops, added temporary resolve-branches function in linker.
Diffstat (limited to 'src/mesa/shader')
-rw-r--r--src/mesa/shader/slang/slang_codegen.c149
-rw-r--r--src/mesa/shader/slang/slang_emit.c26
-rw-r--r--src/mesa/shader/slang/slang_link2.c44
3 files changed, 167 insertions, 52 deletions
diff --git a/src/mesa/shader/slang/slang_codegen.c b/src/mesa/shader/slang/slang_codegen.c
index 2f2b2b2a4e0..9cfcfd45d30 100644
--- a/src/mesa/shader/slang/slang_codegen.c
+++ b/src/mesa/shader/slang/slang_codegen.c
@@ -122,10 +122,10 @@ new_seq(slang_ir_node *left, slang_ir_node *right)
}
static slang_ir_node *
-new_label(const char *name)
+new_label(slang_atom labName)
{
slang_ir_node *n = new_node(IR_LABEL, NULL, NULL);
- n->Target = _mesa_strdup(name);
+ n->Target = (char *) labName; /*_mesa_strdup(name);*/
return n;
}
@@ -141,20 +141,20 @@ new_float_literal(float x, float y, float z, float w)
}
static slang_ir_node *
-new_cjump(slang_ir_node *cond, const char *target)
+new_cjump(slang_atom target)
{
- slang_ir_node *n = new_node(IR_CJUMP, cond, NULL);
- n->Target = _mesa_strdup(target);
+ slang_ir_node *n = new_node(IR_CJUMP, NULL, NULL);
+ if (n)
+ n->Target = (char *) target;
return n;
}
static slang_ir_node *
-new_jump(const char *target)
+new_jump(slang_atom target)
{
slang_ir_node *n = new_node(IR_JUMP, NULL, NULL);
- if (n) {
- n->Target = _mesa_strdup(target);
- }
+ if (n)
+ n->Target = (char *) target;
return n;
}
@@ -893,6 +893,16 @@ slang_assemble_asm(slang_assemble_ctx *A, slang_operation *oper,
+static GLboolean
+_slang_is_noop(const slang_operation *oper)
+{
+ if (!oper ||
+ oper->type == slang_oper_void ||
+ (oper->num_children == 1 && oper->children[0].type == slang_oper_void))
+ return GL_TRUE;
+ else
+ return GL_FALSE;
+}
/**
@@ -923,6 +933,88 @@ slang_assemble_function_call_name(slang_assemble_ctx *A, const char *name,
static slang_ir_node *
+_slang_gen_while(slang_assemble_ctx * A, const slang_operation *oper)
+{
+ /*
+ * label "__whileStart"
+ * eval expr (child[0]), updating condcodes
+ * branch if false to "__endWhile"
+ * code body
+ * jump "__whileStart"
+ * label "__endWhile"
+ */
+ slang_atom startAtom = slang_atom_pool_gen(A->atoms, "__startWhile");
+ slang_atom endAtom = slang_atom_pool_gen(A->atoms, "__endWhile");
+ slang_ir_node *startLab, *cond, *bra, *body, *jump, *endLab, *tree;
+
+ startLab = new_label(startAtom);
+ cond = slang_assemble_operation(A, &oper->children[0]);
+ tree = new_seq(startLab, cond);
+
+ bra = new_cjump(endAtom);
+ tree = new_seq(tree, bra);
+
+ body = slang_assemble_operation(A, &oper->children[1]);
+ tree = new_seq(tree, body);
+
+ jump = new_jump(startAtom);
+ tree = new_seq(tree, jump);
+
+ endLab = new_label(endAtom);
+ tree = new_seq(tree, endLab);
+
+ return tree;
+}
+
+
+static slang_ir_node *
+_slang_gen_if(slang_assemble_ctx * A, const slang_operation *oper)
+{
+ /*
+ * eval expr (child[0]), updating condcodes
+ * branch if false to _else or _endif
+ * "true" code block
+ * if haveElseClause clause:
+ * jump "__endif"
+ * label "__else"
+ * "false" code block
+ * label "__endif"
+ */
+ const GLboolean haveElseClause = !_slang_is_noop(&oper->children[2]);
+ slang_ir_node *cond, *bra, *trueBody, *endifLab, *tree;
+ slang_atom elseAtom = slang_atom_pool_gen(A->atoms, "__else");
+ slang_atom endifAtom = slang_atom_pool_gen(A->atoms, "__endif");
+
+ cond = slang_assemble_operation(A, &oper->children[0]);
+ /*assert(cond->Store);*/
+ bra = new_cjump(haveElseClause ? elseAtom : endifAtom);
+ tree = new_seq(cond, bra);
+
+ trueBody = slang_assemble_operation(A, &oper->children[1]);
+ tree = new_seq(tree, trueBody);
+
+ if (haveElseClause) {
+ /* else clause */
+ slang_ir_node *jump, *elseLab, *falseBody;
+ jump = new_jump(endifAtom);
+ tree = new_seq(tree, jump);
+
+ elseLab = new_label(elseAtom);
+ tree = new_seq(tree, elseLab);
+
+ falseBody = slang_assemble_operation(A, &oper->children[2]);
+ tree = new_seq(tree, falseBody);
+ }
+
+ endifLab = new_label(endifAtom);
+ tree = new_seq(tree, endifLab);
+
+ return tree;
+}
+
+
+
+static slang_ir_node *
slang_assemble_operation(slang_assemble_ctx * A, slang_operation *oper)
{
switch (oper->type) {
@@ -944,25 +1036,7 @@ slang_assemble_operation(slang_assemble_ctx * A, slang_operation *oper)
return slang_assemble_operation(A, &oper->children[0]);
break;
case slang_oper_while:
- {
- slang_ir_node *tree;
- slang_ir_node *nStartLabel = new_label("while-start");
- slang_ir_node *nCond = slang_assemble_operation(A, &oper->children[0]);
- slang_ir_node *nNotCond = new_node(IR_NOT, nCond, NULL);
- slang_ir_node *nBody = slang_assemble_operation(A, &oper->children[1]);
- slang_ir_node *nEndLabel = new_label("while-end");
- slang_ir_node *nCJump = new_cjump(nNotCond, "while-end");
- slang_ir_node *nJump = new_jump("while-start");
-
- tree = new_seq(nStartLabel, nCond);
- tree = new_seq(tree, nNotCond);
- tree = new_seq(tree, nBody);
- tree = new_seq(tree, nEndLabel);
- tree = new_seq(tree, nCJump);
- tree = new_seq(tree, nJump);
- return tree;
- }
- break;
+ return _slang_gen_while(A, oper);
case slang_oper_equal:
return new_node(IR_SEQUAL,
slang_assemble_operation(A, &oper->children[0]),
@@ -1145,24 +1219,7 @@ slang_assemble_operation(slang_assemble_ctx * A, slang_operation *oper)
}
break;
case slang_oper_if:
- {
- slang_ir_node *cond, *bra, *body, *endif, *tree;
-
- cond = slang_assemble_operation(A, &oper->children[0]);
- /*assert(cond->Store);*/
- bra = new_node(IR_CJUMP, NULL, NULL);
- bra->Target = _mesa_strdup("__endif");
-
- body = slang_assemble_operation(A, &oper->children[1]);
-
- endif = new_label("__endif");
-
- tree = new_seq(cond, bra);
- tree = new_seq(tree, body);
- tree = new_seq(tree, endif);
- return tree;
- }
- break;
+ return _slang_gen_if(A, oper);
case slang_oper_field:
{
slang_assembly_typeinfo ti;
diff --git a/src/mesa/shader/slang/slang_emit.c b/src/mesa/shader/slang/slang_emit.c
index fbee314d242..ba1290b45e4 100644
--- a/src/mesa/shader/slang/slang_emit.c
+++ b/src/mesa/shader/slang/slang_emit.c
@@ -897,6 +897,12 @@ emit_binop(slang_gen_context *gc, slang_ir_node *n, struct gl_program *prog)
storage_to_src_reg(&inst->SrcReg[1], n->Children[1]->Store,
n->Children[1]->Swizzle);
inst->Comment = n->Comment;
+
+ if (inst->Opcode == OPCODE_SGT) {
+ /* update cond codes */
+ inst->CondUpdate = GL_TRUE;
+ }
+
return inst;
}
@@ -951,6 +957,18 @@ emit_cjump(const char *target, struct gl_program *prog)
}
+static struct prog_instruction *
+emit_jump(const char *target, struct gl_program *prog)
+{
+ struct prog_instruction *inst;
+ inst = new_instruction(prog, OPCODE_BRA);
+ inst->DstReg.CondMask = COND_TR; /* always branch */
+ /*inst->DstReg.CondSwizzle = SWIZZLE_X;*/
+ inst->Comment = _mesa_strdup(target);
+ return inst;
+}
+
+
static struct prog_instruction *
emit(slang_gen_context *gc, slang_ir_node *n, struct gl_program *prog)
@@ -1069,15 +1087,11 @@ emit(slang_gen_context *gc, slang_ir_node *n, struct gl_program *prog)
break;
case IR_LABEL:
return emit_label(n->Target, prog);
- case IR_JUMP:
-#if 0
- inst = new_instruction(prog, OPCODE_BRA);
- inst->Comment = _mesa_strdup(n->Target);
-#endif
- break;
case IR_FLOAT:
n->Store = alloc_constant(n->Value, 4, prog); /*XXX fix size */
break;
+ case IR_JUMP:
+ return emit_jump(n->Target, prog);
case IR_CJUMP:
return emit_cjump(n->Target, prog);
default:
diff --git a/src/mesa/shader/slang/slang_link2.c b/src/mesa/shader/slang/slang_link2.c
index 6a276d69ac0..c170b3e053f 100644
--- a/src/mesa/shader/slang/slang_link2.c
+++ b/src/mesa/shader/slang/slang_link2.c
@@ -230,6 +230,47 @@ link_uniform_vars(struct gl_linked_program *linked, struct gl_program *prog)
/**
+ * XXX Temporary
+ */
+static void
+slang_resolve_branches(struct gl_program *prog)
+{
+ struct target {
+ const char *Name;
+ GLuint Pos;
+ };
+ struct target targets[500];
+ GLuint numTargets = 0;
+ GLuint i, j;
+
+ for (i = 0; i < prog->NumInstructions; i++) {
+ struct prog_instruction *inst = prog->Instructions + i;
+ if (inst->Opcode == OPCODE_NOP && inst->Comment) {
+ targets[numTargets].Name = inst->Comment;
+ targets[numTargets].Pos = i;
+ numTargets++;
+ }
+ }
+
+ for (i = 0; i < prog->NumInstructions; i++) {
+ struct prog_instruction *inst = prog->Instructions + i;
+ if (inst->Opcode == OPCODE_BRA) {
+ for (j = 0; j < numTargets; j++) {
+ if (!strcmp(inst->Comment, targets[j].Name)) {
+ inst->BranchTarget = targets[j].Pos;
+ break;
+ }
+ }
+ if (j == numTargets) {
+ abort();
+ }
+ }
+ }
+}
+
+
+
+/**
* Shader linker. Currently:
*
* 1. The last attached vertex shader and fragment shader are linked.
@@ -298,6 +339,9 @@ _slang_link2(GLcontext *ctx,
linked->VertexProgram->Base.Parameters = linked->Uniforms;
linked->FragmentProgram->Base.Parameters = linked->Uniforms;
+ slang_resolve_branches(&linked->VertexProgram->Base);
+ slang_resolve_branches(&linked->FragmentProgram->Base);
+
#if 1
printf("************** original fragment program\n");
_mesa_print_program(&fragProg->Base);