/* These instructions need special treatment */ static void emit_special_inst(struct st_translate *t, const struct instruction_desc *desc, struct ureg_dst *dst, struct ureg_src *args, unsigned argcount) { struct ureg_dst tmp[1]; struct ureg_src src[3]; if (!strcmp(desc->name, "CND")) { tmp[0] = get_temp(t, MAX_NUM_FRAGMENT_REGISTERS_ATI + 2); /* re-purpose a3 */ src[0] = ureg_imm1f(t->ureg, 0.5f); src[1] = args[2]; ureg_insn(t->ureg, TGSI_OPCODE_SUB, tmp, 1, src, 2); src[0] = ureg_src(tmp[0]); src[1] = args[0]; src[2] = args[1]; ureg_insn(t->ureg, TGSI_OPCODE_CMP, dst, 1, src, 3); } else if (!strcmp(desc->name, "CND0")) { src[0] = args[2]; src[1] = args[1]; src[2] = args[0]; ureg_insn(t->ureg, TGSI_OPCODE_CMP, dst, 1, src, 3); } else if (!strcmp(desc->name, "DOT2_ADD")) { /* note: DP2A is not implemented in most pipe drivers */ tmp[0] = get_temp(t, MAX_NUM_FRAGMENT_REGISTERS_ATI); /* re-purpose a1 */ src[0] = args[0]; src[1] = args[1]; ureg_insn(t->ureg, TGSI_OPCODE_DP2, tmp, 1, src, 2); src[0] = ureg_src(tmp[0]); src[1] = ureg_scalar(args[2], TGSI_SWIZZLE_Z); ureg_insn(t->ureg, TGSI_OPCODE_ADD, dst, 1, src, 2); } }
static struct ureg_src prepare_argument(struct st_translate *t, const unsigned argId, const struct atifragshader_src_register *srcReg) { struct ureg_src src = get_source(t, srcReg->Index); struct ureg_dst arg = get_temp(t, MAX_NUM_FRAGMENT_REGISTERS_ATI + argId); switch (srcReg->argRep) { case GL_NONE: break; case GL_RED: src = ureg_scalar(src, TGSI_SWIZZLE_X); break; case GL_GREEN: src = ureg_scalar(src, TGSI_SWIZZLE_Y); break; case GL_BLUE: src = ureg_scalar(src, TGSI_SWIZZLE_Z); break; case GL_ALPHA: src = ureg_scalar(src, TGSI_SWIZZLE_W); break; } ureg_insn(t->ureg, TGSI_OPCODE_MOV, &arg, 1, &src, 1); if (srcReg->argMod & GL_COMP_BIT_ATI) { struct ureg_src modsrc[2]; modsrc[0] = ureg_imm1f(t->ureg, 1.0f); modsrc[1] = ureg_src(arg); ureg_insn(t->ureg, TGSI_OPCODE_SUB, &arg, 1, modsrc, 2); } if (srcReg->argMod & GL_BIAS_BIT_ATI) { struct ureg_src modsrc[2]; modsrc[0] = ureg_src(arg); modsrc[1] = ureg_imm1f(t->ureg, 0.5f); ureg_insn(t->ureg, TGSI_OPCODE_SUB, &arg, 1, modsrc, 2); } if (srcReg->argMod & GL_2X_BIT_ATI) { struct ureg_src modsrc[2]; modsrc[0] = ureg_src(arg); modsrc[1] = ureg_src(arg); ureg_insn(t->ureg, TGSI_OPCODE_ADD, &arg, 1, modsrc, 2); } if (srcReg->argMod & GL_NEGATE_BIT_ATI) { struct ureg_src modsrc[2]; modsrc[0] = ureg_src(arg); modsrc[1] = ureg_imm1f(t->ureg, -1.0f); ureg_insn(t->ureg, TGSI_OPCODE_MUL, &arg, 1, modsrc, 2); } return ureg_src(arg); }
static void finalize_shader(struct st_translate *t, unsigned numPasses) { struct ureg_dst dst[1] = { { 0 } }; struct ureg_src src[1] = { { 0 } }; if (t->regs_written[numPasses-1][0]) { /* copy the result into the OUT slot */ dst[0] = t->outputs[t->outputMapping[FRAG_RESULT_COLOR]]; src[0] = ureg_src(t->temps[0]); ureg_insn(t->ureg, TGSI_OPCODE_MOV, dst, 1, src, 1); } /* signal the end of the program */ ureg_insn(t->ureg, TGSI_OPCODE_END, dst, 0, src, 0); }
static void emit_arith_inst(struct st_translate *t, const struct instruction_desc *desc, struct ureg_dst *dst, struct ureg_src *args, unsigned argcount) { if (desc->TGSI_opcode == TGSI_OPCODE_NOP) { return emit_special_inst(t, desc, dst, args, argcount); } ureg_insn(t->ureg, desc->TGSI_opcode, dst, 1, args, argcount); }
static struct ureg_src apply_swizzle(struct st_translate *t, struct ureg_src src, GLuint swizzle) { if (swizzle == GL_SWIZZLE_STR_ATI) { return src; } else if (swizzle == GL_SWIZZLE_STQ_ATI) { return ureg_swizzle(src, TGSI_SWIZZLE_X, TGSI_SWIZZLE_Y, TGSI_SWIZZLE_W, TGSI_SWIZZLE_Z); } else { struct ureg_dst tmp[2]; struct ureg_src imm[3]; tmp[0] = get_temp(t, MAX_NUM_FRAGMENT_REGISTERS_ATI); tmp[1] = get_temp(t, MAX_NUM_FRAGMENT_REGISTERS_ATI + 1); imm[0] = src; imm[1] = ureg_imm4f(t->ureg, 1.0f, 1.0f, 0.0f, 0.0f); imm[2] = ureg_imm4f(t->ureg, 0.0f, 0.0f, 1.0f, 1.0f); ureg_insn(t->ureg, TGSI_OPCODE_MAD, &tmp[0], 1, imm, 3); if (swizzle == GL_SWIZZLE_STR_DR_ATI) { imm[0] = ureg_scalar(src, TGSI_SWIZZLE_Z); } else { imm[0] = ureg_scalar(src, TGSI_SWIZZLE_W); } ureg_insn(t->ureg, TGSI_OPCODE_RCP, &tmp[1], 1, &imm[0], 1); imm[0] = ureg_src(tmp[0]); imm[1] = ureg_src(tmp[1]); ureg_insn(t->ureg, TGSI_OPCODE_MUL, &tmp[0], 1, imm, 2); return ureg_src(tmp[0]); } }
void * util_make_geometry_passthrough_shader(struct pipe_context *pipe, uint num_attribs, const ubyte *semantic_names, const ubyte *semantic_indexes) { static const unsigned zero[4] = {0, 0, 0, 0}; struct ureg_program *ureg; struct ureg_dst dst[PIPE_MAX_SHADER_OUTPUTS]; struct ureg_src src[PIPE_MAX_SHADER_INPUTS]; struct ureg_src imm; unsigned i; ureg = ureg_create(PIPE_SHADER_GEOMETRY); if (!ureg) return NULL; ureg_property(ureg, TGSI_PROPERTY_GS_INPUT_PRIM, PIPE_PRIM_POINTS); ureg_property(ureg, TGSI_PROPERTY_GS_OUTPUT_PRIM, PIPE_PRIM_POINTS); ureg_property(ureg, TGSI_PROPERTY_GS_MAX_OUTPUT_VERTICES, 1); ureg_property(ureg, TGSI_PROPERTY_GS_INVOCATIONS, 1); imm = ureg_DECL_immediate_uint(ureg, zero, 4); /** * Loop over all the attribs and declare the corresponding * declarations in the geometry shader */ for (i = 0; i < num_attribs; i++) { src[i] = ureg_DECL_input(ureg, semantic_names[i], semantic_indexes[i], 0, 1); src[i] = ureg_src_dimension(src[i], 0); dst[i] = ureg_DECL_output(ureg, semantic_names[i], semantic_indexes[i]); } /* MOV dst[i] src[i] */ for (i = 0; i < num_attribs; i++) { ureg_MOV(ureg, dst[i], src[i]); } /* EMIT IMM[0] */ ureg_insn(ureg, TGSI_OPCODE_EMIT, NULL, 0, &imm, 1, 0); /* END */ ureg_END(ureg); return ureg_create_shader_and_destroy(ureg, pipe); }
/** * Compile one setup instruction to TGSI instructions. */ static void compile_setupinst(struct st_translate *t, const unsigned r, const struct atifs_setupinst *texinst) { struct ureg_dst dst[1]; struct ureg_src src[2]; if (!texinst->Opcode) return; dst[0] = get_temp(t, r); GLuint pass_tex = texinst->src; if (pass_tex >= GL_TEXTURE0_ARB && pass_tex <= GL_TEXTURE7_ARB) { unsigned attr = pass_tex - GL_TEXTURE0_ARB + VARYING_SLOT_TEX0; src[0] = t->inputs[t->inputMapping[attr]]; } else if (pass_tex >= GL_REG_0_ATI && pass_tex <= GL_REG_5_ATI) { unsigned reg = pass_tex - GL_REG_0_ATI; /* the frontend already validated that REG is only allowed in second pass */ if (t->regs_written[0][reg]) { src[0] = ureg_src(t->temps[reg]); } else { src[0] = ureg_imm1f(t->ureg, 0.0f); } } src[0] = apply_swizzle(t, src[0], texinst->swizzle); if (texinst->Opcode == ATI_FRAGMENT_SHADER_SAMPLE_OP) { /* by default texture and sampler indexes are the same */ src[1] = t->samplers[r]; /* the texture target is still unknown, it will be fixed in the draw call */ ureg_tex_insn(t->ureg, TGSI_OPCODE_TEX, dst, 1, TGSI_TEXTURE_2D, NULL, 0, src, 2); } else if (texinst->Opcode == ATI_FRAGMENT_SHADER_PASS_OP) { ureg_insn(t->ureg, TGSI_OPCODE_MOV, dst, 1, src, 1); } t->regs_written[t->current_pass][r] = true; }
static void emit_dstmod(struct st_translate *t, struct ureg_dst dst, GLuint dstMod) { float imm; struct ureg_src src[3]; GLuint scale = dstMod & ~GL_SATURATE_BIT_ATI; if (dstMod == GL_NONE) { return; } switch (scale) { case GL_2X_BIT_ATI: imm = 2.0f; break; case GL_4X_BIT_ATI: imm = 4.0f; break; case GL_8X_BIT_ATI: imm = 8.0f; break; case GL_HALF_BIT_ATI: imm = 0.5f; break; case GL_QUARTER_BIT_ATI: imm = 0.25f; break; case GL_EIGHTH_BIT_ATI: imm = 0.125f; break; default: imm = 1.0f; } src[0] = ureg_src(dst); src[1] = ureg_imm1f(t->ureg, imm); if (dstMod & GL_SATURATE_BIT_ATI) { dst = ureg_saturate(dst); } ureg_insn(t->ureg, TGSI_OPCODE_MUL, &dst, 1, src, 2); }
static void compile_instruction( struct gl_context *ctx, struct st_translate *t, const struct prog_instruction *inst, boolean clamp_dst_color_output) { struct ureg_program *ureg = t->ureg; GLuint i; struct ureg_dst dst[1] = { { 0 } }; struct ureg_src src[4]; unsigned num_dst; unsigned num_src; num_dst = _mesa_num_inst_dst_regs( inst->Opcode ); num_src = _mesa_num_inst_src_regs( inst->Opcode ); if (num_dst) dst[0] = translate_dst( t, &inst->DstReg, inst->Saturate, clamp_dst_color_output); for (i = 0; i < num_src; i++) src[i] = translate_src( t, &inst->SrcReg[i] ); switch( inst->Opcode ) { case OPCODE_SWZ: emit_swz( t, dst[0], &inst->SrcReg[0] ); return; case OPCODE_BGNLOOP: case OPCODE_CAL: case OPCODE_ELSE: case OPCODE_ENDLOOP: debug_assert(num_dst == 0); ureg_label_insn( ureg, translate_opcode( inst->Opcode ), src, num_src, get_label( t, inst->BranchTarget )); return; case OPCODE_IF: debug_assert(num_dst == 0); ureg_label_insn( ureg, ctx->Const.NativeIntegers ? TGSI_OPCODE_UIF : TGSI_OPCODE_IF, src, num_src, get_label( t, inst->BranchTarget )); return; case OPCODE_TEX: case OPCODE_TXB: case OPCODE_TXD: case OPCODE_TXL: case OPCODE_TXP: src[num_src++] = t->samplers[inst->TexSrcUnit]; ureg_tex_insn( ureg, translate_opcode( inst->Opcode ), dst, num_dst, st_translate_texture_target( inst->TexSrcTarget, inst->TexShadow ), NULL, 0, src, num_src ); return; case OPCODE_SCS: dst[0] = ureg_writemask(dst[0], TGSI_WRITEMASK_XY ); ureg_insn( ureg, translate_opcode( inst->Opcode ), dst, num_dst, src, num_src ); break; case OPCODE_XPD: dst[0] = ureg_writemask(dst[0], TGSI_WRITEMASK_XYZ ); ureg_insn( ureg, translate_opcode( inst->Opcode ), dst, num_dst, src, num_src ); break; case OPCODE_NOISE1: case OPCODE_NOISE2: case OPCODE_NOISE3: case OPCODE_NOISE4: /* At some point, a motivated person could add a better * implementation of noise. Currently not even the nvidia * binary drivers do anything more than this. In any case, the * place to do this is in the GL state tracker, not the poor * driver. */ ureg_MOV( ureg, dst[0], ureg_imm1f(ureg, 0.5) ); break; case OPCODE_DDY: emit_ddy( t, dst[0], &inst->SrcReg[0] ); break; case OPCODE_RSQ: ureg_RSQ( ureg, dst[0], ureg_abs(src[0]) ); break; default: ureg_insn( ureg, translate_opcode( inst->Opcode ), dst, num_dst, src, num_src ); break; } }
static void compile_instruction( struct gl_context *ctx, struct st_translate *t, const struct prog_instruction *inst) { struct ureg_program *ureg = t->ureg; GLuint i; struct ureg_dst dst[1] = { { 0 } }; struct ureg_src src[4]; unsigned num_dst; unsigned num_src; num_dst = _mesa_num_inst_dst_regs( inst->Opcode ); num_src = _mesa_num_inst_src_regs( inst->Opcode ); if (num_dst) dst[0] = translate_dst( t, &inst->DstReg, inst->Saturate); for (i = 0; i < num_src; i++) src[i] = translate_src( t, &inst->SrcReg[i] ); switch( inst->Opcode ) { case OPCODE_SWZ: emit_swz( t, dst[0], &inst->SrcReg[0] ); return; case OPCODE_TEX: case OPCODE_TXB: case OPCODE_TXP: src[num_src++] = t->samplers[inst->TexSrcUnit]; ureg_tex_insn( ureg, translate_opcode( inst->Opcode ), dst, num_dst, st_translate_texture_target( inst->TexSrcTarget, inst->TexShadow ), NULL, 0, src, num_src ); return; case OPCODE_SCS: dst[0] = ureg_writemask(dst[0], TGSI_WRITEMASK_XY ); ureg_insn( ureg, translate_opcode( inst->Opcode ), dst, num_dst, src, num_src ); break; case OPCODE_XPD: dst[0] = ureg_writemask(dst[0], TGSI_WRITEMASK_XYZ ); ureg_insn( ureg, translate_opcode( inst->Opcode ), dst, num_dst, src, num_src ); break; case OPCODE_RSQ: ureg_RSQ( ureg, dst[0], ureg_abs(src[0]) ); break; case OPCODE_ABS: ureg_MOV(ureg, dst[0], ureg_abs(src[0])); break; case OPCODE_SUB: ureg_ADD(ureg, dst[0], src[0], ureg_negate(src[1])); break; default: ureg_insn( ureg, translate_opcode( inst->Opcode ), dst, num_dst, src, num_src ); break; } }