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"
33 #include "util/u_debug.h"
41 /* Almost a tgsi_src_register, but we need to pull in the Absolute
42 * flag from the _ext token. Indirect flag always implies ADDR[0].
46 unsigned File
: 4; /* TGSI_FILE_ */
47 unsigned SwizzleX
: 2; /* TGSI_SWIZZLE_ */
48 unsigned SwizzleY
: 2; /* TGSI_SWIZZLE_ */
49 unsigned SwizzleZ
: 2; /* TGSI_SWIZZLE_ */
50 unsigned SwizzleW
: 2; /* TGSI_SWIZZLE_ */
51 unsigned Indirect
: 1; /* BOOL */
52 unsigned Dimension
: 1; /* BOOL */
53 unsigned Absolute
: 1; /* BOOL */
54 unsigned Negate
: 1; /* BOOL */
55 int Index
: 16; /* SINT */
56 unsigned IndirectFile
: 4; /* TGSI_FILE_ */
57 int IndirectIndex
: 16; /* SINT */
58 unsigned IndirectSwizzle
: 2; /* TGSI_SWIZZLE_ */
59 int DimensionIndex
: 16; /* SINT */
62 /* Very similar to a tgsi_dst_register, removing unsupported fields
63 * and adding a Saturate flag. It's easier to push saturate into the
64 * destination register than to try and create a _SAT varient of each
65 * instruction function.
69 unsigned File
: 4; /* TGSI_FILE_ */
70 unsigned WriteMask
: 4; /* TGSI_WRITEMASK_ */
71 unsigned Indirect
: 1; /* BOOL */
72 unsigned Saturate
: 1; /* BOOL */
73 unsigned Predicate
: 1;
74 unsigned PredNegate
: 1; /* BOOL */
75 unsigned PredSwizzleX
: 2; /* TGSI_SWIZZLE_ */
76 unsigned PredSwizzleY
: 2; /* TGSI_SWIZZLE_ */
77 unsigned PredSwizzleZ
: 2; /* TGSI_SWIZZLE_ */
78 unsigned PredSwizzleW
: 2; /* TGSI_SWIZZLE_ */
79 int Index
: 16; /* SINT */
80 int IndirectIndex
: 16; /* SINT */
81 int IndirectSwizzle
: 2; /* TGSI_SWIZZLE_ */
87 ureg_create( unsigned processor
);
89 const struct tgsi_token
*
90 ureg_finalize( struct ureg_program
* );
92 /* Create and return a shader:
95 ureg_create_shader( struct ureg_program
*,
96 struct pipe_context
*pipe
);
99 /* Alternately, return the built token stream and hand ownership of
100 * that memory to the caller:
102 const struct tgsi_token
*
103 ureg_get_tokens( struct ureg_program
*ureg
,
104 unsigned *nr_tokens
);
107 /* Free the tokens created by ureg_get_tokens() */
108 void ureg_free_tokens( const struct tgsi_token
*tokens
);
112 ureg_destroy( struct ureg_program
* );
115 /***********************************************************************
116 * Convenience routine:
119 ureg_create_shader_and_destroy( struct ureg_program
*p
,
120 struct pipe_context
*pipe
)
122 void *result
= ureg_create_shader( p
, pipe
);
128 /***********************************************************************
129 * Build shader properties:
133 ureg_property_gs_input_prim(struct ureg_program
*ureg
,
134 unsigned input_prim
);
137 ureg_property_gs_output_prim(struct ureg_program
*ureg
,
138 unsigned output_prim
);
141 ureg_property_gs_max_vertices(struct ureg_program
*ureg
,
142 unsigned max_vertices
);
145 ureg_property_fs_coord_origin(struct ureg_program
*ureg
,
146 unsigned fs_coord_origin
);
149 ureg_property_fs_coord_pixel_center(struct ureg_program
*ureg
,
150 unsigned fs_coord_pixel_center
);
152 /***********************************************************************
153 * Build shader declarations:
157 ureg_DECL_fs_input_cyl(struct ureg_program
*,
158 unsigned semantic_name
,
159 unsigned semantic_index
,
160 unsigned interp_mode
,
161 unsigned cylindrical_wrap
);
163 static INLINE
struct ureg_src
164 ureg_DECL_fs_input(struct ureg_program
*ureg
,
165 unsigned semantic_name
,
166 unsigned semantic_index
,
167 unsigned interp_mode
)
169 return ureg_DECL_fs_input_cyl(ureg
,
177 ureg_DECL_vs_input( struct ureg_program
*,
181 ureg_DECL_gs_input(struct ureg_program
*,
183 unsigned semantic_name
,
184 unsigned semantic_index
);
187 ureg_DECL_system_value(struct ureg_program
*,
189 unsigned semantic_name
,
190 unsigned semantic_index
);
193 ureg_DECL_output( struct ureg_program
*,
194 unsigned semantic_name
,
195 unsigned semantic_index
);
198 ureg_DECL_immediate( struct ureg_program
*,
203 ureg_DECL_immediate_uint( struct ureg_program
*,
208 ureg_DECL_immediate_block_uint( struct ureg_program
*,
213 ureg_DECL_immediate_int( struct ureg_program
*,
218 ureg_DECL_constant2D(struct ureg_program
*ureg
,
224 ureg_DECL_constant( struct ureg_program
*,
228 ureg_DECL_temporary( struct ureg_program
* );
231 ureg_release_temporary( struct ureg_program
*ureg
,
232 struct ureg_dst tmp
);
235 ureg_DECL_address( struct ureg_program
* );
238 ureg_DECL_predicate(struct ureg_program
*);
240 /* Supply an index to the sampler declaration as this is the hook to
241 * the external pipe_sampler state. Users of this function probably
242 * don't want just any sampler, but a specific one which they've set
243 * up state for in the context.
246 ureg_DECL_sampler( struct ureg_program
*,
250 static INLINE
struct ureg_src
251 ureg_imm4f( struct ureg_program
*ureg
,
260 return ureg_DECL_immediate( ureg
, v
, 4 );
263 static INLINE
struct ureg_src
264 ureg_imm3f( struct ureg_program
*ureg
,
272 return ureg_DECL_immediate( ureg
, v
, 3 );
275 static INLINE
struct ureg_src
276 ureg_imm2f( struct ureg_program
*ureg
,
282 return ureg_DECL_immediate( ureg
, v
, 2 );
285 static INLINE
struct ureg_src
286 ureg_imm1f( struct ureg_program
*ureg
,
291 return ureg_DECL_immediate( ureg
, v
, 1 );
294 static INLINE
struct ureg_src
295 ureg_imm4u( struct ureg_program
*ureg
,
296 unsigned a
, unsigned b
,
297 unsigned c
, unsigned d
)
304 return ureg_DECL_immediate_uint( ureg
, v
, 4 );
307 static INLINE
struct ureg_src
308 ureg_imm3u( struct ureg_program
*ureg
,
309 unsigned a
, unsigned b
,
316 return ureg_DECL_immediate_uint( ureg
, v
, 3 );
319 static INLINE
struct ureg_src
320 ureg_imm2u( struct ureg_program
*ureg
,
321 unsigned a
, unsigned b
)
326 return ureg_DECL_immediate_uint( ureg
, v
, 2 );
329 static INLINE
struct ureg_src
330 ureg_imm1u( struct ureg_program
*ureg
,
333 return ureg_DECL_immediate_uint( ureg
, &a
, 1 );
336 static INLINE
struct ureg_src
337 ureg_imm4i( struct ureg_program
*ureg
,
346 return ureg_DECL_immediate_int( ureg
, v
, 4 );
349 static INLINE
struct ureg_src
350 ureg_imm3i( struct ureg_program
*ureg
,
358 return ureg_DECL_immediate_int( ureg
, v
, 3 );
361 static INLINE
struct ureg_src
362 ureg_imm2i( struct ureg_program
*ureg
,
368 return ureg_DECL_immediate_int( ureg
, v
, 2 );
371 static INLINE
struct ureg_src
372 ureg_imm1i( struct ureg_program
*ureg
,
375 return ureg_DECL_immediate_int( ureg
, &a
, 1 );
378 /***********************************************************************
379 * Functions for patching up labels
383 /* Will return a number which can be used in a label to point to the
384 * next instruction to be emitted.
387 ureg_get_instruction_number( struct ureg_program
*ureg
);
390 /* Patch a given label (expressed as a token number) to point to a
391 * given instruction (expressed as an instruction number).
393 * Labels are obtained from instruction emitters, eg ureg_CAL().
394 * Instruction numbers are obtained from ureg_get_instruction_number(),
398 ureg_fixup_label(struct ureg_program
*ureg
,
399 unsigned label_token
,
400 unsigned instruction_number
);
403 /* Generic instruction emitter. Use if you need to pass the opcode as
404 * a parameter, rather than using the emit_OP() varients below.
407 ureg_insn(struct ureg_program
*ureg
,
409 const struct ureg_dst
*dst
,
411 const struct ureg_src
*src
,
416 ureg_tex_insn(struct ureg_program
*ureg
,
418 const struct ureg_dst
*dst
,
421 const struct ureg_src
*src
,
426 ureg_label_insn(struct ureg_program
*ureg
,
428 const struct ureg_src
*src
,
433 /***********************************************************************
434 * Internal instruction helpers, don't call these directly:
437 struct ureg_emit_insn_result
{
438 unsigned insn_token
; /*< Used to fixup insn size. */
439 unsigned extended_token
; /*< Used to set the Extended bit, usually the same as insn_token. */
442 struct ureg_emit_insn_result
443 ureg_emit_insn(struct ureg_program
*ureg
,
448 unsigned pred_swizzle_x
,
449 unsigned pred_swizzle_y
,
450 unsigned pred_swizzle_z
,
451 unsigned pred_swizzle_w
,
456 ureg_emit_label(struct ureg_program
*ureg
,
458 unsigned *label_token
);
461 ureg_emit_texture(struct ureg_program
*ureg
,
466 ureg_emit_dst( struct ureg_program
*ureg
,
467 struct ureg_dst dst
);
470 ureg_emit_src( struct ureg_program
*ureg
,
471 struct ureg_src src
);
474 ureg_fixup_insn_size(struct ureg_program
*ureg
,
479 static INLINE void ureg_##op( struct ureg_program *ureg ) \
481 unsigned opcode = TGSI_OPCODE_##op; \
482 unsigned insn = ureg_emit_insn(ureg, \
493 ureg_fixup_insn_size( ureg, insn ); \
497 static INLINE void ureg_##op( struct ureg_program *ureg, \
498 struct ureg_src src ) \
500 unsigned opcode = TGSI_OPCODE_##op; \
501 unsigned insn = ureg_emit_insn(ureg, \
512 ureg_emit_src( ureg, src ); \
513 ureg_fixup_insn_size( ureg, insn ); \
516 #define OP00_LBL( op ) \
517 static INLINE void ureg_##op( struct ureg_program *ureg, \
518 unsigned *label_token ) \
520 unsigned opcode = TGSI_OPCODE_##op; \
521 struct ureg_emit_insn_result insn; \
522 insn = ureg_emit_insn(ureg, \
533 ureg_emit_label( ureg, insn.extended_token, label_token ); \
534 ureg_fixup_insn_size( ureg, insn.insn_token ); \
537 #define OP01_LBL( op ) \
538 static INLINE void ureg_##op( struct ureg_program *ureg, \
539 struct ureg_src src, \
540 unsigned *label_token ) \
542 unsigned opcode = TGSI_OPCODE_##op; \
543 struct ureg_emit_insn_result insn; \
544 insn = ureg_emit_insn(ureg, \
555 ureg_emit_label( ureg, insn.extended_token, label_token ); \
556 ureg_emit_src( ureg, src ); \
557 ureg_fixup_insn_size( ureg, insn.insn_token ); \
561 static INLINE void ureg_##op( struct ureg_program *ureg, \
562 struct ureg_dst dst ) \
564 unsigned opcode = TGSI_OPCODE_##op; \
565 unsigned insn = ureg_emit_insn(ureg, \
576 ureg_emit_dst( ureg, dst ); \
577 ureg_fixup_insn_size( ureg, insn ); \
582 static INLINE void ureg_##op( struct ureg_program *ureg, \
583 struct ureg_dst dst, \
584 struct ureg_src src ) \
586 unsigned opcode = TGSI_OPCODE_##op; \
587 unsigned insn = ureg_emit_insn(ureg, \
598 ureg_emit_dst( ureg, dst ); \
599 ureg_emit_src( ureg, src ); \
600 ureg_fixup_insn_size( ureg, insn ); \
604 static INLINE void ureg_##op( struct ureg_program *ureg, \
605 struct ureg_dst dst, \
606 struct ureg_src src0, \
607 struct ureg_src src1 ) \
609 unsigned opcode = TGSI_OPCODE_##op; \
610 unsigned insn = ureg_emit_insn(ureg, \
621 ureg_emit_dst( ureg, dst ); \
622 ureg_emit_src( ureg, src0 ); \
623 ureg_emit_src( ureg, src1 ); \
624 ureg_fixup_insn_size( ureg, insn ); \
627 #define OP12_TEX( op ) \
628 static INLINE void ureg_##op( struct ureg_program *ureg, \
629 struct ureg_dst dst, \
631 struct ureg_src src0, \
632 struct ureg_src src1 ) \
634 unsigned opcode = TGSI_OPCODE_##op; \
635 struct ureg_emit_insn_result insn; \
636 insn = ureg_emit_insn(ureg, \
647 ureg_emit_texture( ureg, insn.extended_token, target ); \
648 ureg_emit_dst( ureg, dst ); \
649 ureg_emit_src( ureg, src0 ); \
650 ureg_emit_src( ureg, src1 ); \
651 ureg_fixup_insn_size( ureg, insn.insn_token ); \
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 struct ureg_src src2 ) \
661 unsigned opcode = TGSI_OPCODE_##op; \
662 unsigned insn = ureg_emit_insn(ureg, \
673 ureg_emit_dst( ureg, dst ); \
674 ureg_emit_src( ureg, src0 ); \
675 ureg_emit_src( ureg, src1 ); \
676 ureg_emit_src( ureg, src2 ); \
677 ureg_fixup_insn_size( ureg, insn ); \
680 #define OP14_TEX( op ) \
681 static INLINE void ureg_##op( struct ureg_program *ureg, \
682 struct ureg_dst dst, \
684 struct ureg_src src0, \
685 struct ureg_src src1, \
686 struct ureg_src src2, \
687 struct ureg_src src3 ) \
689 unsigned opcode = TGSI_OPCODE_##op; \
690 struct ureg_emit_insn_result insn; \
691 insn = ureg_emit_insn(ureg, \
702 ureg_emit_texture( ureg, insn.extended_token, target ); \
703 ureg_emit_dst( ureg, dst ); \
704 ureg_emit_src( ureg, src0 ); \
705 ureg_emit_src( ureg, src1 ); \
706 ureg_emit_src( ureg, src2 ); \
707 ureg_emit_src( ureg, src3 ); \
708 ureg_fixup_insn_size( ureg, insn.insn_token ); \
712 /* Use a template include to generate a correctly-typed ureg_OP()
713 * function for each TGSI opcode:
715 #include "tgsi_opcode_tmp.h"
718 /***********************************************************************
719 * Inline helpers for manipulating register structs:
721 static INLINE
struct ureg_src
722 ureg_negate( struct ureg_src reg
)
724 assert(reg
.File
!= TGSI_FILE_NULL
);
729 static INLINE
struct ureg_src
730 ureg_abs( struct ureg_src reg
)
732 assert(reg
.File
!= TGSI_FILE_NULL
);
738 static INLINE
struct ureg_src
739 ureg_swizzle( struct ureg_src reg
,
740 int x
, int y
, int z
, int w
)
742 unsigned swz
= ( (reg
.SwizzleX
<< 0) |
743 (reg
.SwizzleY
<< 2) |
744 (reg
.SwizzleZ
<< 4) |
745 (reg
.SwizzleW
<< 6));
747 assert(reg
.File
!= TGSI_FILE_NULL
);
753 reg
.SwizzleX
= (swz
>> (x
*2)) & 0x3;
754 reg
.SwizzleY
= (swz
>> (y
*2)) & 0x3;
755 reg
.SwizzleZ
= (swz
>> (z
*2)) & 0x3;
756 reg
.SwizzleW
= (swz
>> (w
*2)) & 0x3;
760 static INLINE
struct ureg_src
761 ureg_scalar( struct ureg_src reg
, int x
)
763 return ureg_swizzle(reg
, x
, x
, x
, x
);
766 static INLINE
struct ureg_dst
767 ureg_writemask( struct ureg_dst reg
,
770 assert(reg
.File
!= TGSI_FILE_NULL
);
771 reg
.WriteMask
&= writemask
;
775 static INLINE
struct ureg_dst
776 ureg_saturate( struct ureg_dst reg
)
778 assert(reg
.File
!= TGSI_FILE_NULL
);
783 static INLINE
struct ureg_dst
784 ureg_predicate(struct ureg_dst reg
,
791 assert(reg
.File
!= TGSI_FILE_NULL
);
793 reg
.PredNegate
= negate
;
794 reg
.PredSwizzleX
= swizzle_x
;
795 reg
.PredSwizzleY
= swizzle_y
;
796 reg
.PredSwizzleZ
= swizzle_z
;
797 reg
.PredSwizzleW
= swizzle_w
;
801 static INLINE
struct ureg_dst
802 ureg_dst_indirect( struct ureg_dst reg
, struct ureg_src addr
)
804 assert(reg
.File
!= TGSI_FILE_NULL
);
805 assert(addr
.File
== TGSI_FILE_ADDRESS
);
807 reg
.IndirectIndex
= addr
.Index
;
808 reg
.IndirectSwizzle
= addr
.SwizzleX
;
812 static INLINE
struct ureg_src
813 ureg_src_indirect( struct ureg_src reg
, struct ureg_src addr
)
815 assert(reg
.File
!= TGSI_FILE_NULL
);
816 assert(addr
.File
== TGSI_FILE_ADDRESS
|| addr
.File
== TGSI_FILE_TEMPORARY
);
818 reg
.IndirectFile
= addr
.File
;
819 reg
.IndirectIndex
= addr
.Index
;
820 reg
.IndirectSwizzle
= addr
.SwizzleX
;
824 static INLINE
struct ureg_src
825 ureg_src_dimension( struct ureg_src reg
, int index
)
827 assert(reg
.File
!= TGSI_FILE_NULL
);
829 reg
.DimensionIndex
= index
;
833 static INLINE
struct ureg_dst
834 ureg_dst( struct ureg_src src
)
838 assert(!src
.Indirect
|| src
.IndirectFile
== TGSI_FILE_ADDRESS
);
841 dst
.WriteMask
= TGSI_WRITEMASK_XYZW
;
842 dst
.Indirect
= src
.Indirect
;
843 dst
.IndirectIndex
= src
.IndirectIndex
;
844 dst
.IndirectSwizzle
= src
.IndirectSwizzle
;
848 dst
.PredSwizzleX
= TGSI_SWIZZLE_X
;
849 dst
.PredSwizzleY
= TGSI_SWIZZLE_Y
;
850 dst
.PredSwizzleZ
= TGSI_SWIZZLE_Z
;
851 dst
.PredSwizzleW
= TGSI_SWIZZLE_W
;
852 dst
.Index
= src
.Index
;
857 static INLINE
struct ureg_src
858 ureg_src_register(unsigned file
,
864 src
.SwizzleX
= TGSI_SWIZZLE_X
;
865 src
.SwizzleY
= TGSI_SWIZZLE_Y
;
866 src
.SwizzleZ
= TGSI_SWIZZLE_Z
;
867 src
.SwizzleW
= TGSI_SWIZZLE_W
;
869 src
.IndirectFile
= TGSI_FILE_NULL
;
870 src
.IndirectIndex
= 0;
871 src
.IndirectSwizzle
= 0;
876 src
.DimensionIndex
= 0;
881 static INLINE
struct ureg_src
882 ureg_src( struct ureg_dst dst
)
887 src
.SwizzleX
= TGSI_SWIZZLE_X
;
888 src
.SwizzleY
= TGSI_SWIZZLE_Y
;
889 src
.SwizzleZ
= TGSI_SWIZZLE_Z
;
890 src
.SwizzleW
= TGSI_SWIZZLE_W
;
891 src
.Indirect
= dst
.Indirect
;
892 src
.IndirectFile
= TGSI_FILE_ADDRESS
;
893 src
.IndirectIndex
= dst
.IndirectIndex
;
894 src
.IndirectSwizzle
= dst
.IndirectSwizzle
;
896 src
.Index
= dst
.Index
;
899 src
.DimensionIndex
= 0;
906 static INLINE
struct ureg_dst
907 ureg_dst_undef( void )
911 dst
.File
= TGSI_FILE_NULL
;
914 dst
.IndirectIndex
= 0;
915 dst
.IndirectSwizzle
= 0;
919 dst
.PredSwizzleX
= TGSI_SWIZZLE_X
;
920 dst
.PredSwizzleY
= TGSI_SWIZZLE_Y
;
921 dst
.PredSwizzleZ
= TGSI_SWIZZLE_Z
;
922 dst
.PredSwizzleW
= TGSI_SWIZZLE_W
;
928 static INLINE
struct ureg_src
929 ureg_src_undef( void )
933 src
.File
= TGSI_FILE_NULL
;
939 src
.IndirectFile
= TGSI_FILE_NULL
;
940 src
.IndirectIndex
= 0;
941 src
.IndirectSwizzle
= 0;
946 src
.DimensionIndex
= 0;
951 static INLINE boolean
952 ureg_src_is_undef( struct ureg_src src
)
954 return src
.File
== TGSI_FILE_NULL
;
957 static INLINE boolean
958 ureg_dst_is_undef( struct ureg_dst dst
)
960 return dst
.File
== TGSI_FILE_NULL
;