tgsi/ureg: add support for GS input array declarations
[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 #include "util/u_debug.h"
34
35 #ifdef __cplusplus
36 extern "C" {
37 #endif
38
39 struct ureg_program;
40 struct pipe_stream_output_info;
41
42 /* Almost a tgsi_src_register, but we need to pull in the Absolute
43 * flag from the _ext token. Indirect flag always implies ADDR[0].
44 */
45 struct ureg_src
46 {
47 unsigned File : 4; /* TGSI_FILE_ */
48 unsigned SwizzleX : 2; /* TGSI_SWIZZLE_ */
49 unsigned SwizzleY : 2; /* TGSI_SWIZZLE_ */
50 unsigned SwizzleZ : 2; /* TGSI_SWIZZLE_ */
51 unsigned SwizzleW : 2; /* TGSI_SWIZZLE_ */
52 unsigned Indirect : 1; /* BOOL */
53 unsigned DimIndirect : 1; /* BOOL */
54 unsigned Dimension : 1; /* BOOL */
55 unsigned Absolute : 1; /* BOOL */
56 unsigned Negate : 1; /* BOOL */
57 unsigned IndirectFile : 4; /* TGSI_FILE_ */
58 unsigned IndirectSwizzle : 2; /* TGSI_SWIZZLE_ */
59 unsigned DimIndFile : 4; /* TGSI_FILE_ */
60 unsigned DimIndSwizzle : 2; /* TGSI_SWIZZLE_ */
61 int Index : 16; /* SINT */
62 int IndirectIndex : 16; /* SINT */
63 int DimensionIndex : 16; /* SINT */
64 int DimIndIndex : 16; /* SINT */
65 unsigned ArrayID : 10; /* UINT */
66 };
67
68 /* Very similar to a tgsi_dst_register, removing unsupported fields
69 * and adding a Saturate flag. It's easier to push saturate into the
70 * destination register than to try and create a _SAT variant of each
71 * instruction function.
72 */
73 struct ureg_dst
74 {
75 unsigned File : 4; /* TGSI_FILE_ */
76 unsigned WriteMask : 4; /* TGSI_WRITEMASK_ */
77 unsigned Indirect : 1; /* BOOL */
78 unsigned DimIndirect : 1; /* BOOL */
79 unsigned Dimension : 1; /* BOOL */
80 unsigned Saturate : 1; /* BOOL */
81 unsigned Predicate : 1;
82 unsigned PredNegate : 1; /* BOOL */
83 unsigned PredSwizzleX : 2; /* TGSI_SWIZZLE_ */
84 unsigned PredSwizzleY : 2; /* TGSI_SWIZZLE_ */
85 unsigned PredSwizzleZ : 2; /* TGSI_SWIZZLE_ */
86 unsigned PredSwizzleW : 2; /* TGSI_SWIZZLE_ */
87 int Index : 16; /* SINT */
88 int IndirectIndex : 16; /* SINT */
89 unsigned IndirectFile : 4; /* TGSI_FILE_ */
90 int IndirectSwizzle : 2; /* TGSI_SWIZZLE_ */
91 unsigned DimIndFile : 4; /* TGSI_FILE_ */
92 unsigned DimIndSwizzle : 2; /* TGSI_SWIZZLE_ */
93 int DimensionIndex : 16; /* SINT */
94 int DimIndIndex : 16; /* SINT */
95 unsigned ArrayID : 10; /* UINT */
96 };
97
98 struct pipe_context;
99
100 struct ureg_program *
101 ureg_create( unsigned processor );
102
103 const struct tgsi_token *
104 ureg_finalize( struct ureg_program * );
105
106 /* Create and return a shader:
107 */
108 void *
109 ureg_create_shader( struct ureg_program *,
110 struct pipe_context *pipe,
111 const struct pipe_stream_output_info *so );
112
113
114 /* Alternately, return the built token stream and hand ownership of
115 * that memory to the caller:
116 */
117 const struct tgsi_token *
118 ureg_get_tokens( struct ureg_program *ureg,
119 unsigned *nr_tokens );
120
121 /*
122 * Returns the number of currently declared outputs.
123 */
124 unsigned
125 ureg_get_nr_outputs( const struct ureg_program *ureg );
126
127
128 /* Free the tokens created by ureg_get_tokens() */
129 void ureg_free_tokens( const struct tgsi_token *tokens );
130
131
132 void
133 ureg_destroy( struct ureg_program * );
134
135
136 /***********************************************************************
137 * Convenience routine:
138 */
139 static INLINE void *
140 ureg_create_shader_with_so_and_destroy( struct ureg_program *p,
141 struct pipe_context *pipe,
142 const struct pipe_stream_output_info *so )
143 {
144 void *result = ureg_create_shader( p, pipe, so );
145 ureg_destroy( p );
146 return result;
147 }
148
149 static INLINE void *
150 ureg_create_shader_and_destroy( struct ureg_program *p,
151 struct pipe_context *pipe )
152 {
153 return ureg_create_shader_with_so_and_destroy(p, pipe, NULL);
154 }
155
156
157 /***********************************************************************
158 * Build shader properties:
159 */
160
161 void
162 ureg_property(struct ureg_program *ureg, unsigned name, unsigned value);
163
164
165 /***********************************************************************
166 * Build shader declarations:
167 */
168
169 struct ureg_src
170 ureg_DECL_fs_input_cyl_centroid(struct ureg_program *,
171 unsigned semantic_name,
172 unsigned semantic_index,
173 unsigned interp_mode,
174 unsigned cylindrical_wrap,
175 unsigned interp_location,
176 unsigned array_id,
177 unsigned array_size);
178
179 static INLINE struct ureg_src
180 ureg_DECL_fs_input_cyl(struct ureg_program *ureg,
181 unsigned semantic_name,
182 unsigned semantic_index,
183 unsigned interp_mode,
184 unsigned cylindrical_wrap)
185 {
186 return ureg_DECL_fs_input_cyl_centroid(ureg,
187 semantic_name,
188 semantic_index,
189 interp_mode,
190 cylindrical_wrap,
191 0, 0, 1);
192 }
193
194 static INLINE struct ureg_src
195 ureg_DECL_fs_input(struct ureg_program *ureg,
196 unsigned semantic_name,
197 unsigned semantic_index,
198 unsigned interp_mode)
199 {
200 return ureg_DECL_fs_input_cyl_centroid(ureg,
201 semantic_name,
202 semantic_index,
203 interp_mode,
204 0, 0, 0, 1);
205 }
206
207 struct ureg_src
208 ureg_DECL_vs_input( struct ureg_program *,
209 unsigned index );
210
211 struct ureg_src
212 ureg_DECL_input(struct ureg_program *,
213 unsigned semantic_name,
214 unsigned semantic_index,
215 unsigned array_id,
216 unsigned array_size);
217
218 struct ureg_src
219 ureg_DECL_system_value(struct ureg_program *,
220 unsigned index,
221 unsigned semantic_name,
222 unsigned semantic_index);
223
224 struct ureg_dst
225 ureg_DECL_output_masked( struct ureg_program *,
226 unsigned semantic_name,
227 unsigned semantic_index,
228 unsigned usage_mask );
229
230 struct ureg_dst
231 ureg_DECL_output( struct ureg_program *,
232 unsigned semantic_name,
233 unsigned semantic_index );
234
235 struct ureg_src
236 ureg_DECL_immediate( struct ureg_program *,
237 const float *v,
238 unsigned nr );
239
240 struct ureg_src
241 ureg_DECL_immediate_f64( struct ureg_program *,
242 const double *v,
243 unsigned nr );
244
245 struct ureg_src
246 ureg_DECL_immediate_uint( struct ureg_program *,
247 const unsigned *v,
248 unsigned nr );
249
250 struct ureg_src
251 ureg_DECL_immediate_block_uint( struct ureg_program *,
252 const unsigned *v,
253 unsigned nr );
254
255 struct ureg_src
256 ureg_DECL_immediate_int( struct ureg_program *,
257 const int *v,
258 unsigned nr );
259
260 void
261 ureg_DECL_constant2D(struct ureg_program *ureg,
262 unsigned first,
263 unsigned last,
264 unsigned index2D);
265
266 struct ureg_src
267 ureg_DECL_constant( struct ureg_program *,
268 unsigned index );
269
270 struct ureg_dst
271 ureg_DECL_temporary( struct ureg_program * );
272
273 /**
274 * Emit a temporary with the LOCAL declaration flag set. For use when
275 * the register value is not required to be preserved across
276 * subroutine boundaries.
277 */
278 struct ureg_dst
279 ureg_DECL_local_temporary( struct ureg_program * );
280
281 /**
282 * Declare "size" continuous temporary registers.
283 */
284 struct ureg_dst
285 ureg_DECL_array_temporary( struct ureg_program *,
286 unsigned size,
287 boolean local );
288
289 void
290 ureg_release_temporary( struct ureg_program *ureg,
291 struct ureg_dst tmp );
292
293 struct ureg_dst
294 ureg_DECL_address( struct ureg_program * );
295
296 struct ureg_dst
297 ureg_DECL_predicate(struct ureg_program *);
298
299 /* Supply an index to the sampler declaration as this is the hook to
300 * the external pipe_sampler state. Users of this function probably
301 * don't want just any sampler, but a specific one which they've set
302 * up state for in the context.
303 */
304 struct ureg_src
305 ureg_DECL_sampler( struct ureg_program *,
306 unsigned index );
307
308 struct ureg_src
309 ureg_DECL_sampler_view(struct ureg_program *,
310 unsigned index,
311 unsigned target,
312 unsigned return_type_x,
313 unsigned return_type_y,
314 unsigned return_type_z,
315 unsigned return_type_w );
316
317
318 static INLINE struct ureg_src
319 ureg_imm4f( struct ureg_program *ureg,
320 float a, float b,
321 float c, float d)
322 {
323 float v[4];
324 v[0] = a;
325 v[1] = b;
326 v[2] = c;
327 v[3] = d;
328 return ureg_DECL_immediate( ureg, v, 4 );
329 }
330
331 static INLINE struct ureg_src
332 ureg_imm3f( struct ureg_program *ureg,
333 float a, float b,
334 float c)
335 {
336 float v[3];
337 v[0] = a;
338 v[1] = b;
339 v[2] = c;
340 return ureg_DECL_immediate( ureg, v, 3 );
341 }
342
343 static INLINE struct ureg_src
344 ureg_imm2f( struct ureg_program *ureg,
345 float a, float b)
346 {
347 float v[2];
348 v[0] = a;
349 v[1] = b;
350 return ureg_DECL_immediate( ureg, v, 2 );
351 }
352
353 static INLINE struct ureg_src
354 ureg_imm1f( struct ureg_program *ureg,
355 float a)
356 {
357 float v[1];
358 v[0] = a;
359 return ureg_DECL_immediate( ureg, v, 1 );
360 }
361
362 static INLINE struct ureg_src
363 ureg_imm4u( struct ureg_program *ureg,
364 unsigned a, unsigned b,
365 unsigned c, unsigned d)
366 {
367 unsigned v[4];
368 v[0] = a;
369 v[1] = b;
370 v[2] = c;
371 v[3] = d;
372 return ureg_DECL_immediate_uint( ureg, v, 4 );
373 }
374
375 static INLINE struct ureg_src
376 ureg_imm3u( struct ureg_program *ureg,
377 unsigned a, unsigned b,
378 unsigned c)
379 {
380 unsigned v[3];
381 v[0] = a;
382 v[1] = b;
383 v[2] = c;
384 return ureg_DECL_immediate_uint( ureg, v, 3 );
385 }
386
387 static INLINE struct ureg_src
388 ureg_imm2u( struct ureg_program *ureg,
389 unsigned a, unsigned b)
390 {
391 unsigned v[2];
392 v[0] = a;
393 v[1] = b;
394 return ureg_DECL_immediate_uint( ureg, v, 2 );
395 }
396
397 static INLINE struct ureg_src
398 ureg_imm1u( struct ureg_program *ureg,
399 unsigned a)
400 {
401 return ureg_DECL_immediate_uint( ureg, &a, 1 );
402 }
403
404 static INLINE struct ureg_src
405 ureg_imm4i( struct ureg_program *ureg,
406 int a, int b,
407 int c, int d)
408 {
409 int v[4];
410 v[0] = a;
411 v[1] = b;
412 v[2] = c;
413 v[3] = d;
414 return ureg_DECL_immediate_int( ureg, v, 4 );
415 }
416
417 static INLINE struct ureg_src
418 ureg_imm3i( struct ureg_program *ureg,
419 int a, int b,
420 int c)
421 {
422 int v[3];
423 v[0] = a;
424 v[1] = b;
425 v[2] = c;
426 return ureg_DECL_immediate_int( ureg, v, 3 );
427 }
428
429 static INLINE struct ureg_src
430 ureg_imm2i( struct ureg_program *ureg,
431 int a, int b)
432 {
433 int v[2];
434 v[0] = a;
435 v[1] = b;
436 return ureg_DECL_immediate_int( ureg, v, 2 );
437 }
438
439 static INLINE struct ureg_src
440 ureg_imm1i( struct ureg_program *ureg,
441 int a)
442 {
443 return ureg_DECL_immediate_int( ureg, &a, 1 );
444 }
445
446 /* Where the destination register has a valid file, but an empty
447 * writemask.
448 */
449 static INLINE boolean
450 ureg_dst_is_empty( struct ureg_dst dst )
451 {
452 return dst.File != TGSI_FILE_NULL &&
453 dst.WriteMask == 0;
454 }
455
456 /***********************************************************************
457 * Functions for patching up labels
458 */
459
460
461 /* Will return a number which can be used in a label to point to the
462 * next instruction to be emitted.
463 */
464 unsigned
465 ureg_get_instruction_number( struct ureg_program *ureg );
466
467
468 /* Patch a given label (expressed as a token number) to point to a
469 * given instruction (expressed as an instruction number).
470 *
471 * Labels are obtained from instruction emitters, eg ureg_CAL().
472 * Instruction numbers are obtained from ureg_get_instruction_number(),
473 * above.
474 */
475 void
476 ureg_fixup_label(struct ureg_program *ureg,
477 unsigned label_token,
478 unsigned instruction_number );
479
480
481 /* Generic instruction emitter. Use if you need to pass the opcode as
482 * a parameter, rather than using the emit_OP() variants below.
483 */
484 void
485 ureg_insn(struct ureg_program *ureg,
486 unsigned opcode,
487 const struct ureg_dst *dst,
488 unsigned nr_dst,
489 const struct ureg_src *src,
490 unsigned nr_src );
491
492
493 void
494 ureg_tex_insn(struct ureg_program *ureg,
495 unsigned opcode,
496 const struct ureg_dst *dst,
497 unsigned nr_dst,
498 unsigned target,
499 const struct tgsi_texture_offset *texoffsets,
500 unsigned nr_offset,
501 const struct ureg_src *src,
502 unsigned nr_src );
503
504
505 void
506 ureg_label_insn(struct ureg_program *ureg,
507 unsigned opcode,
508 const struct ureg_src *src,
509 unsigned nr_src,
510 unsigned *label);
511
512
513 /***********************************************************************
514 * Internal instruction helpers, don't call these directly:
515 */
516
517 struct ureg_emit_insn_result {
518 unsigned insn_token; /*< Used to fixup insn size. */
519 unsigned extended_token; /*< Used to set the Extended bit, usually the same as insn_token. */
520 };
521
522 struct ureg_emit_insn_result
523 ureg_emit_insn(struct ureg_program *ureg,
524 unsigned opcode,
525 boolean saturate,
526 boolean predicate,
527 boolean pred_negate,
528 unsigned pred_swizzle_x,
529 unsigned pred_swizzle_y,
530 unsigned pred_swizzle_z,
531 unsigned pred_swizzle_w,
532 unsigned num_dst,
533 unsigned num_src );
534
535 void
536 ureg_emit_label(struct ureg_program *ureg,
537 unsigned insn_token,
538 unsigned *label_token );
539
540 void
541 ureg_emit_texture(struct ureg_program *ureg,
542 unsigned insn_token,
543 unsigned target, unsigned num_offsets);
544
545 void
546 ureg_emit_texture_offset(struct ureg_program *ureg,
547 const struct tgsi_texture_offset *offset);
548
549 void
550 ureg_emit_dst( struct ureg_program *ureg,
551 struct ureg_dst dst );
552
553 void
554 ureg_emit_src( struct ureg_program *ureg,
555 struct ureg_src src );
556
557 void
558 ureg_fixup_insn_size(struct ureg_program *ureg,
559 unsigned insn );
560
561
562 #define OP00( op ) \
563 static INLINE void ureg_##op( struct ureg_program *ureg ) \
564 { \
565 unsigned opcode = TGSI_OPCODE_##op; \
566 struct ureg_emit_insn_result insn; \
567 insn = ureg_emit_insn(ureg, \
568 opcode, \
569 FALSE, \
570 FALSE, \
571 FALSE, \
572 TGSI_SWIZZLE_X, \
573 TGSI_SWIZZLE_Y, \
574 TGSI_SWIZZLE_Z, \
575 TGSI_SWIZZLE_W, \
576 0, \
577 0); \
578 ureg_fixup_insn_size( ureg, insn.insn_token ); \
579 }
580
581 #define OP01( op ) \
582 static INLINE void ureg_##op( struct ureg_program *ureg, \
583 struct ureg_src src ) \
584 { \
585 unsigned opcode = TGSI_OPCODE_##op; \
586 struct ureg_emit_insn_result insn; \
587 insn = ureg_emit_insn(ureg, \
588 opcode, \
589 FALSE, \
590 FALSE, \
591 FALSE, \
592 TGSI_SWIZZLE_X, \
593 TGSI_SWIZZLE_Y, \
594 TGSI_SWIZZLE_Z, \
595 TGSI_SWIZZLE_W, \
596 0, \
597 1); \
598 ureg_emit_src( ureg, src ); \
599 ureg_fixup_insn_size( ureg, insn.insn_token ); \
600 }
601
602 #define OP00_LBL( op ) \
603 static INLINE void ureg_##op( struct ureg_program *ureg, \
604 unsigned *label_token ) \
605 { \
606 unsigned opcode = TGSI_OPCODE_##op; \
607 struct ureg_emit_insn_result insn; \
608 insn = ureg_emit_insn(ureg, \
609 opcode, \
610 FALSE, \
611 FALSE, \
612 FALSE, \
613 TGSI_SWIZZLE_X, \
614 TGSI_SWIZZLE_Y, \
615 TGSI_SWIZZLE_Z, \
616 TGSI_SWIZZLE_W, \
617 0, \
618 0); \
619 ureg_emit_label( ureg, insn.extended_token, label_token ); \
620 ureg_fixup_insn_size( ureg, insn.insn_token ); \
621 }
622
623 #define OP01_LBL( op ) \
624 static INLINE void ureg_##op( struct ureg_program *ureg, \
625 struct ureg_src src, \
626 unsigned *label_token ) \
627 { \
628 unsigned opcode = TGSI_OPCODE_##op; \
629 struct ureg_emit_insn_result insn; \
630 insn = ureg_emit_insn(ureg, \
631 opcode, \
632 FALSE, \
633 FALSE, \
634 FALSE, \
635 TGSI_SWIZZLE_X, \
636 TGSI_SWIZZLE_Y, \
637 TGSI_SWIZZLE_Z, \
638 TGSI_SWIZZLE_W, \
639 0, \
640 1); \
641 ureg_emit_label( ureg, insn.extended_token, label_token ); \
642 ureg_emit_src( ureg, src ); \
643 ureg_fixup_insn_size( ureg, insn.insn_token ); \
644 }
645
646 #define OP10( op ) \
647 static INLINE void ureg_##op( struct ureg_program *ureg, \
648 struct ureg_dst dst ) \
649 { \
650 unsigned opcode = TGSI_OPCODE_##op; \
651 struct ureg_emit_insn_result insn; \
652 if (ureg_dst_is_empty(dst)) \
653 return; \
654 insn = ureg_emit_insn(ureg, \
655 opcode, \
656 dst.Saturate, \
657 dst.Predicate, \
658 dst.PredNegate, \
659 dst.PredSwizzleX, \
660 dst.PredSwizzleY, \
661 dst.PredSwizzleZ, \
662 dst.PredSwizzleW, \
663 1, \
664 0); \
665 ureg_emit_dst( ureg, dst ); \
666 ureg_fixup_insn_size( ureg, insn.insn_token ); \
667 }
668
669
670 #define OP11( op ) \
671 static INLINE void ureg_##op( struct ureg_program *ureg, \
672 struct ureg_dst dst, \
673 struct ureg_src src ) \
674 { \
675 unsigned opcode = TGSI_OPCODE_##op; \
676 struct ureg_emit_insn_result insn; \
677 if (ureg_dst_is_empty(dst)) \
678 return; \
679 insn = ureg_emit_insn(ureg, \
680 opcode, \
681 dst.Saturate, \
682 dst.Predicate, \
683 dst.PredNegate, \
684 dst.PredSwizzleX, \
685 dst.PredSwizzleY, \
686 dst.PredSwizzleZ, \
687 dst.PredSwizzleW, \
688 1, \
689 1); \
690 ureg_emit_dst( ureg, dst ); \
691 ureg_emit_src( ureg, src ); \
692 ureg_fixup_insn_size( ureg, insn.insn_token ); \
693 }
694
695 #define OP12( op ) \
696 static INLINE void ureg_##op( struct ureg_program *ureg, \
697 struct ureg_dst dst, \
698 struct ureg_src src0, \
699 struct ureg_src src1 ) \
700 { \
701 unsigned opcode = TGSI_OPCODE_##op; \
702 struct ureg_emit_insn_result insn; \
703 if (ureg_dst_is_empty(dst)) \
704 return; \
705 insn = ureg_emit_insn(ureg, \
706 opcode, \
707 dst.Saturate, \
708 dst.Predicate, \
709 dst.PredNegate, \
710 dst.PredSwizzleX, \
711 dst.PredSwizzleY, \
712 dst.PredSwizzleZ, \
713 dst.PredSwizzleW, \
714 1, \
715 2); \
716 ureg_emit_dst( ureg, dst ); \
717 ureg_emit_src( ureg, src0 ); \
718 ureg_emit_src( ureg, src1 ); \
719 ureg_fixup_insn_size( ureg, insn.insn_token ); \
720 }
721
722 #define OP12_TEX( op ) \
723 static INLINE void ureg_##op( struct ureg_program *ureg, \
724 struct ureg_dst dst, \
725 unsigned target, \
726 struct ureg_src src0, \
727 struct ureg_src src1 ) \
728 { \
729 unsigned opcode = TGSI_OPCODE_##op; \
730 struct ureg_emit_insn_result insn; \
731 if (ureg_dst_is_empty(dst)) \
732 return; \
733 insn = ureg_emit_insn(ureg, \
734 opcode, \
735 dst.Saturate, \
736 dst.Predicate, \
737 dst.PredNegate, \
738 dst.PredSwizzleX, \
739 dst.PredSwizzleY, \
740 dst.PredSwizzleZ, \
741 dst.PredSwizzleW, \
742 1, \
743 2); \
744 ureg_emit_texture( ureg, insn.extended_token, target, 0 ); \
745 ureg_emit_dst( ureg, dst ); \
746 ureg_emit_src( ureg, src0 ); \
747 ureg_emit_src( ureg, src1 ); \
748 ureg_fixup_insn_size( ureg, insn.insn_token ); \
749 }
750
751 #define OP12_SAMPLE( op ) \
752 static INLINE void ureg_##op( struct ureg_program *ureg, \
753 struct ureg_dst dst, \
754 struct ureg_src src0, \
755 struct ureg_src src1 ) \
756 { \
757 unsigned opcode = TGSI_OPCODE_##op; \
758 unsigned target = TGSI_TEXTURE_UNKNOWN; \
759 struct ureg_emit_insn_result insn; \
760 if (ureg_dst_is_empty(dst)) \
761 return; \
762 insn = ureg_emit_insn(ureg, \
763 opcode, \
764 dst.Saturate, \
765 dst.Predicate, \
766 dst.PredNegate, \
767 dst.PredSwizzleX, \
768 dst.PredSwizzleY, \
769 dst.PredSwizzleZ, \
770 dst.PredSwizzleW, \
771 1, \
772 2); \
773 ureg_emit_texture( ureg, insn.extended_token, target, 0 ); \
774 ureg_emit_dst( ureg, dst ); \
775 ureg_emit_src( ureg, src0 ); \
776 ureg_emit_src( ureg, src1 ); \
777 ureg_fixup_insn_size( ureg, insn.insn_token ); \
778 }
779
780 #define OP13( op ) \
781 static INLINE void ureg_##op( struct ureg_program *ureg, \
782 struct ureg_dst dst, \
783 struct ureg_src src0, \
784 struct ureg_src src1, \
785 struct ureg_src src2 ) \
786 { \
787 unsigned opcode = TGSI_OPCODE_##op; \
788 struct ureg_emit_insn_result insn; \
789 if (ureg_dst_is_empty(dst)) \
790 return; \
791 insn = ureg_emit_insn(ureg, \
792 opcode, \
793 dst.Saturate, \
794 dst.Predicate, \
795 dst.PredNegate, \
796 dst.PredSwizzleX, \
797 dst.PredSwizzleY, \
798 dst.PredSwizzleZ, \
799 dst.PredSwizzleW, \
800 1, \
801 3); \
802 ureg_emit_dst( ureg, dst ); \
803 ureg_emit_src( ureg, src0 ); \
804 ureg_emit_src( ureg, src1 ); \
805 ureg_emit_src( ureg, src2 ); \
806 ureg_fixup_insn_size( ureg, insn.insn_token ); \
807 }
808
809 #define OP13_SAMPLE( op ) \
810 static INLINE void ureg_##op( struct ureg_program *ureg, \
811 struct ureg_dst dst, \
812 struct ureg_src src0, \
813 struct ureg_src src1, \
814 struct ureg_src src2 ) \
815 { \
816 unsigned opcode = TGSI_OPCODE_##op; \
817 unsigned target = TGSI_TEXTURE_UNKNOWN; \
818 struct ureg_emit_insn_result insn; \
819 if (ureg_dst_is_empty(dst)) \
820 return; \
821 insn = ureg_emit_insn(ureg, \
822 opcode, \
823 dst.Saturate, \
824 dst.Predicate, \
825 dst.PredNegate, \
826 dst.PredSwizzleX, \
827 dst.PredSwizzleY, \
828 dst.PredSwizzleZ, \
829 dst.PredSwizzleW, \
830 1, \
831 3); \
832 ureg_emit_texture( ureg, insn.extended_token, target, 0 ); \
833 ureg_emit_dst( ureg, dst ); \
834 ureg_emit_src( ureg, src0 ); \
835 ureg_emit_src( ureg, src1 ); \
836 ureg_emit_src( ureg, src2 ); \
837 ureg_fixup_insn_size( ureg, insn.insn_token ); \
838 }
839
840 #define OP14_TEX( op ) \
841 static INLINE void ureg_##op( struct ureg_program *ureg, \
842 struct ureg_dst dst, \
843 unsigned target, \
844 struct ureg_src src0, \
845 struct ureg_src src1, \
846 struct ureg_src src2, \
847 struct ureg_src src3 ) \
848 { \
849 unsigned opcode = TGSI_OPCODE_##op; \
850 struct ureg_emit_insn_result insn; \
851 if (ureg_dst_is_empty(dst)) \
852 return; \
853 insn = ureg_emit_insn(ureg, \
854 opcode, \
855 dst.Saturate, \
856 dst.Predicate, \
857 dst.PredNegate, \
858 dst.PredSwizzleX, \
859 dst.PredSwizzleY, \
860 dst.PredSwizzleZ, \
861 dst.PredSwizzleW, \
862 1, \
863 4); \
864 ureg_emit_texture( ureg, insn.extended_token, target, 0 ); \
865 ureg_emit_dst( ureg, dst ); \
866 ureg_emit_src( ureg, src0 ); \
867 ureg_emit_src( ureg, src1 ); \
868 ureg_emit_src( ureg, src2 ); \
869 ureg_emit_src( ureg, src3 ); \
870 ureg_fixup_insn_size( ureg, insn.insn_token ); \
871 }
872
873 #define OP14_SAMPLE( op ) \
874 static INLINE void ureg_##op( struct ureg_program *ureg, \
875 struct ureg_dst dst, \
876 struct ureg_src src0, \
877 struct ureg_src src1, \
878 struct ureg_src src2, \
879 struct ureg_src src3 ) \
880 { \
881 unsigned opcode = TGSI_OPCODE_##op; \
882 unsigned target = TGSI_TEXTURE_UNKNOWN; \
883 struct ureg_emit_insn_result insn; \
884 if (ureg_dst_is_empty(dst)) \
885 return; \
886 insn = ureg_emit_insn(ureg, \
887 opcode, \
888 dst.Saturate, \
889 dst.Predicate, \
890 dst.PredNegate, \
891 dst.PredSwizzleX, \
892 dst.PredSwizzleY, \
893 dst.PredSwizzleZ, \
894 dst.PredSwizzleW, \
895 1, \
896 4); \
897 ureg_emit_texture( ureg, insn.extended_token, target, 0 ); \
898 ureg_emit_dst( ureg, dst ); \
899 ureg_emit_src( ureg, src0 ); \
900 ureg_emit_src( ureg, src1 ); \
901 ureg_emit_src( ureg, src2 ); \
902 ureg_emit_src( ureg, src3 ); \
903 ureg_fixup_insn_size( ureg, insn.insn_token ); \
904 }
905
906
907 #define OP14( op ) \
908 static INLINE void ureg_##op( struct ureg_program *ureg, \
909 struct ureg_dst dst, \
910 struct ureg_src src0, \
911 struct ureg_src src1, \
912 struct ureg_src src2, \
913 struct ureg_src src3 ) \
914 { \
915 unsigned opcode = TGSI_OPCODE_##op; \
916 struct ureg_emit_insn_result insn; \
917 if (ureg_dst_is_empty(dst)) \
918 return; \
919 insn = ureg_emit_insn(ureg, \
920 opcode, \
921 dst.Saturate, \
922 dst.Predicate, \
923 dst.PredNegate, \
924 dst.PredSwizzleX, \
925 dst.PredSwizzleY, \
926 dst.PredSwizzleZ, \
927 dst.PredSwizzleW, \
928 1, \
929 4); \
930 ureg_emit_dst( ureg, dst ); \
931 ureg_emit_src( ureg, src0 ); \
932 ureg_emit_src( ureg, src1 ); \
933 ureg_emit_src( ureg, src2 ); \
934 ureg_emit_src( ureg, src3 ); \
935 ureg_fixup_insn_size( ureg, insn.insn_token ); \
936 }
937
938
939 #define OP15( op ) \
940 static INLINE void ureg_##op( struct ureg_program *ureg, \
941 struct ureg_dst dst, \
942 struct ureg_src src0, \
943 struct ureg_src src1, \
944 struct ureg_src src2, \
945 struct ureg_src src3, \
946 struct ureg_src src4 ) \
947 { \
948 unsigned opcode = TGSI_OPCODE_##op; \
949 struct ureg_emit_insn_result insn; \
950 if (ureg_dst_is_empty(dst)) \
951 return; \
952 insn = ureg_emit_insn(ureg, \
953 opcode, \
954 dst.Saturate, \
955 dst.Predicate, \
956 dst.PredNegate, \
957 dst.PredSwizzleX, \
958 dst.PredSwizzleY, \
959 dst.PredSwizzleZ, \
960 dst.PredSwizzleW, \
961 1, \
962 5); \
963 ureg_emit_dst( ureg, dst ); \
964 ureg_emit_src( ureg, src0 ); \
965 ureg_emit_src( ureg, src1 ); \
966 ureg_emit_src( ureg, src2 ); \
967 ureg_emit_src( ureg, src3 ); \
968 ureg_emit_src( ureg, src4 ); \
969 ureg_fixup_insn_size( ureg, insn.insn_token ); \
970 }
971
972 #define OP15_SAMPLE( op ) \
973 static INLINE void ureg_##op( struct ureg_program *ureg, \
974 struct ureg_dst dst, \
975 struct ureg_src src0, \
976 struct ureg_src src1, \
977 struct ureg_src src2, \
978 struct ureg_src src3, \
979 struct ureg_src src4 ) \
980 { \
981 unsigned opcode = TGSI_OPCODE_##op; \
982 unsigned target = TGSI_TEXTURE_UNKNOWN; \
983 struct ureg_emit_insn_result insn; \
984 if (ureg_dst_is_empty(dst)) \
985 return; \
986 insn = ureg_emit_insn(ureg, \
987 opcode, \
988 dst.Saturate, \
989 dst.Predicate, \
990 dst.PredNegate, \
991 dst.PredSwizzleX, \
992 dst.PredSwizzleY, \
993 dst.PredSwizzleZ, \
994 dst.PredSwizzleW, \
995 1, \
996 5); \
997 ureg_emit_texture( ureg, insn.extended_token, target, 0 ); \
998 ureg_emit_dst( ureg, dst ); \
999 ureg_emit_src( ureg, src0 ); \
1000 ureg_emit_src( ureg, src1 ); \
1001 ureg_emit_src( ureg, src2 ); \
1002 ureg_emit_src( ureg, src3 ); \
1003 ureg_emit_src( ureg, src4 ); \
1004 ureg_fixup_insn_size( ureg, insn.insn_token ); \
1005 }
1006
1007 /* Use a template include to generate a correctly-typed ureg_OP()
1008 * function for each TGSI opcode:
1009 */
1010 #include "tgsi_opcode_tmp.h"
1011
1012
1013 /***********************************************************************
1014 * Inline helpers for manipulating register structs:
1015 */
1016 static INLINE struct ureg_src
1017 ureg_negate( struct ureg_src reg )
1018 {
1019 assert(reg.File != TGSI_FILE_NULL);
1020 reg.Negate ^= 1;
1021 return reg;
1022 }
1023
1024 static INLINE struct ureg_src
1025 ureg_abs( struct ureg_src reg )
1026 {
1027 assert(reg.File != TGSI_FILE_NULL);
1028 reg.Absolute = 1;
1029 reg.Negate = 0;
1030 return reg;
1031 }
1032
1033 static INLINE struct ureg_src
1034 ureg_swizzle( struct ureg_src reg,
1035 int x, int y, int z, int w )
1036 {
1037 unsigned swz = ( (reg.SwizzleX << 0) |
1038 (reg.SwizzleY << 2) |
1039 (reg.SwizzleZ << 4) |
1040 (reg.SwizzleW << 6));
1041
1042 assert(reg.File != TGSI_FILE_NULL);
1043 assert(x < 4);
1044 assert(y < 4);
1045 assert(z < 4);
1046 assert(w < 4);
1047
1048 reg.SwizzleX = (swz >> (x*2)) & 0x3;
1049 reg.SwizzleY = (swz >> (y*2)) & 0x3;
1050 reg.SwizzleZ = (swz >> (z*2)) & 0x3;
1051 reg.SwizzleW = (swz >> (w*2)) & 0x3;
1052 return reg;
1053 }
1054
1055 static INLINE struct ureg_src
1056 ureg_scalar( struct ureg_src reg, int x )
1057 {
1058 return ureg_swizzle(reg, x, x, x, x);
1059 }
1060
1061 static INLINE struct ureg_dst
1062 ureg_writemask( struct ureg_dst reg,
1063 unsigned writemask )
1064 {
1065 assert(reg.File != TGSI_FILE_NULL);
1066 reg.WriteMask &= writemask;
1067 return reg;
1068 }
1069
1070 static INLINE struct ureg_dst
1071 ureg_saturate( struct ureg_dst reg )
1072 {
1073 assert(reg.File != TGSI_FILE_NULL);
1074 reg.Saturate = 1;
1075 return reg;
1076 }
1077
1078 static INLINE struct ureg_dst
1079 ureg_predicate(struct ureg_dst reg,
1080 boolean negate,
1081 unsigned swizzle_x,
1082 unsigned swizzle_y,
1083 unsigned swizzle_z,
1084 unsigned swizzle_w)
1085 {
1086 assert(reg.File != TGSI_FILE_NULL);
1087 reg.Predicate = 1;
1088 reg.PredNegate = negate;
1089 reg.PredSwizzleX = swizzle_x;
1090 reg.PredSwizzleY = swizzle_y;
1091 reg.PredSwizzleZ = swizzle_z;
1092 reg.PredSwizzleW = swizzle_w;
1093 return reg;
1094 }
1095
1096 static INLINE struct ureg_dst
1097 ureg_dst_indirect( struct ureg_dst reg, struct ureg_src addr )
1098 {
1099 assert(reg.File != TGSI_FILE_NULL);
1100 assert(addr.File == TGSI_FILE_ADDRESS || addr.File == TGSI_FILE_TEMPORARY);
1101 reg.Indirect = 1;
1102 reg.IndirectFile = addr.File;
1103 reg.IndirectIndex = addr.Index;
1104 reg.IndirectSwizzle = addr.SwizzleX;
1105 return reg;
1106 }
1107
1108 static INLINE struct ureg_src
1109 ureg_src_indirect( struct ureg_src reg, struct ureg_src addr )
1110 {
1111 assert(reg.File != TGSI_FILE_NULL);
1112 assert(addr.File == TGSI_FILE_ADDRESS || addr.File == TGSI_FILE_TEMPORARY);
1113 reg.Indirect = 1;
1114 reg.IndirectFile = addr.File;
1115 reg.IndirectIndex = addr.Index;
1116 reg.IndirectSwizzle = addr.SwizzleX;
1117 return reg;
1118 }
1119
1120 static INLINE struct ureg_dst
1121 ureg_dst_dimension( struct ureg_dst reg, int index )
1122 {
1123 assert(reg.File != TGSI_FILE_NULL);
1124 reg.Dimension = 1;
1125 reg.DimIndirect = 0;
1126 reg.DimensionIndex = index;
1127 return reg;
1128 }
1129
1130 static INLINE struct ureg_src
1131 ureg_src_dimension( struct ureg_src reg, int index )
1132 {
1133 assert(reg.File != TGSI_FILE_NULL);
1134 reg.Dimension = 1;
1135 reg.DimIndirect = 0;
1136 reg.DimensionIndex = index;
1137 return reg;
1138 }
1139
1140 static INLINE struct ureg_dst
1141 ureg_dst_dimension_indirect( struct ureg_dst reg, struct ureg_src addr,
1142 int index )
1143 {
1144 assert(reg.File != TGSI_FILE_NULL);
1145 reg.Dimension = 1;
1146 reg.DimIndirect = 1;
1147 reg.DimensionIndex = index;
1148 reg.DimIndFile = addr.File;
1149 reg.DimIndIndex = addr.Index;
1150 reg.DimIndSwizzle = addr.SwizzleX;
1151 return reg;
1152 }
1153
1154 static INLINE struct ureg_src
1155 ureg_src_dimension_indirect( struct ureg_src reg, struct ureg_src addr,
1156 int index )
1157 {
1158 assert(reg.File != TGSI_FILE_NULL);
1159 reg.Dimension = 1;
1160 reg.DimIndirect = 1;
1161 reg.DimensionIndex = index;
1162 reg.DimIndFile = addr.File;
1163 reg.DimIndIndex = addr.Index;
1164 reg.DimIndSwizzle = addr.SwizzleX;
1165 return reg;
1166 }
1167
1168 static INLINE struct ureg_src
1169 ureg_src_array_offset(struct ureg_src reg, int offset)
1170 {
1171 reg.Index += offset;
1172 return reg;
1173 }
1174
1175 static INLINE struct ureg_dst
1176 ureg_dst_array_offset( struct ureg_dst reg, int offset )
1177 {
1178 assert(reg.File == TGSI_FILE_TEMPORARY);
1179 reg.Index += offset;
1180 return reg;
1181 }
1182
1183 static INLINE struct ureg_dst
1184 ureg_dst_register( unsigned file,
1185 unsigned index )
1186 {
1187 struct ureg_dst dst;
1188
1189 dst.File = file;
1190 dst.WriteMask = TGSI_WRITEMASK_XYZW;
1191 dst.Indirect = 0;
1192 dst.IndirectFile = TGSI_FILE_NULL;
1193 dst.IndirectIndex = 0;
1194 dst.IndirectSwizzle = 0;
1195 dst.Saturate = 0;
1196 dst.Predicate = 0;
1197 dst.PredNegate = 0;
1198 dst.PredSwizzleX = TGSI_SWIZZLE_X;
1199 dst.PredSwizzleY = TGSI_SWIZZLE_Y;
1200 dst.PredSwizzleZ = TGSI_SWIZZLE_Z;
1201 dst.PredSwizzleW = TGSI_SWIZZLE_W;
1202 dst.Index = index;
1203 dst.Dimension = 0;
1204 dst.DimensionIndex = 0;
1205 dst.DimIndirect = 0;
1206 dst.DimIndFile = TGSI_FILE_NULL;
1207 dst.DimIndIndex = 0;
1208 dst.DimIndSwizzle = 0;
1209 dst.ArrayID = 0;
1210
1211 return dst;
1212 }
1213
1214 static INLINE struct ureg_dst
1215 ureg_dst( struct ureg_src src )
1216 {
1217 struct ureg_dst dst;
1218
1219 assert(!src.Indirect ||
1220 (src.IndirectFile == TGSI_FILE_ADDRESS ||
1221 src.IndirectFile == TGSI_FILE_TEMPORARY));
1222
1223 dst.File = src.File;
1224 dst.WriteMask = TGSI_WRITEMASK_XYZW;
1225 dst.IndirectFile = src.IndirectFile;
1226 dst.Indirect = src.Indirect;
1227 dst.IndirectIndex = src.IndirectIndex;
1228 dst.IndirectSwizzle = src.IndirectSwizzle;
1229 dst.Saturate = 0;
1230 dst.Predicate = 0;
1231 dst.PredNegate = 0;
1232 dst.PredSwizzleX = TGSI_SWIZZLE_X;
1233 dst.PredSwizzleY = TGSI_SWIZZLE_Y;
1234 dst.PredSwizzleZ = TGSI_SWIZZLE_Z;
1235 dst.PredSwizzleW = TGSI_SWIZZLE_W;
1236 dst.Index = src.Index;
1237 dst.Dimension = src.Dimension;
1238 dst.DimensionIndex = src.DimensionIndex;
1239 dst.DimIndirect = src.DimIndirect;
1240 dst.DimIndFile = src.DimIndFile;
1241 dst.DimIndIndex = src.DimIndIndex;
1242 dst.DimIndSwizzle = src.DimIndSwizzle;
1243 dst.ArrayID = src.ArrayID;
1244
1245 return dst;
1246 }
1247
1248 static INLINE struct ureg_src
1249 ureg_src_array_register(unsigned file,
1250 unsigned index,
1251 unsigned array_id)
1252 {
1253 struct ureg_src src;
1254
1255 src.File = file;
1256 src.SwizzleX = TGSI_SWIZZLE_X;
1257 src.SwizzleY = TGSI_SWIZZLE_Y;
1258 src.SwizzleZ = TGSI_SWIZZLE_Z;
1259 src.SwizzleW = TGSI_SWIZZLE_W;
1260 src.Indirect = 0;
1261 src.IndirectFile = TGSI_FILE_NULL;
1262 src.IndirectIndex = 0;
1263 src.IndirectSwizzle = 0;
1264 src.Absolute = 0;
1265 src.Index = index;
1266 src.Negate = 0;
1267 src.Dimension = 0;
1268 src.DimensionIndex = 0;
1269 src.DimIndirect = 0;
1270 src.DimIndFile = TGSI_FILE_NULL;
1271 src.DimIndIndex = 0;
1272 src.DimIndSwizzle = 0;
1273 src.ArrayID = array_id;
1274
1275 return src;
1276 }
1277
1278 static INLINE struct ureg_src
1279 ureg_src_register(unsigned file,
1280 unsigned index)
1281 {
1282 return ureg_src_array_register(file, index, 0);
1283 }
1284
1285 static INLINE struct ureg_src
1286 ureg_src( struct ureg_dst dst )
1287 {
1288 struct ureg_src src;
1289
1290 src.File = dst.File;
1291 src.SwizzleX = TGSI_SWIZZLE_X;
1292 src.SwizzleY = TGSI_SWIZZLE_Y;
1293 src.SwizzleZ = TGSI_SWIZZLE_Z;
1294 src.SwizzleW = TGSI_SWIZZLE_W;
1295 src.Indirect = dst.Indirect;
1296 src.IndirectFile = dst.IndirectFile;
1297 src.IndirectIndex = dst.IndirectIndex;
1298 src.IndirectSwizzle = dst.IndirectSwizzle;
1299 src.Absolute = 0;
1300 src.Index = dst.Index;
1301 src.Negate = 0;
1302 src.Dimension = dst.Dimension;
1303 src.DimensionIndex = dst.DimensionIndex;
1304 src.DimIndirect = dst.DimIndirect;
1305 src.DimIndFile = dst.DimIndFile;
1306 src.DimIndIndex = dst.DimIndIndex;
1307 src.DimIndSwizzle = dst.DimIndSwizzle;
1308 src.ArrayID = dst.ArrayID;
1309
1310 return src;
1311 }
1312
1313
1314
1315 static INLINE struct ureg_dst
1316 ureg_dst_undef( void )
1317 {
1318 struct ureg_dst dst;
1319
1320 dst.File = TGSI_FILE_NULL;
1321 dst.WriteMask = 0;
1322 dst.Indirect = 0;
1323 dst.IndirectFile = TGSI_FILE_NULL;
1324 dst.IndirectIndex = 0;
1325 dst.IndirectSwizzle = 0;
1326 dst.Saturate = 0;
1327 dst.Predicate = 0;
1328 dst.PredNegate = 0;
1329 dst.PredSwizzleX = TGSI_SWIZZLE_X;
1330 dst.PredSwizzleY = TGSI_SWIZZLE_Y;
1331 dst.PredSwizzleZ = TGSI_SWIZZLE_Z;
1332 dst.PredSwizzleW = TGSI_SWIZZLE_W;
1333 dst.Index = 0;
1334 dst.Dimension = 0;
1335 dst.DimensionIndex = 0;
1336 dst.DimIndirect = 0;
1337 dst.DimIndFile = TGSI_FILE_NULL;
1338 dst.DimIndIndex = 0;
1339 dst.DimIndSwizzle = 0;
1340 dst.ArrayID = 0;
1341
1342 return dst;
1343 }
1344
1345 static INLINE struct ureg_src
1346 ureg_src_undef( void )
1347 {
1348 struct ureg_src src;
1349
1350 src.File = TGSI_FILE_NULL;
1351 src.SwizzleX = 0;
1352 src.SwizzleY = 0;
1353 src.SwizzleZ = 0;
1354 src.SwizzleW = 0;
1355 src.Indirect = 0;
1356 src.IndirectFile = TGSI_FILE_NULL;
1357 src.IndirectIndex = 0;
1358 src.IndirectSwizzle = 0;
1359 src.Absolute = 0;
1360 src.Index = 0;
1361 src.Negate = 0;
1362 src.Dimension = 0;
1363 src.DimensionIndex = 0;
1364 src.DimIndirect = 0;
1365 src.DimIndFile = TGSI_FILE_NULL;
1366 src.DimIndIndex = 0;
1367 src.DimIndSwizzle = 0;
1368 src.ArrayID = 0;
1369
1370 return src;
1371 }
1372
1373 static INLINE boolean
1374 ureg_src_is_undef( struct ureg_src src )
1375 {
1376 return src.File == TGSI_FILE_NULL;
1377 }
1378
1379 static INLINE boolean
1380 ureg_dst_is_undef( struct ureg_dst dst )
1381 {
1382 return dst.File == TGSI_FILE_NULL;
1383 }
1384
1385
1386 #ifdef __cplusplus
1387 }
1388 #endif
1389
1390 #endif