921aa906527e781c256caf37f7622678f1bf9755
[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_temp_decl(struct tgsi_transform_context *ctx,
99 unsigned index)
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 =
106 decl.Range.Last = index;
107 ctx->emit_declaration(ctx, &decl);
108 }
109
110
111 static INLINE void
112 tgsi_transform_input_decl(struct tgsi_transform_context *ctx,
113 unsigned index,
114 unsigned sem_name, unsigned sem_index,
115 unsigned interp)
116 {
117 struct tgsi_full_declaration decl;
118
119 decl = tgsi_default_full_declaration();
120 decl.Declaration.File = TGSI_FILE_INPUT;
121 decl.Declaration.Interpolate = 1;
122 decl.Declaration.Semantic = 1;
123 decl.Semantic.Name = sem_name;
124 decl.Semantic.Index = sem_index;
125 decl.Range.First =
126 decl.Range.Last = index;
127 decl.Interp.Interpolate = interp;
128
129 ctx->emit_declaration(ctx, &decl);
130 }
131
132
133 static INLINE void
134 tgsi_transform_sampler_decl(struct tgsi_transform_context *ctx,
135 unsigned index)
136 {
137 struct tgsi_full_declaration decl;
138
139 decl = tgsi_default_full_declaration();
140 decl.Declaration.File = TGSI_FILE_SAMPLER;
141 decl.Range.First =
142 decl.Range.Last = index;
143 ctx->emit_declaration(ctx, &decl);
144 }
145
146
147 static INLINE void
148 tgsi_transform_immediate_decl(struct tgsi_transform_context *ctx,
149 float x, float y, float z, float w)
150 {
151 struct tgsi_full_immediate immed;
152 unsigned size = 4;
153
154 immed = tgsi_default_full_immediate();
155 immed.Immediate.NrTokens = 1 + size; /* one for the token itself */
156 immed.u[0].Float = x;
157 immed.u[1].Float = y;
158 immed.u[2].Float = z;
159 immed.u[3].Float = w;
160
161 ctx->emit_immediate(ctx, &immed);
162 }
163
164
165 /**
166 * Helper for emitting 1-operand instructions.
167 */
168 static INLINE void
169 tgsi_transform_op1_inst(struct tgsi_transform_context *ctx,
170 unsigned opcode,
171 unsigned dst_file,
172 unsigned dst_index,
173 unsigned dst_writemask,
174 unsigned src0_file,
175 unsigned src0_index)
176 {
177 struct tgsi_full_instruction inst;
178
179 inst = tgsi_default_full_instruction();
180 inst.Instruction.Opcode = opcode;
181 inst.Instruction.NumDstRegs = 1;
182 inst.Dst[0].Register.File = dst_file,
183 inst.Dst[0].Register.Index = dst_index;
184 inst.Dst[0].Register.WriteMask = dst_writemask;
185 inst.Instruction.NumSrcRegs = 1;
186 inst.Src[0].Register.File = src0_file;
187 inst.Src[0].Register.Index = src0_index;
188
189 ctx->emit_instruction(ctx, &inst);
190 }
191
192
193 static INLINE void
194 tgsi_transform_op2_inst(struct tgsi_transform_context *ctx,
195 unsigned opcode,
196 unsigned dst_file,
197 unsigned dst_index,
198 unsigned dst_writemask,
199 unsigned src0_file,
200 unsigned src0_index,
201 unsigned src1_file,
202 unsigned src1_index)
203 {
204 struct tgsi_full_instruction inst;
205
206 inst = tgsi_default_full_instruction();
207 inst.Instruction.Opcode = opcode;
208 inst.Instruction.NumDstRegs = 1;
209 inst.Dst[0].Register.File = dst_file,
210 inst.Dst[0].Register.Index = dst_index;
211 inst.Dst[0].Register.WriteMask = dst_writemask;
212 inst.Instruction.NumSrcRegs = 2;
213 inst.Src[0].Register.File = src0_file;
214 inst.Src[0].Register.Index = src0_index;
215 inst.Src[1].Register.File = src1_file;
216 inst.Src[1].Register.Index = src1_index;
217
218 ctx->emit_instruction(ctx, &inst);
219 }
220
221
222 static INLINE void
223 tgsi_transform_op1_swz_inst(struct tgsi_transform_context *ctx,
224 unsigned opcode,
225 unsigned dst_file,
226 unsigned dst_index,
227 unsigned dst_writemask,
228 unsigned src0_file,
229 unsigned src0_index,
230 unsigned src0_swizzle)
231 {
232 struct tgsi_full_instruction inst;
233
234 inst = tgsi_default_full_instruction();
235 inst.Instruction.Opcode = opcode;
236 inst.Instruction.NumDstRegs = 1;
237 inst.Dst[0].Register.File = dst_file,
238 inst.Dst[0].Register.Index = dst_index;
239 inst.Dst[0].Register.WriteMask = dst_writemask;
240 inst.Instruction.NumSrcRegs = 1;
241 inst.Src[0].Register.File = src0_file;
242 inst.Src[0].Register.Index = src0_index;
243 switch (dst_writemask) {
244 case TGSI_WRITEMASK_X:
245 inst.Src[0].Register.SwizzleX = src0_swizzle;
246 break;
247 case TGSI_WRITEMASK_Y:
248 inst.Src[0].Register.SwizzleY = src0_swizzle;
249 break;
250 case TGSI_WRITEMASK_Z:
251 inst.Src[0].Register.SwizzleZ = src0_swizzle;
252 break;
253 case TGSI_WRITEMASK_W:
254 inst.Src[0].Register.SwizzleW = src0_swizzle;
255 break;
256 default:
257 ; /* nothing */
258 }
259
260 ctx->emit_instruction(ctx, &inst);
261 }
262
263
264 static INLINE void
265 tgsi_transform_op2_swz_inst(struct tgsi_transform_context *ctx,
266 unsigned opcode,
267 unsigned dst_file,
268 unsigned dst_index,
269 unsigned dst_writemask,
270 unsigned src0_file,
271 unsigned src0_index,
272 unsigned src0_swizzle,
273 unsigned src1_file,
274 unsigned src1_index,
275 unsigned src1_swizzle)
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 = 2;
286 inst.Src[0].Register.File = src0_file;
287 inst.Src[0].Register.Index = src0_index;
288 inst.Src[1].Register.File = src1_file;
289 inst.Src[1].Register.Index = src1_index;
290 switch (dst_writemask) {
291 case TGSI_WRITEMASK_X:
292 inst.Src[0].Register.SwizzleX = src0_swizzle;
293 inst.Src[1].Register.SwizzleX = src1_swizzle;
294 break;
295 case TGSI_WRITEMASK_Y:
296 inst.Src[0].Register.SwizzleY = src0_swizzle;
297 inst.Src[1].Register.SwizzleY = src1_swizzle;
298 break;
299 case TGSI_WRITEMASK_Z:
300 inst.Src[0].Register.SwizzleZ = src0_swizzle;
301 inst.Src[1].Register.SwizzleZ = src1_swizzle;
302 break;
303 case TGSI_WRITEMASK_W:
304 inst.Src[0].Register.SwizzleW = src0_swizzle;
305 inst.Src[1].Register.SwizzleW = src1_swizzle;
306 break;
307 default:
308 ; /* nothing */
309 }
310
311 ctx->emit_instruction(ctx, &inst);
312 }
313
314
315 static INLINE void
316 tgsi_transform_op3_swz_inst(struct tgsi_transform_context *ctx,
317 unsigned opcode,
318 unsigned dst_file,
319 unsigned dst_index,
320 unsigned dst_writemask,
321 unsigned src0_file,
322 unsigned src0_index,
323 unsigned src0_swizzle,
324 unsigned src0_negate,
325 unsigned src1_file,
326 unsigned src1_index,
327 unsigned src1_swizzle,
328 unsigned src2_file,
329 unsigned src2_index,
330 unsigned src2_swizzle)
331 {
332 struct tgsi_full_instruction inst;
333
334 inst = tgsi_default_full_instruction();
335 inst.Instruction.Opcode = opcode;
336 inst.Instruction.NumDstRegs = 1;
337 inst.Dst[0].Register.File = dst_file,
338 inst.Dst[0].Register.Index = dst_index;
339 inst.Dst[0].Register.WriteMask = dst_writemask;
340 inst.Instruction.NumSrcRegs = 3;
341 inst.Src[0].Register.File = src0_file;
342 inst.Src[0].Register.Index = src0_index;
343 inst.Src[0].Register.Negate = src0_negate;
344 inst.Src[1].Register.File = src1_file;
345 inst.Src[1].Register.Index = src1_index;
346 inst.Src[2].Register.File = src2_file;
347 inst.Src[2].Register.Index = src2_index;
348 switch (dst_writemask) {
349 case TGSI_WRITEMASK_X:
350 inst.Src[0].Register.SwizzleX = src0_swizzle;
351 inst.Src[1].Register.SwizzleX = src1_swizzle;
352 inst.Src[2].Register.SwizzleX = src2_swizzle;
353 break;
354 case TGSI_WRITEMASK_Y:
355 inst.Src[0].Register.SwizzleY = src0_swizzle;
356 inst.Src[1].Register.SwizzleY = src1_swizzle;
357 inst.Src[2].Register.SwizzleY = src2_swizzle;
358 break;
359 case TGSI_WRITEMASK_Z:
360 inst.Src[0].Register.SwizzleZ = src0_swizzle;
361 inst.Src[1].Register.SwizzleZ = src1_swizzle;
362 inst.Src[2].Register.SwizzleZ = src2_swizzle;
363 break;
364 case TGSI_WRITEMASK_W:
365 inst.Src[0].Register.SwizzleW = src0_swizzle;
366 inst.Src[1].Register.SwizzleW = src1_swizzle;
367 inst.Src[2].Register.SwizzleW = src2_swizzle;
368 break;
369 default:
370 ; /* nothing */
371 }
372
373 ctx->emit_instruction(ctx, &inst);
374 }
375
376
377 static INLINE void
378 tgsi_transform_kill_inst(struct tgsi_transform_context *ctx,
379 unsigned src_file,
380 unsigned src_index,
381 unsigned src_swizzle)
382 {
383 struct tgsi_full_instruction inst;
384
385 inst = tgsi_default_full_instruction();
386 inst.Instruction.Opcode = TGSI_OPCODE_KILL_IF;
387 inst.Instruction.NumDstRegs = 0;
388 inst.Instruction.NumSrcRegs = 1;
389 inst.Src[0].Register.File = src_file;
390 inst.Src[0].Register.Index = src_index;
391 inst.Src[0].Register.SwizzleX =
392 inst.Src[0].Register.SwizzleY =
393 inst.Src[0].Register.SwizzleZ =
394 inst.Src[0].Register.SwizzleW = src_swizzle;
395 inst.Src[0].Register.Negate = 1;
396
397 ctx->emit_instruction(ctx, &inst);
398 }
399
400
401 static INLINE void
402 tgsi_transform_tex_2d_inst(struct tgsi_transform_context *ctx,
403 unsigned dst_file,
404 unsigned dst_index,
405 unsigned src_file,
406 unsigned src_index,
407 unsigned sampler_index)
408 {
409 struct tgsi_full_instruction inst;
410
411 inst = tgsi_default_full_instruction();
412 inst.Instruction.Opcode = TGSI_OPCODE_TEX;
413 inst.Instruction.NumDstRegs = 1;
414 inst.Dst[0].Register.File = dst_file;
415 inst.Dst[0].Register.Index = dst_index;
416 inst.Instruction.NumSrcRegs = 2;
417 inst.Instruction.Texture = TRUE;
418 inst.Texture.Texture = TGSI_TEXTURE_2D;
419 inst.Src[0].Register.File = src_file;
420 inst.Src[0].Register.Index = src_index;
421 inst.Src[1].Register.File = TGSI_FILE_SAMPLER;
422 inst.Src[1].Register.Index = sampler_index;
423
424 ctx->emit_instruction(ctx, &inst);
425 }
426
427
428 extern int
429 tgsi_transform_shader(const struct tgsi_token *tokens_in,
430 struct tgsi_token *tokens_out,
431 uint max_tokens_out,
432 struct tgsi_transform_context *ctx);
433
434
435 #endif /* TGSI_TRANSFORM_H */