1 /**************************************************************************
2  *
3  * Copyright 2008 VMware, Inc.
4  * All Rights Reserved.
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a
7  * copy of this software and associated documentation files (the
8  * "Software"), to deal in the Software without restriction, including
9  * without limitation the rights to use, copy, modify, merge, publish,
10  * distribute, sub license, and/or sell copies of the Software, and to
11  * permit persons to whom the Software is furnished to do so, subject to
12  * the following conditions:
13  *
14  * The above copyright notice and this permission notice (including the
15  * next paragraph) shall be included in all copies or substantial portions
16  * of the Software.
17  *
18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21  * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
22  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25  *
26  **************************************************************************/
27 
28 #ifndef TGSI_TRANSFORM_H
29 #define TGSI_TRANSFORM_H
30 
31 
32 #include "pipe/p_shader_tokens.h"
33 #include "tgsi/tgsi_parse.h"
34 #include "tgsi/tgsi_build.h"
35 
36 
37 
38 /**
39  * Subclass this to add caller-specific data
40  */
41 struct tgsi_transform_context
42 {
43 /**** PUBLIC ***/
44 
45    /**
46     * User-defined callbacks invoked per instruction.
47     */
48    void (*transform_instruction)(struct tgsi_transform_context *ctx,
49                                  struct tgsi_full_instruction *inst);
50 
51    void (*transform_declaration)(struct tgsi_transform_context *ctx,
52                                  struct tgsi_full_declaration *decl);
53 
54    void (*transform_immediate)(struct tgsi_transform_context *ctx,
55                                struct tgsi_full_immediate *imm);
56    void (*transform_property)(struct tgsi_transform_context *ctx,
57                               struct tgsi_full_property *prop);
58 
59    /**
60     * Called after last declaration, before first instruction.  This is
61     * where the user might insert new declarations and/or instructions.
62     */
63    void (*prolog)(struct tgsi_transform_context *ctx);
64 
65    /**
66     * Called at end of input program to allow caller to append extra
67     * instructions.  Return number of tokens emitted.
68     */
69    void (*epilog)(struct tgsi_transform_context *ctx);
70 
71 
72 /*** PRIVATE ***/
73 
74    /**
75     * These are setup by tgsi_transform_shader() and cannot be overridden.
76     * Meant to be called from in the above user callback functions.
77     */
78    void (*emit_instruction)(struct tgsi_transform_context *ctx,
79                             const struct tgsi_full_instruction *inst);
80    void (*emit_declaration)(struct tgsi_transform_context *ctx,
81                             const struct tgsi_full_declaration *decl);
82    void (*emit_immediate)(struct tgsi_transform_context *ctx,
83                           const struct tgsi_full_immediate *imm);
84    void (*emit_property)(struct tgsi_transform_context *ctx,
85                          const struct tgsi_full_property *prop);
86 
87    struct tgsi_header *header;
88    uint max_tokens_out;
89    struct tgsi_token *tokens_out;
90    uint ti;
91 };
92 
93 
94 /**
95  * Helper for emitting temporary register declarations.
96  */
97 static inline void
tgsi_transform_temps_decl(struct tgsi_transform_context * ctx,unsigned firstIdx,unsigned lastIdx)98 tgsi_transform_temps_decl(struct tgsi_transform_context *ctx,
99                           unsigned firstIdx, unsigned lastIdx)
100 {
101    struct tgsi_full_declaration decl;
102 
103    decl = tgsi_default_full_declaration();
104    decl.Declaration.File = TGSI_FILE_TEMPORARY;
105    decl.Range.First = firstIdx;
106    decl.Range.Last = lastIdx;
107    ctx->emit_declaration(ctx, &decl);
108 }
109 
110 static inline void
tgsi_transform_temp_decl(struct tgsi_transform_context * ctx,unsigned index)111 tgsi_transform_temp_decl(struct tgsi_transform_context *ctx,
112                          unsigned index)
113 {
114    tgsi_transform_temps_decl(ctx, index, index);
115 }
116 
117 static inline void
tgsi_transform_const_decl(struct tgsi_transform_context * ctx,unsigned firstIdx,unsigned lastIdx)118 tgsi_transform_const_decl(struct tgsi_transform_context *ctx,
119                           unsigned firstIdx, unsigned lastIdx)
120 {
121    struct tgsi_full_declaration decl;
122 
123    decl = tgsi_default_full_declaration();
124    decl.Declaration.File = TGSI_FILE_CONSTANT;
125    decl.Range.First = firstIdx;
126    decl.Range.Last = lastIdx;
127    decl.Declaration.Dimension = 1;
128    /* Dim.Index2D is already 0 */
129    ctx->emit_declaration(ctx, &decl);
130 }
131 
132 static inline void
tgsi_transform_input_decl(struct tgsi_transform_context * ctx,unsigned index,unsigned sem_name,unsigned sem_index,unsigned interp)133 tgsi_transform_input_decl(struct tgsi_transform_context *ctx,
134                           unsigned index,
135                           unsigned sem_name, unsigned sem_index,
136                           unsigned interp)
137 {
138    struct tgsi_full_declaration decl;
139 
140    decl = tgsi_default_full_declaration();
141    decl.Declaration.File = TGSI_FILE_INPUT;
142    decl.Declaration.Interpolate = 1;
143    decl.Declaration.Semantic = 1;
144    decl.Semantic.Name = sem_name;
145    decl.Semantic.Index = sem_index;
146    decl.Range.First =
147    decl.Range.Last = index;
148    decl.Interp.Interpolate = interp;
149 
150    ctx->emit_declaration(ctx, &decl);
151 }
152 
153 static inline void
tgsi_transform_output_decl(struct tgsi_transform_context * ctx,unsigned index,unsigned sem_name,unsigned sem_index,unsigned interp)154 tgsi_transform_output_decl(struct tgsi_transform_context *ctx,
155                           unsigned index,
156                           unsigned sem_name, unsigned sem_index,
157                           unsigned interp)
158 {
159    struct tgsi_full_declaration decl;
160 
161    decl = tgsi_default_full_declaration();
162    decl.Declaration.File = TGSI_FILE_OUTPUT;
163    decl.Declaration.Interpolate = 1;
164    decl.Declaration.Semantic = 1;
165    decl.Semantic.Name = sem_name;
166    decl.Semantic.Index = sem_index;
167    decl.Range.First =
168    decl.Range.Last = index;
169    decl.Interp.Interpolate = interp;
170 
171    ctx->emit_declaration(ctx, &decl);
172 }
173 
174 static inline void
tgsi_transform_sampler_decl(struct tgsi_transform_context * ctx,unsigned index)175 tgsi_transform_sampler_decl(struct tgsi_transform_context *ctx,
176                             unsigned index)
177 {
178    struct tgsi_full_declaration decl;
179 
180    decl = tgsi_default_full_declaration();
181    decl.Declaration.File = TGSI_FILE_SAMPLER;
182    decl.Range.First =
183    decl.Range.Last = index;
184    ctx->emit_declaration(ctx, &decl);
185 }
186 
187 static inline void
tgsi_transform_sampler_view_decl(struct tgsi_transform_context * ctx,unsigned index,unsigned target,enum tgsi_return_type type)188 tgsi_transform_sampler_view_decl(struct tgsi_transform_context *ctx,
189                                  unsigned index,
190                                  unsigned target,
191                                  enum tgsi_return_type type)
192 {
193    struct tgsi_full_declaration decl;
194 
195    decl = tgsi_default_full_declaration();
196    decl.Declaration.File = TGSI_FILE_SAMPLER_VIEW;
197    decl.Declaration.UsageMask = TGSI_WRITEMASK_XYZW;
198    decl.Range.First =
199    decl.Range.Last = index;
200    decl.SamplerView.Resource = target;
201    decl.SamplerView.ReturnTypeX = type;
202    decl.SamplerView.ReturnTypeY = type;
203    decl.SamplerView.ReturnTypeZ = type;
204    decl.SamplerView.ReturnTypeW = type;
205 
206    ctx->emit_declaration(ctx, &decl);
207 }
208 
209 static inline void
tgsi_transform_immediate_decl(struct tgsi_transform_context * ctx,float x,float y,float z,float w)210 tgsi_transform_immediate_decl(struct tgsi_transform_context *ctx,
211                               float x, float y, float z, float w)
212 {
213    struct tgsi_full_immediate immed;
214    unsigned size = 4;
215 
216    immed = tgsi_default_full_immediate();
217    immed.Immediate.NrTokens = 1 + size; /* one for the token itself */
218    immed.u[0].Float = x;
219    immed.u[1].Float = y;
220    immed.u[2].Float = z;
221    immed.u[3].Float = w;
222 
223    ctx->emit_immediate(ctx, &immed);
224 }
225 
226 static inline void
tgsi_transform_dst_reg(struct tgsi_full_dst_register * reg,unsigned file,unsigned index,unsigned writemask)227 tgsi_transform_dst_reg(struct tgsi_full_dst_register *reg,
228                        unsigned file, unsigned index, unsigned writemask)
229 {
230    reg->Register.File = file;
231    reg->Register.Index = index;
232    reg->Register.WriteMask = writemask;
233 }
234 
235 static inline void
tgsi_transform_src_reg_xyzw(struct tgsi_full_src_register * reg,unsigned file,unsigned index)236 tgsi_transform_src_reg_xyzw(struct tgsi_full_src_register *reg,
237                             unsigned file, unsigned index)
238 {
239    reg->Register.File = file;
240    reg->Register.Index = index;
241    if (file == TGSI_FILE_CONSTANT) {
242       reg->Register.Dimension = 1;
243       reg->Dimension.Index = 0;
244    }
245 }
246 
247 static inline void
tgsi_transform_src_reg(struct tgsi_full_src_register * reg,unsigned file,unsigned index,unsigned swizzleX,unsigned swizzleY,unsigned swizzleZ,unsigned swizzleW)248 tgsi_transform_src_reg(struct tgsi_full_src_register *reg,
249                        unsigned file, unsigned index,
250                        unsigned swizzleX, unsigned swizzleY,
251                        unsigned swizzleZ, unsigned swizzleW)
252 {
253    reg->Register.File = file;
254    reg->Register.Index = index;
255    if (file == TGSI_FILE_CONSTANT) {
256       reg->Register.Dimension = 1;
257       reg->Dimension.Index = 0;
258    }
259    reg->Register.SwizzleX = swizzleX;
260    reg->Register.SwizzleY = swizzleY;
261    reg->Register.SwizzleZ = swizzleZ;
262    reg->Register.SwizzleW = swizzleW;
263 }
264 
265 /**
266  * Helper for emitting 1-operand instructions.
267  */
268 static inline void
tgsi_transform_op1_inst(struct tgsi_transform_context * ctx,unsigned opcode,unsigned dst_file,unsigned dst_index,unsigned dst_writemask,unsigned src0_file,unsigned src0_index)269 tgsi_transform_op1_inst(struct tgsi_transform_context *ctx,
270                         unsigned opcode,
271                         unsigned dst_file,
272                         unsigned dst_index,
273                         unsigned dst_writemask,
274                         unsigned src0_file,
275                         unsigned src0_index)
276 {
277    struct tgsi_full_instruction inst;
278 
279    inst = tgsi_default_full_instruction();
280    inst.Instruction.Opcode = opcode;
281    inst.Instruction.NumDstRegs = 1;
282    inst.Dst[0].Register.File = dst_file,
283    inst.Dst[0].Register.Index = dst_index;
284    inst.Dst[0].Register.WriteMask = dst_writemask;
285    inst.Instruction.NumSrcRegs = 1;
286    tgsi_transform_src_reg_xyzw(&inst.Src[0], src0_file, src0_index);
287 
288    ctx->emit_instruction(ctx, &inst);
289 }
290 
291 
292 static inline void
tgsi_transform_op2_inst(struct tgsi_transform_context * ctx,unsigned opcode,unsigned dst_file,unsigned dst_index,unsigned dst_writemask,unsigned src0_file,unsigned src0_index,unsigned src1_file,unsigned src1_index,bool src1_negate)293 tgsi_transform_op2_inst(struct tgsi_transform_context *ctx,
294                         unsigned opcode,
295                         unsigned dst_file,
296                         unsigned dst_index,
297                         unsigned dst_writemask,
298                         unsigned src0_file,
299                         unsigned src0_index,
300                         unsigned src1_file,
301                         unsigned src1_index,
302                         bool src1_negate)
303 {
304    struct tgsi_full_instruction inst;
305 
306    inst = tgsi_default_full_instruction();
307    inst.Instruction.Opcode = opcode;
308    inst.Instruction.NumDstRegs = 1;
309    inst.Dst[0].Register.File = dst_file,
310    inst.Dst[0].Register.Index = dst_index;
311    inst.Dst[0].Register.WriteMask = dst_writemask;
312    inst.Instruction.NumSrcRegs = 2;
313    tgsi_transform_src_reg_xyzw(&inst.Src[0], src0_file, src0_index);
314    tgsi_transform_src_reg_xyzw(&inst.Src[1], src1_file, src1_index);
315    inst.Src[1].Register.Negate = src1_negate;
316 
317    ctx->emit_instruction(ctx, &inst);
318 }
319 
320 
321 static inline void
tgsi_transform_op3_inst(struct tgsi_transform_context * ctx,unsigned opcode,unsigned dst_file,unsigned dst_index,unsigned dst_writemask,unsigned src0_file,unsigned src0_index,unsigned src1_file,unsigned src1_index,unsigned src2_file,unsigned src2_index)322 tgsi_transform_op3_inst(struct tgsi_transform_context *ctx,
323                         unsigned opcode,
324                         unsigned dst_file,
325                         unsigned dst_index,
326                         unsigned dst_writemask,
327                         unsigned src0_file,
328                         unsigned src0_index,
329                         unsigned src1_file,
330                         unsigned src1_index,
331                         unsigned src2_file,
332                         unsigned src2_index)
333 {
334    struct tgsi_full_instruction inst;
335 
336    inst = tgsi_default_full_instruction();
337    inst.Instruction.Opcode = opcode;
338    inst.Instruction.NumDstRegs = 1;
339    inst.Dst[0].Register.File = dst_file,
340    inst.Dst[0].Register.Index = dst_index;
341    inst.Dst[0].Register.WriteMask = dst_writemask;
342    inst.Instruction.NumSrcRegs = 3;
343    tgsi_transform_src_reg_xyzw(&inst.Src[0], src0_file, src0_index);
344    tgsi_transform_src_reg_xyzw(&inst.Src[1], src1_file, src1_index);
345    tgsi_transform_src_reg_xyzw(&inst.Src[2], src2_file, src2_index);
346 
347    ctx->emit_instruction(ctx, &inst);
348 }
349 
350 
351 
352 static inline void
tgsi_transform_op1_swz_inst(struct tgsi_transform_context * ctx,unsigned opcode,unsigned dst_file,unsigned dst_index,unsigned dst_writemask,unsigned src0_file,unsigned src0_index,unsigned src0_swizzle)353 tgsi_transform_op1_swz_inst(struct tgsi_transform_context *ctx,
354                             unsigned opcode,
355                             unsigned dst_file,
356                             unsigned dst_index,
357                             unsigned dst_writemask,
358                             unsigned src0_file,
359                             unsigned src0_index,
360                             unsigned src0_swizzle)
361 {
362    struct tgsi_full_instruction inst;
363 
364    inst = tgsi_default_full_instruction();
365    inst.Instruction.Opcode = opcode;
366    inst.Instruction.NumDstRegs = 1;
367    inst.Dst[0].Register.File = dst_file,
368    inst.Dst[0].Register.Index = dst_index;
369    inst.Dst[0].Register.WriteMask = dst_writemask;
370    inst.Instruction.NumSrcRegs = 1;
371    tgsi_transform_src_reg_xyzw(&inst.Src[0], src0_file, src0_index);
372    switch (dst_writemask) {
373    case TGSI_WRITEMASK_X:
374       inst.Src[0].Register.SwizzleX = src0_swizzle;
375       break;
376    case TGSI_WRITEMASK_Y:
377       inst.Src[0].Register.SwizzleY = src0_swizzle;
378       break;
379    case TGSI_WRITEMASK_Z:
380       inst.Src[0].Register.SwizzleZ = src0_swizzle;
381       break;
382    case TGSI_WRITEMASK_W:
383       inst.Src[0].Register.SwizzleW = src0_swizzle;
384       break;
385    default:
386       ; /* nothing */
387    }
388 
389    ctx->emit_instruction(ctx, &inst);
390 }
391 
392 
393 static inline void
tgsi_transform_op2_swz_inst(struct tgsi_transform_context * ctx,unsigned opcode,unsigned dst_file,unsigned dst_index,unsigned dst_writemask,unsigned src0_file,unsigned src0_index,unsigned src0_swizzle,unsigned src1_file,unsigned src1_index,unsigned src1_swizzle,bool src1_negate)394 tgsi_transform_op2_swz_inst(struct tgsi_transform_context *ctx,
395                             unsigned opcode,
396                             unsigned dst_file,
397                             unsigned dst_index,
398                             unsigned dst_writemask,
399                             unsigned src0_file,
400                             unsigned src0_index,
401                             unsigned src0_swizzle,
402                             unsigned src1_file,
403                             unsigned src1_index,
404                             unsigned src1_swizzle,
405                             bool src1_negate)
406 {
407    struct tgsi_full_instruction inst;
408 
409    inst = tgsi_default_full_instruction();
410    inst.Instruction.Opcode = opcode;
411    inst.Instruction.NumDstRegs = 1;
412    inst.Dst[0].Register.File = dst_file,
413    inst.Dst[0].Register.Index = dst_index;
414    inst.Dst[0].Register.WriteMask = dst_writemask;
415    inst.Instruction.NumSrcRegs = 2;
416    tgsi_transform_src_reg_xyzw(&inst.Src[0], src0_file, src0_index);
417    tgsi_transform_src_reg_xyzw(&inst.Src[1], src1_file, src1_index);
418    inst.Src[1].Register.Negate = src1_negate;
419    switch (dst_writemask) {
420    case TGSI_WRITEMASK_X:
421       inst.Src[0].Register.SwizzleX = src0_swizzle;
422       inst.Src[1].Register.SwizzleX = src1_swizzle;
423       break;
424    case TGSI_WRITEMASK_Y:
425       inst.Src[0].Register.SwizzleY = src0_swizzle;
426       inst.Src[1].Register.SwizzleY = src1_swizzle;
427       break;
428    case TGSI_WRITEMASK_Z:
429       inst.Src[0].Register.SwizzleZ = src0_swizzle;
430       inst.Src[1].Register.SwizzleZ = src1_swizzle;
431       break;
432    case TGSI_WRITEMASK_W:
433       inst.Src[0].Register.SwizzleW = src0_swizzle;
434       inst.Src[1].Register.SwizzleW = src1_swizzle;
435       break;
436    default:
437       ; /* nothing */
438    }
439 
440    ctx->emit_instruction(ctx, &inst);
441 }
442 
443 
444 static inline void
tgsi_transform_op3_swz_inst(struct tgsi_transform_context * ctx,unsigned opcode,unsigned dst_file,unsigned dst_index,unsigned dst_writemask,unsigned src0_file,unsigned src0_index,unsigned src0_swizzle,unsigned src0_negate,unsigned src1_file,unsigned src1_index,unsigned src1_swizzle,unsigned src2_file,unsigned src2_index,unsigned src2_swizzle)445 tgsi_transform_op3_swz_inst(struct tgsi_transform_context *ctx,
446                             unsigned opcode,
447                             unsigned dst_file,
448                             unsigned dst_index,
449                             unsigned dst_writemask,
450                             unsigned src0_file,
451                             unsigned src0_index,
452                             unsigned src0_swizzle,
453                             unsigned src0_negate,
454                             unsigned src1_file,
455                             unsigned src1_index,
456                             unsigned src1_swizzle,
457                             unsigned src2_file,
458                             unsigned src2_index,
459                             unsigned src2_swizzle)
460 {
461    struct tgsi_full_instruction inst;
462 
463    inst = tgsi_default_full_instruction();
464    inst.Instruction.Opcode = opcode;
465    inst.Instruction.NumDstRegs = 1;
466    inst.Dst[0].Register.File = dst_file,
467    inst.Dst[0].Register.Index = dst_index;
468    inst.Dst[0].Register.WriteMask = dst_writemask;
469    inst.Instruction.NumSrcRegs = 3;
470    tgsi_transform_src_reg_xyzw(&inst.Src[0], src0_file, src0_index);
471    inst.Src[0].Register.Negate = src0_negate;
472    tgsi_transform_src_reg_xyzw(&inst.Src[1], src1_file, src1_index);
473    tgsi_transform_src_reg_xyzw(&inst.Src[2], src2_file, src2_index);
474    switch (dst_writemask) {
475    case TGSI_WRITEMASK_X:
476       inst.Src[0].Register.SwizzleX = src0_swizzle;
477       inst.Src[1].Register.SwizzleX = src1_swizzle;
478       inst.Src[2].Register.SwizzleX = src2_swizzle;
479       break;
480    case TGSI_WRITEMASK_Y:
481       inst.Src[0].Register.SwizzleY = src0_swizzle;
482       inst.Src[1].Register.SwizzleY = src1_swizzle;
483       inst.Src[2].Register.SwizzleY = src2_swizzle;
484       break;
485    case TGSI_WRITEMASK_Z:
486       inst.Src[0].Register.SwizzleZ = src0_swizzle;
487       inst.Src[1].Register.SwizzleZ = src1_swizzle;
488       inst.Src[2].Register.SwizzleZ = src2_swizzle;
489       break;
490    case TGSI_WRITEMASK_W:
491       inst.Src[0].Register.SwizzleW = src0_swizzle;
492       inst.Src[1].Register.SwizzleW = src1_swizzle;
493       inst.Src[2].Register.SwizzleW = src2_swizzle;
494       break;
495    default:
496       ; /* nothing */
497    }
498 
499    ctx->emit_instruction(ctx, &inst);
500 }
501 
502 
503 static inline void
tgsi_transform_kill_inst(struct tgsi_transform_context * ctx,unsigned src_file,unsigned src_index,unsigned src_swizzle,boolean negate)504 tgsi_transform_kill_inst(struct tgsi_transform_context *ctx,
505                          unsigned src_file,
506                          unsigned src_index,
507                          unsigned src_swizzle,
508                          boolean negate)
509 {
510    struct tgsi_full_instruction inst;
511 
512    inst = tgsi_default_full_instruction();
513    inst.Instruction.Opcode = TGSI_OPCODE_KILL_IF;
514    inst.Instruction.NumDstRegs = 0;
515    inst.Instruction.NumSrcRegs = 1;
516    tgsi_transform_src_reg_xyzw(&inst.Src[0], src_file, src_index);
517    inst.Src[0].Register.SwizzleX =
518    inst.Src[0].Register.SwizzleY =
519    inst.Src[0].Register.SwizzleZ =
520    inst.Src[0].Register.SwizzleW = src_swizzle;
521    inst.Src[0].Register.Negate = negate;
522 
523    ctx->emit_instruction(ctx, &inst);
524 }
525 
526 
527 static inline void
tgsi_transform_tex_inst(struct tgsi_transform_context * ctx,unsigned dst_file,unsigned dst_index,unsigned src_file,unsigned src_index,unsigned tex_target,unsigned sampler_index)528 tgsi_transform_tex_inst(struct tgsi_transform_context *ctx,
529                         unsigned dst_file,
530                         unsigned dst_index,
531                         unsigned src_file,
532                         unsigned src_index,
533                         unsigned tex_target,
534                         unsigned sampler_index)
535 {
536    struct tgsi_full_instruction inst;
537 
538    assert(tex_target < TGSI_TEXTURE_COUNT);
539 
540    inst = tgsi_default_full_instruction();
541    inst.Instruction.Opcode = TGSI_OPCODE_TEX;
542    inst.Instruction.NumDstRegs = 1;
543    inst.Dst[0].Register.File = dst_file;
544    inst.Dst[0].Register.Index = dst_index;
545    inst.Instruction.NumSrcRegs = 2;
546    inst.Instruction.Texture = TRUE;
547    inst.Texture.Texture = tex_target;
548    tgsi_transform_src_reg_xyzw(&inst.Src[0], src_file, src_index);
549    tgsi_transform_src_reg_xyzw(&inst.Src[1], TGSI_FILE_SAMPLER, sampler_index);
550 
551    ctx->emit_instruction(ctx, &inst);
552 }
553 
554 
555 extern int
556 tgsi_transform_shader(const struct tgsi_token *tokens_in,
557                       struct tgsi_token *tokens_out,
558                       uint max_tokens_out,
559                       struct tgsi_transform_context *ctx);
560 
561 
562 #endif /* TGSI_TRANSFORM_H */
563