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