summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrian <brian@yutani.localnet.net>2007-03-23 14:47:46 -0600
committerBrian <brian@yutani.localnet.net>2007-03-23 14:47:46 -0600
commit63556fa9949f543a8134b6b5ff3d216acb71dd9f (patch)
tree347e41773e171e24ef3a6a476567e2b706bd341d
parentbf020d8d7f719dfea7ea3c65bd2833df6439b59e (diff)
Add the ability to generate programs that doesn't use condition codes.
ctx->Shader.EmitCondCodes determines if we use condition codes. If not, IF statement uses first operand's X component as the condition. Added OPCODE_BRK0, OPCODE_BRK1, OPCODE_CONT0, OPCODE_CONT1 to handle the common cases of conditional break/continue.
-rw-r--r--src/mesa/main/mtypes.h6
-rw-r--r--src/mesa/shader/prog_execute.c53
-rw-r--r--src/mesa/shader/prog_instruction.c6
-rw-r--r--src/mesa/shader/prog_instruction.h4
-rw-r--r--src/mesa/shader/prog_print.c30
-rw-r--r--src/mesa/shader/shader_api.c1
-rw-r--r--src/mesa/shader/slang/slang_emit.c123
-rw-r--r--src/mesa/tnl/t_vb_arbprogram.c4
8 files changed, 176 insertions, 51 deletions
diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h
index 0c9bf200d8..828b0f2384 100644
--- a/src/mesa/main/mtypes.h
+++ b/src/mesa/main/mtypes.h
@@ -2127,8 +2127,10 @@ struct gl_shader_program
struct gl_shader_state
{
struct gl_shader_program *CurrentProgram; /**< The user-bound program */
- GLboolean EmitHighLevelInstructions; /**< Driver-selectable */
- GLboolean EmitComments; /**< Driver-selectable */
+ /** Driver-selectable options: */
+ GLboolean EmitHighLevelInstructions; /**< IF/ELSE/ENDIF vs. BRA, etc. */
+ GLboolean EmitCondCodes; /**< Use condition codes? */
+ GLboolean EmitComments; /**< Annotated instructions */
};
diff --git a/src/mesa/shader/prog_execute.c b/src/mesa/shader/prog_execute.c
index 092c07f7b6..f881d477ca 100644
--- a/src/mesa/shader/prog_execute.c
+++ b/src/mesa/shader/prog_execute.c
@@ -720,6 +720,32 @@ _mesa_execute_program(GLcontext * ctx,
pc = inst->BranchTarget - 1;
}
break;
+ case OPCODE_BRK0: /* Break if zero */
+ /* fall-through */
+ case OPCODE_CONT0: /* Continue if zero */
+ {
+ GLfloat a[4];
+ fetch_vector1(&inst->SrcReg[0], machine, a);
+ if (a[0] == 0.0) {
+ /* take branch */
+ /* Subtract 1 here since we'll do pc++ at end of for-loop */
+ pc = inst->BranchTarget - 1;
+ }
+ }
+ break;
+ case OPCODE_BRK1: /* Break if non-zero */
+ /* fall-through */
+ case OPCODE_CONT1: /* Continue if non-zero */
+ {
+ GLfloat a[4];
+ fetch_vector1(&inst->SrcReg[0], machine, a);
+ if (a[0] != 0.0) {
+ /* take branch */
+ /* Subtract 1 here since we'll do pc++ at end of for-loop */
+ pc = inst->BranchTarget - 1;
+ }
+ }
+ break;
case OPCODE_CAL: /* Call subroutine (conditional) */
if (eval_condition(machine, inst)) {
/* call the subroutine */
@@ -914,13 +940,26 @@ _mesa_execute_program(GLcontext * ctx,
}
break;
case OPCODE_IF:
- if (eval_condition(machine, inst)) {
- /* do if-clause (just continue execution) */
- }
- else {
- /* go to the instruction after ELSE or ENDIF */
- assert(inst->BranchTarget >= 0);
- pc = inst->BranchTarget - 1;
+ {
+ GLboolean cond;
+ /* eval condition */
+ if (inst->SrcReg[0].File != PROGRAM_UNDEFINED) {
+ GLfloat a[4];
+ fetch_vector1(&inst->SrcReg[0], machine, a);
+ cond = (a[0] != 0.0);
+ }
+ else {
+ cond = eval_condition(machine, inst);
+ }
+ /* do if/else */
+ if (cond) {
+ /* do if-clause (just continue execution) */
+ }
+ else {
+ /* go to the instruction after ELSE or ENDIF */
+ assert(inst->BranchTarget >= 0);
+ pc = inst->BranchTarget - 1;
+ }
}
break;
case OPCODE_ELSE:
diff --git a/src/mesa/shader/prog_instruction.c b/src/mesa/shader/prog_instruction.c
index ed479a7f61..272caf6c74 100644
--- a/src/mesa/shader/prog_instruction.c
+++ b/src/mesa/shader/prog_instruction.c
@@ -138,9 +138,13 @@ static const struct instruction_info InstInfo[MAX_OPCODE] = {
{ OPCODE_BGNSUB, "BGNSUB", 0 },
{ OPCODE_BRA, "BRA", 0 },
{ OPCODE_BRK, "BRK", 0 },
+ { OPCODE_BRK0, "BRK0", 1 },
+ { OPCODE_BRK1, "BRK1", 1 },
{ OPCODE_CAL, "CAL", 0 },
{ OPCODE_CMP, "CMP", 3 },
- { OPCODE_CONT, "CONT", 1 },
+ { OPCODE_CONT, "CONT", 0 },
+ { OPCODE_CONT0, "CONT0", 1 },
+ { OPCODE_CONT1, "CONT1", 1 },
{ OPCODE_COS, "COS", 1 },
{ OPCODE_DDX, "DDX", 1 },
{ OPCODE_DDY, "DDY", 1 },
diff --git a/src/mesa/shader/prog_instruction.h b/src/mesa/shader/prog_instruction.h
index c800757aa0..dc2d2dc29b 100644
--- a/src/mesa/shader/prog_instruction.h
+++ b/src/mesa/shader/prog_instruction.h
@@ -153,9 +153,13 @@ typedef enum prog_opcode {
OPCODE_BGNSUB, /* opt */
OPCODE_BRA, /* 2 X */
OPCODE_BRK, /* 2 opt */
+ OPCODE_BRK0, /* opt */
+ OPCODE_BRK1, /* opt */
OPCODE_CAL, /* 2 2 */
OPCODE_CMP, /* X */
OPCODE_CONT, /* opt */
+ OPCODE_CONT0, /* opt */
+ OPCODE_CONT1, /* opt */
OPCODE_COS, /* X 2 X X */
OPCODE_DDX, /* X X */
OPCODE_DDY, /* X X */
diff --git a/src/mesa/shader/prog_print.c b/src/mesa/shader/prog_print.c
index d290ce0a2a..39d2a07812 100644
--- a/src/mesa/shader/prog_print.c
+++ b/src/mesa/shader/prog_print.c
@@ -572,10 +572,20 @@ _mesa_print_instruction_opt(const struct prog_instruction *inst, GLint indent,
print_comment(inst);
break;
case OPCODE_IF:
- _mesa_printf("IF (%s%s); # (if false, goto %d)",
- condcode_string(inst->DstReg.CondMask),
- _mesa_swizzle_string(inst->DstReg.CondSwizzle, 0, GL_FALSE),
- inst->BranchTarget);
+ if (inst->SrcReg[0].File != PROGRAM_UNDEFINED) {
+ /* Use ordinary register */
+ _mesa_printf("IF ");
+ print_src_reg(&inst->SrcReg[0], mode, prog);
+ _mesa_printf("; ");
+ }
+ else {
+ /* Use cond codes */
+ _mesa_printf("IF (%s%s);",
+ condcode_string(inst->DstReg.CondMask),
+ _mesa_swizzle_string(inst->DstReg.CondSwizzle,
+ 0, GL_FALSE));
+ }
+ _mesa_printf(" # (if false, goto %d)", inst->BranchTarget);
print_comment(inst);
return indent + 3;
case OPCODE_ELSE:
@@ -604,6 +614,18 @@ _mesa_print_instruction_opt(const struct prog_instruction *inst, GLint indent,
inst->BranchTarget);
print_comment(inst);
break;
+
+ case OPCODE_BRK0:
+ case OPCODE_BRK1:
+ case OPCODE_CONT0:
+ case OPCODE_CONT1:
+ _mesa_printf("%s ", _mesa_opcode_string(inst->Opcode));
+ print_src_reg(&inst->SrcReg[0], mode, prog);
+ _mesa_printf("; ");
+ _mesa_printf(" # (goto %d)", inst->BranchTarget);
+ print_comment(inst);
+ break;
+
case OPCODE_BGNSUB:
_mesa_printf("SUB");
print_comment(inst);
diff --git a/src/mesa/shader/shader_api.c b/src/mesa/shader/shader_api.c
index aab522e292..88aa8c50f5 100644
--- a/src/mesa/shader/shader_api.c
+++ b/src/mesa/shader/shader_api.c
@@ -206,6 +206,7 @@ _mesa_init_shader_state(GLcontext * ctx)
* are generated by the GLSL compiler.
*/
ctx->Shader.EmitHighLevelInstructions = GL_TRUE;
+ ctx->Shader.EmitCondCodes = GL_TRUE; /* XXX probably want GL_FALSE... */
ctx->Shader.EmitComments = GL_FALSE;
}
diff --git a/src/mesa/shader/slang/slang_emit.c b/src/mesa/shader/slang/slang_emit.c
index 16a054b35e..9e476b8a0f 100644
--- a/src/mesa/shader/slang/slang_emit.c
+++ b/src/mesa/shader/slang/slang_emit.c
@@ -61,6 +61,7 @@ typedef struct
struct gl_program *prog;
/* code-gen options */
GLboolean EmitHighLevelInstructions;
+ GLboolean EmitCondCodes;
GLboolean EmitComments;
} slang_emit_info;
@@ -1155,10 +1156,6 @@ emit_move(slang_emit_info *emitInfo, slang_ir_node *n)
static struct prog_instruction *
emit_cond(slang_emit_info *emitInfo, slang_ir_node *n)
{
- /* Conditional expression (in if/while/for stmts).
- * Need to update condition code register.
- * Next instruction is typically an IR_IF.
- */
struct prog_instruction *inst;
if (!n->Children[0])
@@ -1166,28 +1163,39 @@ emit_cond(slang_emit_info *emitInfo, slang_ir_node *n)
inst = emit(emitInfo, n->Children[0]);
- if (inst) {
- /* set inst's CondUpdate flag */
- inst->CondUpdate = GL_TRUE;
- n->Store = n->Children[0]->Store;
- return inst; /* XXX or null? */
+ if (emitInfo->EmitCondCodes) {
+ /* Conditional expression (in if/while/for stmts).
+ * Need to update condition code register.
+ * Next instruction is typically an IR_IF.
+ */
+ if (inst) {
+ /* set inst's CondUpdate flag */
+ inst->CondUpdate = GL_TRUE;
+ n->Store = n->Children[0]->Store;
+ return inst; /* XXX or null? */
+ }
+ else {
+ /* This'll happen for things like "if (i) ..." where no code
+ * is normally generated for the expression "i".
+ * Generate a move instruction just to set condition codes.
+ * Note: must use full 4-component vector since all four
+ * condition codes must be set identically.
+ */
+ if (!alloc_temp_storage(emitInfo, n, 4))
+ return NULL;
+ inst = new_instruction(emitInfo, OPCODE_MOV);
+ inst->CondUpdate = GL_TRUE;
+ storage_to_dst_reg(&inst->DstReg, n->Store, n->Writemask);
+ storage_to_src_reg(&inst->SrcReg[0], n->Children[0]->Store);
+ _slang_free_temp(emitInfo->vt, n->Store);
+ inst->Comment = _mesa_strdup("COND expr");
+ return inst; /* XXX or null? */
+ }
}
else {
- /* This'll happen for things like "if (i) ..." where no code
- * is normally generated for the expression "i".
- * Generate a move instruction just to set condition codes.
- * Note: must use full 4-component vector since all four
- * condition codes must be set identically.
- */
- if (!alloc_temp_storage(emitInfo, n, 4))
- return NULL;
- inst = new_instruction(emitInfo, OPCODE_MOV);
- inst->CondUpdate = GL_TRUE;
- storage_to_dst_reg(&inst->DstReg, n->Store, n->Writemask);
- storage_to_src_reg(&inst->SrcReg[0], n->Children[0]->Store);
- _slang_free_temp(emitInfo->vt, n->Store);
- inst->Comment = _mesa_strdup("COND expr");
- return inst; /* XXX or null? */
+ /* No-op */
+ n->Store = n->Children[0]->Store;
+ return NULL;
}
}
@@ -1244,7 +1252,13 @@ emit_if(slang_emit_info *emitInfo, slang_ir_node *n)
ifInstLoc = prog->NumInstructions;
if (emitInfo->EmitHighLevelInstructions) {
ifInst = new_instruction(emitInfo, OPCODE_IF);
- ifInst->DstReg.CondMask = COND_NE; /* if cond is non-zero */
+ if (emitInfo->EmitCondCodes) {
+ ifInst->DstReg.CondMask = COND_NE; /* if cond is non-zero */
+ }
+ else {
+ /* test reg.x */
+ storage_to_src_reg(&ifInst->SrcReg[0], n->Children[0]->Store);
+ }
}
else {
/* conditional jump to else, or endif */
@@ -1252,8 +1266,10 @@ emit_if(slang_emit_info *emitInfo, slang_ir_node *n)
ifInst->DstReg.CondMask = COND_EQ; /* BRA if cond is zero */
ifInst->Comment = _mesa_strdup("if zero");
}
- /* which condition code to use: */
- ifInst->DstReg.CondSwizzle = n->Children[0]->Store->Swizzle;
+ if (emitInfo->EmitCondCodes) {
+ /* which condition code to use: */
+ ifInst->DstReg.CondSwizzle = n->Children[0]->Store->Swizzle;
+ }
/* if body */
emit(emitInfo, n->Children[1]);
@@ -1342,6 +1358,8 @@ emit_loop(slang_emit_info *emitInfo, slang_ir_node *n)
ir->Opcode == IR_BREAK_IF_FALSE ||
ir->Opcode == IR_BREAK_IF_TRUE) {
assert(inst->Opcode == OPCODE_BRK ||
+ inst->Opcode == OPCODE_BRK0 ||
+ inst->Opcode == OPCODE_BRK1 ||
inst->Opcode == OPCODE_BRA);
/* go to instruction after end of loop */
inst->BranchTarget = endInstLoc + 1;
@@ -1351,6 +1369,8 @@ emit_loop(slang_emit_info *emitInfo, slang_ir_node *n)
ir->Opcode == IR_CONT_IF_FALSE ||
ir->Opcode == IR_CONT_IF_TRUE);
assert(inst->Opcode == OPCODE_CONT ||
+ inst->Opcode == OPCODE_CONT0 ||
+ inst->Opcode == OPCODE_CONT1 ||
inst->Opcode == OPCODE_BRA);
/* to go instruction at top of loop */
inst->BranchTarget = beginInstLoc;
@@ -1361,7 +1381,7 @@ emit_loop(slang_emit_info *emitInfo, slang_ir_node *n)
/**
- * "Continue" or "break" statement.
+ * Unconditional "continue" or "break" statement.
* Either OPCODE_CONT, OPCODE_BRK or OPCODE_BRA will be emitted.
*/
static struct prog_instruction *
@@ -1393,24 +1413,52 @@ emit_cont_break_if(slang_emit_info *emitInfo, slang_ir_node *n,
gl_inst_opcode opcode;
struct prog_instruction *inst;
+ assert(n->Opcode == IR_CONT_IF_TRUE ||
+ n->Opcode == IR_CONT_IF_FALSE ||
+ n->Opcode == IR_BREAK_IF_TRUE ||
+ n->Opcode == IR_BREAK_IF_FALSE);
+
/* evaluate condition expr, setting cond codes */
inst = emit(emitInfo, n->Children[0]);
- assert(inst);
- inst->CondUpdate = GL_TRUE;
+ if (emitInfo->EmitCondCodes) {
+ assert(inst);
+ inst->CondUpdate = GL_TRUE;
+ }
n->InstLocation = emitInfo->prog->NumInstructions;
+
+ /* opcode selection */
if (emitInfo->EmitHighLevelInstructions) {
- if (n->Opcode == IR_CONT_IF_TRUE ||
- n->Opcode == IR_CONT_IF_FALSE)
- opcode = OPCODE_CONT;
- else
- opcode = OPCODE_BRK;
+ if (emitInfo->EmitCondCodes) {
+ if (n->Opcode == IR_CONT_IF_TRUE ||
+ n->Opcode == IR_CONT_IF_FALSE)
+ opcode = OPCODE_CONT;
+ else
+ opcode = OPCODE_BRK;
+ }
+ else {
+ if (n->Opcode == IR_CONT_IF_TRUE)
+ opcode = OPCODE_CONT1;
+ else if (n->Opcode == IR_CONT_IF_FALSE)
+ opcode = OPCODE_CONT0;
+ else if (n->Opcode == IR_BREAK_IF_TRUE)
+ opcode = OPCODE_BRK1;
+ else if (n->Opcode == IR_BREAK_IF_FALSE)
+ opcode = OPCODE_BRK0;
+ }
}
else {
opcode = OPCODE_BRA;
}
+
inst = new_instruction(emitInfo, opcode);
- inst->DstReg.CondMask = breakTrue ? COND_NE : COND_EQ;
+ if (emitInfo->EmitCondCodes) {
+ inst->DstReg.CondMask = breakTrue ? COND_NE : COND_EQ;
+ }
+ else {
+ /* BRK0, BRK1, CONT0, CONT1 */
+ storage_to_src_reg(&inst->SrcReg[0], n->Children[0]->Store);
+ }
return inst;
}
@@ -1779,7 +1827,8 @@ _slang_emit_code(slang_ir_node *n, slang_var_table *vt,
emitInfo.prog = prog;
emitInfo.EmitHighLevelInstructions = ctx->Shader.EmitHighLevelInstructions;
- emitInfo.EmitComments = 1+ctx->Shader.EmitComments;
+ emitInfo.EmitCondCodes = 0; /* XXX temporary! */
+ emitInfo.EmitComments = ctx->Shader.EmitComments;
(void) emit(&emitInfo, n);
diff --git a/src/mesa/tnl/t_vb_arbprogram.c b/src/mesa/tnl/t_vb_arbprogram.c
index b322d48b23..425a866994 100644
--- a/src/mesa/tnl/t_vb_arbprogram.c
+++ b/src/mesa/tnl/t_vb_arbprogram.c
@@ -741,9 +741,13 @@ static gpu_function opcode_func[MAX_OPCODE+3] =
do_NOP,/*BGNSUB*/
do_NOP,/*BRA*/
do_NOP,/*BRK*/
+ do_NOP,/*BRK0*/
+ do_NOP,/*BRK1*/
do_NOP,/*CAL*/
do_NOP,/*CMP*/
do_NOP,/*CONT*/
+ do_NOP,/*CONT0*/
+ do_NOP,/*CONT1*/
do_NOP,/*COS*/
do_NOP,/*DDX*/
do_NOP,/*DDY*/