summaryrefslogtreecommitdiff
path: root/src/mesa/shader/slang/slang_emit.c
diff options
context:
space:
mode:
authorBrian <brian@yutani.localnet.net>2007-01-31 08:55:10 -0700
committerBrian <brian@yutani.localnet.net>2007-01-31 08:55:10 -0700
commit309d5b665051179b7e135d7329da1ea45bfeb8e5 (patch)
tree49af2dba55623498a1eb895ed8794545f76ffdea /src/mesa/shader/slang/slang_emit.c
parent9d5853813f90cf03581d5150b4f2d46fd847211b (diff)
New asm instruction and IR_CLAMP node type to allow clamping to [0,1] with instruction saturate-write option. Not finished yet.
Diffstat (limited to 'src/mesa/shader/slang/slang_emit.c')
-rw-r--r--src/mesa/shader/slang/slang_emit.c96
1 files changed, 91 insertions, 5 deletions
diff --git a/src/mesa/shader/slang/slang_emit.c b/src/mesa/shader/slang/slang_emit.c
index 8e598bf660..1c945fa0ba 100644
--- a/src/mesa/shader/slang/slang_emit.c
+++ b/src/mesa/shader/slang/slang_emit.c
@@ -68,6 +68,7 @@ static slang_ir_info IrInfo[] = {
{ IR_LRP, "IR_LRP", OPCODE_LRP, 4, 3 },
{ IR_MIN, "IR_MIN", OPCODE_MIN, 4, 2 },
{ IR_MAX, "IR_MAX", OPCODE_MAX, 4, 2 },
+ { IR_CLAMP, "IR_CLAMP", OPCODE_NOP, 4, 3 }, /* special case: emit_clamp() */
{ IR_SEQUAL, "IR_SEQUAL", OPCODE_SEQ, 4, 2 },
{ IR_SNEQUAL, "IR_SNEQUAL", OPCODE_SNE, 4, 2 },
{ IR_SGE, "IR_SGE", OPCODE_SGE, 4, 2 },
@@ -84,7 +85,7 @@ static slang_ir_info IrInfo[] = {
{ IR_FLOOR, "IR_FLOOR", OPCODE_FLR, 4, 1 },
{ IR_FRAC, "IR_FRAC", OPCODE_FRC, 4, 1 },
{ IR_ABS, "IR_ABS", OPCODE_ABS, 4, 1 },
- { IR_NEG, "IR_NEG", OPCODE_NOP/*spec case*/, 4, 1 },
+ { IR_NEG, "IR_NEG", OPCODE_NOP, 4, 1 }, /* special case: emit_negation() */
{ IR_DDX, "IR_DDX", OPCODE_DDX, 4, 1 },
{ IR_DDX, "IR_DDY", OPCODE_DDX, 4, 1 },
{ IR_SIN, "IR_SIN", OPCODE_SIN, 1, 1 },
@@ -298,12 +299,14 @@ slang_print_ir(const slang_ir_node *n, int indent)
case IR_VAR:
printf("VAR %s%s at %s store %p\n",
- (char *) n->Var->a_name, swizzle_string(n->Store->Swizzle),
+ (n->Var ? (char *) n->Var->a_name : "TEMP"),
+ swizzle_string(n->Store->Swizzle),
storage_string(n->Store), (void*) n->Store);
break;
case IR_VAR_DECL:
printf("VAR_DECL %s (%p) at %s store %p\n",
- (char *) n->Var->a_name, (void*) n->Var, storage_string(n->Store),
+ (n->Var ? (char *) n->Var->a_name : "TEMP"),
+ (void*) n->Var, storage_string(n->Store),
(void*) n->Store);
break;
case IR_FIELD:
@@ -447,6 +450,19 @@ new_instruction(struct gl_program *prog, gl_inst_opcode opcode)
}
+/**
+ * Return pointer to last instruction in program.
+ */
+static struct prog_instruction *
+prev_instruction(struct gl_program *prog)
+{
+ if (prog->NumInstructions == 0)
+ return NULL;
+ else
+ return prog->Instructions + prog->NumInstructions - 1;
+}
+
+
static struct prog_instruction *
emit(slang_var_table *vt, slang_ir_node *n, struct gl_program *prog);
@@ -674,6 +690,73 @@ emit_arith(slang_var_table *vt, slang_ir_node *n, struct gl_program *prog)
}
+/**
+ * Generate code for an IR_CLAMP instruction.
+ */
+static struct prog_instruction *
+emit_clamp(slang_var_table *vt, slang_ir_node *n, struct gl_program *prog)
+{
+ struct prog_instruction *inst;
+
+ assert(n->Opcode == IR_CLAMP);
+ /* ch[0] = value
+ * ch[1] = min limit
+ * ch[2] = max limit
+ */
+
+ inst = emit(vt, n->Children[0], prog);
+
+ /* If lower limit == 0.0 and upper limit == 1.0,
+ * set prev instruction's SaturateMode field to SATURATE_ZERO_ONE.
+ * Else,
+ * emit OPCODE_MIN, OPCODE_MAX sequence.
+ */
+#if 0
+ /* XXX this isn't quite finished yet */
+ if (n->Children[1]->Opcode == IR_FLOAT &&
+ n->Children[1]->Value[0] == 0.0 &&
+ n->Children[1]->Value[1] == 0.0 &&
+ n->Children[1]->Value[2] == 0.0 &&
+ n->Children[1]->Value[3] == 0.0 &&
+ n->Children[2]->Opcode == IR_FLOAT &&
+ n->Children[2]->Value[0] == 1.0 &&
+ n->Children[2]->Value[1] == 1.0 &&
+ n->Children[2]->Value[2] == 1.0 &&
+ n->Children[2]->Value[3] == 1.0) {
+ if (!inst) {
+ inst = prev_instruction(prog);
+ }
+ if (inst && inst->Opcode != OPCODE_NOP) {
+ /* and prev instruction's DstReg matches n->Children[0]->Store */
+ inst->SaturateMode = SATURATE_ZERO_ONE;
+ n->Store = n->Children[0]->Store;
+ return inst;
+ }
+ }
+#endif
+
+ if (!n->Store)
+ if (!alloc_temp_storage(vt, n, n->Children[0]->Store->Size))
+ return NULL;
+
+ emit(vt, n->Children[1], prog);
+ emit(vt, n->Children[2], prog);
+
+ /* tmp = max(ch[0], ch[1]) */
+ inst = new_instruction(prog, OPCODE_MAX);
+ storage_to_dst_reg(&inst->DstReg, n->Store, n->Writemask);
+ storage_to_src_reg(&inst->SrcReg[0], n->Children[0]->Store);
+ storage_to_src_reg(&inst->SrcReg[1], n->Children[1]->Store);
+
+ /* tmp = min(tmp, ch[2]) */
+ inst = new_instruction(prog, OPCODE_MIN);
+ storage_to_dst_reg(&inst->DstReg, n->Store, n->Writemask);
+ storage_to_src_reg(&inst->SrcReg[0], n->Store);
+ storage_to_src_reg(&inst->SrcReg[1], n->Children[2]->Store);
+
+ return inst;
+}
+
static struct prog_instruction *
emit_negation(slang_var_table *vt, slang_ir_node *n, struct gl_program *prog)
@@ -800,6 +883,9 @@ emit_move(slang_var_table *vt, slang_ir_node *n, struct gl_program *prog)
/* lhs */
emit(vt, n->Children[0], prog);
+ assert(!n->Store);
+ n->Store = n->Children[0]->Store;
+
#if PEEPHOLE_OPTIMIZATIONS
if (inst && _slang_is_temp(vt, n->Children[1]->Store)) {
/* Peephole optimization:
@@ -850,8 +936,6 @@ emit_move(slang_var_table *vt, slang_ir_node *n, struct gl_program *prog)
srcAnnot, NULL, NULL);
}
free_temp_storage(vt, n->Children[1]);
- assert(!n->Store);
- n->Store = n->Children[0]->Store; /*XXX new */
return inst;
}
}
@@ -1022,6 +1106,8 @@ emit(slang_var_table *vt, slang_ir_node *n, struct gl_program *prog)
/* trinary operators */
case IR_LRP:
return emit_arith(vt, n, prog);
+ case IR_CLAMP:
+ return emit_clamp(vt, n, prog);
case IR_TEX:
case IR_TEXB:
case IR_TEXP: