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