r300: Zero-initialize register for NV_vertex_program
[mesa.git] / src / gallium / auxiliary / tgsi / tgsi_ureg.h
1 /**************************************************************************
2 *
3 * Copyright 2009 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, INC 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_UREG_H
29 #define TGSI_UREG_H
30
31 #include "pipe/p_compiler.h"
32 #include "pipe/p_shader_tokens.h"
33
34 #ifdef __cplusplus
35 extern "C" {
36 #endif
37
38 struct ureg_program;
39
40 /* Almost a tgsi_src_register, but we need to pull in the Absolute
41 * flag from the _ext token. Indirect flag always implies ADDR[0].
42 */
43 struct ureg_src
44 {
45 unsigned File : 4; /* TGSI_FILE_ */
46 unsigned SwizzleX : 2; /* TGSI_SWIZZLE_ */
47 unsigned SwizzleY : 2; /* TGSI_SWIZZLE_ */
48 unsigned SwizzleZ : 2; /* TGSI_SWIZZLE_ */
49 unsigned SwizzleW : 2; /* TGSI_SWIZZLE_ */
50 unsigned Pad : 1; /* BOOL */
51 unsigned Indirect : 1; /* BOOL */
52 unsigned Absolute : 1; /* BOOL */
53 int Index : 16; /* SINT */
54 unsigned Negate : 1; /* BOOL */
55 int IndirectIndex : 16; /* SINT */
56 int IndirectSwizzle : 2; /* TGSI_SWIZZLE_ */
57 };
58
59 /* Very similar to a tgsi_dst_register, removing unsupported fields
60 * and adding a Saturate flag. It's easier to push saturate into the
61 * destination register than to try and create a _SAT varient of each
62 * instruction function.
63 */
64 struct ureg_dst
65 {
66 unsigned File : 4; /* TGSI_FILE_ */
67 unsigned WriteMask : 4; /* TGSI_WRITEMASK_ */
68 unsigned Indirect : 1; /* BOOL */
69 unsigned Saturate : 1; /* BOOL */
70 int Index : 16; /* SINT */
71 unsigned Pad1 : 5;
72 unsigned Pad2 : 1; /* BOOL */
73 int IndirectIndex : 16; /* SINT */
74 int IndirectSwizzle : 2; /* TGSI_SWIZZLE_ */
75 };
76
77 struct pipe_context;
78
79 struct ureg_program *
80 ureg_create( unsigned processor );
81
82 const struct tgsi_token *
83 ureg_finalize( struct ureg_program * );
84
85 void *
86 ureg_create_shader( struct ureg_program *,
87 struct pipe_context *pipe );
88
89 void
90 ureg_destroy( struct ureg_program * );
91
92
93 /***********************************************************************
94 * Convenience routine:
95 */
96 static INLINE void *
97 ureg_create_shader_and_destroy( struct ureg_program *p,
98 struct pipe_context *pipe )
99 {
100 void *result = ureg_create_shader( p, pipe );
101 ureg_destroy( p );
102 return result;
103 }
104
105
106
107 /***********************************************************************
108 * Build shader declarations:
109 */
110
111 struct ureg_src
112 ureg_DECL_fs_input( struct ureg_program *,
113 unsigned semantic_name,
114 unsigned semantic_index,
115 unsigned interp_mode );
116
117 struct ureg_src
118 ureg_DECL_vs_input( struct ureg_program *,
119 unsigned semantic_name,
120 unsigned semantic_index );
121
122 struct ureg_dst
123 ureg_DECL_output( struct ureg_program *,
124 unsigned semantic_name,
125 unsigned semantic_index );
126
127 struct ureg_src
128 ureg_DECL_immediate( struct ureg_program *,
129 const float *v,
130 unsigned nr );
131
132 struct ureg_src
133 ureg_DECL_constant( struct ureg_program * );
134
135 struct ureg_dst
136 ureg_DECL_temporary( struct ureg_program * );
137
138 void
139 ureg_release_temporary( struct ureg_program *ureg,
140 struct ureg_dst tmp );
141
142 struct ureg_dst
143 ureg_DECL_address( struct ureg_program * );
144
145 /* Supply an index to the sampler declaration as this is the hook to
146 * the external pipe_sampler state. Users of this function probably
147 * don't want just any sampler, but a specific one which they've set
148 * up state for in the context.
149 */
150 struct ureg_src
151 ureg_DECL_sampler( struct ureg_program *,
152 unsigned index );
153
154
155 static INLINE struct ureg_src
156 ureg_imm4f( struct ureg_program *ureg,
157 float a, float b,
158 float c, float d)
159 {
160 float v[4];
161 v[0] = a;
162 v[1] = b;
163 v[2] = c;
164 v[3] = d;
165 return ureg_DECL_immediate( ureg, v, 4 );
166 }
167
168 static INLINE struct ureg_src
169 ureg_imm3f( struct ureg_program *ureg,
170 float a, float b,
171 float c)
172 {
173 float v[3];
174 v[0] = a;
175 v[1] = b;
176 v[2] = c;
177 return ureg_DECL_immediate( ureg, v, 3 );
178 }
179
180 static INLINE struct ureg_src
181 ureg_imm2f( struct ureg_program *ureg,
182 float a, float b)
183 {
184 float v[2];
185 v[0] = a;
186 v[1] = b;
187 return ureg_DECL_immediate( ureg, v, 2 );
188 }
189
190 static INLINE struct ureg_src
191 ureg_imm1f( struct ureg_program *ureg,
192 float a)
193 {
194 float v[1];
195 v[0] = a;
196 return ureg_DECL_immediate( ureg, v, 1 );
197 }
198
199 /***********************************************************************
200 * Functions for patching up labels
201 */
202
203
204 /* Will return a number which can be used in a label to point to the
205 * next instruction to be emitted.
206 */
207 unsigned
208 ureg_get_instruction_number( struct ureg_program *ureg );
209
210
211 /* Patch a given label (expressed as a token number) to point to a
212 * given instruction (expressed as an instruction number).
213 *
214 * Labels are obtained from instruction emitters, eg ureg_CAL().
215 * Instruction numbers are obtained from ureg_get_instruction_number(),
216 * above.
217 */
218 void
219 ureg_fixup_label(struct ureg_program *ureg,
220 unsigned label_token,
221 unsigned instruction_number );
222
223
224 /* Generic instruction emitter. Use if you need to pass the opcode as
225 * a parameter, rather than using the emit_OP() varients below.
226 */
227 void
228 ureg_insn(struct ureg_program *ureg,
229 unsigned opcode,
230 const struct ureg_dst *dst,
231 unsigned nr_dst,
232 const struct ureg_src *src,
233 unsigned nr_src );
234
235
236 /***********************************************************************
237 * Internal instruction helpers, don't call these directly:
238 */
239
240 unsigned
241 ureg_emit_insn(struct ureg_program *ureg,
242 unsigned opcode,
243 boolean saturate,
244 unsigned num_dst,
245 unsigned num_src );
246
247 void
248 ureg_emit_label(struct ureg_program *ureg,
249 unsigned insn_token,
250 unsigned *label_token );
251
252 void
253 ureg_emit_texture(struct ureg_program *ureg,
254 unsigned insn_token,
255 unsigned target );
256
257 void
258 ureg_emit_dst( struct ureg_program *ureg,
259 struct ureg_dst dst );
260
261 void
262 ureg_emit_src( struct ureg_program *ureg,
263 struct ureg_src src );
264
265 void
266 ureg_fixup_insn_size(struct ureg_program *ureg,
267 unsigned insn );
268
269
270 #define OP00( op ) \
271 static INLINE void ureg_##op( struct ureg_program *ureg ) \
272 { \
273 unsigned opcode = TGSI_OPCODE_##op; \
274 unsigned insn = ureg_emit_insn( ureg, opcode, FALSE, 0, 0 ); \
275 ureg_fixup_insn_size( ureg, insn ); \
276 }
277
278 #define OP01( op ) \
279 static INLINE void ureg_##op( struct ureg_program *ureg, \
280 struct ureg_src src ) \
281 { \
282 unsigned opcode = TGSI_OPCODE_##op; \
283 unsigned insn = ureg_emit_insn( ureg, opcode, FALSE, 0, 1 ); \
284 ureg_emit_src( ureg, src ); \
285 ureg_fixup_insn_size( ureg, insn ); \
286 }
287
288 #define OP00_LBL( op ) \
289 static INLINE void ureg_##op( struct ureg_program *ureg, \
290 unsigned *label_token ) \
291 { \
292 unsigned opcode = TGSI_OPCODE_##op; \
293 unsigned insn = ureg_emit_insn( ureg, opcode, FALSE, 0, 0 ); \
294 ureg_emit_label( ureg, insn, label_token ); \
295 ureg_fixup_insn_size( ureg, insn ); \
296 }
297
298 #define OP01_LBL( op ) \
299 static INLINE void ureg_##op( struct ureg_program *ureg, \
300 struct ureg_src src, \
301 unsigned *label_token ) \
302 { \
303 unsigned opcode = TGSI_OPCODE_##op; \
304 unsigned insn = ureg_emit_insn( ureg, opcode, FALSE, 0, 1 ); \
305 ureg_emit_label( ureg, insn, label_token ); \
306 ureg_emit_src( ureg, src ); \
307 ureg_fixup_insn_size( ureg, insn ); \
308 }
309
310 #define OP10( op ) \
311 static INLINE void ureg_##op( struct ureg_program *ureg, \
312 struct ureg_dst dst ) \
313 { \
314 unsigned opcode = TGSI_OPCODE_##op; \
315 unsigned insn = ureg_emit_insn( ureg, opcode, dst.Saturate, 1, 0 ); \
316 ureg_emit_dst( ureg, dst ); \
317 ureg_fixup_insn_size( ureg, insn ); \
318 }
319
320
321 #define OP11( op ) \
322 static INLINE void ureg_##op( struct ureg_program *ureg, \
323 struct ureg_dst dst, \
324 struct ureg_src src ) \
325 { \
326 unsigned opcode = TGSI_OPCODE_##op; \
327 unsigned insn = ureg_emit_insn( ureg, opcode, dst.Saturate, 1, 1 ); \
328 ureg_emit_dst( ureg, dst ); \
329 ureg_emit_src( ureg, src ); \
330 ureg_fixup_insn_size( ureg, insn ); \
331 }
332
333 #define OP12( op ) \
334 static INLINE void ureg_##op( struct ureg_program *ureg, \
335 struct ureg_dst dst, \
336 struct ureg_src src0, \
337 struct ureg_src src1 ) \
338 { \
339 unsigned opcode = TGSI_OPCODE_##op; \
340 unsigned insn = ureg_emit_insn( ureg, opcode, dst.Saturate, 1, 2 ); \
341 ureg_emit_dst( ureg, dst ); \
342 ureg_emit_src( ureg, src0 ); \
343 ureg_emit_src( ureg, src1 ); \
344 ureg_fixup_insn_size( ureg, insn ); \
345 }
346
347 #define OP12_TEX( op ) \
348 static INLINE void ureg_##op( struct ureg_program *ureg, \
349 struct ureg_dst dst, \
350 unsigned target, \
351 struct ureg_src src0, \
352 struct ureg_src src1 ) \
353 { \
354 unsigned opcode = TGSI_OPCODE_##op; \
355 unsigned insn = ureg_emit_insn( ureg, opcode, dst.Saturate, 1, 2 ); \
356 ureg_emit_texture( ureg, insn, target ); \
357 ureg_emit_dst( ureg, dst ); \
358 ureg_emit_src( ureg, src0 ); \
359 ureg_emit_src( ureg, src1 ); \
360 ureg_fixup_insn_size( ureg, insn ); \
361 }
362
363 #define OP13( op ) \
364 static INLINE void ureg_##op( struct ureg_program *ureg, \
365 struct ureg_dst dst, \
366 struct ureg_src src0, \
367 struct ureg_src src1, \
368 struct ureg_src src2 ) \
369 { \
370 unsigned opcode = TGSI_OPCODE_##op; \
371 unsigned insn = ureg_emit_insn( ureg, opcode, dst.Saturate, 1, 3 ); \
372 ureg_emit_dst( ureg, dst ); \
373 ureg_emit_src( ureg, src0 ); \
374 ureg_emit_src( ureg, src1 ); \
375 ureg_emit_src( ureg, src2 ); \
376 ureg_fixup_insn_size( ureg, insn ); \
377 }
378
379 #define OP14_TEX( op ) \
380 static INLINE void ureg_##op( struct ureg_program *ureg, \
381 struct ureg_dst dst, \
382 unsigned target, \
383 struct ureg_src src0, \
384 struct ureg_src src1, \
385 struct ureg_src src2, \
386 struct ureg_src src3 ) \
387 { \
388 unsigned opcode = TGSI_OPCODE_##op; \
389 unsigned insn = ureg_emit_insn( ureg, opcode, dst.Saturate, 1, 4 ); \
390 ureg_emit_texture( ureg, insn, target ); \
391 ureg_emit_dst( ureg, dst ); \
392 ureg_emit_src( ureg, src0 ); \
393 ureg_emit_src( ureg, src1 ); \
394 ureg_emit_src( ureg, src2 ); \
395 ureg_emit_src( ureg, src3 ); \
396 ureg_fixup_insn_size( ureg, insn ); \
397 }
398
399
400 /* Use a template include to generate a correctly-typed ureg_OP()
401 * function for each TGSI opcode:
402 */
403 #include "tgsi_opcode_tmp.h"
404
405
406 /***********************************************************************
407 * Inline helpers for manipulating register structs:
408 */
409 static INLINE struct ureg_src
410 ureg_negate( struct ureg_src reg )
411 {
412 assert(reg.File != TGSI_FILE_NULL);
413 reg.Negate ^= 1;
414 return reg;
415 }
416
417 static INLINE struct ureg_src
418 ureg_abs( struct ureg_src reg )
419 {
420 assert(reg.File != TGSI_FILE_NULL);
421 reg.Absolute = 1;
422 reg.Negate = 0;
423 return reg;
424 }
425
426 static INLINE struct ureg_src
427 ureg_swizzle( struct ureg_src reg,
428 int x, int y, int z, int w )
429 {
430 unsigned swz = ( (reg.SwizzleX << 0) |
431 (reg.SwizzleY << 2) |
432 (reg.SwizzleZ << 4) |
433 (reg.SwizzleW << 6));
434
435 assert(reg.File != TGSI_FILE_NULL);
436 assert(x < 4);
437 assert(y < 4);
438 assert(z < 4);
439 assert(w < 4);
440
441 reg.SwizzleX = (swz >> (x*2)) & 0x3;
442 reg.SwizzleY = (swz >> (y*2)) & 0x3;
443 reg.SwizzleZ = (swz >> (z*2)) & 0x3;
444 reg.SwizzleW = (swz >> (w*2)) & 0x3;
445 return reg;
446 }
447
448 static INLINE struct ureg_src
449 ureg_scalar( struct ureg_src reg, int x )
450 {
451 return ureg_swizzle(reg, x, x, x, x);
452 }
453
454 static INLINE struct ureg_dst
455 ureg_writemask( struct ureg_dst reg,
456 unsigned writemask )
457 {
458 assert(reg.File != TGSI_FILE_NULL);
459 reg.WriteMask &= writemask;
460 return reg;
461 }
462
463 static INLINE struct ureg_dst
464 ureg_saturate( struct ureg_dst reg )
465 {
466 assert(reg.File != TGSI_FILE_NULL);
467 reg.Saturate = 1;
468 return reg;
469 }
470
471 static INLINE struct ureg_dst
472 ureg_dst_indirect( struct ureg_dst reg, struct ureg_src addr )
473 {
474 assert(reg.File != TGSI_FILE_NULL);
475 assert(addr.File == TGSI_FILE_ADDRESS);
476 reg.Indirect = 1;
477 reg.IndirectIndex = addr.Index;
478 reg.IndirectSwizzle = addr.SwizzleX;
479 return reg;
480 }
481
482 static INLINE struct ureg_src
483 ureg_src_indirect( struct ureg_src reg, struct ureg_src addr )
484 {
485 assert(reg.File != TGSI_FILE_NULL);
486 assert(addr.File == TGSI_FILE_ADDRESS);
487 reg.Indirect = 1;
488 reg.IndirectIndex = addr.Index;
489 reg.IndirectSwizzle = addr.SwizzleX;
490 return reg;
491 }
492
493 static INLINE struct ureg_dst
494 ureg_dst( struct ureg_src src )
495 {
496 struct ureg_dst dst;
497
498 dst.File = src.File;
499 dst.WriteMask = TGSI_WRITEMASK_XYZW;
500 dst.Indirect = src.Indirect;
501 dst.IndirectIndex = src.IndirectIndex;
502 dst.IndirectSwizzle = src.IndirectSwizzle;
503 dst.Saturate = 0;
504 dst.Index = src.Index;
505 dst.Pad1 = 0;
506 dst.Pad2 = 0;
507
508 return dst;
509 }
510
511 static INLINE struct ureg_src
512 ureg_src( struct ureg_dst dst )
513 {
514 struct ureg_src src;
515
516 src.File = dst.File;
517 src.SwizzleX = TGSI_SWIZZLE_X;
518 src.SwizzleY = TGSI_SWIZZLE_Y;
519 src.SwizzleZ = TGSI_SWIZZLE_Z;
520 src.SwizzleW = TGSI_SWIZZLE_W;
521 src.Pad = 0;
522 src.Indirect = dst.Indirect;
523 src.IndirectIndex = dst.IndirectIndex;
524 src.IndirectSwizzle = dst.IndirectSwizzle;
525 src.Absolute = 0;
526 src.Index = dst.Index;
527 src.Negate = 0;
528
529 return src;
530 }
531
532
533
534 static INLINE struct ureg_dst
535 ureg_dst_undef( void )
536 {
537 struct ureg_dst dst;
538
539 dst.File = TGSI_FILE_NULL;
540 dst.WriteMask = 0;
541 dst.Indirect = 0;
542 dst.IndirectIndex = 0;
543 dst.IndirectSwizzle = 0;
544 dst.Saturate = 0;
545 dst.Index = 0;
546 dst.Pad1 = 0;
547 dst.Pad2 = 0;
548
549 return dst;
550 }
551
552 static INLINE struct ureg_src
553 ureg_src_undef( void )
554 {
555 struct ureg_src src;
556
557 src.File = TGSI_FILE_NULL;
558 src.SwizzleX = 0;
559 src.SwizzleY = 0;
560 src.SwizzleZ = 0;
561 src.SwizzleW = 0;
562 src.Pad = 0;
563 src.Indirect = 0;
564 src.IndirectIndex = 0;
565 src.IndirectSwizzle = 0;
566 src.Absolute = 0;
567 src.Index = 0;
568 src.Negate = 0;
569
570 return src;
571 }
572
573 static INLINE boolean
574 ureg_src_is_undef( struct ureg_src src )
575 {
576 return src.File == TGSI_FILE_NULL;
577 }
578
579 static INLINE boolean
580 ureg_dst_is_undef( struct ureg_dst dst )
581 {
582 return dst.File == TGSI_FILE_NULL;
583 }
584
585
586 #ifdef __cplusplus
587 }
588 #endif
589
590 #endif