1 /**************************************************************************
3 * Copyright 2009 VMware, Inc.
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:
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
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.
26 **************************************************************************/
31 #include "pipe/p_compiler.h"
32 #include "pipe/p_shader_tokens.h"
40 /* Almost a tgsi_src_register, but we need to pull in the Absolute
41 * flag from the _ext token. Indirect flag always implies ADDR[0].
45 unsigned File
: 4; /* TGSI_FILE_ */
46 unsigned SwizzleX
: 2; /* TGSI_SWIZZLE_ */
47 unsigned SwizzleY
: 2; /* TGSI_SWIZZLE_ */
48 unsigned SwizzleZ
: 2; /* TGSI_SWIZZLE_ */
49 unsigned SwizzleW
: 2; /* TGSI_SWIZZLE_ */
50 unsigned Pad
: 1; /* BOOL */
51 unsigned Indirect
: 1; /* BOOL */
52 unsigned Absolute
: 1; /* BOOL */
53 int Index
: 16; /* SINT */
54 unsigned Negate
: 1; /* BOOL */
55 int IndirectIndex
: 16; /* SINT */
56 int IndirectSwizzle
: 2; /* TGSI_SWIZZLE_ */
59 /* Very similar to a tgsi_dst_register, removing unsupported fields
60 * and adding a Saturate flag. It's easier to push saturate into the
61 * destination register than to try and create a _SAT varient of each
62 * instruction function.
66 unsigned File
: 4; /* TGSI_FILE_ */
67 unsigned WriteMask
: 4; /* TGSI_WRITEMASK_ */
68 unsigned Indirect
: 1; /* BOOL */
69 unsigned Saturate
: 1; /* BOOL */
70 unsigned Predicate
: 1;
71 unsigned PredNegate
: 1; /* BOOL */
72 unsigned PredSwizzleX
: 2; /* TGSI_SWIZZLE_ */
73 unsigned PredSwizzleY
: 2; /* TGSI_SWIZZLE_ */
74 unsigned PredSwizzleZ
: 2; /* TGSI_SWIZZLE_ */
75 unsigned PredSwizzleW
: 2; /* TGSI_SWIZZLE_ */
76 int Index
: 16; /* SINT */
77 int IndirectIndex
: 16; /* SINT */
78 int IndirectSwizzle
: 2; /* TGSI_SWIZZLE_ */
84 ureg_create( unsigned processor
);
86 const struct tgsi_token
*
87 ureg_finalize( struct ureg_program
* );
89 /* Create and return a shader:
92 ureg_create_shader( struct ureg_program
*,
93 struct pipe_context
*pipe
);
96 /* Alternately, return the built token stream and hand ownership of
97 * that memory to the caller:
99 const struct tgsi_token
*
100 ureg_get_tokens( struct ureg_program
*ureg
,
101 unsigned *nr_tokens
);
105 ureg_destroy( struct ureg_program
* );
108 /***********************************************************************
109 * Convenience routine:
112 ureg_create_shader_and_destroy( struct ureg_program
*p
,
113 struct pipe_context
*pipe
)
115 void *result
= ureg_create_shader( p
, pipe
);
122 /***********************************************************************
123 * Build shader declarations:
127 ureg_DECL_fs_input( struct ureg_program
*,
128 unsigned semantic_name
,
129 unsigned semantic_index
,
130 unsigned interp_mode
);
133 ureg_DECL_vs_input( struct ureg_program
*,
137 ureg_DECL_gs_input(struct ureg_program
*,
141 ureg_DECL_output( struct ureg_program
*,
142 unsigned semantic_name
,
143 unsigned semantic_index
);
146 ureg_DECL_immediate( struct ureg_program
*,
151 ureg_DECL_immediate_uint( struct ureg_program
*,
156 ureg_DECL_immediate_int( struct ureg_program
*,
161 ureg_DECL_constant( struct ureg_program
*,
165 ureg_DECL_temporary( struct ureg_program
* );
168 ureg_release_temporary( struct ureg_program
*ureg
,
169 struct ureg_dst tmp
);
172 ureg_DECL_address( struct ureg_program
* );
175 ureg_DECL_loop( struct ureg_program
* );
178 ureg_DECL_predicate(struct ureg_program
*);
180 /* Supply an index to the sampler declaration as this is the hook to
181 * the external pipe_sampler state. Users of this function probably
182 * don't want just any sampler, but a specific one which they've set
183 * up state for in the context.
186 ureg_DECL_sampler( struct ureg_program
*,
190 static INLINE
struct ureg_src
191 ureg_imm4f( struct ureg_program
*ureg
,
200 return ureg_DECL_immediate( ureg
, v
, 4 );
203 static INLINE
struct ureg_src
204 ureg_imm3f( struct ureg_program
*ureg
,
212 return ureg_DECL_immediate( ureg
, v
, 3 );
215 static INLINE
struct ureg_src
216 ureg_imm2f( struct ureg_program
*ureg
,
222 return ureg_DECL_immediate( ureg
, v
, 2 );
225 static INLINE
struct ureg_src
226 ureg_imm1f( struct ureg_program
*ureg
,
231 return ureg_DECL_immediate( ureg
, v
, 1 );
234 static INLINE
struct ureg_src
235 ureg_imm4u( struct ureg_program
*ureg
,
236 unsigned a
, unsigned b
,
237 unsigned c
, unsigned d
)
244 return ureg_DECL_immediate_uint( ureg
, v
, 4 );
247 static INLINE
struct ureg_src
248 ureg_imm3u( struct ureg_program
*ureg
,
249 unsigned a
, unsigned b
,
256 return ureg_DECL_immediate_uint( ureg
, v
, 3 );
259 static INLINE
struct ureg_src
260 ureg_imm2u( struct ureg_program
*ureg
,
261 unsigned a
, unsigned b
)
266 return ureg_DECL_immediate_uint( ureg
, v
, 2 );
269 static INLINE
struct ureg_src
270 ureg_imm1u( struct ureg_program
*ureg
,
273 return ureg_DECL_immediate_uint( ureg
, &a
, 1 );
276 static INLINE
struct ureg_src
277 ureg_imm4i( struct ureg_program
*ureg
,
286 return ureg_DECL_immediate_int( ureg
, v
, 4 );
289 static INLINE
struct ureg_src
290 ureg_imm3i( struct ureg_program
*ureg
,
298 return ureg_DECL_immediate_int( ureg
, v
, 3 );
301 static INLINE
struct ureg_src
302 ureg_imm2i( struct ureg_program
*ureg
,
308 return ureg_DECL_immediate_int( ureg
, v
, 2 );
311 static INLINE
struct ureg_src
312 ureg_imm1i( struct ureg_program
*ureg
,
315 return ureg_DECL_immediate_int( ureg
, &a
, 1 );
318 /***********************************************************************
319 * Functions for patching up labels
323 /* Will return a number which can be used in a label to point to the
324 * next instruction to be emitted.
327 ureg_get_instruction_number( struct ureg_program
*ureg
);
330 /* Patch a given label (expressed as a token number) to point to a
331 * given instruction (expressed as an instruction number).
333 * Labels are obtained from instruction emitters, eg ureg_CAL().
334 * Instruction numbers are obtained from ureg_get_instruction_number(),
338 ureg_fixup_label(struct ureg_program
*ureg
,
339 unsigned label_token
,
340 unsigned instruction_number
);
343 /* Generic instruction emitter. Use if you need to pass the opcode as
344 * a parameter, rather than using the emit_OP() varients below.
347 ureg_insn(struct ureg_program
*ureg
,
349 const struct ureg_dst
*dst
,
351 const struct ureg_src
*src
,
356 ureg_tex_insn(struct ureg_program
*ureg
,
358 const struct ureg_dst
*dst
,
361 const struct ureg_src
*src
,
366 ureg_label_insn(struct ureg_program
*ureg
,
368 const struct ureg_src
*src
,
373 /***********************************************************************
374 * Internal instruction helpers, don't call these directly:
377 struct ureg_emit_insn_result
{
378 unsigned insn_token
; /*< Used to fixup insn size. */
379 unsigned extended_token
; /*< Used to set the Extended bit, usually the same as insn_token. */
382 struct ureg_emit_insn_result
383 ureg_emit_insn(struct ureg_program
*ureg
,
388 unsigned pred_swizzle_x
,
389 unsigned pred_swizzle_y
,
390 unsigned pred_swizzle_z
,
391 unsigned pred_swizzle_w
,
396 ureg_emit_label(struct ureg_program
*ureg
,
398 unsigned *label_token
);
401 ureg_emit_texture(struct ureg_program
*ureg
,
406 ureg_emit_dst( struct ureg_program
*ureg
,
407 struct ureg_dst dst
);
410 ureg_emit_src( struct ureg_program
*ureg
,
411 struct ureg_src src
);
414 ureg_fixup_insn_size(struct ureg_program
*ureg
,
419 static INLINE void ureg_##op( struct ureg_program *ureg ) \
421 unsigned opcode = TGSI_OPCODE_##op; \
422 unsigned insn = ureg_emit_insn(ureg, \
433 ureg_fixup_insn_size( ureg, insn ); \
437 static INLINE void ureg_##op( struct ureg_program *ureg, \
438 struct ureg_src src ) \
440 unsigned opcode = TGSI_OPCODE_##op; \
441 unsigned insn = ureg_emit_insn(ureg, \
452 ureg_emit_src( ureg, src ); \
453 ureg_fixup_insn_size( ureg, insn ); \
456 #define OP00_LBL( op ) \
457 static INLINE void ureg_##op( struct ureg_program *ureg, \
458 unsigned *label_token ) \
460 unsigned opcode = TGSI_OPCODE_##op; \
461 struct ureg_emit_insn_result insn; \
462 insn = ureg_emit_insn(ureg, \
473 ureg_emit_label( ureg, insn.extended_token, label_token ); \
474 ureg_fixup_insn_size( ureg, insn.insn_token ); \
477 #define OP01_LBL( op ) \
478 static INLINE void ureg_##op( struct ureg_program *ureg, \
479 struct ureg_src src, \
480 unsigned *label_token ) \
482 unsigned opcode = TGSI_OPCODE_##op; \
483 struct ureg_emit_insn_result insn; \
484 insn = ureg_emit_insn(ureg, \
495 ureg_emit_label( ureg, insn.extended_token, label_token ); \
496 ureg_emit_src( ureg, src ); \
497 ureg_fixup_insn_size( ureg, insn.insn_token ); \
501 static INLINE void ureg_##op( struct ureg_program *ureg, \
502 struct ureg_dst dst ) \
504 unsigned opcode = TGSI_OPCODE_##op; \
505 unsigned insn = ureg_emit_insn(ureg, \
516 ureg_emit_dst( ureg, dst ); \
517 ureg_fixup_insn_size( ureg, insn ); \
522 static INLINE void ureg_##op( struct ureg_program *ureg, \
523 struct ureg_dst dst, \
524 struct ureg_src src ) \
526 unsigned opcode = TGSI_OPCODE_##op; \
527 unsigned insn = ureg_emit_insn(ureg, \
538 ureg_emit_dst( ureg, dst ); \
539 ureg_emit_src( ureg, src ); \
540 ureg_fixup_insn_size( ureg, insn ); \
544 static INLINE void ureg_##op( struct ureg_program *ureg, \
545 struct ureg_dst dst, \
546 struct ureg_src src0, \
547 struct ureg_src src1 ) \
549 unsigned opcode = TGSI_OPCODE_##op; \
550 unsigned insn = ureg_emit_insn(ureg, \
561 ureg_emit_dst( ureg, dst ); \
562 ureg_emit_src( ureg, src0 ); \
563 ureg_emit_src( ureg, src1 ); \
564 ureg_fixup_insn_size( ureg, insn ); \
567 #define OP12_TEX( op ) \
568 static INLINE void ureg_##op( struct ureg_program *ureg, \
569 struct ureg_dst dst, \
571 struct ureg_src src0, \
572 struct ureg_src src1 ) \
574 unsigned opcode = TGSI_OPCODE_##op; \
575 struct ureg_emit_insn_result insn; \
576 insn = ureg_emit_insn(ureg, \
587 ureg_emit_texture( ureg, insn.extended_token, target ); \
588 ureg_emit_dst( ureg, dst ); \
589 ureg_emit_src( ureg, src0 ); \
590 ureg_emit_src( ureg, src1 ); \
591 ureg_fixup_insn_size( ureg, insn.insn_token ); \
595 static INLINE void ureg_##op( struct ureg_program *ureg, \
596 struct ureg_dst dst, \
597 struct ureg_src src0, \
598 struct ureg_src src1, \
599 struct ureg_src src2 ) \
601 unsigned opcode = TGSI_OPCODE_##op; \
602 unsigned insn = ureg_emit_insn(ureg, \
613 ureg_emit_dst( ureg, dst ); \
614 ureg_emit_src( ureg, src0 ); \
615 ureg_emit_src( ureg, src1 ); \
616 ureg_emit_src( ureg, src2 ); \
617 ureg_fixup_insn_size( ureg, insn ); \
620 #define OP14_TEX( op ) \
621 static INLINE void ureg_##op( struct ureg_program *ureg, \
622 struct ureg_dst dst, \
624 struct ureg_src src0, \
625 struct ureg_src src1, \
626 struct ureg_src src2, \
627 struct ureg_src src3 ) \
629 unsigned opcode = TGSI_OPCODE_##op; \
630 struct ureg_emit_insn_result insn; \
631 insn = ureg_emit_insn(ureg, \
642 ureg_emit_texture( ureg, insn.extended_token, target ); \
643 ureg_emit_dst( ureg, dst ); \
644 ureg_emit_src( ureg, src0 ); \
645 ureg_emit_src( ureg, src1 ); \
646 ureg_emit_src( ureg, src2 ); \
647 ureg_emit_src( ureg, src3 ); \
648 ureg_fixup_insn_size( ureg, insn.insn_token ); \
652 /* Use a template include to generate a correctly-typed ureg_OP()
653 * function for each TGSI opcode:
655 #include "tgsi_opcode_tmp.h"
658 /***********************************************************************
659 * Inline helpers for manipulating register structs:
661 static INLINE
struct ureg_src
662 ureg_negate( struct ureg_src reg
)
664 assert(reg
.File
!= TGSI_FILE_NULL
);
669 static INLINE
struct ureg_src
670 ureg_abs( struct ureg_src reg
)
672 assert(reg
.File
!= TGSI_FILE_NULL
);
678 static INLINE
struct ureg_src
679 ureg_swizzle( struct ureg_src reg
,
680 int x
, int y
, int z
, int w
)
682 unsigned swz
= ( (reg
.SwizzleX
<< 0) |
683 (reg
.SwizzleY
<< 2) |
684 (reg
.SwizzleZ
<< 4) |
685 (reg
.SwizzleW
<< 6));
687 assert(reg
.File
!= TGSI_FILE_NULL
);
693 reg
.SwizzleX
= (swz
>> (x
*2)) & 0x3;
694 reg
.SwizzleY
= (swz
>> (y
*2)) & 0x3;
695 reg
.SwizzleZ
= (swz
>> (z
*2)) & 0x3;
696 reg
.SwizzleW
= (swz
>> (w
*2)) & 0x3;
700 static INLINE
struct ureg_src
701 ureg_scalar( struct ureg_src reg
, int x
)
703 return ureg_swizzle(reg
, x
, x
, x
, x
);
706 static INLINE
struct ureg_dst
707 ureg_writemask( struct ureg_dst reg
,
710 assert(reg
.File
!= TGSI_FILE_NULL
);
711 reg
.WriteMask
&= writemask
;
715 static INLINE
struct ureg_dst
716 ureg_saturate( struct ureg_dst reg
)
718 assert(reg
.File
!= TGSI_FILE_NULL
);
723 static INLINE
struct ureg_dst
724 ureg_predicate(struct ureg_dst reg
,
731 assert(reg
.File
!= TGSI_FILE_NULL
);
733 reg
.PredNegate
= negate
;
734 reg
.PredSwizzleX
= swizzle_x
;
735 reg
.PredSwizzleY
= swizzle_y
;
736 reg
.PredSwizzleZ
= swizzle_z
;
737 reg
.PredSwizzleW
= swizzle_w
;
741 static INLINE
struct ureg_dst
742 ureg_dst_indirect( struct ureg_dst reg
, struct ureg_src addr
)
744 assert(reg
.File
!= TGSI_FILE_NULL
);
745 assert(addr
.File
== TGSI_FILE_ADDRESS
);
747 reg
.IndirectIndex
= addr
.Index
;
748 reg
.IndirectSwizzle
= addr
.SwizzleX
;
752 static INLINE
struct ureg_src
753 ureg_src_indirect( struct ureg_src reg
, struct ureg_src addr
)
755 assert(reg
.File
!= TGSI_FILE_NULL
);
756 assert(addr
.File
== TGSI_FILE_ADDRESS
);
758 reg
.IndirectIndex
= addr
.Index
;
759 reg
.IndirectSwizzle
= addr
.SwizzleX
;
763 static INLINE
struct ureg_dst
764 ureg_dst( struct ureg_src src
)
769 dst
.WriteMask
= TGSI_WRITEMASK_XYZW
;
770 dst
.Indirect
= src
.Indirect
;
771 dst
.IndirectIndex
= src
.IndirectIndex
;
772 dst
.IndirectSwizzle
= src
.IndirectSwizzle
;
776 dst
.PredSwizzleX
= TGSI_SWIZZLE_X
;
777 dst
.PredSwizzleY
= TGSI_SWIZZLE_Y
;
778 dst
.PredSwizzleZ
= TGSI_SWIZZLE_Z
;
779 dst
.PredSwizzleW
= TGSI_SWIZZLE_W
;
780 dst
.Index
= src
.Index
;
785 static INLINE
struct ureg_src
786 ureg_src( struct ureg_dst dst
)
791 src
.SwizzleX
= TGSI_SWIZZLE_X
;
792 src
.SwizzleY
= TGSI_SWIZZLE_Y
;
793 src
.SwizzleZ
= TGSI_SWIZZLE_Z
;
794 src
.SwizzleW
= TGSI_SWIZZLE_W
;
796 src
.Indirect
= dst
.Indirect
;
797 src
.IndirectIndex
= dst
.IndirectIndex
;
798 src
.IndirectSwizzle
= dst
.IndirectSwizzle
;
800 src
.Index
= dst
.Index
;
808 static INLINE
struct ureg_dst
809 ureg_dst_undef( void )
813 dst
.File
= TGSI_FILE_NULL
;
816 dst
.IndirectIndex
= 0;
817 dst
.IndirectSwizzle
= 0;
821 dst
.PredSwizzleX
= TGSI_SWIZZLE_X
;
822 dst
.PredSwizzleY
= TGSI_SWIZZLE_Y
;
823 dst
.PredSwizzleZ
= TGSI_SWIZZLE_Z
;
824 dst
.PredSwizzleW
= TGSI_SWIZZLE_W
;
830 static INLINE
struct ureg_src
831 ureg_src_undef( void )
835 src
.File
= TGSI_FILE_NULL
;
842 src
.IndirectIndex
= 0;
843 src
.IndirectSwizzle
= 0;
851 static INLINE boolean
852 ureg_src_is_undef( struct ureg_src src
)
854 return src
.File
== TGSI_FILE_NULL
;
857 static INLINE boolean
858 ureg_dst_is_undef( struct ureg_dst dst
)
860 return dst
.File
== TGSI_FILE_NULL
;