/** helper for building simple TGSI instruction, one src register */ static void build_tgsi_instruction1(struct tgsi_full_instruction *inst, int opcode, int dstFile, int dstIndex, int writemask, int srcFile1, int srcIndex1) { *inst = tgsi_default_full_instruction(); inst->Instruction.Opcode = opcode; inst->Instruction.NumDstRegs = 1; inst->FullDstRegisters[0].DstRegister.File = dstFile; inst->FullDstRegisters[0].DstRegister.Index = dstIndex; inst->FullDstRegisters[0].DstRegister.WriteMask = writemask; inst->Instruction.NumSrcRegs = 1; inst->FullSrcRegisters[0].SrcRegister.File = srcFile1; inst->FullSrcRegisters[0].SrcRegister.Index = srcIndex1; }
static void passthrough_edgeflag(struct tgsi_transform_context *tctx) { struct tgsi_emulation_context *ctx = tgsi_emulation_context(tctx); struct tgsi_full_declaration decl; struct tgsi_full_instruction new_inst; /* Input */ decl = tgsi_default_full_declaration(); decl.Declaration.File = TGSI_FILE_INPUT; decl.Range.First = decl.Range.Last = ctx->info.num_inputs; tctx->emit_declaration(tctx, &decl); /* Output */ decl = tgsi_default_full_declaration(); decl.Declaration.File = TGSI_FILE_OUTPUT; decl.Declaration.Semantic = true; decl.Range.First = decl.Range.Last = ctx->info.num_outputs; decl.Semantic.Name = TGSI_SEMANTIC_EDGEFLAG; decl.Semantic.Index = 0; tctx->emit_declaration(tctx, &decl); /* MOV */ new_inst = tgsi_default_full_instruction(); new_inst.Instruction.Opcode = TGSI_OPCODE_MOV; new_inst.Instruction.NumDstRegs = 1; new_inst.Dst[0].Register.File = TGSI_FILE_OUTPUT; new_inst.Dst[0].Register.Index = ctx->info.num_outputs; new_inst.Dst[0].Register.WriteMask = TGSI_WRITEMASK_XYZW; new_inst.Instruction.NumSrcRegs = 1; new_inst.Src[0].Register.File = TGSI_FILE_INPUT; new_inst.Src[0].Register.Index = ctx->info.num_inputs; new_inst.Src[0].Register.SwizzleX = TGSI_SWIZZLE_X; new_inst.Src[0].Register.SwizzleY = TGSI_SWIZZLE_X; new_inst.Src[0].Register.SwizzleZ = TGSI_SWIZZLE_X; new_inst.Src[0].Register.SwizzleW = TGSI_SWIZZLE_X; tctx->emit_instruction(tctx, &new_inst); }
static boolean parse_instruction( struct translate_ctx *ctx, boolean has_label ) { uint i; uint saturate = 0; const struct tgsi_opcode_info *info; struct tgsi_full_instruction inst; const char *cur; uint advance; inst = tgsi_default_full_instruction(); /* Parse predicate. */ eat_opt_white( &ctx->cur ); if (*ctx->cur == '(') { uint file; int index; uint swizzle[4]; boolean parsed_swizzle; inst.Instruction.Predicate = 1; ctx->cur++; if (*ctx->cur == '!') { ctx->cur++; inst.Predicate.Negate = 1; } if (!parse_register_1d( ctx, &file, &index )) return FALSE; if (parse_optional_swizzle( ctx, swizzle, &parsed_swizzle, 4 )) { if (parsed_swizzle) { inst.Predicate.SwizzleX = swizzle[0]; inst.Predicate.SwizzleY = swizzle[1]; inst.Predicate.SwizzleZ = swizzle[2]; inst.Predicate.SwizzleW = swizzle[3]; } } if (*ctx->cur != ')') { report_error( ctx, "Expected `)'" ); return FALSE; } ctx->cur++; } /* Parse instruction name. */ eat_opt_white( &ctx->cur ); for (i = 0; i < TGSI_OPCODE_LAST; i++) { cur = ctx->cur; info = tgsi_get_opcode_info( i ); if (match_inst(&cur, &saturate, info)) { if (info->num_dst + info->num_src + info->is_tex == 0) { ctx->cur = cur; break; } else if (*cur == '\0' || eat_white( &cur )) { ctx->cur = cur; break; } } } if (i == TGSI_OPCODE_LAST) { if (has_label) report_error( ctx, "Unknown opcode" ); else report_error( ctx, "Expected `DCL', `IMM' or a label" ); return FALSE; } inst.Instruction.Opcode = i; inst.Instruction.Saturate = saturate; inst.Instruction.NumDstRegs = info->num_dst; inst.Instruction.NumSrcRegs = info->num_src; if (i >= TGSI_OPCODE_SAMPLE && i <= TGSI_OPCODE_GATHER4) { /* * These are not considered tex opcodes here (no additional * target argument) however we're required to set the Texture * bit so we can set the number of tex offsets. */ inst.Instruction.Texture = 1; inst.Texture.Texture = TGSI_TEXTURE_UNKNOWN; } if ((i >= TGSI_OPCODE_LOAD && i <= TGSI_OPCODE_ATOMIMAX) || i == TGSI_OPCODE_RESQ) { inst.Instruction.Memory = 1; inst.Memory.Qualifier = 0; } /* Parse instruction operands. */ for (i = 0; i < info->num_dst + info->num_src + info->is_tex; i++) { if (i > 0) { eat_opt_white( &ctx->cur ); if (*ctx->cur != ',') { report_error( ctx, "Expected `,'" ); return FALSE; } ctx->cur++; eat_opt_white( &ctx->cur ); } if (i < info->num_dst) { if (!parse_dst_operand( ctx, &inst.Dst[i] )) return FALSE; } else if (i < info->num_dst + info->num_src) { if (!parse_src_operand( ctx, &inst.Src[i - info->num_dst] )) return FALSE; } else { uint j; for (j = 0; j < TGSI_TEXTURE_COUNT; j++) { if (str_match_nocase_whole( &ctx->cur, tgsi_texture_names[j] )) { inst.Instruction.Texture = 1; inst.Texture.Texture = j; break; } } if (j == TGSI_TEXTURE_COUNT) { report_error( ctx, "Expected texture target" ); return FALSE; } } } cur = ctx->cur; eat_opt_white( &cur ); for (i = 0; inst.Instruction.Texture && *cur == ','; i++) { cur++; eat_opt_white( &cur ); ctx->cur = cur; if (!parse_texoffset_operand( ctx, &inst.TexOffsets[i] )) return FALSE; cur = ctx->cur; eat_opt_white( &cur ); } inst.Texture.NumOffsets = i; cur = ctx->cur; eat_opt_white(&cur); for (i = 0; inst.Instruction.Memory && *cur == ','; i++) { uint j; cur++; eat_opt_white(&cur); ctx->cur = cur; for (j = 0; j < 3; j++) { if (str_match_nocase_whole(&ctx->cur, tgsi_memory_names[j])) { inst.Memory.Qualifier |= 1U << j; break; } } if (j == 3) { report_error(ctx, "Expected memory qualifier"); return FALSE; } cur = ctx->cur; eat_opt_white(&cur); } cur = ctx->cur; eat_opt_white( &cur ); if (info->is_branch && *cur == ':') { uint target; cur++; eat_opt_white( &cur ); if (!parse_uint( &cur, &target )) { report_error( ctx, "Expected a label" ); return FALSE; } inst.Instruction.Label = 1; inst.Label.Label = target; ctx->cur = cur; } advance = tgsi_build_full_instruction( &inst, ctx->tokens_cur, ctx->header, (uint) (ctx->tokens_end - ctx->tokens_cur) ); if (advance == 0) return FALSE; ctx->tokens_cur += advance; return TRUE; }
static void transform_instr(struct tgsi_transform_context *tctx, struct tgsi_full_instruction *current_inst) { struct tgsi_atifs_transform *ctx = tgsi_atifs_transform(tctx); if (ctx->first_instruction_emitted) goto transform_inst; ctx->first_instruction_emitted = true; if (ctx->key->fog) { /* add a new temp for the fog factor */ ctx->fog_factor_temp = ctx->info.file_max[TGSI_FILE_TEMPORARY] + 1; tgsi_transform_temp_decl(tctx, ctx->fog_factor_temp); /* add immediates for clamp */ ctx->fog_clamp_imm = ctx->info.immediate_count; tgsi_transform_immediate_decl(tctx, 1.0f, 0.0f, 0.0f, 0.0f); } transform_inst: if (current_inst->Instruction.Opcode == TGSI_OPCODE_TEX) { /* fix texture target */ unsigned newtarget = ctx->key->texture_targets[current_inst->Src[1].Register.Index]; if (newtarget) current_inst->Texture.Texture = newtarget; } else if (ctx->key->fog && current_inst->Instruction.Opcode == TGSI_OPCODE_MOV && current_inst->Dst[0].Register.File == TGSI_FILE_OUTPUT) { struct tgsi_full_instruction inst; unsigned i; int fogc_index = -1; int reg0_index = current_inst->Src[0].Register.Index; /* find FOGC input */ for (i = 0; i < ctx->info.num_inputs; i++) { if (ctx->info.input_semantic_name[i] == TGSI_SEMANTIC_FOG) { fogc_index = i; break; } } if (fogc_index < 0) { /* should never be reached, because fog coord input is always declared */ tctx->emit_instruction(tctx, current_inst); return; } /* compute the 1 component fog factor f */ if (ctx->key->fog == 1) { /* LINEAR formula: f = (end - z) / (end - start) * with optimized parameters: * f = MAD(fogcoord, oparams.x, oparams.y) */ inst = tgsi_default_full_instruction(); inst.Instruction.Opcode = TGSI_OPCODE_MAD; inst.Instruction.NumDstRegs = 1; inst.Dst[0].Register.File = TGSI_FILE_TEMPORARY; inst.Dst[0].Register.Index = ctx->fog_factor_temp; inst.Dst[0].Register.WriteMask = TGSI_WRITEMASK_XYZW; inst.Instruction.NumSrcRegs = 3; SET_SRC(&inst, 0, TGSI_FILE_INPUT, fogc_index, X, Y, Z, W); SET_SRC(&inst, 1, TGSI_FILE_CONSTANT, MAX_NUM_FRAGMENT_CONSTANTS_ATI, X, X, X, X); SET_SRC(&inst, 2, TGSI_FILE_CONSTANT, MAX_NUM_FRAGMENT_CONSTANTS_ATI, Y, Y, Y, Y); tctx->emit_instruction(tctx, &inst); } else if (ctx->key->fog == 2) { /* EXP formula: f = exp(-dens * z) * with optimized parameters: * f = MUL(fogcoord, oparams.z); f= EX2(-f) */ inst = tgsi_default_full_instruction(); inst.Instruction.Opcode = TGSI_OPCODE_MUL; inst.Instruction.NumDstRegs = 1; inst.Dst[0].Register.File = TGSI_FILE_TEMPORARY; inst.Dst[0].Register.Index = ctx->fog_factor_temp; inst.Dst[0].Register.WriteMask = TGSI_WRITEMASK_XYZW; inst.Instruction.NumSrcRegs = 2; SET_SRC(&inst, 0, TGSI_FILE_INPUT, fogc_index, X, Y, Z, W); SET_SRC(&inst, 1, TGSI_FILE_CONSTANT, MAX_NUM_FRAGMENT_CONSTANTS_ATI, Z, Z, Z, Z); tctx->emit_instruction(tctx, &inst); inst = tgsi_default_full_instruction(); inst.Instruction.Opcode = TGSI_OPCODE_EX2; inst.Instruction.NumDstRegs = 1; inst.Dst[0].Register.File = TGSI_FILE_TEMPORARY; inst.Dst[0].Register.Index = ctx->fog_factor_temp; inst.Dst[0].Register.WriteMask = TGSI_WRITEMASK_XYZW; inst.Instruction.NumSrcRegs = 1; SET_SRC(&inst, 0, TGSI_FILE_TEMPORARY, ctx->fog_factor_temp, X, Y, Z, W); inst.Src[0].Register.Negate = 1; tctx->emit_instruction(tctx, &inst); } else if (ctx->key->fog == 3) { /* EXP2 formula: f = exp(-(dens * z)^2) * with optimized parameters: * f = MUL(fogcoord, oparams.w); f=MUL(f, f); f= EX2(-f) */ inst = tgsi_default_full_instruction(); inst.Instruction.Opcode = TGSI_OPCODE_MUL; inst.Instruction.NumDstRegs = 1; inst.Dst[0].Register.File = TGSI_FILE_TEMPORARY; inst.Dst[0].Register.Index = ctx->fog_factor_temp; inst.Dst[0].Register.WriteMask = TGSI_WRITEMASK_XYZW; inst.Instruction.NumSrcRegs = 2; SET_SRC(&inst, 0, TGSI_FILE_INPUT, fogc_index, X, Y, Z, W); SET_SRC(&inst, 1, TGSI_FILE_CONSTANT, MAX_NUM_FRAGMENT_CONSTANTS_ATI, W, W, W, W); tctx->emit_instruction(tctx, &inst); inst = tgsi_default_full_instruction(); inst.Instruction.Opcode = TGSI_OPCODE_MUL; inst.Instruction.NumDstRegs = 1; inst.Dst[0].Register.File = TGSI_FILE_TEMPORARY; inst.Dst[0].Register.Index = ctx->fog_factor_temp; inst.Dst[0].Register.WriteMask = TGSI_WRITEMASK_XYZW; inst.Instruction.NumSrcRegs = 2; SET_SRC(&inst, 0, TGSI_FILE_TEMPORARY, ctx->fog_factor_temp, X, Y, Z, W); SET_SRC(&inst, 1, TGSI_FILE_TEMPORARY, ctx->fog_factor_temp, X, Y, Z, W); tctx->emit_instruction(tctx, &inst); inst = tgsi_default_full_instruction(); inst.Instruction.Opcode = TGSI_OPCODE_EX2; inst.Instruction.NumDstRegs = 1; inst.Dst[0].Register.File = TGSI_FILE_TEMPORARY; inst.Dst[0].Register.Index = ctx->fog_factor_temp; inst.Dst[0].Register.WriteMask = TGSI_WRITEMASK_XYZW; inst.Instruction.NumSrcRegs = 1; SET_SRC(&inst, 0, TGSI_FILE_TEMPORARY, ctx->fog_factor_temp, X, Y, Z, W); inst.Src[0].Register.Negate ^= 1; tctx->emit_instruction(tctx, &inst); } /* f = CLAMP(f, 0.0, 1.0) */ inst = tgsi_default_full_instruction(); inst.Instruction.Opcode = TGSI_OPCODE_CLAMP; inst.Instruction.NumDstRegs = 1; inst.Dst[0].Register.File = TGSI_FILE_TEMPORARY; inst.Dst[0].Register.Index = ctx->fog_factor_temp; inst.Dst[0].Register.WriteMask = TGSI_WRITEMASK_XYZW; inst.Instruction.NumSrcRegs = 3; SET_SRC(&inst, 0, TGSI_FILE_TEMPORARY, ctx->fog_factor_temp, X, Y, Z, W); SET_SRC(&inst, 1, TGSI_FILE_IMMEDIATE, ctx->fog_clamp_imm, Y, Y, Y, Y); // 0.0 SET_SRC(&inst, 2, TGSI_FILE_IMMEDIATE, ctx->fog_clamp_imm, X, X, X, X); // 1.0 tctx->emit_instruction(tctx, &inst); /* REG0 = LRP(f, REG0, fogcolor) */ inst = tgsi_default_full_instruction(); inst.Instruction.Opcode = TGSI_OPCODE_LRP; inst.Instruction.NumDstRegs = 1; inst.Dst[0].Register.File = TGSI_FILE_TEMPORARY; inst.Dst[0].Register.Index = reg0_index; inst.Dst[0].Register.WriteMask = TGSI_WRITEMASK_XYZW; inst.Instruction.NumSrcRegs = 3; SET_SRC(&inst, 0, TGSI_FILE_TEMPORARY, ctx->fog_factor_temp, X, X, X, Y); SET_SRC(&inst, 1, TGSI_FILE_TEMPORARY, reg0_index, X, Y, Z, W); SET_SRC(&inst, 2, TGSI_FILE_CONSTANT, MAX_NUM_FRAGMENT_CONSTANTS_ATI + 1, X, Y, Z, W); tctx->emit_instruction(tctx, &inst); } tctx->emit_instruction(tctx, current_inst); }
/** * TGSI instruction transform callback. * Replace writes to result.color w/ a temp reg. * Upon END instruction, insert texture sampling code for antialiasing. */ static void aa_transform_inst(struct tgsi_transform_context *ctx, struct tgsi_full_instruction *inst) { struct aa_transform_context *aactx = (struct aa_transform_context *) ctx; struct tgsi_full_instruction newInst; if (aactx->firstInstruction) { /* emit our new declarations before the first instruction */ struct tgsi_full_declaration decl; const int texInput = aactx->maxInput + 1; int tmp0; uint i; /* find two free temp regs */ for (i = 0; i < 32; i++) { if ((aactx->tempsUsed & (1 << i)) == 0) { /* found a free temp */ if (aactx->tmp0 < 0) aactx->tmp0 = i; else if (aactx->colorTemp < 0) aactx->colorTemp = i; else break; } } assert(aactx->colorTemp != aactx->tmp0); tmp0 = aactx->tmp0; /* declare new generic input/texcoord */ decl = tgsi_default_full_declaration(); decl.Declaration.File = TGSI_FILE_INPUT; /* XXX this could be linear... */ decl.Declaration.Interpolate = TGSI_INTERPOLATE_PERSPECTIVE; decl.Declaration.Semantic = 1; decl.Semantic.Name = TGSI_SEMANTIC_GENERIC; decl.Semantic.Index = aactx->maxGeneric + 1; decl.Range.First = decl.Range.Last = texInput; ctx->emit_declaration(ctx, &decl); /* declare new temp regs */ decl = tgsi_default_full_declaration(); decl.Declaration.File = TGSI_FILE_TEMPORARY; decl.Range.First = decl.Range.Last = tmp0; ctx->emit_declaration(ctx, &decl); decl = tgsi_default_full_declaration(); decl.Declaration.File = TGSI_FILE_TEMPORARY; decl.Range.First = decl.Range.Last = aactx->colorTemp; ctx->emit_declaration(ctx, &decl); aactx->firstInstruction = FALSE; /* * Emit code to compute fragment coverage, kill if outside point radius * * Temp reg0 usage: * t0.x = distance of fragment from center point * t0.y = boolean, is t0.x > 1.0, also misc temp usage * t0.z = temporary for computing 1/(1-k) value * t0.w = final coverage value */ /* MUL t0.xy, tex, tex; # compute x^2, y^2 */ newInst = tgsi_default_full_instruction(); newInst.Instruction.Opcode = TGSI_OPCODE_MUL; newInst.Instruction.NumDstRegs = 1; newInst.Dst[0].Register.File = TGSI_FILE_TEMPORARY; newInst.Dst[0].Register.Index = tmp0; newInst.Dst[0].Register.WriteMask = TGSI_WRITEMASK_XY; newInst.Instruction.NumSrcRegs = 2; newInst.Src[0].Register.File = TGSI_FILE_INPUT; newInst.Src[0].Register.Index = texInput; newInst.Src[1].Register.File = TGSI_FILE_INPUT; newInst.Src[1].Register.Index = texInput; ctx->emit_instruction(ctx, &newInst); /* ADD t0.x, t0.x, t0.y; # x^2 + y^2 */ newInst = tgsi_default_full_instruction(); newInst.Instruction.Opcode = TGSI_OPCODE_ADD; newInst.Instruction.NumDstRegs = 1; newInst.Dst[0].Register.File = TGSI_FILE_TEMPORARY; newInst.Dst[0].Register.Index = tmp0; newInst.Dst[0].Register.WriteMask = TGSI_WRITEMASK_X; newInst.Instruction.NumSrcRegs = 2; newInst.Src[0].Register.File = TGSI_FILE_TEMPORARY; newInst.Src[0].Register.Index = tmp0; newInst.Src[0].Register.SwizzleX = TGSI_SWIZZLE_X; newInst.Src[1].Register.File = TGSI_FILE_TEMPORARY; newInst.Src[1].Register.Index = tmp0; newInst.Src[1].Register.SwizzleX = TGSI_SWIZZLE_Y; ctx->emit_instruction(ctx, &newInst); #if NORMALIZE /* OPTIONAL normalization of length */ /* RSQ t0.x, t0.x; */ newInst = tgsi_default_full_instruction(); newInst.Instruction.Opcode = TGSI_OPCODE_RSQ; newInst.Instruction.NumDstRegs = 1; newInst.Dst[0].Register.File = TGSI_FILE_TEMPORARY; newInst.Dst[0].Register.Index = tmp0; newInst.Dst[0].Register.WriteMask = TGSI_WRITEMASK_X; newInst.Instruction.NumSrcRegs = 1; newInst.Src[0].Register.File = TGSI_FILE_TEMPORARY; newInst.Src[0].Register.Index = tmp0; ctx->emit_instruction(ctx, &newInst); /* RCP t0.x, t0.x; */ newInst = tgsi_default_full_instruction(); newInst.Instruction.Opcode = TGSI_OPCODE_RCP; newInst.Instruction.NumDstRegs = 1; newInst.Dst[0].Register.File = TGSI_FILE_TEMPORARY; newInst.Dst[0].Register.Index = tmp0; newInst.Dst[0].Register.WriteMask = TGSI_WRITEMASK_X; newInst.Instruction.NumSrcRegs = 1; newInst.Src[0].Register.File = TGSI_FILE_TEMPORARY; newInst.Src[0].Register.Index = tmp0; ctx->emit_instruction(ctx, &newInst); #endif /* SGT t0.y, t0.xxxx, tex.wwww; # bool b = d > 1 (NOTE tex.w == 1) */ newInst = tgsi_default_full_instruction(); newInst.Instruction.Opcode = TGSI_OPCODE_SGT; newInst.Instruction.NumDstRegs = 1; newInst.Dst[0].Register.File = TGSI_FILE_TEMPORARY; newInst.Dst[0].Register.Index = tmp0; newInst.Dst[0].Register.WriteMask = TGSI_WRITEMASK_Y; newInst.Instruction.NumSrcRegs = 2; newInst.Src[0].Register.File = TGSI_FILE_TEMPORARY; newInst.Src[0].Register.Index = tmp0; newInst.Src[0].Register.SwizzleY = TGSI_SWIZZLE_X; newInst.Src[1].Register.File = TGSI_FILE_INPUT; newInst.Src[1].Register.Index = texInput; newInst.Src[1].Register.SwizzleY = TGSI_SWIZZLE_W; ctx->emit_instruction(ctx, &newInst); /* KIL -tmp0.yyyy; # if -tmp0.y < 0, KILL */ newInst = tgsi_default_full_instruction(); newInst.Instruction.Opcode = TGSI_OPCODE_KIL; newInst.Instruction.NumDstRegs = 0; newInst.Instruction.NumSrcRegs = 1; newInst.Src[0].Register.File = TGSI_FILE_TEMPORARY; newInst.Src[0].Register.Index = tmp0; newInst.Src[0].Register.SwizzleX = TGSI_SWIZZLE_Y; newInst.Src[0].Register.SwizzleY = TGSI_SWIZZLE_Y; newInst.Src[0].Register.SwizzleZ = TGSI_SWIZZLE_Y; newInst.Src[0].Register.SwizzleW = TGSI_SWIZZLE_Y; newInst.Src[0].Register.Negate = 1; ctx->emit_instruction(ctx, &newInst); /* compute coverage factor = (1-d)/(1-k) */ /* SUB t0.z, tex.w, tex.z; # m = 1 - k */ newInst = tgsi_default_full_instruction(); newInst.Instruction.Opcode = TGSI_OPCODE_SUB; newInst.Instruction.NumDstRegs = 1; newInst.Dst[0].Register.File = TGSI_FILE_TEMPORARY; newInst.Dst[0].Register.Index = tmp0; newInst.Dst[0].Register.WriteMask = TGSI_WRITEMASK_Z; newInst.Instruction.NumSrcRegs = 2; newInst.Src[0].Register.File = TGSI_FILE_INPUT; newInst.Src[0].Register.Index = texInput; newInst.Src[0].Register.SwizzleZ = TGSI_SWIZZLE_W; newInst.Src[1].Register.File = TGSI_FILE_INPUT; newInst.Src[1].Register.Index = texInput; newInst.Src[1].Register.SwizzleZ = TGSI_SWIZZLE_Z; ctx->emit_instruction(ctx, &newInst); /* RCP t0.z, t0.z; # t0.z = 1 / m */ newInst = tgsi_default_full_instruction(); newInst.Instruction.Opcode = TGSI_OPCODE_RCP; newInst.Instruction.NumDstRegs = 1; newInst.Dst[0].Register.File = TGSI_FILE_TEMPORARY; newInst.Dst[0].Register.Index = tmp0; newInst.Dst[0].Register.WriteMask = TGSI_WRITEMASK_Z; newInst.Instruction.NumSrcRegs = 1; newInst.Src[0].Register.File = TGSI_FILE_TEMPORARY; newInst.Src[0].Register.Index = tmp0; newInst.Src[0].Register.SwizzleX = TGSI_SWIZZLE_Z; ctx->emit_instruction(ctx, &newInst); /* SUB t0.y, 1, t0.x; # d = 1 - d */ newInst = tgsi_default_full_instruction(); newInst.Instruction.Opcode = TGSI_OPCODE_SUB; newInst.Instruction.NumDstRegs = 1; newInst.Dst[0].Register.File = TGSI_FILE_TEMPORARY; newInst.Dst[0].Register.Index = tmp0; newInst.Dst[0].Register.WriteMask = TGSI_WRITEMASK_Y; newInst.Instruction.NumSrcRegs = 2; newInst.Src[0].Register.File = TGSI_FILE_INPUT; newInst.Src[0].Register.Index = texInput; newInst.Src[0].Register.SwizzleY = TGSI_SWIZZLE_W; newInst.Src[1].Register.File = TGSI_FILE_TEMPORARY; newInst.Src[1].Register.Index = tmp0; newInst.Src[1].Register.SwizzleY = TGSI_SWIZZLE_X; ctx->emit_instruction(ctx, &newInst); /* MUL t0.w, t0.y, t0.z; # coverage = d * m */ newInst = tgsi_default_full_instruction(); newInst.Instruction.Opcode = TGSI_OPCODE_MUL; newInst.Instruction.NumDstRegs = 1; newInst.Dst[0].Register.File = TGSI_FILE_TEMPORARY; newInst.Dst[0].Register.Index = tmp0; newInst.Dst[0].Register.WriteMask = TGSI_WRITEMASK_W; newInst.Instruction.NumSrcRegs = 2; newInst.Src[0].Register.File = TGSI_FILE_TEMPORARY; newInst.Src[0].Register.Index = tmp0; newInst.Src[0].Register.SwizzleW = TGSI_SWIZZLE_Y; newInst.Src[1].Register.File = TGSI_FILE_TEMPORARY; newInst.Src[1].Register.Index = tmp0; newInst.Src[1].Register.SwizzleW = TGSI_SWIZZLE_Z; ctx->emit_instruction(ctx, &newInst); /* SLE t0.y, t0.x, tex.z; # bool b = distance <= k */ newInst = tgsi_default_full_instruction(); newInst.Instruction.Opcode = TGSI_OPCODE_SLE; newInst.Instruction.NumDstRegs = 1; newInst.Dst[0].Register.File = TGSI_FILE_TEMPORARY; newInst.Dst[0].Register.Index = tmp0; newInst.Dst[0].Register.WriteMask = TGSI_WRITEMASK_Y; newInst.Instruction.NumSrcRegs = 2; newInst.Src[0].Register.File = TGSI_FILE_TEMPORARY; newInst.Src[0].Register.Index = tmp0; newInst.Src[0].Register.SwizzleY = TGSI_SWIZZLE_X; newInst.Src[1].Register.File = TGSI_FILE_INPUT; newInst.Src[1].Register.Index = texInput; newInst.Src[1].Register.SwizzleY = TGSI_SWIZZLE_Z; ctx->emit_instruction(ctx, &newInst); /* CMP t0.w, -t0.y, tex.w, t0.w; * # if -t0.y < 0 then * t0.w = 1 * else * t0.w = t0.w */ newInst = tgsi_default_full_instruction(); newInst.Instruction.Opcode = TGSI_OPCODE_CMP; newInst.Instruction.NumDstRegs = 1; newInst.Dst[0].Register.File = TGSI_FILE_TEMPORARY; newInst.Dst[0].Register.Index = tmp0; newInst.Dst[0].Register.WriteMask = TGSI_WRITEMASK_W; newInst.Instruction.NumSrcRegs = 3; newInst.Src[0].Register.File = TGSI_FILE_TEMPORARY; newInst.Src[0].Register.Index = tmp0; newInst.Src[0].Register.SwizzleX = TGSI_SWIZZLE_Y; newInst.Src[0].Register.SwizzleY = TGSI_SWIZZLE_Y; newInst.Src[0].Register.SwizzleZ = TGSI_SWIZZLE_Y; newInst.Src[0].Register.SwizzleW = TGSI_SWIZZLE_Y; newInst.Src[0].Register.Negate = 1; newInst.Src[1].Register.File = TGSI_FILE_INPUT; newInst.Src[1].Register.Index = texInput; newInst.Src[1].Register.SwizzleX = TGSI_SWIZZLE_W; newInst.Src[1].Register.SwizzleY = TGSI_SWIZZLE_W; newInst.Src[1].Register.SwizzleZ = TGSI_SWIZZLE_W; newInst.Src[1].Register.SwizzleW = TGSI_SWIZZLE_W; newInst.Src[2].Register.File = TGSI_FILE_TEMPORARY; newInst.Src[2].Register.Index = tmp0; newInst.Src[2].Register.SwizzleX = TGSI_SWIZZLE_W; newInst.Src[2].Register.SwizzleY = TGSI_SWIZZLE_W; newInst.Src[2].Register.SwizzleZ = TGSI_SWIZZLE_W; newInst.Src[2].Register.SwizzleW = TGSI_SWIZZLE_W; ctx->emit_instruction(ctx, &newInst); } if (inst->Instruction.Opcode == TGSI_OPCODE_END) { /* add alpha modulation code at tail of program */ /* MOV result.color.xyz, colorTemp; */ newInst = tgsi_default_full_instruction(); newInst.Instruction.Opcode = TGSI_OPCODE_MOV; newInst.Instruction.NumDstRegs = 1; newInst.Dst[0].Register.File = TGSI_FILE_OUTPUT; newInst.Dst[0].Register.Index = aactx->colorOutput; newInst.Dst[0].Register.WriteMask = TGSI_WRITEMASK_XYZ; newInst.Instruction.NumSrcRegs = 1; newInst.Src[0].Register.File = TGSI_FILE_TEMPORARY; newInst.Src[0].Register.Index = aactx->colorTemp; ctx->emit_instruction(ctx, &newInst); /* MUL result.color.w, colorTemp, tmp0.w; */ newInst = tgsi_default_full_instruction(); newInst.Instruction.Opcode = TGSI_OPCODE_MUL; newInst.Instruction.NumDstRegs = 1; newInst.Dst[0].Register.File = TGSI_FILE_OUTPUT; newInst.Dst[0].Register.Index = aactx->colorOutput; newInst.Dst[0].Register.WriteMask = TGSI_WRITEMASK_W; newInst.Instruction.NumSrcRegs = 2; newInst.Src[0].Register.File = TGSI_FILE_TEMPORARY; newInst.Src[0].Register.Index = aactx->colorTemp; newInst.Src[1].Register.File = TGSI_FILE_TEMPORARY; newInst.Src[1].Register.Index = aactx->tmp0; ctx->emit_instruction(ctx, &newInst); } else { /* Not an END instruction. * Look for writes to result.color and replace with colorTemp reg. */ uint i; for (i = 0; i < inst->Instruction.NumDstRegs; i++) { struct tgsi_full_dst_register *dst = &inst->Dst[i]; if (dst->Register.File == TGSI_FILE_OUTPUT && dst->Register.Index == aactx->colorOutput) { dst->Register.File = TGSI_FILE_TEMPORARY; dst->Register.Index = aactx->colorTemp; } } } ctx->emit_instruction(ctx, inst); }
void tgsi_dump_c( const struct tgsi_token *tokens, uint flags ) { struct tgsi_parse_context parse; struct tgsi_full_instruction fi; struct tgsi_full_declaration fd; uint ignored = flags & TGSI_DUMP_C_IGNORED; uint deflt = flags & TGSI_DUMP_C_DEFAULT; uint instno = 0; tgsi_parse_init( &parse, tokens ); TXT( "tgsi-dump begin -----------------" ); TXT( "\nMajorVersion: " ); UID( parse.FullVersion.Version.MajorVersion ); TXT( "\nMinorVersion: " ); UID( parse.FullVersion.Version.MinorVersion ); EOL(); TXT( "\nHeaderSize: " ); UID( parse.FullHeader.Header.HeaderSize ); TXT( "\nBodySize : " ); UID( parse.FullHeader.Header.BodySize ); TXT( "\nProcessor : " ); ENM( parse.FullHeader.Processor.Processor, TGSI_PROCESSOR_TYPES ); EOL(); fi = tgsi_default_full_instruction(); fd = tgsi_default_full_declaration(); while( !tgsi_parse_end_of_tokens( &parse ) ) { tgsi_parse_token( &parse ); TXT( "\nType : " ); ENM( parse.FullToken.Token.Type, TGSI_TOKEN_TYPES ); if( ignored ) { TXT( "\nSize : " ); UID( parse.FullToken.Token.Size ); if( deflt || parse.FullToken.Token.Extended ) { TXT( "\nExtended : " ); UID( parse.FullToken.Token.Extended ); } } switch( parse.FullToken.Token.Type ) { case TGSI_TOKEN_TYPE_DECLARATION: dump_declaration_verbose( &parse.FullToken.FullDeclaration, ignored, deflt, &fd ); break; case TGSI_TOKEN_TYPE_IMMEDIATE: dump_immediate_verbose( &parse.FullToken.FullImmediate, ignored ); break; case TGSI_TOKEN_TYPE_INSTRUCTION: dump_instruction_verbose( &parse.FullToken.FullInstruction, ignored, deflt, &fi ); break; default: assert( 0 ); } EOL(); } TXT( "\ntgsi-dump end -------------------\n" ); tgsi_parse_free( &parse ); }
/** * TGSI instruction transform callback. * Replace writes to result.color w/ a temp reg. * Upon END instruction, insert texture sampling code for antialiasing. */ static void aa_transform_inst(struct tgsi_transform_context *ctx, struct tgsi_full_instruction *inst) { struct aa_transform_context *aactx = (struct aa_transform_context *) ctx; if (aactx->firstInstruction) { /* emit our new declarations before the first instruction */ struct tgsi_full_declaration decl; uint i; /* find free sampler */ aactx->freeSampler = free_bit(aactx->samplersUsed); if (aactx->freeSampler >= PIPE_MAX_SAMPLERS) aactx->freeSampler = PIPE_MAX_SAMPLERS - 1; /* find two free temp regs */ for (i = 0; i < 32; i++) { if ((aactx->tempsUsed & (1 << i)) == 0) { /* found a free temp */ if (aactx->colorTemp < 0) aactx->colorTemp = i; else if (aactx->texTemp < 0) aactx->texTemp = i; else break; } } assert(aactx->colorTemp >= 0); assert(aactx->texTemp >= 0); /* declare new generic input/texcoord */ decl = tgsi_default_full_declaration(); decl.Declaration.File = TGSI_FILE_INPUT; /* XXX this could be linear... */ decl.Declaration.Interpolate = TGSI_INTERPOLATE_PERSPECTIVE; decl.Declaration.Semantic = 1; decl.Semantic.Name = TGSI_SEMANTIC_GENERIC; decl.Semantic.Index = aactx->maxGeneric + 1; decl.Range.First = decl.Range.Last = aactx->maxInput + 1; ctx->emit_declaration(ctx, &decl); /* declare new sampler */ decl = tgsi_default_full_declaration(); decl.Declaration.File = TGSI_FILE_SAMPLER; decl.Range.First = decl.Range.Last = aactx->freeSampler; ctx->emit_declaration(ctx, &decl); /* declare new temp regs */ decl = tgsi_default_full_declaration(); decl.Declaration.File = TGSI_FILE_TEMPORARY; decl.Range.First = decl.Range.Last = aactx->texTemp; ctx->emit_declaration(ctx, &decl); decl = tgsi_default_full_declaration(); decl.Declaration.File = TGSI_FILE_TEMPORARY; decl.Range.First = decl.Range.Last = aactx->colorTemp; ctx->emit_declaration(ctx, &decl); aactx->firstInstruction = FALSE; } if (inst->Instruction.Opcode == TGSI_OPCODE_END && aactx->colorOutput != -1) { struct tgsi_full_instruction newInst; /* TEX */ newInst = tgsi_default_full_instruction(); newInst.Instruction.Opcode = TGSI_OPCODE_TEX; newInst.Instruction.NumDstRegs = 1; newInst.Dst[0].Register.File = TGSI_FILE_TEMPORARY; newInst.Dst[0].Register.Index = aactx->texTemp; newInst.Instruction.NumSrcRegs = 2; newInst.Instruction.Texture = TRUE; newInst.Texture.Texture = TGSI_TEXTURE_2D; newInst.Src[0].Register.File = TGSI_FILE_INPUT; newInst.Src[0].Register.Index = aactx->maxInput + 1; newInst.Src[1].Register.File = TGSI_FILE_SAMPLER; newInst.Src[1].Register.Index = aactx->freeSampler; ctx->emit_instruction(ctx, &newInst); /* MOV rgb */ newInst = tgsi_default_full_instruction(); newInst.Instruction.Opcode = TGSI_OPCODE_MOV; newInst.Instruction.NumDstRegs = 1; newInst.Dst[0].Register.File = TGSI_FILE_OUTPUT; newInst.Dst[0].Register.Index = aactx->colorOutput; newInst.Dst[0].Register.WriteMask = TGSI_WRITEMASK_XYZ; newInst.Instruction.NumSrcRegs = 1; newInst.Src[0].Register.File = TGSI_FILE_TEMPORARY; newInst.Src[0].Register.Index = aactx->colorTemp; ctx->emit_instruction(ctx, &newInst); /* MUL alpha */ newInst = tgsi_default_full_instruction(); newInst.Instruction.Opcode = TGSI_OPCODE_MUL; newInst.Instruction.NumDstRegs = 1; newInst.Dst[0].Register.File = TGSI_FILE_OUTPUT; newInst.Dst[0].Register.Index = aactx->colorOutput; newInst.Dst[0].Register.WriteMask = TGSI_WRITEMASK_W; newInst.Instruction.NumSrcRegs = 2; newInst.Src[0].Register.File = TGSI_FILE_TEMPORARY; newInst.Src[0].Register.Index = aactx->colorTemp; newInst.Src[1].Register.File = TGSI_FILE_TEMPORARY; newInst.Src[1].Register.Index = aactx->texTemp; ctx->emit_instruction(ctx, &newInst); /* END */ newInst = tgsi_default_full_instruction(); newInst.Instruction.Opcode = TGSI_OPCODE_END; newInst.Instruction.NumDstRegs = 0; newInst.Instruction.NumSrcRegs = 0; ctx->emit_instruction(ctx, &newInst); } else { /* Not an END instruction. * Look for writes to result.color and replace with colorTemp reg. */ uint i; for (i = 0; i < inst->Instruction.NumDstRegs; i++) { struct tgsi_full_dst_register *dst = &inst->Dst[i]; if (dst->Register.File == TGSI_FILE_OUTPUT && dst->Register.Index == aactx->colorOutput) { dst->Register.File = TGSI_FILE_TEMPORARY; dst->Register.Index = aactx->colorTemp; } } ctx->emit_instruction(ctx, inst); } }
static void transform_inst(struct tgsi_transform_context *ctx, struct tgsi_full_instruction *inst) { struct vs_transform_context *vsctx = (struct vs_transform_context *) ctx; struct tgsi_full_instruction new_inst; unsigned i; if (!vsctx->first_instruction) { vsctx->first_instruction = TRUE; /* Insert the generic output for WPOS. */ emit_output(ctx, TGSI_SEMANTIC_GENERIC, vsctx->last_generic + 1, TGSI_INTERPOLATE_PERSPECTIVE, vsctx->num_outputs); /* Find a free temp for POSITION. */ for (i = 0; i < Elements(vsctx->temp_used); i++) { if (!vsctx->temp_used[i]) { emit_temp(ctx, i); vsctx->pos_temp = i; break; } } } if (inst->Instruction.Opcode == TGSI_OPCODE_END) { /* MOV OUT[pos_output], TEMP[pos_temp]; */ new_inst = tgsi_default_full_instruction(); new_inst.Instruction.Opcode = TGSI_OPCODE_MOV; new_inst.Instruction.NumDstRegs = 1; new_inst.Dst[0].Register.File = TGSI_FILE_OUTPUT; new_inst.Dst[0].Register.Index = vsctx->pos_output; new_inst.Dst[0].Register.WriteMask = TGSI_WRITEMASK_XYZW; new_inst.Instruction.NumSrcRegs = 1; new_inst.Src[0].Register.File = TGSI_FILE_TEMPORARY; new_inst.Src[0].Register.Index = vsctx->pos_temp; ctx->emit_instruction(ctx, &new_inst); /* MOV OUT[n-1], TEMP[pos_temp]; */ new_inst = tgsi_default_full_instruction(); new_inst.Instruction.Opcode = TGSI_OPCODE_MOV; new_inst.Instruction.NumDstRegs = 1; new_inst.Dst[0].Register.File = TGSI_FILE_OUTPUT; new_inst.Dst[0].Register.Index = vsctx->num_outputs - 1; new_inst.Dst[0].Register.WriteMask = TGSI_WRITEMASK_XYZW; new_inst.Instruction.NumSrcRegs = 1; new_inst.Src[0].Register.File = TGSI_FILE_TEMPORARY; new_inst.Src[0].Register.Index = vsctx->pos_temp; ctx->emit_instruction(ctx, &new_inst); vsctx->end_instruction = TRUE; } else { /* Not an END instruction. */ /* Fix writes to outputs. */ for (i = 0; i < inst->Instruction.NumDstRegs; i++) { struct tgsi_full_dst_register *dst = &inst->Dst[i]; if (dst->Register.File == TGSI_FILE_OUTPUT) { if (dst->Register.Index == vsctx->pos_output) { /* Replace writes to OUT[pos_output] with TEMP[pos_temp]. */ dst->Register.File = TGSI_FILE_TEMPORARY; dst->Register.Index = vsctx->pos_temp; } else { /* Not a position, good... * Since we were changing the indices of output decls, * we must redirect writes into them too. */ dst->Register.Index = vsctx->out_remap[dst->Register.Index]; } } } /* Inserting 2 instructions before the END opcode moves all following * labels by 2. Subroutines are always after the END opcode so * they're always moved. */ if (inst->Instruction.Opcode == TGSI_OPCODE_CAL) { inst->Label.Label += 2; } /* The labels of the following opcodes are moved only after * the END opcode. */ if (vsctx->end_instruction && (inst->Instruction.Opcode == TGSI_OPCODE_IF || inst->Instruction.Opcode == TGSI_OPCODE_ELSE || inst->Instruction.Opcode == TGSI_OPCODE_BGNLOOP || inst->Instruction.Opcode == TGSI_OPCODE_ENDLOOP)) { inst->Label.Label += 2; } } ctx->emit_instruction(ctx, inst); }
static boolean parse_instruction( struct translate_ctx *ctx, boolean has_label ) { uint i; uint saturate = TGSI_SAT_NONE; const struct tgsi_opcode_info *info; struct tgsi_full_instruction inst; uint advance; inst = tgsi_default_full_instruction(); /* Parse predicate. */ eat_opt_white( &ctx->cur ); if (*ctx->cur == '(') { uint file; int index; uint swizzle[4]; boolean parsed_swizzle; inst.Instruction.Predicate = 1; ctx->cur++; if (*ctx->cur == '!') { ctx->cur++; inst.Predicate.Negate = 1; } if (!parse_register_1d( ctx, &file, &index )) return FALSE; if (parse_optional_swizzle( ctx, swizzle, &parsed_swizzle )) { if (parsed_swizzle) { inst.Predicate.SwizzleX = swizzle[0]; inst.Predicate.SwizzleY = swizzle[1]; inst.Predicate.SwizzleZ = swizzle[2]; inst.Predicate.SwizzleW = swizzle[3]; } } if (*ctx->cur != ')') { report_error( ctx, "Expected `)'" ); return FALSE; } ctx->cur++; } /* Parse instruction name. */ eat_opt_white( &ctx->cur ); for (i = 0; i < TGSI_OPCODE_LAST; i++) { const char *cur = ctx->cur; info = tgsi_get_opcode_info( i ); if (match_inst_mnemonic(&cur, info)) { if (str_match_no_case( &cur, "_SATNV" )) saturate = TGSI_SAT_MINUS_PLUS_ONE; else if (str_match_no_case( &cur, "_SAT" )) saturate = TGSI_SAT_ZERO_ONE; if (info->num_dst + info->num_src + info->is_tex == 0) { if (!is_digit_alpha_underscore( cur )) { ctx->cur = cur; break; } } else if (*cur == '\0' || eat_white( &cur )) { ctx->cur = cur; break; } } } if (i == TGSI_OPCODE_LAST) { if (has_label) report_error( ctx, "Unknown opcode" ); else report_error( ctx, "Expected `DCL', `IMM' or a label" ); return FALSE; } inst.Instruction.Opcode = i; inst.Instruction.Saturate = saturate; inst.Instruction.NumDstRegs = info->num_dst; inst.Instruction.NumSrcRegs = info->num_src; /* Parse instruction operands. */ for (i = 0; i < info->num_dst + info->num_src + info->is_tex; i++) { if (i > 0) { eat_opt_white( &ctx->cur ); if (*ctx->cur != ',') { report_error( ctx, "Expected `,'" ); return FALSE; } ctx->cur++; eat_opt_white( &ctx->cur ); } if (i < info->num_dst) { if (!parse_dst_operand( ctx, &inst.Dst[i] )) return FALSE; } else if (i < info->num_dst + info->num_src) { if (!parse_src_operand( ctx, &inst.Src[i - info->num_dst] )) return FALSE; } else { uint j; for (j = 0; j < TGSI_TEXTURE_COUNT; j++) { if (str_match_no_case( &ctx->cur, texture_names[j] )) { if (!is_digit_alpha_underscore( ctx->cur )) { inst.Instruction.Texture = 1; inst.Texture.Texture = j; break; } } } if (j == TGSI_TEXTURE_COUNT) { report_error( ctx, "Expected texture target" ); return FALSE; } } } if (info->is_branch) { uint target; eat_opt_white( &ctx->cur ); if (*ctx->cur != ':') { report_error( ctx, "Expected `:'" ); return FALSE; } ctx->cur++; eat_opt_white( &ctx->cur ); if (!parse_uint( &ctx->cur, &target )) { report_error( ctx, "Expected a label" ); return FALSE; } inst.Instruction.Label = 1; inst.Label.Label = target; } advance = tgsi_build_full_instruction( &inst, ctx->tokens_cur, ctx->header, (uint) (ctx->tokens_end - ctx->tokens_cur) ); if (advance == 0) return FALSE; ctx->tokens_cur += advance; return TRUE; }
static void compile_instruction( const struct prog_instruction *inst, struct tgsi_full_instruction *fullinst, const GLuint inputMapping[], const GLuint outputMapping[], const GLuint immediateMapping[], GLboolean indirectAccess, GLuint preamble_size, GLuint procType, GLboolean *insideSubroutine, GLint wposTemp) { GLuint i; struct tgsi_full_dst_register *fulldst; struct tgsi_full_src_register *fullsrc; *fullinst = tgsi_default_full_instruction(); fullinst->Instruction.Saturate = convert_sat( inst->SaturateMode ); fullinst->Instruction.NumDstRegs = _mesa_num_inst_dst_regs( inst->Opcode ); fullinst->Instruction.NumSrcRegs = _mesa_num_inst_src_regs( inst->Opcode ); fulldst = &fullinst->FullDstRegisters[0]; fulldst->DstRegister.File = map_register_file( inst->DstReg.File, 0, NULL, GL_FALSE ); fulldst->DstRegister.Index = map_register_file_index( fulldst->DstRegister.File, inst->DstReg.Index, inputMapping, outputMapping, NULL, GL_FALSE ); fulldst->DstRegister.WriteMask = convert_writemask( inst->DstReg.WriteMask ); for (i = 0; i < fullinst->Instruction.NumSrcRegs; i++) { GLuint j; fullsrc = &fullinst->FullSrcRegisters[i]; if (procType == TGSI_PROCESSOR_FRAGMENT && inst->SrcReg[i].File == PROGRAM_INPUT && inst->SrcReg[i].Index == FRAG_ATTRIB_WPOS) { /* special case of INPUT[WPOS] */ fullsrc->SrcRegister.File = TGSI_FILE_TEMPORARY; fullsrc->SrcRegister.Index = wposTemp; } else { /* any other src register */ fullsrc->SrcRegister.File = map_register_file( inst->SrcReg[i].File, inst->SrcReg[i].Index, immediateMapping, indirectAccess ); fullsrc->SrcRegister.Index = map_register_file_index( fullsrc->SrcRegister.File, inst->SrcReg[i].Index, inputMapping, outputMapping, immediateMapping, indirectAccess ); } /* swizzle (ext swizzle also depends on negation) */ { GLuint swz[4]; GLboolean extended = (inst->SrcReg[i].Negate != NEGATE_NONE && inst->SrcReg[i].Negate != NEGATE_XYZW); for( j = 0; j < 4; j++ ) { swz[j] = GET_SWZ( inst->SrcReg[i].Swizzle, j ); if (swz[j] > SWIZZLE_W) extended = GL_TRUE; } if (extended) { for (j = 0; j < 4; j++) { tgsi_util_set_src_register_extswizzle(&fullsrc->SrcRegisterExtSwz, swz[j], j); } } else { for (j = 0; j < 4; j++) { tgsi_util_set_src_register_swizzle(&fullsrc->SrcRegister, swz[j], j); } } } if( inst->SrcReg[i].Negate == NEGATE_XYZW ) { fullsrc->SrcRegister.Negate = 1; } else if( inst->SrcReg[i].Negate != NEGATE_NONE ) { if( inst->SrcReg[i].Negate & NEGATE_X ) { fullsrc->SrcRegisterExtSwz.NegateX = 1; } if( inst->SrcReg[i].Negate & NEGATE_Y ) { fullsrc->SrcRegisterExtSwz.NegateY = 1; } if( inst->SrcReg[i].Negate & NEGATE_Z ) { fullsrc->SrcRegisterExtSwz.NegateZ = 1; } if( inst->SrcReg[i].Negate & NEGATE_W ) { fullsrc->SrcRegisterExtSwz.NegateW = 1; } } if( inst->SrcReg[i].Abs ) { fullsrc->SrcRegisterExtMod.Absolute = 1; } if( inst->SrcReg[i].RelAddr ) { fullsrc->SrcRegister.Indirect = 1; fullsrc->SrcRegisterInd.File = TGSI_FILE_ADDRESS; fullsrc->SrcRegisterInd.Index = 0; } } switch( inst->Opcode ) { case OPCODE_ARL: fullinst->Instruction.Opcode = TGSI_OPCODE_ARL; break; case OPCODE_ABS: fullinst->Instruction.Opcode = TGSI_OPCODE_ABS; break; case OPCODE_ADD: fullinst->Instruction.Opcode = TGSI_OPCODE_ADD; break; case OPCODE_BGNLOOP: fullinst->Instruction.Opcode = TGSI_OPCODE_BGNLOOP2; fullinst->InstructionExtLabel.Label = inst->BranchTarget + preamble_size; break; case OPCODE_BGNSUB: fullinst->Instruction.Opcode = TGSI_OPCODE_BGNSUB; *insideSubroutine = GL_TRUE; break; case OPCODE_BRA: fullinst->Instruction.Opcode = TGSI_OPCODE_BRA; break; case OPCODE_BRK: fullinst->Instruction.Opcode = TGSI_OPCODE_BRK; break; case OPCODE_CAL: fullinst->Instruction.Opcode = TGSI_OPCODE_CAL; fullinst->InstructionExtLabel.Label = inst->BranchTarget + preamble_size; break; case OPCODE_CMP: fullinst->Instruction.Opcode = TGSI_OPCODE_CMP; break; case OPCODE_CONT: fullinst->Instruction.Opcode = TGSI_OPCODE_CONT; break; case OPCODE_COS: fullinst->Instruction.Opcode = TGSI_OPCODE_COS; break; case OPCODE_DDX: fullinst->Instruction.Opcode = TGSI_OPCODE_DDX; break; case OPCODE_DDY: fullinst->Instruction.Opcode = TGSI_OPCODE_DDY; break; case OPCODE_DP2: fullinst->Instruction.Opcode = TGSI_OPCODE_DP2; break; case OPCODE_DP2A: fullinst->Instruction.Opcode = TGSI_OPCODE_DP2A; break; case OPCODE_DP3: fullinst->Instruction.Opcode = TGSI_OPCODE_DP3; break; case OPCODE_DP4: fullinst->Instruction.Opcode = TGSI_OPCODE_DP4; break; case OPCODE_DPH: fullinst->Instruction.Opcode = TGSI_OPCODE_DPH; break; case OPCODE_DST: fullinst->Instruction.Opcode = TGSI_OPCODE_DST; break; case OPCODE_ELSE: fullinst->Instruction.Opcode = TGSI_OPCODE_ELSE; fullinst->InstructionExtLabel.Label = inst->BranchTarget + preamble_size; break; case OPCODE_ENDIF: fullinst->Instruction.Opcode = TGSI_OPCODE_ENDIF; break; case OPCODE_ENDLOOP: fullinst->Instruction.Opcode = TGSI_OPCODE_ENDLOOP2; fullinst->InstructionExtLabel.Label = inst->BranchTarget + preamble_size; break; case OPCODE_ENDSUB: fullinst->Instruction.Opcode = TGSI_OPCODE_ENDSUB; *insideSubroutine = GL_FALSE; break; case OPCODE_EX2: fullinst->Instruction.Opcode = TGSI_OPCODE_EX2; break; case OPCODE_EXP: fullinst->Instruction.Opcode = TGSI_OPCODE_EXP; break; case OPCODE_FLR: fullinst->Instruction.Opcode = TGSI_OPCODE_FLR; break; case OPCODE_FRC: fullinst->Instruction.Opcode = TGSI_OPCODE_FRC; break; case OPCODE_IF: fullinst->Instruction.Opcode = TGSI_OPCODE_IF; fullinst->InstructionExtLabel.Label = inst->BranchTarget + preamble_size; break; case OPCODE_TRUNC: fullinst->Instruction.Opcode = TGSI_OPCODE_TRUNC; break; case OPCODE_KIL: /* conditional */ fullinst->Instruction.Opcode = TGSI_OPCODE_KIL; break; case OPCODE_KIL_NV: /* predicated */ assert(inst->DstReg.CondMask == COND_TR); fullinst->Instruction.Opcode = TGSI_OPCODE_KILP; break; case OPCODE_LG2: fullinst->Instruction.Opcode = TGSI_OPCODE_LG2; break; case OPCODE_LOG: fullinst->Instruction.Opcode = TGSI_OPCODE_LOG; break; case OPCODE_LIT: fullinst->Instruction.Opcode = TGSI_OPCODE_LIT; break; case OPCODE_LRP: fullinst->Instruction.Opcode = TGSI_OPCODE_LRP; break; case OPCODE_MAD: fullinst->Instruction.Opcode = TGSI_OPCODE_MAD; break; case OPCODE_MAX: fullinst->Instruction.Opcode = TGSI_OPCODE_MAX; break; case OPCODE_MIN: fullinst->Instruction.Opcode = TGSI_OPCODE_MIN; break; case OPCODE_MOV: fullinst->Instruction.Opcode = TGSI_OPCODE_MOV; break; case OPCODE_MUL: fullinst->Instruction.Opcode = TGSI_OPCODE_MUL; break; case OPCODE_NOISE1: fullinst->Instruction.Opcode = TGSI_OPCODE_NOISE1; break; case OPCODE_NOISE2: fullinst->Instruction.Opcode = TGSI_OPCODE_NOISE2; break; case OPCODE_NOISE3: fullinst->Instruction.Opcode = TGSI_OPCODE_NOISE3; break; case OPCODE_NOISE4: fullinst->Instruction.Opcode = TGSI_OPCODE_NOISE4; break; case OPCODE_NOP: fullinst->Instruction.Opcode = TGSI_OPCODE_NOP; break; case OPCODE_NRM3: fullinst->Instruction.Opcode = TGSI_OPCODE_NRM; break; case OPCODE_NRM4: fullinst->Instruction.Opcode = TGSI_OPCODE_NRM4; break; case OPCODE_POW: fullinst->Instruction.Opcode = TGSI_OPCODE_POW; break; case OPCODE_RCP: fullinst->Instruction.Opcode = TGSI_OPCODE_RCP; break; case OPCODE_RET: /* If RET is used inside main (not a real subroutine) we may want * to execute END instead of RET. TBD... */ if (1 /* *insideSubroutine */) { fullinst->Instruction.Opcode = TGSI_OPCODE_RET; } else { /* inside main() pseudo-function */ fullinst->Instruction.Opcode = TGSI_OPCODE_END; } break; case OPCODE_RSQ: fullinst->Instruction.Opcode = TGSI_OPCODE_RSQ; break; case OPCODE_SCS: fullinst->Instruction.Opcode = TGSI_OPCODE_SCS; fulldst->DstRegister.WriteMask &= TGSI_WRITEMASK_XY; break; case OPCODE_SEQ: fullinst->Instruction.Opcode = TGSI_OPCODE_SEQ; break; case OPCODE_SGE: fullinst->Instruction.Opcode = TGSI_OPCODE_SGE; break; case OPCODE_SGT: fullinst->Instruction.Opcode = TGSI_OPCODE_SGT; break; case OPCODE_SIN: fullinst->Instruction.Opcode = TGSI_OPCODE_SIN; break; case OPCODE_SLE: fullinst->Instruction.Opcode = TGSI_OPCODE_SLE; break; case OPCODE_SLT: fullinst->Instruction.Opcode = TGSI_OPCODE_SLT; break; case OPCODE_SNE: fullinst->Instruction.Opcode = TGSI_OPCODE_SNE; break; case OPCODE_SSG: fullinst->Instruction.Opcode = TGSI_OPCODE_SSG; break; case OPCODE_SUB: fullinst->Instruction.Opcode = TGSI_OPCODE_SUB; break; case OPCODE_SWZ: fullinst->Instruction.Opcode = TGSI_OPCODE_SWZ; break; case OPCODE_TEX: /* ordinary texture lookup */ fullinst->Instruction.Opcode = TGSI_OPCODE_TEX; fullinst->Instruction.NumSrcRegs = 2; fullinst->InstructionExtTexture.Texture = map_texture_target( inst->TexSrcTarget, inst->TexShadow ); fullinst->FullSrcRegisters[1].SrcRegister.File = TGSI_FILE_SAMPLER; fullinst->FullSrcRegisters[1].SrcRegister.Index = inst->TexSrcUnit; break; case OPCODE_TXB: /* texture lookup with LOD bias */ fullinst->Instruction.Opcode = TGSI_OPCODE_TXB; fullinst->Instruction.NumSrcRegs = 2; fullinst->InstructionExtTexture.Texture = map_texture_target( inst->TexSrcTarget, inst->TexShadow ); fullinst->FullSrcRegisters[1].SrcRegister.File = TGSI_FILE_SAMPLER; fullinst->FullSrcRegisters[1].SrcRegister.Index = inst->TexSrcUnit; break; case OPCODE_TXD: /* texture lookup with explicit partial derivatives */ fullinst->Instruction.Opcode = TGSI_OPCODE_TXD; fullinst->Instruction.NumSrcRegs = 4; fullinst->InstructionExtTexture.Texture = map_texture_target( inst->TexSrcTarget, inst->TexShadow ); /* src[0] = coord, src[1] = d[strq]/dx, src[2] = d[strq]/dy */ fullinst->FullSrcRegisters[3].SrcRegister.File = TGSI_FILE_SAMPLER; fullinst->FullSrcRegisters[3].SrcRegister.Index = inst->TexSrcUnit; break; case OPCODE_TXL: /* texture lookup with explicit LOD */ fullinst->Instruction.Opcode = TGSI_OPCODE_TXL; fullinst->Instruction.NumSrcRegs = 2; fullinst->InstructionExtTexture.Texture = map_texture_target( inst->TexSrcTarget, inst->TexShadow ); fullinst->FullSrcRegisters[1].SrcRegister.File = TGSI_FILE_SAMPLER; fullinst->FullSrcRegisters[1].SrcRegister.Index = inst->TexSrcUnit; break; case OPCODE_TXP: /* texture lookup with divide by Q component */ /* convert to TEX w/ special flag for division */ fullinst->Instruction.Opcode = TGSI_OPCODE_TXP; fullinst->Instruction.NumSrcRegs = 2; fullinst->InstructionExtTexture.Texture = map_texture_target( inst->TexSrcTarget, inst->TexShadow ); fullinst->FullSrcRegisters[1].SrcRegister.File = TGSI_FILE_SAMPLER; fullinst->FullSrcRegisters[1].SrcRegister.Index = inst->TexSrcUnit; break; case OPCODE_XPD: fullinst->Instruction.Opcode = TGSI_OPCODE_XPD; fulldst->DstRegister.WriteMask &= TGSI_WRITEMASK_XYZ; break; case OPCODE_END: fullinst->Instruction.Opcode = TGSI_OPCODE_END; break; default: assert( 0 ); } }
/** * TGSI transform callback. * Insert new declarations and instructions before first instruction. */ static void aa_transform_prolog(struct tgsi_transform_context *ctx) { /* emit our new declarations before the first instruction */ struct aa_transform_context *aactx = (struct aa_transform_context *) ctx; struct tgsi_full_instruction newInst; const int texInput = aactx->maxInput + 1; int tmp0; uint i; /* find two free temp regs */ for (i = 0; i < 32; i++) { if ((aactx->tempsUsed & (1 << i)) == 0) { /* found a free temp */ if (aactx->tmp0 < 0) aactx->tmp0 = i; else if (aactx->colorTemp < 0) aactx->colorTemp = i; else break; } } assert(aactx->colorTemp != aactx->tmp0); tmp0 = aactx->tmp0; /* declare new generic input/texcoord */ tgsi_transform_input_decl(ctx, texInput, TGSI_SEMANTIC_GENERIC, aactx->maxGeneric + 1, TGSI_INTERPOLATE_LINEAR); /* declare new temp regs */ tgsi_transform_temp_decl(ctx, tmp0); tgsi_transform_temp_decl(ctx, aactx->colorTemp); /* * Emit code to compute fragment coverage, kill if outside point radius * * Temp reg0 usage: * t0.x = distance of fragment from center point * t0.y = boolean, is t0.x > 1.0, also misc temp usage * t0.z = temporary for computing 1/(1-k) value * t0.w = final coverage value */ /* MUL t0.xy, tex, tex; # compute x^2, y^2 */ tgsi_transform_op2_inst(ctx, TGSI_OPCODE_MUL, TGSI_FILE_TEMPORARY, tmp0, TGSI_WRITEMASK_XY, TGSI_FILE_INPUT, texInput, TGSI_FILE_INPUT, texInput); /* ADD t0.x, t0.x, t0.y; # x^2 + y^2 */ tgsi_transform_op2_swz_inst(ctx, TGSI_OPCODE_ADD, TGSI_FILE_TEMPORARY, tmp0, TGSI_WRITEMASK_X, TGSI_FILE_TEMPORARY, tmp0, TGSI_SWIZZLE_X, TGSI_FILE_TEMPORARY, tmp0, TGSI_SWIZZLE_Y); #if NORMALIZE /* OPTIONAL normalization of length */ /* RSQ t0.x, t0.x; */ tgsi_transform_op1_inst(ctx, TGSI_OPCODE_RSQ, TGSI_FILE_TEMPORARY, tmp0, TGSI_WRITEMASK_X, TGSI_FILE_TEMPORARY, tmp0); /* RCP t0.x, t0.x; */ tgsi_transform_op1_inst(ctx, TGSI_OPCODE_RCP, TGSI_FILE_TEMPORARY, tmp0, TGSI_WRITEMASK_X, TGSI_FILE_TEMPORARY, tmp0); #endif /* SGT t0.y, t0.xxxx, tex.wwww; # bool b = d > 1 (NOTE tex.w == 1) */ tgsi_transform_op2_swz_inst(ctx, TGSI_OPCODE_SGT, TGSI_FILE_TEMPORARY, tmp0, TGSI_WRITEMASK_Y, TGSI_FILE_TEMPORARY, tmp0, TGSI_SWIZZLE_X, TGSI_FILE_INPUT, texInput, TGSI_SWIZZLE_W); /* KILL_IF -tmp0.yyyy; # if -tmp0.y < 0, KILL */ tgsi_transform_kill_inst(ctx, TGSI_FILE_TEMPORARY, tmp0, TGSI_SWIZZLE_Y); /* compute coverage factor = (1-d)/(1-k) */ /* SUB t0.z, tex.w, tex.z; # m = 1 - k */ tgsi_transform_op2_swz_inst(ctx, TGSI_OPCODE_SUB, TGSI_FILE_TEMPORARY, tmp0, TGSI_WRITEMASK_Z, TGSI_FILE_INPUT, texInput, TGSI_SWIZZLE_W, TGSI_FILE_INPUT, texInput, TGSI_SWIZZLE_Z); /* RCP t0.z, t0.z; # t0.z = 1 / m */ newInst = tgsi_default_full_instruction(); newInst.Instruction.Opcode = TGSI_OPCODE_RCP; newInst.Instruction.NumDstRegs = 1; newInst.Dst[0].Register.File = TGSI_FILE_TEMPORARY; newInst.Dst[0].Register.Index = tmp0; newInst.Dst[0].Register.WriteMask = TGSI_WRITEMASK_Z; newInst.Instruction.NumSrcRegs = 1; newInst.Src[0].Register.File = TGSI_FILE_TEMPORARY; newInst.Src[0].Register.Index = tmp0; newInst.Src[0].Register.SwizzleX = TGSI_SWIZZLE_Z; ctx->emit_instruction(ctx, &newInst); /* SUB t0.y, 1, t0.x; # d = 1 - d */ tgsi_transform_op2_swz_inst(ctx, TGSI_OPCODE_SUB, TGSI_FILE_TEMPORARY, tmp0, TGSI_WRITEMASK_Y, TGSI_FILE_INPUT, texInput, TGSI_SWIZZLE_W, TGSI_FILE_TEMPORARY, tmp0, TGSI_SWIZZLE_X); /* MUL t0.w, t0.y, t0.z; # coverage = d * m */ tgsi_transform_op2_swz_inst(ctx, TGSI_OPCODE_MUL, TGSI_FILE_TEMPORARY, tmp0, TGSI_WRITEMASK_W, TGSI_FILE_TEMPORARY, tmp0, TGSI_SWIZZLE_Y, TGSI_FILE_TEMPORARY, tmp0, TGSI_SWIZZLE_Z); /* SLE t0.y, t0.x, tex.z; # bool b = distance <= k */ tgsi_transform_op2_swz_inst(ctx, TGSI_OPCODE_SLE, TGSI_FILE_TEMPORARY, tmp0, TGSI_WRITEMASK_Y, TGSI_FILE_TEMPORARY, tmp0, TGSI_SWIZZLE_X, TGSI_FILE_INPUT, texInput, TGSI_SWIZZLE_Z); /* CMP t0.w, -t0.y, tex.w, t0.w; * # if -t0.y < 0 then * t0.w = 1 * else * t0.w = t0.w */ tgsi_transform_op3_swz_inst(ctx, TGSI_OPCODE_CMP, TGSI_FILE_TEMPORARY, tmp0, TGSI_WRITEMASK_W, TGSI_FILE_TEMPORARY, tmp0, TGSI_SWIZZLE_Y, 1, TGSI_FILE_INPUT, texInput, TGSI_SWIZZLE_W, TGSI_FILE_TEMPORARY, tmp0, TGSI_SWIZZLE_W); }
static boolean parse_instruction( struct translate_ctx *ctx, boolean has_label ) { uint i; uint saturate = 0; uint precise = 0; const struct tgsi_opcode_info *info; struct tgsi_full_instruction inst; const char *cur; uint advance; inst = tgsi_default_full_instruction(); /* Parse instruction name. */ eat_opt_white( &ctx->cur ); for (i = 0; i < TGSI_OPCODE_LAST; i++) { cur = ctx->cur; info = tgsi_get_opcode_info( i ); if (match_inst(&cur, &saturate, &precise, info)) { if (info->num_dst + info->num_src + info->is_tex == 0) { ctx->cur = cur; break; } else if (*cur == '\0' || eat_white( &cur )) { ctx->cur = cur; break; } } } if (i == TGSI_OPCODE_LAST) { if (has_label) report_error( ctx, "Unknown opcode" ); else report_error( ctx, "Expected `DCL', `IMM' or a label" ); return FALSE; } inst.Instruction.Opcode = i; inst.Instruction.Saturate = saturate; inst.Instruction.Precise = precise; inst.Instruction.NumDstRegs = info->num_dst; inst.Instruction.NumSrcRegs = info->num_src; if (i >= TGSI_OPCODE_SAMPLE && i <= TGSI_OPCODE_GATHER4) { /* * These are not considered tex opcodes here (no additional * target argument) however we're required to set the Texture * bit so we can set the number of tex offsets. */ inst.Instruction.Texture = 1; inst.Texture.Texture = TGSI_TEXTURE_UNKNOWN; } if ((i >= TGSI_OPCODE_LOAD && i <= TGSI_OPCODE_ATOMIMAX) || i == TGSI_OPCODE_RESQ) { inst.Instruction.Memory = 1; inst.Memory.Qualifier = 0; } assume(info->num_dst <= TGSI_FULL_MAX_DST_REGISTERS); assume(info->num_src <= TGSI_FULL_MAX_SRC_REGISTERS); /* Parse instruction operands. */ for (i = 0; i < info->num_dst + info->num_src + info->is_tex; i++) { if (i > 0) { eat_opt_white( &ctx->cur ); if (*ctx->cur != ',') { report_error( ctx, "Expected `,'" ); return FALSE; } ctx->cur++; eat_opt_white( &ctx->cur ); } if (i < info->num_dst) { if (!parse_dst_operand( ctx, &inst.Dst[i] )) return FALSE; } else if (i < info->num_dst + info->num_src) { if (!parse_src_operand( ctx, &inst.Src[i - info->num_dst] )) return FALSE; } else { uint j; for (j = 0; j < TGSI_TEXTURE_COUNT; j++) { if (str_match_nocase_whole( &ctx->cur, tgsi_texture_names[j] )) { inst.Instruction.Texture = 1; inst.Texture.Texture = j; break; } } if (j == TGSI_TEXTURE_COUNT) { report_error( ctx, "Expected texture target" ); return FALSE; } } } cur = ctx->cur; eat_opt_white( &cur ); for (i = 0; inst.Instruction.Texture && *cur == ',' && i < TGSI_FULL_MAX_TEX_OFFSETS; i++) { cur++; eat_opt_white( &cur ); ctx->cur = cur; if (!parse_texoffset_operand( ctx, &inst.TexOffsets[i] )) return FALSE; cur = ctx->cur; eat_opt_white( &cur ); } inst.Texture.NumOffsets = i; cur = ctx->cur; eat_opt_white(&cur); for (; inst.Instruction.Memory && *cur == ','; ctx->cur = cur, eat_opt_white(&cur)) { int j; cur++; eat_opt_white(&cur); j = str_match_name_from_array(&cur, tgsi_memory_names, ARRAY_SIZE(tgsi_memory_names)); if (j >= 0) { inst.Memory.Qualifier |= 1U << j; continue; } j = str_match_name_from_array(&cur, tgsi_texture_names, ARRAY_SIZE(tgsi_texture_names)); if (j >= 0) { inst.Memory.Texture = j; continue; } j = str_match_format(&cur); if (j >= 0) { inst.Memory.Format = j; continue; } ctx->cur = cur; report_error(ctx, "Expected memory qualifier, texture target, or format\n"); return FALSE; } cur = ctx->cur; eat_opt_white( &cur ); if (info->is_branch && *cur == ':') { uint target; cur++; eat_opt_white( &cur ); if (!parse_uint( &cur, &target )) { report_error( ctx, "Expected a label" ); return FALSE; } inst.Instruction.Label = 1; inst.Label.Label = target; ctx->cur = cur; } advance = tgsi_build_full_instruction( &inst, ctx->tokens_cur, ctx->header, (uint) (ctx->tokens_end - ctx->tokens_cur) ); if (advance == 0) return FALSE; ctx->tokens_cur += advance; return TRUE; }