X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fgallium%2Fdrivers%2Fsvga%2Fsvga_tgsi_insn.c;h=3d4f56a67bd5388b7b90aac4808b7df307047103;hb=42910ebe7b9748c0ecb6a597bae3e7d43c7e170f;hp=2ab13cbfbc04623ab747d4fca2cc7bacdd613002;hpb=0748fc4f038a0878a981024ac4364f82a23e1ca1;p=mesa.git diff --git a/src/gallium/drivers/svga/svga_tgsi_insn.c b/src/gallium/drivers/svga/svga_tgsi_insn.c index 2ab13cbfbc0..3d4f56a67bd 100644 --- a/src/gallium/drivers/svga/svga_tgsi_insn.c +++ b/src/gallium/drivers/svga/svga_tgsi_insn.c @@ -112,6 +112,7 @@ translate_dst_register( struct svga_shader_emitter *emit, } dest.mask = reg->Register.WriteMask; + assert(dest.mask); if (insn->Instruction.Saturate) dest.dstMod = SVGA3DDSTMOD_SATURATE; @@ -413,6 +414,88 @@ static boolean submit_op3( struct svga_shader_emitter *emit, } + + +/* SVGA shaders may not refer to >1 constant register in a single + * instruction. This function checks for that usage and inserts a + * move to temporary if detected. + */ +static boolean submit_op4( struct svga_shader_emitter *emit, + SVGA3dShaderInstToken inst, + SVGA3dShaderDestToken dest, + struct src_register src0, + struct src_register src1, + struct src_register src2, + struct src_register src3) +{ + SVGA3dShaderDestToken temp0; + SVGA3dShaderDestToken temp3; + boolean need_temp0 = FALSE; + boolean need_temp3 = FALSE; + SVGA3dShaderRegType type0, type1, type2, type3; + + temp0.value = 0; + temp3.value = 0; + type0 = SVGA3dShaderGetRegType( src0.base.value ); + type1 = SVGA3dShaderGetRegType( src1.base.value ); + type2 = SVGA3dShaderGetRegType( src2.base.value ); + type3 = SVGA3dShaderGetRegType( src2.base.value ); + + /* Make life a little easier - this is only used by the TXD + * instruction which is guaranteed not to have a constant/input reg + * in one slot at least: + */ + assert(type1 == SVGA3DREG_SAMPLER); + + if (type0 == SVGA3DREG_CONST && + ((type3 == SVGA3DREG_CONST && src0.base.num != src3.base.num) || + (type2 == SVGA3DREG_CONST && src0.base.num != src2.base.num))) + need_temp0 = TRUE; + + if (type3 == SVGA3DREG_CONST && + (type2 == SVGA3DREG_CONST && src3.base.num != src2.base.num)) + need_temp3 = TRUE; + + if (type0 == SVGA3DREG_INPUT && + ((type3 == SVGA3DREG_INPUT && src0.base.num != src3.base.num) || + (type2 == SVGA3DREG_INPUT && src0.base.num != src2.base.num))) + need_temp0 = TRUE; + + if (type3 == SVGA3DREG_INPUT && + (type2 == SVGA3DREG_INPUT && src3.base.num != src2.base.num)) + need_temp3 = TRUE; + + if (need_temp0) + { + temp0 = get_temp( emit ); + + if (!emit_op1( emit, inst_token( SVGA3DOP_MOV ), temp0, src0 )) + return FALSE; + + src0 = src( temp0 ); + } + + if (need_temp3) + { + temp3 = get_temp( emit ); + + if (!emit_op1( emit, inst_token( SVGA3DOP_MOV ), temp3, src3 )) + return FALSE; + + src3 = src( temp3 ); + } + + if (!emit_op4( emit, inst, dest, src0, src1, src2, src3 )) + return FALSE; + + if (need_temp3) + release_temp( emit, temp3 ); + if (need_temp0) + release_temp( emit, temp0 ); + return TRUE; +} + + static boolean emit_def_const( struct svga_shader_emitter *emit, SVGA3dShaderConstType type, unsigned idx, @@ -443,6 +526,7 @@ static boolean emit_def_const( struct svga_shader_emitter *emit, break; default: assert(0); + opcode = inst_token( SVGA3DOP_NOP ); break; } @@ -1176,17 +1260,22 @@ static boolean emit_tex2(struct svga_shader_emitter *emit, SVGA3dShaderDestToken tmp; inst.value = 0; - inst.op = SVGA3DOP_TEX; switch (insn->Instruction.Opcode) { case TGSI_OPCODE_TEX: + inst.op = SVGA3DOP_TEX; break; case TGSI_OPCODE_TXP: + inst.op = SVGA3DOP_TEX; inst.control = SVGA3DOPCONT_PROJECT; break; case TGSI_OPCODE_TXB: + inst.op = SVGA3DOP_TEX; inst.control = SVGA3DOPCONT_BIAS; break; + case TGSI_OPCODE_TXL: + inst.op = SVGA3DOP_TEXLDL; + break; default: assert(0); return FALSE; @@ -1203,6 +1292,7 @@ static boolean emit_tex2(struct svga_shader_emitter *emit, * zero in that case. */ if (emit->dynamic_branching_level > 0 && + inst.op == SVGA3DOP_TEX && SVGA3dShaderGetRegType(texcoord.base.value) == SVGA3DREG_TEMP) { struct src_register zero = get_zero_immediate( emit ); @@ -1245,14 +1335,20 @@ static boolean emit_tex2(struct svga_shader_emitter *emit, /* Translate texture instructions to SVGA3D representation. */ -static boolean emit_tex3(struct svga_shader_emitter *emit, +static boolean emit_tex4(struct svga_shader_emitter *emit, const struct tgsi_full_instruction *insn, SVGA3dShaderDestToken dst ) { SVGA3dShaderInstToken inst; - struct src_register src0; - struct src_register src1; - struct src_register src2; + struct src_register texcoord; + struct src_register ddx; + struct src_register ddy; + struct src_register sampler; + + texcoord = translate_src_register( emit, &insn->Src[0] ); + ddx = translate_src_register( emit, &insn->Src[1] ); + ddy = translate_src_register( emit, &insn->Src[2] ); + sampler = translate_src_register( emit, &insn->Src[3] ); inst.value = 0; @@ -1260,16 +1356,12 @@ static boolean emit_tex3(struct svga_shader_emitter *emit, case TGSI_OPCODE_TXD: inst.op = SVGA3DOP_TEXLDD; /* 4 args! */ break; - case TGSI_OPCODE_TXL: - inst.op = SVGA3DOP_TEXLDL; /* 2 args! */ - break; + default: + assert(0); + return FALSE; } - src0 = translate_src_register( emit, &insn->Src[0] ); - src1 = translate_src_register( emit, &insn->Src[1] ); - src2 = translate_src_register( emit, &insn->Src[2] ); - - return submit_op3( emit, inst, dst, src0, src1, src2 ); + return submit_op4( emit, inst, dst, texcoord, sampler, ddx, ddy ); } @@ -1305,12 +1397,12 @@ static boolean emit_tex(struct svga_shader_emitter *emit, case TGSI_OPCODE_TEX: case TGSI_OPCODE_TXB: case TGSI_OPCODE_TXP: + case TGSI_OPCODE_TXL: if (!emit_tex2( emit, insn, tex_result )) return FALSE; break; - case TGSI_OPCODE_TXL: case TGSI_OPCODE_TXD: - if (!emit_tex3( emit, insn, tex_result )) + if (!emit_tex4( emit, insn, tex_result )) return FALSE; break; default: @@ -1319,34 +1411,42 @@ static boolean emit_tex(struct svga_shader_emitter *emit, if (compare) { - SVGA3dShaderDestToken src0_zdivw = get_temp( emit ); - struct src_register tex_src_x = scalar(src(tex_result), TGSI_SWIZZLE_Y); - struct src_register one = - scalar( get_zero_immediate( emit ), TGSI_SWIZZLE_W ); - - /* Divide texcoord R by Q */ - if (!submit_op1( emit, inst_token( SVGA3DOP_RCP ), - src0_zdivw, - scalar(src0, TGSI_SWIZZLE_W) )) - return FALSE; + if (dst.mask & TGSI_WRITEMASK_XYZ) { + SVGA3dShaderDestToken src0_zdivw = get_temp( emit ); + struct src_register tex_src_x = scalar(src(tex_result), TGSI_SWIZZLE_Y); + + /* Divide texcoord R by Q */ + if (!submit_op1( emit, inst_token( SVGA3DOP_RCP ), + writemask(src0_zdivw, TGSI_WRITEMASK_X), + scalar(src0, TGSI_SWIZZLE_W) )) + return FALSE; - if (!submit_op2( emit, inst_token( SVGA3DOP_MUL ), - src0_zdivw, - scalar(src0, TGSI_SWIZZLE_Z), - src(src0_zdivw) )) - return FALSE; + if (!submit_op2( emit, inst_token( SVGA3DOP_MUL ), + writemask(src0_zdivw, TGSI_WRITEMASK_X), + scalar(src0, TGSI_SWIZZLE_Z), + scalar(src(src0_zdivw), TGSI_SWIZZLE_X) )) + return FALSE; - if (!emit_select( - emit, - emit->key.fkey.tex[src1.base.num].compare_func, - dst, - src(src0_zdivw), - tex_src_x)) - return FALSE; + if (!emit_select( + emit, + emit->key.fkey.tex[src1.base.num].compare_func, + writemask( dst, TGSI_WRITEMASK_XYZ ), + scalar(src(src0_zdivw), TGSI_SWIZZLE_X), + tex_src_x)) + return FALSE; + } - return submit_op1( emit, inst_token( SVGA3DOP_MOV ), - writemask( dst, TGSI_WRITEMASK_W), - one ); + if (dst.mask & TGSI_WRITEMASK_W) { + struct src_register one = + scalar( get_zero_immediate( emit ), TGSI_SWIZZLE_W ); + + if (!submit_op1( emit, inst_token( SVGA3DOP_MOV ), + writemask( dst, TGSI_WRITEMASK_W ), + one )) + return FALSE; + } + + return TRUE; } else if (!emit->use_sm30 && dst.mask != TGSI_WRITEMASK_XYZW) { @@ -1720,6 +1820,8 @@ static boolean emit_exp(struct svga_shader_emitter *emit, fraction = dst; else if (dst.mask & TGSI_WRITEMASK_X) fraction = get_temp( emit ); + else + fraction.value = 0; /* If y is being written, fill it with src0 - floor(src0). */ @@ -1734,13 +1836,13 @@ static boolean emit_exp(struct svga_shader_emitter *emit, */ if (dst.mask & TGSI_WRITEMASK_X) { if (!submit_op2( emit, inst_token( SVGA3DOP_ADD ), - writemask( dst, dst.mask & TGSI_WRITEMASK_X ), + writemask( dst, TGSI_WRITEMASK_X ), src0, scalar( negate( src( fraction ) ), TGSI_SWIZZLE_Y ) ) ) return FALSE; if (!submit_op1( emit, inst_token( SVGA3DOP_EXP ), - writemask( dst, dst.mask & TGSI_WRITEMASK_X ), + writemask( dst, TGSI_WRITEMASK_X ), scalar( src( dst ), TGSI_SWIZZLE_X ) ) ) return FALSE; @@ -1752,7 +1854,7 @@ static boolean emit_exp(struct svga_shader_emitter *emit, */ if (dst.mask & TGSI_WRITEMASK_Z) { if (!submit_op1( emit, inst_token( SVGA3DOP_EXPP ), - writemask( dst, dst.mask & TGSI_WRITEMASK_Z ), + writemask( dst, TGSI_WRITEMASK_Z ), src0 ) ) return FALSE; } @@ -1914,10 +2016,14 @@ static boolean emit_log(struct svga_shader_emitter *emit, struct src_register abs_src0; SVGA3dShaderDestToken log2_abs; + abs_tmp.value = 0; + if (dst.mask & TGSI_WRITEMASK_Z) log2_abs = dst; else if (dst.mask & TGSI_WRITEMASK_XY) log2_abs = get_temp( emit ); + else + log2_abs.value = 0; /* If z is being written, fill it with log2( abs( src0 ) ). */