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 ctx->emit_declaration(ctx, &decl);
128 }
129
130 static inline void
tgsi_transform_input_decl(struct tgsi_transform_context * ctx,unsigned index,unsigned sem_name,unsigned sem_index,unsigned interp)131 tgsi_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
151 static inline void
tgsi_transform_output_decl(struct tgsi_transform_context * ctx,unsigned index,unsigned sem_name,unsigned sem_index,unsigned interp)152 tgsi_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
172 static inline void
tgsi_transform_sampler_decl(struct tgsi_transform_context * ctx,unsigned index)173 tgsi_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
185 static inline void
tgsi_transform_sampler_view_decl(struct tgsi_transform_context * ctx,unsigned index,unsigned target,enum tgsi_return_type type)186 tgsi_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
207 static inline void
tgsi_transform_immediate_decl(struct tgsi_transform_context * ctx,float x,float y,float z,float w)208 tgsi_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
224 static inline void
tgsi_transform_dst_reg(struct tgsi_full_dst_register * reg,unsigned file,unsigned index,unsigned writemask)225 tgsi_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
233 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)234 tgsi_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 */
250 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)251 tgsi_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
275 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)276 tgsi_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
306 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)307 tgsi_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
340 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)341 tgsi_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
382 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)383 tgsi_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
435 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)436 tgsi_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
497 static inline void
tgsi_transform_kill_inst(struct tgsi_transform_context * ctx,unsigned src_file,unsigned src_index,unsigned src_swizzle,boolean negate)498 tgsi_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
522 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)523 tgsi_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
552 extern int
553 tgsi_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