summaryrefslogtreecommitdiffstats
path: root/src/mesa/shader
diff options
context:
space:
mode:
authorBrian Paul <[email protected]>2008-03-14 13:50:01 -0600
committerBrian Paul <[email protected]>2008-03-14 13:50:01 -0600
commit7dc449d406a88fbb92aedfacfa3869176ba2cb31 (patch)
tree6d492cfcede356aa60556818a8cc4228c8128895 /src/mesa/shader
parent14150bc8567cf424fc3a635a33f05213505681be (diff)
mesa: fix emit_clamp() so that we don't use an output register as temporary
IR_CLAMP is decomposed into OPCODE_MIN+OPCODE_MAX. Allocate a temporary register for the intermediate value so we don't inadvertantly use an output register (which are write-only on some GPUs).
Diffstat (limited to 'src/mesa/shader')
-rw-r--r--src/mesa/shader/slang/slang_emit.c15
1 files changed, 12 insertions, 3 deletions
diff --git a/src/mesa/shader/slang/slang_emit.c b/src/mesa/shader/slang/slang_emit.c
index 2b08e7020f0..3763b567055 100644
--- a/src/mesa/shader/slang/slang_emit.c
+++ b/src/mesa/shader/slang/slang_emit.c
@@ -677,6 +677,7 @@ static struct prog_instruction *
emit_clamp(slang_emit_info *emitInfo, slang_ir_node *n)
{
struct prog_instruction *inst;
+ slang_ir_node tmpNode;
assert(n->Opcode == IR_CLAMP);
/* ch[0] = value
@@ -722,18 +723,26 @@ emit_clamp(slang_emit_info *emitInfo, slang_ir_node *n)
emit(emitInfo, n->Children[1]);
emit(emitInfo, n->Children[2]);
+ /* Some GPUs don't allow reading from output registers. So if the
+ * dest for this clamp() is an output reg, we can't use that reg for
+ * the intermediate result. Use a temp register instead.
+ */
+ alloc_temp_storage(emitInfo, &tmpNode, n->Store->Size);
+
/* tmp = max(ch[0], ch[1]) */
inst = new_instruction(emitInfo, OPCODE_MAX);
- storage_to_dst_reg(&inst->DstReg, n->Store, n->Writemask);
+ storage_to_dst_reg(&inst->DstReg, tmpNode.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]) */
+ /* n->dest = min(tmp, ch[2]) */
inst = new_instruction(emitInfo, 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[0], tmpNode.Store);
storage_to_src_reg(&inst->SrcReg[1], n->Children[2]->Store);
+ free_temp_storage(emitInfo->vt, &tmpNode);
+
return inst;
}