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 DimIndirect
: 1; /* BOOL */
53 unsigned Dimension
: 1; /* BOOL */
54 unsigned Absolute
: 1; /* BOOL */
55 unsigned Negate
: 1; /* BOOL */
56 int Index
: 16; /* SINT */
57 unsigned IndirectFile
: 4; /* TGSI_FILE_ */
58 int IndirectIndex
: 16; /* SINT */
59 unsigned IndirectSwizzle
: 2; /* TGSI_SWIZZLE_ */
60 int DimensionIndex
: 16; /* SINT */
61 unsigned DimIndFile
: 4; /* TGSI_FILE_ */
62 int DimIndIndex
: 16; /* SINT */
63 unsigned DimIndSwizzle
: 2; /* TGSI_SWIZZLE_ */
66 /* Very similar to a tgsi_dst_register, removing unsupported fields
67 * and adding a Saturate flag. It's easier to push saturate into the
68 * destination register than to try and create a _SAT varient of each
69 * instruction function.
73 unsigned File
: 4; /* TGSI_FILE_ */
74 unsigned WriteMask
: 4; /* TGSI_WRITEMASK_ */
75 unsigned Indirect
: 1; /* BOOL */
76 unsigned Saturate
: 1; /* BOOL */
77 unsigned Predicate
: 1;
78 unsigned PredNegate
: 1; /* BOOL */
79 unsigned PredSwizzleX
: 2; /* TGSI_SWIZZLE_ */
80 unsigned PredSwizzleY
: 2; /* TGSI_SWIZZLE_ */
81 unsigned PredSwizzleZ
: 2; /* TGSI_SWIZZLE_ */
82 unsigned PredSwizzleW
: 2; /* TGSI_SWIZZLE_ */
83 int Index
: 16; /* SINT */
84 int IndirectIndex
: 16; /* SINT */
85 int IndirectSwizzle
: 2; /* TGSI_SWIZZLE_ */
91 ureg_create( unsigned processor
);
93 const struct tgsi_token
*
94 ureg_finalize( struct ureg_program
* );
96 /* Create and return a shader:
99 ureg_create_shader( struct ureg_program
*,
100 struct pipe_context
*pipe
);
103 /* Alternately, return the built token stream and hand ownership of
104 * that memory to the caller:
106 const struct tgsi_token
*
107 ureg_get_tokens( struct ureg_program
*ureg
,
108 unsigned *nr_tokens
);
111 /* Free the tokens created by ureg_get_tokens() */
112 void ureg_free_tokens( const struct tgsi_token
*tokens
);
116 ureg_destroy( struct ureg_program
* );
119 /***********************************************************************
120 * Convenience routine:
123 ureg_create_shader_and_destroy( struct ureg_program
*p
,
124 struct pipe_context
*pipe
)
126 void *result
= ureg_create_shader( p
, pipe
);
132 /***********************************************************************
133 * Build shader properties:
137 ureg_property_gs_input_prim(struct ureg_program
*ureg
,
138 unsigned input_prim
);
141 ureg_property_gs_output_prim(struct ureg_program
*ureg
,
142 unsigned output_prim
);
145 ureg_property_gs_max_vertices(struct ureg_program
*ureg
,
146 unsigned max_vertices
);
149 ureg_property_fs_coord_origin(struct ureg_program
*ureg
,
150 unsigned fs_coord_origin
);
153 ureg_property_fs_coord_pixel_center(struct ureg_program
*ureg
,
154 unsigned fs_coord_pixel_center
);
156 /***********************************************************************
157 * Build shader declarations:
161 ureg_DECL_fs_input_cyl_centroid(struct ureg_program
*,
162 unsigned semantic_name
,
163 unsigned semantic_index
,
164 unsigned interp_mode
,
165 unsigned cylindrical_wrap
,
168 static INLINE
struct ureg_src
169 ureg_DECL_fs_input_cyl(struct ureg_program
*ureg
,
170 unsigned semantic_name
,
171 unsigned semantic_index
,
172 unsigned interp_mode
,
173 unsigned cylindrical_wrap
)
175 return ureg_DECL_fs_input_cyl_centroid(ureg
,
183 static INLINE
struct ureg_src
184 ureg_DECL_fs_input(struct ureg_program
*ureg
,
185 unsigned semantic_name
,
186 unsigned semantic_index
,
187 unsigned interp_mode
)
189 return ureg_DECL_fs_input_cyl_centroid(ureg
,
197 ureg_DECL_vs_input( struct ureg_program
*,
201 ureg_DECL_gs_input(struct ureg_program
*,
203 unsigned semantic_name
,
204 unsigned semantic_index
);
207 ureg_DECL_system_value(struct ureg_program
*,
209 unsigned semantic_name
,
210 unsigned semantic_index
);
213 ureg_DECL_output( struct ureg_program
*,
214 unsigned semantic_name
,
215 unsigned semantic_index
);
218 ureg_DECL_immediate( struct ureg_program
*,
223 ureg_DECL_immediate_uint( struct ureg_program
*,
228 ureg_DECL_immediate_block_uint( struct ureg_program
*,
233 ureg_DECL_immediate_int( struct ureg_program
*,
238 ureg_DECL_constant2D(struct ureg_program
*ureg
,
244 ureg_DECL_constant( struct ureg_program
*,
248 ureg_DECL_temporary( struct ureg_program
* );
251 ureg_release_temporary( struct ureg_program
*ureg
,
252 struct ureg_dst tmp
);
255 ureg_DECL_address( struct ureg_program
* );
258 ureg_DECL_predicate(struct ureg_program
*);
260 /* Supply an index to the sampler declaration as this is the hook to
261 * the external pipe_sampler state. Users of this function probably
262 * don't want just any sampler, but a specific one which they've set
263 * up state for in the context.
266 ureg_DECL_sampler( struct ureg_program
*,
270 static INLINE
struct ureg_src
271 ureg_imm4f( struct ureg_program
*ureg
,
280 return ureg_DECL_immediate( ureg
, v
, 4 );
283 static INLINE
struct ureg_src
284 ureg_imm3f( struct ureg_program
*ureg
,
292 return ureg_DECL_immediate( ureg
, v
, 3 );
295 static INLINE
struct ureg_src
296 ureg_imm2f( struct ureg_program
*ureg
,
302 return ureg_DECL_immediate( ureg
, v
, 2 );
305 static INLINE
struct ureg_src
306 ureg_imm1f( struct ureg_program
*ureg
,
311 return ureg_DECL_immediate( ureg
, v
, 1 );
314 static INLINE
struct ureg_src
315 ureg_imm4u( struct ureg_program
*ureg
,
316 unsigned a
, unsigned b
,
317 unsigned c
, unsigned d
)
324 return ureg_DECL_immediate_uint( ureg
, v
, 4 );
327 static INLINE
struct ureg_src
328 ureg_imm3u( struct ureg_program
*ureg
,
329 unsigned a
, unsigned b
,
336 return ureg_DECL_immediate_uint( ureg
, v
, 3 );
339 static INLINE
struct ureg_src
340 ureg_imm2u( struct ureg_program
*ureg
,
341 unsigned a
, unsigned b
)
346 return ureg_DECL_immediate_uint( ureg
, v
, 2 );
349 static INLINE
struct ureg_src
350 ureg_imm1u( struct ureg_program
*ureg
,
353 return ureg_DECL_immediate_uint( ureg
, &a
, 1 );
356 static INLINE
struct ureg_src
357 ureg_imm4i( struct ureg_program
*ureg
,
366 return ureg_DECL_immediate_int( ureg
, v
, 4 );
369 static INLINE
struct ureg_src
370 ureg_imm3i( struct ureg_program
*ureg
,
378 return ureg_DECL_immediate_int( ureg
, v
, 3 );
381 static INLINE
struct ureg_src
382 ureg_imm2i( struct ureg_program
*ureg
,
388 return ureg_DECL_immediate_int( ureg
, v
, 2 );
391 static INLINE
struct ureg_src
392 ureg_imm1i( struct ureg_program
*ureg
,
395 return ureg_DECL_immediate_int( ureg
, &a
, 1 );
398 /***********************************************************************
399 * Functions for patching up labels
403 /* Will return a number which can be used in a label to point to the
404 * next instruction to be emitted.
407 ureg_get_instruction_number( struct ureg_program
*ureg
);
410 /* Patch a given label (expressed as a token number) to point to a
411 * given instruction (expressed as an instruction number).
413 * Labels are obtained from instruction emitters, eg ureg_CAL().
414 * Instruction numbers are obtained from ureg_get_instruction_number(),
418 ureg_fixup_label(struct ureg_program
*ureg
,
419 unsigned label_token
,
420 unsigned instruction_number
);
423 /* Generic instruction emitter. Use if you need to pass the opcode as
424 * a parameter, rather than using the emit_OP() varients below.
427 ureg_insn(struct ureg_program
*ureg
,
429 const struct ureg_dst
*dst
,
431 const struct ureg_src
*src
,
436 ureg_tex_insn(struct ureg_program
*ureg
,
438 const struct ureg_dst
*dst
,
441 const struct ureg_src
*src
,
446 ureg_label_insn(struct ureg_program
*ureg
,
448 const struct ureg_src
*src
,
453 /***********************************************************************
454 * Internal instruction helpers, don't call these directly:
457 struct ureg_emit_insn_result
{
458 unsigned insn_token
; /*< Used to fixup insn size. */
459 unsigned extended_token
; /*< Used to set the Extended bit, usually the same as insn_token. */
462 struct ureg_emit_insn_result
463 ureg_emit_insn(struct ureg_program
*ureg
,
468 unsigned pred_swizzle_x
,
469 unsigned pred_swizzle_y
,
470 unsigned pred_swizzle_z
,
471 unsigned pred_swizzle_w
,
476 ureg_emit_label(struct ureg_program
*ureg
,
478 unsigned *label_token
);
481 ureg_emit_texture(struct ureg_program
*ureg
,
486 ureg_emit_dst( struct ureg_program
*ureg
,
487 struct ureg_dst dst
);
490 ureg_emit_src( struct ureg_program
*ureg
,
491 struct ureg_src src
);
494 ureg_fixup_insn_size(struct ureg_program
*ureg
,
499 static INLINE void ureg_##op( struct ureg_program *ureg ) \
501 unsigned opcode = TGSI_OPCODE_##op; \
502 unsigned insn = ureg_emit_insn(ureg, \
513 ureg_fixup_insn_size( ureg, insn ); \
517 static INLINE void ureg_##op( struct ureg_program *ureg, \
518 struct ureg_src src ) \
520 unsigned opcode = TGSI_OPCODE_##op; \
521 unsigned insn = ureg_emit_insn(ureg, \
532 ureg_emit_src( ureg, src ); \
533 ureg_fixup_insn_size( ureg, insn ); \
536 #define OP00_LBL( op ) \
537 static INLINE void ureg_##op( struct ureg_program *ureg, \
538 unsigned *label_token ) \
540 unsigned opcode = TGSI_OPCODE_##op; \
541 struct ureg_emit_insn_result insn; \
542 insn = ureg_emit_insn(ureg, \
553 ureg_emit_label( ureg, insn.extended_token, label_token ); \
554 ureg_fixup_insn_size( ureg, insn.insn_token ); \
557 #define OP01_LBL( op ) \
558 static INLINE void ureg_##op( struct ureg_program *ureg, \
559 struct ureg_src src, \
560 unsigned *label_token ) \
562 unsigned opcode = TGSI_OPCODE_##op; \
563 struct ureg_emit_insn_result insn; \
564 insn = ureg_emit_insn(ureg, \
575 ureg_emit_label( ureg, insn.extended_token, label_token ); \
576 ureg_emit_src( ureg, src ); \
577 ureg_fixup_insn_size( ureg, insn.insn_token ); \
581 static INLINE void ureg_##op( struct ureg_program *ureg, \
582 struct ureg_dst dst ) \
584 unsigned opcode = TGSI_OPCODE_##op; \
585 unsigned insn = ureg_emit_insn(ureg, \
596 ureg_emit_dst( ureg, dst ); \
597 ureg_fixup_insn_size( ureg, insn ); \
602 static INLINE void ureg_##op( struct ureg_program *ureg, \
603 struct ureg_dst dst, \
604 struct ureg_src src ) \
606 unsigned opcode = TGSI_OPCODE_##op; \
607 unsigned insn = ureg_emit_insn(ureg, \
618 ureg_emit_dst( ureg, dst ); \
619 ureg_emit_src( ureg, src ); \
620 ureg_fixup_insn_size( ureg, insn ); \
624 static INLINE void ureg_##op( struct ureg_program *ureg, \
625 struct ureg_dst dst, \
626 struct ureg_src src0, \
627 struct ureg_src src1 ) \
629 unsigned opcode = TGSI_OPCODE_##op; \
630 unsigned insn = ureg_emit_insn(ureg, \
641 ureg_emit_dst( ureg, dst ); \
642 ureg_emit_src( ureg, src0 ); \
643 ureg_emit_src( ureg, src1 ); \
644 ureg_fixup_insn_size( ureg, insn ); \
647 #define OP12_TEX( op ) \
648 static INLINE void ureg_##op( struct ureg_program *ureg, \
649 struct ureg_dst dst, \
651 struct ureg_src src0, \
652 struct ureg_src src1 ) \
654 unsigned opcode = TGSI_OPCODE_##op; \
655 struct ureg_emit_insn_result insn; \
656 insn = ureg_emit_insn(ureg, \
667 ureg_emit_texture( ureg, insn.extended_token, target ); \
668 ureg_emit_dst( ureg, dst ); \
669 ureg_emit_src( ureg, src0 ); \
670 ureg_emit_src( ureg, src1 ); \
671 ureg_fixup_insn_size( ureg, insn.insn_token ); \
675 static INLINE void ureg_##op( struct ureg_program *ureg, \
676 struct ureg_dst dst, \
677 struct ureg_src src0, \
678 struct ureg_src src1, \
679 struct ureg_src src2 ) \
681 unsigned opcode = TGSI_OPCODE_##op; \
682 unsigned insn = ureg_emit_insn(ureg, \
693 ureg_emit_dst( ureg, dst ); \
694 ureg_emit_src( ureg, src0 ); \
695 ureg_emit_src( ureg, src1 ); \
696 ureg_emit_src( ureg, src2 ); \
697 ureg_fixup_insn_size( ureg, insn ); \
700 #define OP14_TEX( op ) \
701 static INLINE void ureg_##op( struct ureg_program *ureg, \
702 struct ureg_dst dst, \
704 struct ureg_src src0, \
705 struct ureg_src src1, \
706 struct ureg_src src2, \
707 struct ureg_src src3 ) \
709 unsigned opcode = TGSI_OPCODE_##op; \
710 struct ureg_emit_insn_result insn; \
711 insn = ureg_emit_insn(ureg, \
722 ureg_emit_texture( ureg, insn.extended_token, target ); \
723 ureg_emit_dst( ureg, dst ); \
724 ureg_emit_src( ureg, src0 ); \
725 ureg_emit_src( ureg, src1 ); \
726 ureg_emit_src( ureg, src2 ); \
727 ureg_emit_src( ureg, src3 ); \
728 ureg_fixup_insn_size( ureg, insn.insn_token ); \
732 /* Use a template include to generate a correctly-typed ureg_OP()
733 * function for each TGSI opcode:
735 #include "tgsi_opcode_tmp.h"
738 /***********************************************************************
739 * Inline helpers for manipulating register structs:
741 static INLINE
struct ureg_src
742 ureg_negate( struct ureg_src reg
)
744 assert(reg
.File
!= TGSI_FILE_NULL
);
749 static INLINE
struct ureg_src
750 ureg_abs( struct ureg_src reg
)
752 assert(reg
.File
!= TGSI_FILE_NULL
);
758 static INLINE
struct ureg_src
759 ureg_swizzle( struct ureg_src reg
,
760 int x
, int y
, int z
, int w
)
762 unsigned swz
= ( (reg
.SwizzleX
<< 0) |
763 (reg
.SwizzleY
<< 2) |
764 (reg
.SwizzleZ
<< 4) |
765 (reg
.SwizzleW
<< 6));
767 assert(reg
.File
!= TGSI_FILE_NULL
);
773 reg
.SwizzleX
= (swz
>> (x
*2)) & 0x3;
774 reg
.SwizzleY
= (swz
>> (y
*2)) & 0x3;
775 reg
.SwizzleZ
= (swz
>> (z
*2)) & 0x3;
776 reg
.SwizzleW
= (swz
>> (w
*2)) & 0x3;
780 static INLINE
struct ureg_src
781 ureg_scalar( struct ureg_src reg
, int x
)
783 return ureg_swizzle(reg
, x
, x
, x
, x
);
786 static INLINE
struct ureg_dst
787 ureg_writemask( struct ureg_dst reg
,
790 assert(reg
.File
!= TGSI_FILE_NULL
);
791 reg
.WriteMask
&= writemask
;
795 static INLINE
struct ureg_dst
796 ureg_saturate( struct ureg_dst reg
)
798 assert(reg
.File
!= TGSI_FILE_NULL
);
803 static INLINE
struct ureg_dst
804 ureg_predicate(struct ureg_dst reg
,
811 assert(reg
.File
!= TGSI_FILE_NULL
);
813 reg
.PredNegate
= negate
;
814 reg
.PredSwizzleX
= swizzle_x
;
815 reg
.PredSwizzleY
= swizzle_y
;
816 reg
.PredSwizzleZ
= swizzle_z
;
817 reg
.PredSwizzleW
= swizzle_w
;
821 static INLINE
struct ureg_dst
822 ureg_dst_indirect( struct ureg_dst reg
, struct ureg_src addr
)
824 assert(reg
.File
!= TGSI_FILE_NULL
);
825 assert(addr
.File
== TGSI_FILE_ADDRESS
);
827 reg
.IndirectIndex
= addr
.Index
;
828 reg
.IndirectSwizzle
= addr
.SwizzleX
;
832 static INLINE
struct ureg_src
833 ureg_src_indirect( struct ureg_src reg
, struct ureg_src addr
)
835 assert(reg
.File
!= TGSI_FILE_NULL
);
836 assert(addr
.File
== TGSI_FILE_ADDRESS
|| addr
.File
== TGSI_FILE_TEMPORARY
);
838 reg
.IndirectFile
= addr
.File
;
839 reg
.IndirectIndex
= addr
.Index
;
840 reg
.IndirectSwizzle
= addr
.SwizzleX
;
844 static INLINE
struct ureg_src
845 ureg_src_dimension( struct ureg_src reg
, int index
)
847 assert(reg
.File
!= TGSI_FILE_NULL
);
850 reg
.DimensionIndex
= index
;
855 static INLINE
struct ureg_src
856 ureg_src_dimension_indirect( struct ureg_src reg
, struct ureg_src addr
,
859 assert(reg
.File
!= TGSI_FILE_NULL
);
862 reg
.DimensionIndex
= index
;
863 reg
.DimIndFile
= addr
.File
;
864 reg
.DimIndIndex
= addr
.Index
;
865 reg
.DimIndSwizzle
= addr
.SwizzleX
;
869 static INLINE
struct ureg_dst
870 ureg_dst( struct ureg_src src
)
874 assert(!src
.Indirect
|| src
.IndirectFile
== TGSI_FILE_ADDRESS
);
877 dst
.WriteMask
= TGSI_WRITEMASK_XYZW
;
878 dst
.Indirect
= src
.Indirect
;
879 dst
.IndirectIndex
= src
.IndirectIndex
;
880 dst
.IndirectSwizzle
= src
.IndirectSwizzle
;
884 dst
.PredSwizzleX
= TGSI_SWIZZLE_X
;
885 dst
.PredSwizzleY
= TGSI_SWIZZLE_Y
;
886 dst
.PredSwizzleZ
= TGSI_SWIZZLE_Z
;
887 dst
.PredSwizzleW
= TGSI_SWIZZLE_W
;
888 dst
.Index
= src
.Index
;
893 static INLINE
struct ureg_src
894 ureg_src_register(unsigned file
,
900 src
.SwizzleX
= TGSI_SWIZZLE_X
;
901 src
.SwizzleY
= TGSI_SWIZZLE_Y
;
902 src
.SwizzleZ
= TGSI_SWIZZLE_Z
;
903 src
.SwizzleW
= TGSI_SWIZZLE_W
;
905 src
.IndirectFile
= TGSI_FILE_NULL
;
906 src
.IndirectIndex
= 0;
907 src
.IndirectSwizzle
= 0;
912 src
.DimensionIndex
= 0;
914 src
.DimIndFile
= TGSI_FILE_NULL
;
916 src
.DimIndSwizzle
= 0;
921 static INLINE
struct ureg_src
922 ureg_src( struct ureg_dst dst
)
927 src
.SwizzleX
= TGSI_SWIZZLE_X
;
928 src
.SwizzleY
= TGSI_SWIZZLE_Y
;
929 src
.SwizzleZ
= TGSI_SWIZZLE_Z
;
930 src
.SwizzleW
= TGSI_SWIZZLE_W
;
931 src
.Indirect
= dst
.Indirect
;
932 src
.IndirectFile
= TGSI_FILE_ADDRESS
;
933 src
.IndirectIndex
= dst
.IndirectIndex
;
934 src
.IndirectSwizzle
= dst
.IndirectSwizzle
;
936 src
.Index
= dst
.Index
;
939 src
.DimensionIndex
= 0;
941 src
.DimIndFile
= TGSI_FILE_NULL
;
943 src
.DimIndSwizzle
= 0;
950 static INLINE
struct ureg_dst
951 ureg_dst_undef( void )
955 dst
.File
= TGSI_FILE_NULL
;
958 dst
.IndirectIndex
= 0;
959 dst
.IndirectSwizzle
= 0;
963 dst
.PredSwizzleX
= TGSI_SWIZZLE_X
;
964 dst
.PredSwizzleY
= TGSI_SWIZZLE_Y
;
965 dst
.PredSwizzleZ
= TGSI_SWIZZLE_Z
;
966 dst
.PredSwizzleW
= TGSI_SWIZZLE_W
;
972 static INLINE
struct ureg_src
973 ureg_src_undef( void )
977 src
.File
= TGSI_FILE_NULL
;
983 src
.IndirectFile
= TGSI_FILE_NULL
;
984 src
.IndirectIndex
= 0;
985 src
.IndirectSwizzle
= 0;
990 src
.DimensionIndex
= 0;
992 src
.DimIndFile
= TGSI_FILE_NULL
;
994 src
.DimIndSwizzle
= 0;
999 static INLINE boolean
1000 ureg_src_is_undef( struct ureg_src src
)
1002 return src
.File
== TGSI_FILE_NULL
;
1005 static INLINE boolean
1006 ureg_dst_is_undef( struct ureg_dst dst
)
1008 return dst
.File
== TGSI_FILE_NULL
;