/** * Process a PS output declaration. * Note that we don't actually emit a SVGA3DOpDcl for PS outputs. * \idx register index, such as OUT[2] (not semantic index) */ static boolean ps30_output(struct svga_shader_emitter *emit, struct tgsi_declaration_semantic semantic, unsigned idx) { switch (semantic.Name) { case TGSI_SEMANTIC_COLOR: if (emit->unit == PIPE_SHADER_FRAGMENT) { if (emit->key.fs.white_fragments) { /* Used for XOR logicop mode */ emit->output_map[idx] = dst_register( SVGA3DREG_TEMP, emit->nr_hw_temp++ ); emit->temp_color_output[idx] = emit->output_map[idx]; emit->true_color_output[idx] = dst_register(SVGA3DREG_COLOROUT, semantic.Index); } else if (emit->key.fs.write_color0_to_n_cbufs) { /* We'll write color output [0] to all render targets. * Prepare all the output registers here, but only when the * semantic.Index == 0 so we don't do this more than once. */ if (semantic.Index == 0) { unsigned i; for (i = 0; i < emit->key.fs.write_color0_to_n_cbufs; i++) { emit->output_map[idx+i] = dst_register(SVGA3DREG_TEMP, emit->nr_hw_temp++); emit->temp_color_output[i] = emit->output_map[idx+i]; emit->true_color_output[i] = dst_register(SVGA3DREG_COLOROUT, i); } } } else { emit->output_map[idx] = dst_register(SVGA3DREG_COLOROUT, semantic.Index); } } else { emit->output_map[idx] = dst_register( SVGA3DREG_COLOROUT, semantic.Index ); } break; case TGSI_SEMANTIC_POSITION: emit->output_map[idx] = dst_register( SVGA3DREG_TEMP, emit->nr_hw_temp++ ); emit->temp_pos = emit->output_map[idx]; emit->true_pos = dst_register( SVGA3DREG_DEPTHOUT, semantic.Index ); break; default: assert(0); /* A wild stab in the dark. */ emit->output_map[idx] = dst_register( SVGA3DREG_COLOROUT, 0 ); break; } return TRUE; }
/** * 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))); }
/** * Emit declaration for PS front/back-face input register. */ static boolean emit_vface_decl(struct svga_shader_emitter *emit) { if (!emit->emitted_vface) { SVGA3dShaderDestToken reg = dst_register(SVGA3DREG_MISCTYPE, SVGA3DMISCREG_FACE); if (!emit_decl( emit, reg, 0, 0 )) return FALSE; emit->emitted_vface = TRUE; } return TRUE; }
static boolean vs20_output( struct svga_shader_emitter *emit, struct tgsi_declaration_semantic semantic, unsigned idx ) { /* Don't emit dcl instruction for vs20 inputs */ /* Just build the register map table: */ switch (semantic.SemanticName) { case TGSI_SEMANTIC_POSITION: assert(semantic.SemanticIndex == 0); emit->output_map[idx] = dst_register( SVGA3DREG_TEMP, emit->nr_hw_temp++ ); emit->temp_pos = emit->output_map[idx]; emit->true_pos = dst_register( SVGA3DREG_RASTOUT, SVGA3DRASTOUT_POSITION); break; case TGSI_SEMANTIC_PSIZE: assert(semantic.SemanticIndex == 0); emit->output_map[idx] = dst_register( SVGA3DREG_TEMP, emit->nr_hw_temp++ ); emit->temp_psiz = emit->output_map[idx]; emit->true_psiz = dst_register( SVGA3DREG_RASTOUT, SVGA3DRASTOUT_PSIZE ); break; case TGSI_SEMANTIC_FOG: assert(semantic.SemanticIndex == 0); emit->output_map[idx] = dst_register( SVGA3DREG_TEXCRDOUT, 0 ); break; case TGSI_SEMANTIC_COLOR: /* oD0 */ emit->output_map[idx] = dst_register( SVGA3DREG_ATTROUT, semantic.SemanticIndex ); break; case TGSI_SEMANTIC_GENERIC: emit->output_map[idx] = dst_register( SVGA3DREG_TEXCRDOUT, semantic.SemanticIndex + 1 ); break; default: assert(0); emit->output_map[idx] = dst_register( SVGA3DREG_TEMP, 0 ); return FALSE; } return TRUE; }
static boolean ps20_sampler( 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; dcl.dst = dst_register( SVGA3DREG_SAMPLER, idx ); dcl.type = svga_tgsi_sampler_type( emit, idx ); return (emit_instruction(emit, opcode) && svga_shader_emit_dwords( emit, dcl.values, Elements(dcl.values))); }
/** * Declare VS output for holding depth/fog. */ static boolean vs30_output_emit_depth_fog(struct svga_shader_emitter *emit, SVGA3dShaderDestToken *out) { SVGA3dShaderDestToken reg; if (emit->emitted_depth_fog) { *out = emit->vs_depth_fog; return TRUE; } reg = dst_register( SVGA3DREG_OUTPUT, emit->vs30_output_count++ ); *out = emit->vs_depth_fog = reg; emit->emitted_depth_fog = TRUE; return emit_decl( emit, reg, SVGA3D_DECLUSAGE_TEXCOORD, 0 ); }
/** * 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; }
/** * Create a TGSI ureg_dst register from a Mesa dest register. */ static struct ureg_dst translate_dst( struct st_translate *t, const struct prog_dst_register *DstReg, boolean saturate, boolean clamp_color) { struct ureg_dst dst = dst_register( t, DstReg->File, DstReg->Index ); dst = ureg_writemask( dst, DstReg->WriteMask ); if (saturate) dst = ureg_saturate( dst ); else if (clamp_color && DstReg->File == PROGRAM_OUTPUT) { /* Clamp colors for ARB_color_buffer_float. */ switch (t->procType) { case TGSI_PROCESSOR_VERTEX: /* This can only occur with a compatibility profile, which doesn't * support geometry shaders. */ if (DstReg->Index == VARYING_SLOT_COL0 || DstReg->Index == VARYING_SLOT_COL1 || DstReg->Index == VARYING_SLOT_BFC0 || DstReg->Index == VARYING_SLOT_BFC1) { dst = ureg_saturate(dst); } break; case TGSI_PROCESSOR_FRAGMENT: if (DstReg->Index >= FRAG_RESULT_COLOR) { dst = ureg_saturate(dst); } break; } } if (DstReg->RelAddr) dst = ureg_dst_indirect( dst, ureg_src(t->address[0]) ); return dst; }
/** * Create a TGSI ureg_dst register from a Mesa dest register. */ static struct ureg_dst translate_dst( struct st_translate *t, const struct prog_dst_register *DstReg, boolean saturate, boolean clamp_color) { struct ureg_dst dst = dst_register( t, DstReg->File, DstReg->Index ); dst = ureg_writemask( dst, DstReg->WriteMask ); if (saturate) dst = ureg_saturate( dst ); else if (clamp_color && DstReg->File == PROGRAM_OUTPUT) { /* Clamp colors for ARB_color_buffer_float. */ switch (t->procType) { case TGSI_PROCESSOR_VERTEX: /* XXX if the geometry shader is present, this must be done there * instead of here. */ if (DstReg->Index == VARYING_SLOT_COL0 || DstReg->Index == VARYING_SLOT_COL1 || DstReg->Index == VARYING_SLOT_BFC0 || DstReg->Index == VARYING_SLOT_BFC1) { dst = ureg_saturate(dst); } break; case TGSI_PROCESSOR_FRAGMENT: if (DstReg->Index >= FRAG_RESULT_COLOR) { dst = ureg_saturate(dst); } break; } } if (DstReg->RelAddr) dst = ureg_dst_indirect( dst, ureg_src(t->address[0]) ); return dst; }
/** * Create a TGSI ureg_dst register from a Mesa dest register. */ static struct ureg_dst translate_dst( struct st_translate *t, const struct prog_dst_register *DstReg, boolean saturate) { struct ureg_dst dst = dst_register( t, DstReg->File, DstReg->Index ); dst = ureg_writemask( dst, DstReg->WriteMask ); if (saturate) dst = ureg_saturate( dst ); if (DstReg->RelAddr) dst = ureg_dst_indirect( dst, ureg_src(t->address[0]) ); return dst; }
static boolean ps20_output( struct svga_shader_emitter *emit, struct tgsi_declaration_semantic semantic, unsigned idx ) { SVGA3dShaderDestToken reg; switch (semantic.SemanticName) { case TGSI_SEMANTIC_COLOR: if (semantic.SemanticIndex < PIPE_MAX_COLOR_BUFS) { unsigned cbuf = semantic.SemanticIndex; emit->output_map[idx] = dst_register( SVGA3DREG_TEMP, emit->nr_hw_temp++ ); emit->temp_col[cbuf] = emit->output_map[idx]; emit->true_col[cbuf] = dst_register( SVGA3DREG_COLOROUT, semantic.SemanticIndex ); } else { assert(0); reg = dst_register( SVGA3DREG_COLOROUT, 0 ); } break; case TGSI_SEMANTIC_POSITION: emit->output_map[idx] = dst_register( SVGA3DREG_TEMP, emit->nr_hw_temp++ ); emit->temp_pos = emit->output_map[idx]; emit->true_pos = dst_register( SVGA3DREG_DEPTHOUT, semantic.SemanticIndex ); break; default: assert(0); reg = dst_register( SVGA3DREG_COLOROUT, 0 ); break; } return TRUE; }
/** * Process a PS output declaration. * Note that we don't actually emit a SVGA3DOpDcl for PS outputs. */ static boolean ps30_output(struct svga_shader_emitter *emit, struct tgsi_declaration_semantic semantic, unsigned idx) { switch (semantic.Name) { case TGSI_SEMANTIC_COLOR: if (emit->unit == PIPE_SHADER_FRAGMENT && emit->key.fkey.white_fragments) { emit->output_map[idx] = dst_register( SVGA3DREG_TEMP, emit->nr_hw_temp++ ); emit->temp_col[idx] = emit->output_map[idx]; emit->true_col[idx] = dst_register( SVGA3DREG_COLOROUT, semantic.Index ); } else { emit->output_map[idx] = dst_register( SVGA3DREG_COLOROUT, semantic.Index ); } break; case TGSI_SEMANTIC_POSITION: emit->output_map[idx] = dst_register( SVGA3DREG_TEMP, emit->nr_hw_temp++ ); emit->temp_pos = emit->output_map[idx]; emit->true_pos = dst_register( SVGA3DREG_DEPTHOUT, semantic.Index ); break; default: assert(0); /* A wild stab in the dark. */ emit->output_map[idx] = dst_register( SVGA3DREG_COLOROUT, 0 ); break; } return TRUE; }
/** * Declare a VS output. * VS3.0 outputs have proper declarations and semantic info for * matching against PS inputs. */ static boolean vs30_output(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 (!translate_vs_ps_semantic( emit, semantic, &usage, &index )) return FALSE; if (emit->vs30_output_count >= SVGA3D_OUTPUTREG_MAX) return FALSE; dcl.dst = dst_register( SVGA3DREG_OUTPUT, emit->vs30_output_count++ ); dcl.usage = usage; dcl.index = index; dcl.values[0] |= 1<<31; if (semantic.Name == TGSI_SEMANTIC_POSITION) { assert(idx == 0); emit->output_map[idx] = dst_register( SVGA3DREG_TEMP, emit->nr_hw_temp++ ); emit->temp_pos = emit->output_map[idx]; emit->true_pos = dcl.dst; /* Grab an extra output for the depth output */ if (!vs30_output_emit_depth_fog( emit, &emit->depth_pos )) return FALSE; } else if (semantic.Name == TGSI_SEMANTIC_PSIZE) { emit->output_map[idx] = dst_register( SVGA3DREG_TEMP, emit->nr_hw_temp++ ); emit->temp_psiz = emit->output_map[idx]; /* This has the effect of not declaring psiz (below) and not * emitting the final MOV to true_psiz in the postamble. */ if (!emit->key.vs.allow_psiz) return TRUE; emit->true_psiz = dcl.dst; } else if (semantic.Name == TGSI_SEMANTIC_FOG) { /* * Fog is shared with depth. * So we need to decrement out_count since emit_depth_fog will increment it. */ emit->vs30_output_count--; if (!vs30_output_emit_depth_fog( emit, &emit->output_map[idx] )) return FALSE; return TRUE; } else { emit->output_map[idx] = dcl.dst; } return (emit_instruction(emit, opcode) && svga_shader_emit_dwords( emit, dcl.values, Elements(dcl.values))); }
/** * 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; } }