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 */
41struct 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 */
97static inline void
98tgsi_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
110static inline void
111tgsi_transform_temp_decl(struct tgsi_transform_context *ctx,
112                         unsigned index)
113{
114   tgsi_transform_temps_decl(ctx, index, index);
115}
116
117static inline void
118tgsi_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   ctx->emit_declaration(ctx, &decl);
128}
129
130static inline void
131tgsi_transform_input_decl(struct tgsi_transform_context *ctx,
132                          unsigned index,
133                          unsigned sem_name, unsigned sem_index,
134                          unsigned interp)
135{
136   struct tgsi_full_declaration decl;
137
138   decl = tgsi_default_full_declaration();
139   decl.Declaration.File = TGSI_FILE_INPUT;
140   decl.Declaration.Interpolate = 1;
141   decl.Declaration.Semantic = 1;
142   decl.Semantic.Name = sem_name;
143   decl.Semantic.Index = sem_index;
144   decl.Range.First =
145   decl.Range.Last = index;
146   decl.Interp.Interpolate = interp;
147
148   ctx->emit_declaration(ctx, &decl);
149}
150
151static inline void
152tgsi_transform_output_decl(struct tgsi_transform_context *ctx,
153                          unsigned index,
154                          unsigned sem_name, unsigned sem_index,
155                          unsigned interp)
156{
157   struct tgsi_full_declaration decl;
158
159   decl = tgsi_default_full_declaration();
160   decl.Declaration.File = TGSI_FILE_OUTPUT;
161   decl.Declaration.Interpolate = 1;
162   decl.Declaration.Semantic = 1;
163   decl.Semantic.Name = sem_name;
164   decl.Semantic.Index = sem_index;
165   decl.Range.First =
166   decl.Range.Last = index;
167   decl.Interp.Interpolate = interp;
168
169   ctx->emit_declaration(ctx, &decl);
170}
171
172static inline void
173tgsi_transform_sampler_decl(struct tgsi_transform_context *ctx,
174                            unsigned index)
175{
176   struct tgsi_full_declaration decl;
177
178   decl = tgsi_default_full_declaration();
179   decl.Declaration.File = TGSI_FILE_SAMPLER;
180   decl.Range.First =
181   decl.Range.Last = index;
182   ctx->emit_declaration(ctx, &decl);
183}
184
185static inline void
186tgsi_transform_sampler_view_decl(struct tgsi_transform_context *ctx,
187                                 unsigned index,
188                                 unsigned target,
189                                 enum tgsi_return_type type)
190{
191   struct tgsi_full_declaration decl;
192
193   decl = tgsi_default_full_declaration();
194   decl.Declaration.File = TGSI_FILE_SAMPLER_VIEW;
195   decl.Declaration.UsageMask = TGSI_WRITEMASK_XYZW;
196   decl.Range.First =
197   decl.Range.Last = index;
198   decl.SamplerView.Resource = target;
199   decl.SamplerView.ReturnTypeX = type;
200   decl.SamplerView.ReturnTypeY = type;
201   decl.SamplerView.ReturnTypeZ = type;
202   decl.SamplerView.ReturnTypeW = type;
203
204   ctx->emit_declaration(ctx, &decl);
205}
206
207static inline void
208tgsi_transform_immediate_decl(struct tgsi_transform_context *ctx,
209                              float x, float y, float z, float w)
210{
211   struct tgsi_full_immediate immed;
212   unsigned size = 4;
213
214   immed = tgsi_default_full_immediate();
215   immed.Immediate.NrTokens = 1 + size; /* one for the token itself */
216   immed.u[0].Float = x;
217   immed.u[1].Float = y;
218   immed.u[2].Float = z;
219   immed.u[3].Float = w;
220
221   ctx->emit_immediate(ctx, &immed);
222}
223
224static inline void
225tgsi_transform_dst_reg(struct tgsi_full_dst_register *reg,
226                       unsigned file, unsigned index, unsigned writemask)
227{
228   reg->Register.File = file;
229   reg->Register.Index = index;
230   reg->Register.WriteMask = writemask;
231}
232
233static inline void
234tgsi_transform_src_reg(struct tgsi_full_src_register *reg,
235                       unsigned file, unsigned index,
236                       unsigned swizzleX, unsigned swizzleY,
237                       unsigned swizzleZ, unsigned swizzleW)
238{
239   reg->Register.File = file;
240   reg->Register.Index = index;
241   reg->Register.SwizzleX = swizzleX;
242   reg->Register.SwizzleY = swizzleY;
243   reg->Register.SwizzleZ = swizzleZ;
244   reg->Register.SwizzleW = swizzleW;
245}
246
247/**
248 * Helper for emitting 1-operand instructions.
249 */
250static inline void
251tgsi_transform_op1_inst(struct tgsi_transform_context *ctx,
252                        unsigned opcode,
253                        unsigned dst_file,
254                        unsigned dst_index,
255                        unsigned dst_writemask,
256                        unsigned src0_file,
257                        unsigned src0_index)
258{
259   struct tgsi_full_instruction inst;
260
261   inst = tgsi_default_full_instruction();
262   inst.Instruction.Opcode = opcode;
263   inst.Instruction.NumDstRegs = 1;
264   inst.Dst[0].Register.File = dst_file,
265   inst.Dst[0].Register.Index = dst_index;
266   inst.Dst[0].Register.WriteMask = dst_writemask;
267   inst.Instruction.NumSrcRegs = 1;
268   inst.Src[0].Register.File = src0_file;
269   inst.Src[0].Register.Index = src0_index;
270
271   ctx->emit_instruction(ctx, &inst);
272}
273
274
275static inline void
276tgsi_transform_op2_inst(struct tgsi_transform_context *ctx,
277                        unsigned opcode,
278                        unsigned dst_file,
279                        unsigned dst_index,
280                        unsigned dst_writemask,
281                        unsigned src0_file,
282                        unsigned src0_index,
283                        unsigned src1_file,
284                        unsigned src1_index,
285                        bool src1_negate)
286{
287   struct tgsi_full_instruction inst;
288
289   inst = tgsi_default_full_instruction();
290   inst.Instruction.Opcode = opcode;
291   inst.Instruction.NumDstRegs = 1;
292   inst.Dst[0].Register.File = dst_file,
293   inst.Dst[0].Register.Index = dst_index;
294   inst.Dst[0].Register.WriteMask = dst_writemask;
295   inst.Instruction.NumSrcRegs = 2;
296   inst.Src[0].Register.File = src0_file;
297   inst.Src[0].Register.Index = src0_index;
298   inst.Src[1].Register.File = src1_file;
299   inst.Src[1].Register.Index = src1_index;
300   inst.Src[1].Register.Negate = src1_negate;
301
302   ctx->emit_instruction(ctx, &inst);
303}
304
305
306static inline void
307tgsi_transform_op3_inst(struct tgsi_transform_context *ctx,
308                        unsigned opcode,
309                        unsigned dst_file,
310                        unsigned dst_index,
311                        unsigned dst_writemask,
312                        unsigned src0_file,
313                        unsigned src0_index,
314                        unsigned src1_file,
315                        unsigned src1_index,
316                        unsigned src2_file,
317                        unsigned src2_index)
318{
319   struct tgsi_full_instruction inst;
320
321   inst = tgsi_default_full_instruction();
322   inst.Instruction.Opcode = opcode;
323   inst.Instruction.NumDstRegs = 1;
324   inst.Dst[0].Register.File = dst_file,
325   inst.Dst[0].Register.Index = dst_index;
326   inst.Dst[0].Register.WriteMask = dst_writemask;
327   inst.Instruction.NumSrcRegs = 3;
328   inst.Src[0].Register.File = src0_file;
329   inst.Src[0].Register.Index = src0_index;
330   inst.Src[1].Register.File = src1_file;
331   inst.Src[1].Register.Index = src1_index;
332   inst.Src[2].Register.File = src2_file;
333   inst.Src[2].Register.Index = src2_index;
334
335   ctx->emit_instruction(ctx, &inst);
336}
337
338
339
340static inline void
341tgsi_transform_op1_swz_inst(struct tgsi_transform_context *ctx,
342                            unsigned opcode,
343                            unsigned dst_file,
344                            unsigned dst_index,
345                            unsigned dst_writemask,
346                            unsigned src0_file,
347                            unsigned src0_index,
348                            unsigned src0_swizzle)
349{
350   struct tgsi_full_instruction inst;
351
352   inst = tgsi_default_full_instruction();
353   inst.Instruction.Opcode = opcode;
354   inst.Instruction.NumDstRegs = 1;
355   inst.Dst[0].Register.File = dst_file,
356   inst.Dst[0].Register.Index = dst_index;
357   inst.Dst[0].Register.WriteMask = dst_writemask;
358   inst.Instruction.NumSrcRegs = 1;
359   inst.Src[0].Register.File = src0_file;
360   inst.Src[0].Register.Index = src0_index;
361   switch (dst_writemask) {
362   case TGSI_WRITEMASK_X:
363      inst.Src[0].Register.SwizzleX = src0_swizzle;
364      break;
365   case TGSI_WRITEMASK_Y:
366      inst.Src[0].Register.SwizzleY = src0_swizzle;
367      break;
368   case TGSI_WRITEMASK_Z:
369      inst.Src[0].Register.SwizzleZ = src0_swizzle;
370      break;
371   case TGSI_WRITEMASK_W:
372      inst.Src[0].Register.SwizzleW = src0_swizzle;
373      break;
374   default:
375      ; /* nothing */
376   }
377
378   ctx->emit_instruction(ctx, &inst);
379}
380
381
382static inline void
383tgsi_transform_op2_swz_inst(struct tgsi_transform_context *ctx,
384                            unsigned opcode,
385                            unsigned dst_file,
386                            unsigned dst_index,
387                            unsigned dst_writemask,
388                            unsigned src0_file,
389                            unsigned src0_index,
390                            unsigned src0_swizzle,
391                            unsigned src1_file,
392                            unsigned src1_index,
393                            unsigned src1_swizzle,
394                            bool src1_negate)
395{
396   struct tgsi_full_instruction inst;
397
398   inst = tgsi_default_full_instruction();
399   inst.Instruction.Opcode = opcode;
400   inst.Instruction.NumDstRegs = 1;
401   inst.Dst[0].Register.File = dst_file,
402   inst.Dst[0].Register.Index = dst_index;
403   inst.Dst[0].Register.WriteMask = dst_writemask;
404   inst.Instruction.NumSrcRegs = 2;
405   inst.Src[0].Register.File = src0_file;
406   inst.Src[0].Register.Index = src0_index;
407   inst.Src[1].Register.File = src1_file;
408   inst.Src[1].Register.Index = src1_index;
409   inst.Src[1].Register.Negate = src1_negate;
410   switch (dst_writemask) {
411   case TGSI_WRITEMASK_X:
412      inst.Src[0].Register.SwizzleX = src0_swizzle;
413      inst.Src[1].Register.SwizzleX = src1_swizzle;
414      break;
415   case TGSI_WRITEMASK_Y:
416      inst.Src[0].Register.SwizzleY = src0_swizzle;
417      inst.Src[1].Register.SwizzleY = src1_swizzle;
418      break;
419   case TGSI_WRITEMASK_Z:
420      inst.Src[0].Register.SwizzleZ = src0_swizzle;
421      inst.Src[1].Register.SwizzleZ = src1_swizzle;
422      break;
423   case TGSI_WRITEMASK_W:
424      inst.Src[0].Register.SwizzleW = src0_swizzle;
425      inst.Src[1].Register.SwizzleW = src1_swizzle;
426      break;
427   default:
428      ; /* nothing */
429   }
430
431   ctx->emit_instruction(ctx, &inst);
432}
433
434
435static inline void
436tgsi_transform_op3_swz_inst(struct tgsi_transform_context *ctx,
437                            unsigned opcode,
438                            unsigned dst_file,
439                            unsigned dst_index,
440                            unsigned dst_writemask,
441                            unsigned src0_file,
442                            unsigned src0_index,
443                            unsigned src0_swizzle,
444                            unsigned src0_negate,
445                            unsigned src1_file,
446                            unsigned src1_index,
447                            unsigned src1_swizzle,
448                            unsigned src2_file,
449                            unsigned src2_index,
450                            unsigned src2_swizzle)
451{
452   struct tgsi_full_instruction inst;
453
454   inst = tgsi_default_full_instruction();
455   inst.Instruction.Opcode = opcode;
456   inst.Instruction.NumDstRegs = 1;
457   inst.Dst[0].Register.File = dst_file,
458   inst.Dst[0].Register.Index = dst_index;
459   inst.Dst[0].Register.WriteMask = dst_writemask;
460   inst.Instruction.NumSrcRegs = 3;
461   inst.Src[0].Register.File = src0_file;
462   inst.Src[0].Register.Index = src0_index;
463   inst.Src[0].Register.Negate = src0_negate;
464   inst.Src[1].Register.File = src1_file;
465   inst.Src[1].Register.Index = src1_index;
466   inst.Src[2].Register.File = src2_file;
467   inst.Src[2].Register.Index = src2_index;
468   switch (dst_writemask) {
469   case TGSI_WRITEMASK_X:
470      inst.Src[0].Register.SwizzleX = src0_swizzle;
471      inst.Src[1].Register.SwizzleX = src1_swizzle;
472      inst.Src[2].Register.SwizzleX = src2_swizzle;
473      break;
474   case TGSI_WRITEMASK_Y:
475      inst.Src[0].Register.SwizzleY = src0_swizzle;
476      inst.Src[1].Register.SwizzleY = src1_swizzle;
477      inst.Src[2].Register.SwizzleY = src2_swizzle;
478      break;
479   case TGSI_WRITEMASK_Z:
480      inst.Src[0].Register.SwizzleZ = src0_swizzle;
481      inst.Src[1].Register.SwizzleZ = src1_swizzle;
482      inst.Src[2].Register.SwizzleZ = src2_swizzle;
483      break;
484   case TGSI_WRITEMASK_W:
485      inst.Src[0].Register.SwizzleW = src0_swizzle;
486      inst.Src[1].Register.SwizzleW = src1_swizzle;
487      inst.Src[2].Register.SwizzleW = src2_swizzle;
488      break;
489   default:
490      ; /* nothing */
491   }
492
493   ctx->emit_instruction(ctx, &inst);
494}
495
496
497static inline void
498tgsi_transform_kill_inst(struct tgsi_transform_context *ctx,
499                         unsigned src_file,
500                         unsigned src_index,
501                         unsigned src_swizzle,
502                         boolean negate)
503{
504   struct tgsi_full_instruction inst;
505
506   inst = tgsi_default_full_instruction();
507   inst.Instruction.Opcode = TGSI_OPCODE_KILL_IF;
508   inst.Instruction.NumDstRegs = 0;
509   inst.Instruction.NumSrcRegs = 1;
510   inst.Src[0].Register.File = src_file;
511   inst.Src[0].Register.Index = src_index;
512   inst.Src[0].Register.SwizzleX =
513   inst.Src[0].Register.SwizzleY =
514   inst.Src[0].Register.SwizzleZ =
515   inst.Src[0].Register.SwizzleW = src_swizzle;
516   inst.Src[0].Register.Negate = negate;
517
518   ctx->emit_instruction(ctx, &inst);
519}
520
521
522static inline void
523tgsi_transform_tex_inst(struct tgsi_transform_context *ctx,
524                        unsigned dst_file,
525                        unsigned dst_index,
526                        unsigned src_file,
527                        unsigned src_index,
528                        unsigned tex_target,
529                        unsigned sampler_index)
530{
531   struct tgsi_full_instruction inst;
532
533   assert(tex_target < TGSI_TEXTURE_COUNT);
534
535   inst = tgsi_default_full_instruction();
536   inst.Instruction.Opcode = TGSI_OPCODE_TEX;
537   inst.Instruction.NumDstRegs = 1;
538   inst.Dst[0].Register.File = dst_file;
539   inst.Dst[0].Register.Index = dst_index;
540   inst.Instruction.NumSrcRegs = 2;
541   inst.Instruction.Texture = TRUE;
542   inst.Texture.Texture = tex_target;
543   inst.Src[0].Register.File = src_file;
544   inst.Src[0].Register.Index = src_index;
545   inst.Src[1].Register.File = TGSI_FILE_SAMPLER;
546   inst.Src[1].Register.Index = sampler_index;
547
548   ctx->emit_instruction(ctx, &inst);
549}
550
551
552extern int
553tgsi_transform_shader(const struct tgsi_token *tokens_in,
554                      struct tgsi_token *tokens_out,
555                      uint max_tokens_out,
556                      struct tgsi_transform_context *ctx);
557
558
559#endif /* TGSI_TRANSFORM_H */
560