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