gallium/ureg: Set the next shader stage from the shader info.
[mesa.git] / src / gallium / auxiliary / tgsi / tgsi_transform.h
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
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
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
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
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
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
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
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
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
227 tgsi_transform_immediate_int_decl(struct tgsi_transform_context *ctx,
228 int x, int y, int z, int w)
229 {
230 struct tgsi_full_immediate immed;
231 unsigned size = 4;
232
233 immed = tgsi_default_full_immediate();
234 immed.Immediate.DataType = TGSI_IMM_INT32;
235 immed.Immediate.NrTokens = 1 + size; /* one for the token itself */
236 immed.u[0].Int = x;
237 immed.u[1].Int = y;
238 immed.u[2].Int = z;
239 immed.u[3].Int = w;
240
241 ctx->emit_immediate(ctx, &immed);
242 }
243
244 static inline void
245 tgsi_transform_dst_reg(struct tgsi_full_dst_register *reg,
246 unsigned file, unsigned index, unsigned writemask)
247 {
248 reg->Register.File = file;
249 reg->Register.Index = index;
250 reg->Register.WriteMask = writemask;
251 }
252
253 static inline void
254 tgsi_transform_src_reg_xyzw(struct tgsi_full_src_register *reg,
255 unsigned file, unsigned index)
256 {
257 reg->Register.File = file;
258 reg->Register.Index = index;
259 if (file == TGSI_FILE_CONSTANT) {
260 reg->Register.Dimension = 1;
261 reg->Dimension.Index = 0;
262 }
263 }
264
265 static inline void
266 tgsi_transform_src_reg(struct tgsi_full_src_register *reg,
267 unsigned file, unsigned index,
268 unsigned swizzleX, unsigned swizzleY,
269 unsigned swizzleZ, unsigned swizzleW)
270 {
271 reg->Register.File = file;
272 reg->Register.Index = index;
273 if (file == TGSI_FILE_CONSTANT) {
274 reg->Register.Dimension = 1;
275 reg->Dimension.Index = 0;
276 }
277 reg->Register.SwizzleX = swizzleX;
278 reg->Register.SwizzleY = swizzleY;
279 reg->Register.SwizzleZ = swizzleZ;
280 reg->Register.SwizzleW = swizzleW;
281 }
282
283 /**
284 * Helper for emitting 1-operand instructions.
285 */
286 static inline void
287 tgsi_transform_op1_inst(struct tgsi_transform_context *ctx,
288 enum tgsi_opcode opcode,
289 unsigned dst_file,
290 unsigned dst_index,
291 unsigned dst_writemask,
292 unsigned src0_file,
293 unsigned src0_index)
294 {
295 struct tgsi_full_instruction inst;
296
297 inst = tgsi_default_full_instruction();
298 inst.Instruction.Opcode = opcode;
299 inst.Instruction.NumDstRegs = 1;
300 inst.Dst[0].Register.File = dst_file,
301 inst.Dst[0].Register.Index = dst_index;
302 inst.Dst[0].Register.WriteMask = dst_writemask;
303 inst.Instruction.NumSrcRegs = 1;
304 tgsi_transform_src_reg_xyzw(&inst.Src[0], src0_file, src0_index);
305
306 ctx->emit_instruction(ctx, &inst);
307 }
308
309
310 static inline void
311 tgsi_transform_op2_inst(struct tgsi_transform_context *ctx,
312 enum tgsi_opcode opcode,
313 unsigned dst_file,
314 unsigned dst_index,
315 unsigned dst_writemask,
316 unsigned src0_file,
317 unsigned src0_index,
318 unsigned src1_file,
319 unsigned src1_index,
320 bool src1_negate)
321 {
322 struct tgsi_full_instruction inst;
323
324 inst = tgsi_default_full_instruction();
325 inst.Instruction.Opcode = opcode;
326 inst.Instruction.NumDstRegs = 1;
327 inst.Dst[0].Register.File = dst_file,
328 inst.Dst[0].Register.Index = dst_index;
329 inst.Dst[0].Register.WriteMask = dst_writemask;
330 inst.Instruction.NumSrcRegs = 2;
331 tgsi_transform_src_reg_xyzw(&inst.Src[0], src0_file, src0_index);
332 tgsi_transform_src_reg_xyzw(&inst.Src[1], src1_file, src1_index);
333 inst.Src[1].Register.Negate = src1_negate;
334
335 ctx->emit_instruction(ctx, &inst);
336 }
337
338
339 static inline void
340 tgsi_transform_op3_inst(struct tgsi_transform_context *ctx,
341 enum tgsi_opcode opcode,
342 unsigned dst_file,
343 unsigned dst_index,
344 unsigned dst_writemask,
345 unsigned src0_file,
346 unsigned src0_index,
347 unsigned src1_file,
348 unsigned src1_index,
349 unsigned src2_file,
350 unsigned src2_index)
351 {
352 struct tgsi_full_instruction inst;
353
354 inst = tgsi_default_full_instruction();
355 inst.Instruction.Opcode = opcode;
356 inst.Instruction.NumDstRegs = 1;
357 inst.Dst[0].Register.File = dst_file,
358 inst.Dst[0].Register.Index = dst_index;
359 inst.Dst[0].Register.WriteMask = dst_writemask;
360 inst.Instruction.NumSrcRegs = 3;
361 tgsi_transform_src_reg_xyzw(&inst.Src[0], src0_file, src0_index);
362 tgsi_transform_src_reg_xyzw(&inst.Src[1], src1_file, src1_index);
363 tgsi_transform_src_reg_xyzw(&inst.Src[2], src2_file, src2_index);
364
365 ctx->emit_instruction(ctx, &inst);
366 }
367
368
369
370 static inline void
371 tgsi_transform_op1_swz_inst(struct tgsi_transform_context *ctx,
372 enum tgsi_opcode opcode,
373 unsigned dst_file,
374 unsigned dst_index,
375 unsigned dst_writemask,
376 unsigned src0_file,
377 unsigned src0_index,
378 unsigned src0_swizzle)
379 {
380 struct tgsi_full_instruction inst;
381
382 inst = tgsi_default_full_instruction();
383 inst.Instruction.Opcode = opcode;
384 inst.Instruction.NumDstRegs = 1;
385 inst.Dst[0].Register.File = dst_file,
386 inst.Dst[0].Register.Index = dst_index;
387 inst.Dst[0].Register.WriteMask = dst_writemask;
388 inst.Instruction.NumSrcRegs = 1;
389 tgsi_transform_src_reg_xyzw(&inst.Src[0], src0_file, src0_index);
390 switch (dst_writemask) {
391 case TGSI_WRITEMASK_X:
392 inst.Src[0].Register.SwizzleX = src0_swizzle;
393 break;
394 case TGSI_WRITEMASK_Y:
395 inst.Src[0].Register.SwizzleY = src0_swizzle;
396 break;
397 case TGSI_WRITEMASK_Z:
398 inst.Src[0].Register.SwizzleZ = src0_swizzle;
399 break;
400 case TGSI_WRITEMASK_W:
401 inst.Src[0].Register.SwizzleW = src0_swizzle;
402 break;
403 default:
404 ; /* nothing */
405 }
406
407 ctx->emit_instruction(ctx, &inst);
408 }
409
410
411 static inline void
412 tgsi_transform_op2_swz_inst(struct tgsi_transform_context *ctx,
413 enum tgsi_opcode opcode,
414 unsigned dst_file,
415 unsigned dst_index,
416 unsigned dst_writemask,
417 unsigned src0_file,
418 unsigned src0_index,
419 unsigned src0_swizzle,
420 unsigned src1_file,
421 unsigned src1_index,
422 unsigned src1_swizzle,
423 bool src1_negate)
424 {
425 struct tgsi_full_instruction inst;
426
427 inst = tgsi_default_full_instruction();
428 inst.Instruction.Opcode = opcode;
429 inst.Instruction.NumDstRegs = 1;
430 inst.Dst[0].Register.File = dst_file,
431 inst.Dst[0].Register.Index = dst_index;
432 inst.Dst[0].Register.WriteMask = dst_writemask;
433 inst.Instruction.NumSrcRegs = 2;
434 tgsi_transform_src_reg_xyzw(&inst.Src[0], src0_file, src0_index);
435 tgsi_transform_src_reg_xyzw(&inst.Src[1], src1_file, src1_index);
436 inst.Src[1].Register.Negate = src1_negate;
437 switch (dst_writemask) {
438 case TGSI_WRITEMASK_X:
439 inst.Src[0].Register.SwizzleX = src0_swizzle;
440 inst.Src[1].Register.SwizzleX = src1_swizzle;
441 break;
442 case TGSI_WRITEMASK_Y:
443 inst.Src[0].Register.SwizzleY = src0_swizzle;
444 inst.Src[1].Register.SwizzleY = src1_swizzle;
445 break;
446 case TGSI_WRITEMASK_Z:
447 inst.Src[0].Register.SwizzleZ = src0_swizzle;
448 inst.Src[1].Register.SwizzleZ = src1_swizzle;
449 break;
450 case TGSI_WRITEMASK_W:
451 inst.Src[0].Register.SwizzleW = src0_swizzle;
452 inst.Src[1].Register.SwizzleW = src1_swizzle;
453 break;
454 default:
455 ; /* nothing */
456 }
457
458 ctx->emit_instruction(ctx, &inst);
459 }
460
461
462 static inline void
463 tgsi_transform_op3_swz_inst(struct tgsi_transform_context *ctx,
464 enum tgsi_opcode opcode,
465 unsigned dst_file,
466 unsigned dst_index,
467 unsigned dst_writemask,
468 unsigned src0_file,
469 unsigned src0_index,
470 unsigned src0_swizzle,
471 unsigned src0_negate,
472 unsigned src1_file,
473 unsigned src1_index,
474 unsigned src1_swizzle,
475 unsigned src2_file,
476 unsigned src2_index,
477 unsigned src2_swizzle)
478 {
479 struct tgsi_full_instruction inst;
480
481 inst = tgsi_default_full_instruction();
482 inst.Instruction.Opcode = opcode;
483 inst.Instruction.NumDstRegs = 1;
484 inst.Dst[0].Register.File = dst_file,
485 inst.Dst[0].Register.Index = dst_index;
486 inst.Dst[0].Register.WriteMask = dst_writemask;
487 inst.Instruction.NumSrcRegs = 3;
488 tgsi_transform_src_reg_xyzw(&inst.Src[0], src0_file, src0_index);
489 inst.Src[0].Register.Negate = src0_negate;
490 tgsi_transform_src_reg_xyzw(&inst.Src[1], src1_file, src1_index);
491 tgsi_transform_src_reg_xyzw(&inst.Src[2], src2_file, src2_index);
492 switch (dst_writemask) {
493 case TGSI_WRITEMASK_X:
494 inst.Src[0].Register.SwizzleX = src0_swizzle;
495 inst.Src[1].Register.SwizzleX = src1_swizzle;
496 inst.Src[2].Register.SwizzleX = src2_swizzle;
497 break;
498 case TGSI_WRITEMASK_Y:
499 inst.Src[0].Register.SwizzleY = src0_swizzle;
500 inst.Src[1].Register.SwizzleY = src1_swizzle;
501 inst.Src[2].Register.SwizzleY = src2_swizzle;
502 break;
503 case TGSI_WRITEMASK_Z:
504 inst.Src[0].Register.SwizzleZ = src0_swizzle;
505 inst.Src[1].Register.SwizzleZ = src1_swizzle;
506 inst.Src[2].Register.SwizzleZ = src2_swizzle;
507 break;
508 case TGSI_WRITEMASK_W:
509 inst.Src[0].Register.SwizzleW = src0_swizzle;
510 inst.Src[1].Register.SwizzleW = src1_swizzle;
511 inst.Src[2].Register.SwizzleW = src2_swizzle;
512 break;
513 default:
514 ; /* nothing */
515 }
516
517 ctx->emit_instruction(ctx, &inst);
518 }
519
520
521 static inline void
522 tgsi_transform_kill_inst(struct tgsi_transform_context *ctx,
523 unsigned src_file,
524 unsigned src_index,
525 unsigned src_swizzle,
526 boolean negate)
527 {
528 struct tgsi_full_instruction inst;
529
530 inst = tgsi_default_full_instruction();
531 inst.Instruction.Opcode = TGSI_OPCODE_KILL_IF;
532 inst.Instruction.NumDstRegs = 0;
533 inst.Instruction.NumSrcRegs = 1;
534 tgsi_transform_src_reg_xyzw(&inst.Src[0], src_file, src_index);
535 inst.Src[0].Register.SwizzleX =
536 inst.Src[0].Register.SwizzleY =
537 inst.Src[0].Register.SwizzleZ =
538 inst.Src[0].Register.SwizzleW = src_swizzle;
539 inst.Src[0].Register.Negate = negate;
540
541 ctx->emit_instruction(ctx, &inst);
542 }
543
544
545 static inline void
546 tgsi_transform_tex_inst(struct tgsi_transform_context *ctx,
547 unsigned dst_file,
548 unsigned dst_index,
549 unsigned src_file,
550 unsigned src_index,
551 unsigned tex_target,
552 unsigned sampler_index)
553 {
554 struct tgsi_full_instruction inst;
555
556 assert(tex_target < TGSI_TEXTURE_COUNT);
557
558 inst = tgsi_default_full_instruction();
559 inst.Instruction.Opcode = TGSI_OPCODE_TEX;
560 inst.Instruction.NumDstRegs = 1;
561 inst.Dst[0].Register.File = dst_file;
562 inst.Dst[0].Register.Index = dst_index;
563 inst.Instruction.NumSrcRegs = 2;
564 inst.Instruction.Texture = TRUE;
565 inst.Texture.Texture = tex_target;
566 tgsi_transform_src_reg_xyzw(&inst.Src[0], src_file, src_index);
567 tgsi_transform_src_reg_xyzw(&inst.Src[1], TGSI_FILE_SAMPLER, sampler_index);
568
569 ctx->emit_instruction(ctx, &inst);
570 }
571
572
573 extern int
574 tgsi_transform_shader(const struct tgsi_token *tokens_in,
575 struct tgsi_token *tokens_out,
576 uint max_tokens_out,
577 struct tgsi_transform_context *ctx);
578
579
580 #endif /* TGSI_TRANSFORM_H */