static boolean ps20_input( struct svga_shader_emitter *emit, struct tgsi_declaration_semantic semantic, unsigned idx ) { struct src_register reg; SVGA3DOpDclArgs dcl; SVGA3dShaderInstToken opcode; opcode = inst_token( SVGA3DOP_DCL ); dcl.values[0] = 0; dcl.values[1] = 0; switch (semantic.SemanticName) { case TGSI_SEMANTIC_POSITION: /* Special case: */ reg = src_register( SVGA3DREG_MISCTYPE, SVGA3DMISCREG_POSITION ); break; case TGSI_SEMANTIC_COLOR: reg = src_register( SVGA3DREG_INPUT, semantic.SemanticIndex ); break; case TGSI_SEMANTIC_FOG: assert(semantic.SemanticIndex == 0); reg = src_register( SVGA3DREG_TEXTURE, 0 ); break; case TGSI_SEMANTIC_GENERIC: reg = src_register( SVGA3DREG_TEXTURE, semantic.SemanticIndex + 1 ); break; default: assert(0); return TRUE; } emit->input_map[idx] = reg; dcl.dst = dst( reg ); dcl.usage = 0; dcl.index = 0; dcl.values[0] |= 1<<31; return (emit_instruction(emit, opcode) && svga_shader_emit_dwords( emit, dcl.values, Elements(dcl.values))); }
/** * Declare a VS input register. * We still make up the input semantics the same as in 2.0 */ static boolean vs30_input(struct svga_shader_emitter *emit, struct tgsi_declaration_semantic semantic, unsigned idx) { SVGA3DOpDclArgs dcl; SVGA3dShaderInstToken opcode; unsigned usage, index; opcode = inst_token( SVGA3DOP_DCL ); dcl.values[0] = 0; dcl.values[1] = 0; emit->input_map[idx] = src_register( SVGA3DREG_INPUT, idx ); dcl.dst = dst_register( SVGA3DREG_INPUT, idx ); assert(dcl.dst.reserved0); svga_generate_vdecl_semantics( idx, &usage, &index ); dcl.usage = usage; dcl.index = index; dcl.values[0] |= 1<<31; return (emit_instruction(emit, opcode) && svga_shader_emit_dwords( emit, dcl.values, Elements(dcl.values))); }
static boolean vs20_input( struct svga_shader_emitter *emit, struct tgsi_declaration_semantic semantic, unsigned idx ) { SVGA3DOpDclArgs dcl; SVGA3dShaderInstToken opcode; opcode = inst_token( SVGA3DOP_DCL ); dcl.values[0] = 0; dcl.values[1] = 0; emit->input_map[idx] = src_register( SVGA3DREG_INPUT, idx ); dcl.dst = dst_register( SVGA3DREG_INPUT, idx ); assert(dcl.dst.reserved0); /* Mesa doesn't provide use with VS input semantics (they're * actually pretty meaningless), so we just generate some plausible * ones here. This has to match what we declare in the vdecl code * in svga_pipe_vertex.c. */ if (idx == 0) { dcl.usage = SVGA3D_DECLUSAGE_POSITION; dcl.index = 0; } else { dcl.usage = SVGA3D_DECLUSAGE_TEXCOORD; dcl.index = idx - 1; } dcl.values[0] |= 1<<31; return (emit_instruction(emit, opcode) && svga_shader_emit_dwords( emit, dcl.values, Elements(dcl.values))); }
/** * Create a TGSI ureg_src register from a Mesa src register. */ static struct ureg_src translate_src( struct st_translate *t, const struct prog_src_register *SrcReg ) { struct ureg_src src = src_register( t, SrcReg->File, SrcReg->Index ); src = ureg_swizzle( src, GET_SWZ( SrcReg->Swizzle, 0 ) & 0x3, GET_SWZ( SrcReg->Swizzle, 1 ) & 0x3, GET_SWZ( SrcReg->Swizzle, 2 ) & 0x3, GET_SWZ( SrcReg->Swizzle, 3 ) & 0x3); if (SrcReg->Negate == NEGATE_XYZW) src = ureg_negate(src); if (SrcReg->RelAddr) { src = ureg_src_indirect( src, ureg_src(t->address[0])); if (SrcReg->File != PROGRAM_INPUT && SrcReg->File != PROGRAM_OUTPUT) { /* If SrcReg->Index was negative, it was set to zero in * src_register(). Reassign it now. But don't do this * for input/output regs since they get remapped while * const buffers don't. */ src.Index = SrcReg->Index; } } return src; }
/** * Declare a VS input register. * We still make up the input semantics the same as in 2.0 */ static boolean vs30_input(struct svga_shader_emitter *emit, struct tgsi_declaration_semantic semantic, unsigned idx) { SVGA3DOpDclArgs dcl; SVGA3dShaderInstToken opcode; unsigned usage, index; opcode = inst_token( SVGA3DOP_DCL ); dcl.values[0] = 0; dcl.values[1] = 0; if (emit->key.vkey.zero_stride_vertex_elements & (1 << idx)) { unsigned i; unsigned offset = 0; unsigned start_idx = emit->info.file_max[TGSI_FILE_CONSTANT] + 1; /* adjust for prescale constants */ start_idx += emit->key.vkey.need_prescale ? 2 : 0; /* compute the offset from the start of zero stride constants */ for (i = 0; i < PIPE_MAX_ATTRIBS && i < idx; ++i) { if (emit->key.vkey.zero_stride_vertex_elements & (1<<i)) ++offset; } emit->input_map[idx] = src_register( SVGA3DREG_CONST, start_idx + offset ); } else { emit->input_map[idx] = src_register( SVGA3DREG_INPUT, idx ); dcl.dst = dst_register( SVGA3DREG_INPUT, idx ); assert(dcl.dst.reserved0); svga_generate_vdecl_semantics( idx, &usage, &index ); dcl.usage = usage; dcl.index = index; dcl.values[0] |= 1<<31; return (emit_instruction(emit, opcode) && svga_shader_emit_dwords( emit, dcl.values, Elements(dcl.values))); } return TRUE; }
/** * Emit PS input register to pass depth/fog coordinates. * Note that this always goes into texcoord[0]. */ static boolean ps30_input_emit_depth_fog( struct svga_shader_emitter *emit, struct src_register *out ) { struct src_register reg; if (emit->emitted_depth_fog) { *out = emit->ps_depth_fog; return TRUE; } if (emit->ps30_input_count >= SVGA3D_INPUTREG_MAX) return FALSE; reg = src_register( SVGA3DREG_INPUT, emit->ps30_input_count++ ); *out = emit->ps_depth_fog = reg; emit->emitted_depth_fog = TRUE; return emit_decl( emit, dst( reg ), SVGA3D_DECLUSAGE_TEXCOORD, 0 ); }
/** * Translate a SWZ instruction into a MOV, MUL or MAD instruction. EG: * * SWZ dst, src.x-y10 * * becomes: * * MAD dst {1,-1,0,0}, src.xyxx, {0,0,1,0} */ static void emit_swz( struct st_translate *t, struct ureg_dst dst, const struct prog_src_register *SrcReg ) { struct ureg_program *ureg = t->ureg; struct ureg_src src = src_register( t, SrcReg->File, SrcReg->Index ); unsigned negate_mask = SrcReg->Negate; unsigned one_mask = ((GET_SWZ(SrcReg->Swizzle, 0) == SWIZZLE_ONE) << 0 | (GET_SWZ(SrcReg->Swizzle, 1) == SWIZZLE_ONE) << 1 | (GET_SWZ(SrcReg->Swizzle, 2) == SWIZZLE_ONE) << 2 | (GET_SWZ(SrcReg->Swizzle, 3) == SWIZZLE_ONE) << 3); unsigned zero_mask = ((GET_SWZ(SrcReg->Swizzle, 0) == SWIZZLE_ZERO) << 0 | (GET_SWZ(SrcReg->Swizzle, 1) == SWIZZLE_ZERO) << 1 | (GET_SWZ(SrcReg->Swizzle, 2) == SWIZZLE_ZERO) << 2 | (GET_SWZ(SrcReg->Swizzle, 3) == SWIZZLE_ZERO) << 3); unsigned negative_one_mask = one_mask & negate_mask; unsigned positive_one_mask = one_mask & ~negate_mask; struct ureg_src imm; unsigned i; unsigned mul_swizzle[4] = {0,0,0,0}; unsigned add_swizzle[4] = {0,0,0,0}; unsigned src_swizzle[4] = {0,0,0,0}; boolean need_add = FALSE; boolean need_mul = FALSE; if (dst.WriteMask == 0) return; /* Is this just a MOV? */ if (zero_mask == 0 && one_mask == 0 && (negate_mask == 0 || negate_mask == TGSI_WRITEMASK_XYZW)) { ureg_MOV( ureg, dst, translate_src( t, SrcReg )); return; } #define IMM_ZERO 0 #define IMM_ONE 1 #define IMM_NEG_ONE 2 imm = ureg_imm3f( ureg, 0, 1, -1 ); for (i = 0; i < 4; i++) { unsigned bit = 1 << i; if (dst.WriteMask & bit) { if (positive_one_mask & bit) { mul_swizzle[i] = IMM_ZERO; add_swizzle[i] = IMM_ONE; need_add = TRUE; } else if (negative_one_mask & bit) { mul_swizzle[i] = IMM_ZERO; add_swizzle[i] = IMM_NEG_ONE; need_add = TRUE; } else if (zero_mask & bit) { mul_swizzle[i] = IMM_ZERO; add_swizzle[i] = IMM_ZERO; need_add = TRUE; } else { add_swizzle[i] = IMM_ZERO; src_swizzle[i] = GET_SWZ(SrcReg->Swizzle, i); need_mul = TRUE; if (negate_mask & bit) { mul_swizzle[i] = IMM_NEG_ONE; } else { mul_swizzle[i] = IMM_ONE; } } } } if (need_mul && need_add) { ureg_MAD( ureg, dst, swizzle_4v( src, src_swizzle ), swizzle_4v( imm, mul_swizzle ), swizzle_4v( imm, add_swizzle ) ); } else if (need_mul) { ureg_MUL( ureg, dst, swizzle_4v( src, src_swizzle ), swizzle_4v( imm, mul_swizzle ) ); } else if (need_add) { ureg_MOV( ureg, dst, swizzle_4v( imm, add_swizzle ) ); } else { debug_assert(0); } #undef IMM_ZERO #undef IMM_ONE #undef IMM_NEG_ONE }
/** * Process a PS input declaration. * We'll emit a declaration like "dcl_texcoord1 v2" */ static boolean ps30_input(struct svga_shader_emitter *emit, struct tgsi_declaration_semantic semantic, unsigned idx) { unsigned usage, index; SVGA3dShaderDestToken reg; if (semantic.Name == TGSI_SEMANTIC_POSITION) { emit->ps_true_pos = src_register( SVGA3DREG_MISCTYPE, SVGA3DMISCREG_POSITION ); emit->ps_true_pos.base.swizzle = TRANSLATE_SWIZZLE( TGSI_SWIZZLE_X, TGSI_SWIZZLE_Y, TGSI_SWIZZLE_Y, TGSI_SWIZZLE_Y ); reg = writemask( dst(emit->ps_true_pos), TGSI_WRITEMASK_XY ); emit->ps_reads_pos = TRUE; if (emit->info.reads_z) { emit->ps_temp_pos = dst_register( SVGA3DREG_TEMP, emit->nr_hw_temp ); emit->input_map[idx] = src_register( SVGA3DREG_TEMP, emit->nr_hw_temp ); emit->nr_hw_temp++; if (!ps30_input_emit_depth_fog( emit, &emit->ps_depth_pos )) return FALSE; emit->ps_depth_pos.base.swizzle = TRANSLATE_SWIZZLE( TGSI_SWIZZLE_Z, TGSI_SWIZZLE_Z, TGSI_SWIZZLE_Z, TGSI_SWIZZLE_W ); } else { emit->input_map[idx] = emit->ps_true_pos; } return emit_decl( emit, reg, 0, 0 ); } else if (emit->key.fs.light_twoside && (semantic.Name == TGSI_SEMANTIC_COLOR)) { if (!translate_vs_ps_semantic( emit, semantic, &usage, &index )) return FALSE; emit->internal_color_idx[emit->internal_color_count] = idx; emit->input_map[idx] = src_register( SVGA3DREG_INPUT, emit->ps30_input_count ); emit->ps30_input_count++; emit->internal_color_count++; reg = dst( emit->input_map[idx] ); if (!emit_decl( emit, reg, usage, index )) return FALSE; semantic.Name = TGSI_SEMANTIC_BCOLOR; if (!translate_vs_ps_semantic( emit, semantic, &usage, &index )) return FALSE; if (emit->ps30_input_count >= SVGA3D_INPUTREG_MAX) return FALSE; reg = dst_register( SVGA3DREG_INPUT, emit->ps30_input_count++ ); if (!emit_decl( emit, reg, usage, index )) return FALSE; if (!emit_vface_decl( emit )) return FALSE; return TRUE; } else if (semantic.Name == TGSI_SEMANTIC_FACE) { if (!emit_vface_decl( emit )) return FALSE; emit->emit_frontface = TRUE; emit->internal_frontface_idx = idx; return TRUE; } else if (semantic.Name == TGSI_SEMANTIC_FOG) { assert(semantic.Index == 0); if (!ps30_input_emit_depth_fog( emit, &emit->input_map[idx] )) return FALSE; emit->input_map[idx].base.swizzle = TRANSLATE_SWIZZLE( TGSI_SWIZZLE_X, TGSI_SWIZZLE_X, TGSI_SWIZZLE_X, TGSI_SWIZZLE_X ); return TRUE; } else { if (!translate_vs_ps_semantic( emit, semantic, &usage, &index )) return FALSE; if (emit->ps30_input_count >= SVGA3D_INPUTREG_MAX) return FALSE; emit->input_map[idx] = src_register( SVGA3DREG_INPUT, emit->ps30_input_count++ ); reg = dst( emit->input_map[idx] ); if (!emit_decl( emit, reg, usage, index )) return FALSE; if (semantic.Name == TGSI_SEMANTIC_GENERIC && emit->key.sprite_origin_lower_left && index >= 1 && emit->key.tex[index - 1].sprite_texgen) { /* This is a sprite texture coord with lower-left origin. * We need to invert the texture T coordinate since the SVGA3D * device only supports an upper-left origin. */ unsigned unit = index - 1; emit->inverted_texcoords |= (1 << unit); /* save original texcoord reg */ emit->ps_true_texcoord[unit] = emit->input_map[idx]; /* this temp register will be the results of the MAD instruction */ emit->ps_inverted_texcoord[unit] = src_register(SVGA3DREG_TEMP, emit->nr_hw_temp); emit->nr_hw_temp++; emit->ps_inverted_texcoord_input[unit] = idx; /* replace input_map entry with the temp register */ emit->input_map[idx] = emit->ps_inverted_texcoord[unit]; } return TRUE; } }