summaryrefslogtreecommitdiff
path: root/src/gallium/drivers/svga/svga_tgsi_insn.c
diff options
context:
space:
mode:
authorMichel Dänzer <daenzer@vmware.com>2011-01-28 16:09:05 +0100
committerMichel Dänzer <daenzer@vmware.com>2011-01-31 17:47:57 +0100
commit5a1ce49c82e245f1f86510d9e1ff7db46a32012b (patch)
tree0266e7781abc7a9e3d3de1743477835b408b1387 /src/gallium/drivers/svga/svga_tgsi_insn.c
parent11c11ee0bc96c5b84f98c0223f52fa6d2b4fe5c8 (diff)
svga: Fix translation of TGSI SSG opcode.
SVGA3D only supports SGN for vertex shaders, and this requires two additional temporary registers for intermediate results. For fragment shaders, lower to two CMPs and one ADD.
Diffstat (limited to 'src/gallium/drivers/svga/svga_tgsi_insn.c')
-rw-r--r--src/gallium/drivers/svga/svga_tgsi_insn.c40
1 files changed, 39 insertions, 1 deletions
diff --git a/src/gallium/drivers/svga/svga_tgsi_insn.c b/src/gallium/drivers/svga/svga_tgsi_insn.c
index f2591c5721..5f262b3ead 100644
--- a/src/gallium/drivers/svga/svga_tgsi_insn.c
+++ b/src/gallium/drivers/svga/svga_tgsi_insn.c
@@ -57,7 +57,6 @@ translate_opcode(
case TGSI_OPCODE_MUL: return SVGA3DOP_MUL;
case TGSI_OPCODE_NOP: return SVGA3DOP_NOP;
case TGSI_OPCODE_NRM4: return SVGA3DOP_NRM;
- case TGSI_OPCODE_SSG: return SVGA3DOP_SGN;
default:
debug_printf("Unkown opcode %u\n", opcode);
assert( 0 );
@@ -1066,6 +1065,41 @@ static boolean emit_cos(struct svga_shader_emitter *emit,
return TRUE;
}
+static boolean emit_ssg(struct svga_shader_emitter *emit,
+ const struct tgsi_full_instruction *insn )
+{
+ SVGA3dShaderDestToken dst = translate_dst_register( emit, insn, 0 );
+ struct src_register src0 = translate_src_register(
+ emit, &insn->Src[0] );
+ SVGA3dShaderDestToken temp0 = get_temp( emit );
+ SVGA3dShaderDestToken temp1 = get_temp( emit );
+ struct src_register zero, one;
+
+ if (emit->unit == PIPE_SHADER_VERTEX) {
+ /* SGN DST, SRC0, TMP0, TMP1 */
+ return submit_op3( emit, inst_token( SVGA3DOP_SGN ), dst, src0,
+ src( temp0 ), src( temp1 ) );
+ }
+
+ zero = get_zero_immediate( emit );
+ one = scalar( zero, TGSI_SWIZZLE_W );
+ zero = scalar( zero, TGSI_SWIZZLE_X );
+
+ /* CMP TMP0, SRC0, one, zero */
+ if (!submit_op3( emit, inst_token( SVGA3DOP_CMP ),
+ writemask( temp0, dst.mask ), src0, one, zero ))
+ return FALSE;
+
+ /* CMP TMP1, negate(SRC0), negate(one), zero */
+ if (!submit_op3( emit, inst_token( SVGA3DOP_CMP ),
+ writemask( temp1, dst.mask ), negate( src0 ), negate( one ),
+ zero ))
+ return FALSE;
+
+ /* ADD DST, TMP0, TMP1 */
+ return submit_op2( emit, inst_token( SVGA3DOP_ADD ), dst, src( temp0 ),
+ src( temp1 ) );
+}
/*
* ADD DST SRC0, negate(SRC0)
@@ -2366,6 +2400,9 @@ static boolean svga_emit_instruction( struct svga_shader_emitter *emit,
case TGSI_OPCODE_LRP:
return emit_lrp( emit, insn );
+ case TGSI_OPCODE_SSG:
+ return emit_ssg( emit, insn );
+
default: {
unsigned opcode = translate_opcode(insn->Instruction.Opcode);
@@ -2715,6 +2752,7 @@ needs_to_create_zero( struct svga_shader_emitter *emit )
return TRUE;
if (emit->info.opcode_count[TGSI_OPCODE_DST] >= 1 ||
+ emit->info.opcode_count[TGSI_OPCODE_SSG] >= 1 ||
emit->info.opcode_count[TGSI_OPCODE_LIT] >= 1)
return TRUE;
}