/** * \param usage_mask bitfield of TGSI_WRITEMASK_{XYZW} tokens */ static struct tgsi_full_declaration make_output_decl( GLuint index, GLuint semantic_name, GLuint semantic_index, GLuint usage_mask, GLbitfield output_flags) { struct tgsi_full_declaration decl; assert(semantic_name < TGSI_SEMANTIC_COUNT); decl = tgsi_default_full_declaration(); decl.Declaration.File = TGSI_FILE_OUTPUT; decl.Declaration.UsageMask = usage_mask; decl.Declaration.Semantic = 1; decl.DeclarationRange.First = index; decl.DeclarationRange.Last = index; decl.Semantic.SemanticName = semantic_name; decl.Semantic.SemanticIndex = semantic_index; if (output_flags & PROG_PARAM_BIT_CENTROID) decl.Declaration.Centroid = 1; if (output_flags & PROG_PARAM_BIT_INVARIANT) decl.Declaration.Invariant = 1; return decl; }
static void emit_temp(struct tgsi_transform_context *ctx, unsigned reg) { struct tgsi_full_declaration decl; decl = tgsi_default_full_declaration(); decl.Declaration.File = TGSI_FILE_TEMPORARY; decl.Range.First = decl.Range.Last = reg; ctx->emit_declaration(ctx, &decl); }
/** Reference into a constant buffer */ static struct tgsi_full_declaration make_constant_decl(GLuint first, GLuint last) { struct tgsi_full_declaration decl; decl = tgsi_default_full_declaration(); decl.Declaration.File = TGSI_FILE_CONSTANT; decl.DeclarationRange.First = first; decl.DeclarationRange.Last = last; return decl; }
static struct tgsi_full_declaration make_sampler_decl(GLuint index) { struct tgsi_full_declaration decl; decl = tgsi_default_full_declaration(); decl.Declaration.File = TGSI_FILE_SAMPLER; decl.DeclarationRange.First = index; decl.DeclarationRange.Last = index; return decl; }
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 struct tgsi_full_declaration make_temp_decl( GLuint start_index, GLuint end_index ) { struct tgsi_full_declaration decl; decl = tgsi_default_full_declaration(); decl.Declaration.File = TGSI_FILE_TEMPORARY; decl.DeclarationRange.First = start_index; decl.DeclarationRange.Last = end_index; return decl; }
static void emit_output(struct tgsi_transform_context *ctx, unsigned name, unsigned index, unsigned interp, unsigned reg) { struct vs_transform_context *vsctx = (struct vs_transform_context *)ctx; struct tgsi_full_declaration decl; decl = tgsi_default_full_declaration(); decl.Declaration.File = TGSI_FILE_OUTPUT; decl.Declaration.Interpolate = interp; decl.Declaration.Semantic = TRUE; decl.Semantic.Name = name; decl.Semantic.Index = index; decl.Range.First = decl.Range.Last = reg; ctx->emit_declaration(ctx, &decl); ++vsctx->num_outputs; }
static boolean parse_declaration( struct translate_ctx *ctx ) { struct tgsi_full_declaration decl; uint file; struct parsed_dcl_bracket brackets[2]; int num_brackets; uint writemask; const char *cur, *cur2; uint advance; boolean is_vs_input; if (!eat_white( &ctx->cur )) { report_error( ctx, "Syntax error" ); return FALSE; } if (!parse_register_dcl( ctx, &file, brackets, &num_brackets)) return FALSE; if (!parse_opt_writemask( ctx, &writemask )) return FALSE; decl = tgsi_default_full_declaration(); decl.Declaration.File = file; decl.Declaration.UsageMask = writemask; if (num_brackets == 1) { decl.Range.First = brackets[0].first; decl.Range.Last = brackets[0].last; } else { decl.Range.First = brackets[1].first; decl.Range.Last = brackets[1].last; decl.Declaration.Dimension = 1; decl.Dim.Index2D = brackets[0].first; } is_vs_input = (file == TGSI_FILE_INPUT && ctx->processor == TGSI_PROCESSOR_VERTEX); cur = ctx->cur; eat_opt_white( &cur ); if (*cur == ',') { cur2 = cur; cur2++; eat_opt_white( &cur2 ); if (str_match_nocase_whole( &cur2, "ARRAY" )) { int arrayid; if (*cur2 != '(') { report_error( ctx, "Expected `('" ); return FALSE; } cur2++; eat_opt_white( &cur2 ); if (!parse_int( &cur2, &arrayid )) { report_error( ctx, "Expected `,'" ); return FALSE; } eat_opt_white( &cur2 ); if (*cur2 != ')') { report_error( ctx, "Expected `)'" ); return FALSE; } cur2++; decl.Declaration.Array = 1; decl.Array.ArrayID = arrayid; ctx->cur = cur = cur2; } } if (*cur == ',' && !is_vs_input) { uint i, j; cur++; eat_opt_white( &cur ); if (file == TGSI_FILE_IMAGE) { for (i = 0; i < TGSI_TEXTURE_COUNT; i++) { if (str_match_nocase_whole(&cur, tgsi_texture_names[i])) { decl.Image.Resource = i; break; } } if (i == TGSI_TEXTURE_COUNT) { report_error(ctx, "Expected texture target"); return FALSE; } cur2 = cur; eat_opt_white(&cur2); while (*cur2 == ',') { cur2++; eat_opt_white(&cur2); if (str_match_nocase_whole(&cur2, "RAW")) { decl.Image.Raw = 1; } else if (str_match_nocase_whole(&cur2, "WR")) { decl.Image.Writable = 1; } else { for (i = 0; i < PIPE_FORMAT_COUNT; i++) { const struct util_format_description *desc = util_format_description(i); if (desc && str_match_nocase_whole(&cur2, desc->name)) { decl.Image.Format = i; break; } } if (i == PIPE_FORMAT_COUNT) break; } cur = cur2; eat_opt_white(&cur2); } ctx->cur = cur; } else if (file == TGSI_FILE_SAMPLER_VIEW) { for (i = 0; i < TGSI_TEXTURE_COUNT; i++) { if (str_match_nocase_whole(&cur, tgsi_texture_names[i])) { decl.SamplerView.Resource = i; break; } } if (i == TGSI_TEXTURE_COUNT) { report_error(ctx, "Expected texture target"); return FALSE; } eat_opt_white( &cur ); if (*cur != ',') { report_error( ctx, "Expected `,'" ); return FALSE; } ++cur; eat_opt_white( &cur ); for (j = 0; j < 4; ++j) { for (i = 0; i < TGSI_RETURN_TYPE_COUNT; ++i) { if (str_match_nocase_whole(&cur, tgsi_return_type_names[i])) { switch (j) { case 0: decl.SamplerView.ReturnTypeX = i; break; case 1: decl.SamplerView.ReturnTypeY = i; break; case 2: decl.SamplerView.ReturnTypeZ = i; break; case 3: decl.SamplerView.ReturnTypeW = i; break; default: assert(0); } break; } } if (i == TGSI_RETURN_TYPE_COUNT) { if (j == 0 || j > 2) { report_error(ctx, "Expected type name"); return FALSE; } break; } else { cur2 = cur; eat_opt_white( &cur2 ); if (*cur2 == ',') { cur2++; eat_opt_white( &cur2 ); cur = cur2; continue; } else break; } } if (j < 4) { decl.SamplerView.ReturnTypeY = decl.SamplerView.ReturnTypeZ = decl.SamplerView.ReturnTypeW = decl.SamplerView.ReturnTypeX; } ctx->cur = cur; } else if (file == TGSI_FILE_BUFFER) { if (str_match_nocase_whole(&cur, "ATOMIC")) { decl.Declaration.Atomic = 1; ctx->cur = cur; } } else if (file == TGSI_FILE_MEMORY) { if (str_match_nocase_whole(&cur, "SHARED")) { decl.Declaration.Shared = 1; ctx->cur = cur; } } else { if (str_match_nocase_whole(&cur, "LOCAL")) { decl.Declaration.Local = 1; ctx->cur = cur; } cur = ctx->cur; eat_opt_white( &cur ); if (*cur == ',') { cur++; eat_opt_white( &cur ); for (i = 0; i < TGSI_SEMANTIC_COUNT; i++) { if (str_match_nocase_whole(&cur, tgsi_semantic_names[i])) { uint index; cur2 = cur; eat_opt_white( &cur2 ); if (*cur2 == '[') { cur2++; eat_opt_white( &cur2 ); if (!parse_uint( &cur2, &index )) { report_error( ctx, "Expected literal integer" ); return FALSE; } eat_opt_white( &cur2 ); if (*cur2 != ']') { report_error( ctx, "Expected `]'" ); return FALSE; } cur2++; decl.Semantic.Index = index; cur = cur2; } decl.Declaration.Semantic = 1; decl.Semantic.Name = i; ctx->cur = cur; break; } } } } } cur = ctx->cur; eat_opt_white( &cur ); if (*cur == ',' && !is_vs_input) { uint i; cur++; eat_opt_white( &cur ); for (i = 0; i < TGSI_INTERPOLATE_COUNT; i++) { if (str_match_nocase_whole( &cur, tgsi_interpolate_names[i] )) { decl.Declaration.Interpolate = 1; decl.Interp.Interpolate = i; ctx->cur = cur; break; } } if (i == TGSI_INTERPOLATE_COUNT) { report_error( ctx, "Expected semantic or interpolate attribute" ); return FALSE; } } cur = ctx->cur; eat_opt_white( &cur ); if (*cur == ',' && !is_vs_input) { uint i; cur++; eat_opt_white( &cur ); for (i = 0; i < TGSI_INTERPOLATE_LOC_COUNT; i++) { if (str_match_nocase_whole( &cur, tgsi_interpolate_locations[i] )) { decl.Interp.Location = i; ctx->cur = cur; break; } } } advance = tgsi_build_full_declaration( &decl, ctx->tokens_cur, ctx->header, (uint) (ctx->tokens_end - ctx->tokens_cur) ); if (advance == 0) return FALSE; ctx->tokens_cur += advance; return TRUE; }
/** * 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 boolean parse_declaration( struct translate_ctx *ctx ) { struct tgsi_full_declaration decl; uint file; struct parsed_dcl_bracket brackets[2]; int num_brackets; uint writemask; const char *cur; uint advance; boolean is_vs_input; boolean is_imm_array; assert(Elements(semantic_names) == TGSI_SEMANTIC_COUNT); assert(Elements(interpolate_names) == TGSI_INTERPOLATE_COUNT); if (!eat_white( &ctx->cur )) { report_error( ctx, "Syntax error" ); return FALSE; } if (!parse_register_dcl( ctx, &file, brackets, &num_brackets)) return FALSE; if (!parse_opt_writemask( ctx, &writemask )) return FALSE; decl = tgsi_default_full_declaration(); decl.Declaration.File = file; decl.Declaration.UsageMask = writemask; if (num_brackets == 1) { decl.Range.First = brackets[0].first; decl.Range.Last = brackets[0].last; } else { decl.Range.First = brackets[1].first; decl.Range.Last = brackets[1].last; decl.Declaration.Dimension = 1; decl.Dim.Index2D = brackets[0].first; } is_vs_input = (file == TGSI_FILE_INPUT && ctx->processor == TGSI_PROCESSOR_VERTEX); is_imm_array = (file == TGSI_FILE_IMMEDIATE_ARRAY); cur = ctx->cur; eat_opt_white( &cur ); if (*cur == ',' && !is_vs_input) { uint i, j; cur++; eat_opt_white( &cur ); if (file == TGSI_FILE_RESOURCE) { for (i = 0; i < TGSI_TEXTURE_COUNT; i++) { if (str_match_no_case(&cur, texture_names[i])) { if (!is_digit_alpha_underscore(cur)) { decl.Resource.Resource = i; break; } } } if (i == TGSI_TEXTURE_COUNT) { report_error(ctx, "Expected texture target"); return FALSE; } eat_opt_white( &cur ); if (*cur != ',') { report_error( ctx, "Expected `,'" ); return FALSE; } ++cur; eat_opt_white( &cur ); for (j = 0; j < 4; ++j) { for (i = 0; i < PIPE_TYPE_COUNT; ++i) { if (str_match_no_case(&cur, type_names[i])) { if (!is_digit_alpha_underscore(cur)) { switch (j) { case 0: decl.Resource.ReturnTypeX = i; break; case 1: decl.Resource.ReturnTypeY = i; break; case 2: decl.Resource.ReturnTypeZ = i; break; case 3: decl.Resource.ReturnTypeW = i; break; default: assert(0); } break; } } } if (i == PIPE_TYPE_COUNT) { if (j == 0 || j > 2) { report_error(ctx, "Expected type name"); return FALSE; } break; } else { const char *cur2 = cur; eat_opt_white( &cur2 ); if (*cur2 == ',') { cur2++; eat_opt_white( &cur2 ); cur = cur2; continue; } else break; } } if (j < 4) { decl.Resource.ReturnTypeY = decl.Resource.ReturnTypeZ = decl.Resource.ReturnTypeW = decl.Resource.ReturnTypeX; } ctx->cur = cur; } else { for (i = 0; i < TGSI_SEMANTIC_COUNT; i++) { if (str_match_no_case( &cur, semantic_names[i] )) { const char *cur2 = cur; uint index; if (is_digit_alpha_underscore( cur )) continue; eat_opt_white( &cur2 ); if (*cur2 == '[') { cur2++; eat_opt_white( &cur2 ); if (!parse_uint( &cur2, &index )) { report_error( ctx, "Expected literal integer" ); return FALSE; } eat_opt_white( &cur2 ); if (*cur2 != ']') { report_error( ctx, "Expected `]'" ); return FALSE; } cur2++; decl.Semantic.Index = index; cur = cur2; } decl.Declaration.Semantic = 1; decl.Semantic.Name = i; ctx->cur = cur; break; } } } } else if (is_imm_array) { unsigned i; float *vals_itr; /* we have our immediate data */ if (*cur != '{') { report_error( ctx, "Immediate array without data" ); return FALSE; } ++cur; ctx->cur = cur; decl.ImmediateData.u = MALLOC(sizeof(union tgsi_immediate_data) * 4 * (decl.Range.Last + 1)); vals_itr = (float*)decl.ImmediateData.u; for (i = 0; i <= decl.Range.Last; ++i) { if (!parse_immediate_data(ctx, vals_itr)) { FREE(decl.ImmediateData.u); return FALSE; } vals_itr += 4; eat_opt_white( &ctx->cur ); if (*ctx->cur != ',') { if (i != decl.Range.Last) { report_error( ctx, "Not enough data in immediate array!" ); FREE(decl.ImmediateData.u); return FALSE; } } else ++ctx->cur; } eat_opt_white( &ctx->cur ); if (*ctx->cur != '}') { FREE(decl.ImmediateData.u); report_error( ctx, "Immediate array data missing closing '}'" ); return FALSE; } ++ctx->cur; } cur = ctx->cur; eat_opt_white( &cur ); if (*cur == ',' && !is_vs_input) { uint i; cur++; eat_opt_white( &cur ); for (i = 0; i < TGSI_INTERPOLATE_COUNT; i++) { if (str_match_no_case( &cur, interpolate_names[i] )) { if (is_digit_alpha_underscore( cur )) continue; decl.Declaration.Interpolate = i; ctx->cur = cur; break; } } if (i == TGSI_INTERPOLATE_COUNT) { report_error( ctx, "Expected semantic or interpolate attribute" ); return FALSE; } } advance = tgsi_build_full_declaration( &decl, ctx->tokens_cur, ctx->header, (uint) (ctx->tokens_end - ctx->tokens_cur) ); if (is_imm_array) FREE(decl.ImmediateData.u); if (advance == 0) return FALSE; ctx->tokens_cur += advance; return TRUE; }