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
);
108 ureg_destroy( struct ureg_program
* );
111 /***********************************************************************
112 * Convenience routine:
115 ureg_create_shader_and_destroy( struct ureg_program
*p
,
116 struct pipe_context
*pipe
)
118 void *result
= ureg_create_shader( p
, pipe
);
124 /***********************************************************************
125 * Build shader properties:
129 ureg_property_gs_input_prim(struct ureg_program
*ureg
,
130 unsigned input_prim
);
133 ureg_property_gs_output_prim(struct ureg_program
*ureg
,
134 unsigned output_prim
);
137 ureg_property_gs_max_vertices(struct ureg_program
*ureg
,
138 unsigned max_vertices
);
141 ureg_property_fs_coord_origin(struct ureg_program
*ureg
,
142 unsigned fs_coord_origin
);
145 ureg_property_fs_coord_pixel_center(struct ureg_program
*ureg
,
146 unsigned fs_coord_pixel_center
);
148 /***********************************************************************
149 * Build shader declarations:
153 ureg_DECL_fs_input( struct ureg_program
*,
154 unsigned semantic_name
,
155 unsigned semantic_index
,
156 unsigned interp_mode
);
159 ureg_DECL_vs_input( struct ureg_program
*,
163 ureg_DECL_gs_input(struct ureg_program
*,
165 unsigned semantic_name
,
166 unsigned semantic_index
);
169 ureg_DECL_system_value(struct ureg_program
*,
171 unsigned semantic_name
,
172 unsigned semantic_index
);
175 ureg_DECL_output( struct ureg_program
*,
176 unsigned semantic_name
,
177 unsigned semantic_index
);
180 ureg_DECL_immediate( struct ureg_program
*,
185 ureg_DECL_immediate_uint( struct ureg_program
*,
190 ureg_DECL_immediate_block_uint( struct ureg_program
*,
195 ureg_DECL_immediate_int( struct ureg_program
*,
200 ureg_DECL_constant2D(struct ureg_program
*ureg
,
206 ureg_DECL_constant( struct ureg_program
*,
210 ureg_DECL_temporary( struct ureg_program
* );
213 ureg_release_temporary( struct ureg_program
*ureg
,
214 struct ureg_dst tmp
);
217 ureg_DECL_address( struct ureg_program
* );
220 ureg_DECL_loop( struct ureg_program
* );
223 ureg_DECL_predicate(struct ureg_program
*);
225 /* Supply an index to the sampler declaration as this is the hook to
226 * the external pipe_sampler state. Users of this function probably
227 * don't want just any sampler, but a specific one which they've set
228 * up state for in the context.
231 ureg_DECL_sampler( struct ureg_program
*,
235 static INLINE
struct ureg_src
236 ureg_imm4f( struct ureg_program
*ureg
,
245 return ureg_DECL_immediate( ureg
, v
, 4 );
248 static INLINE
struct ureg_src
249 ureg_imm3f( struct ureg_program
*ureg
,
257 return ureg_DECL_immediate( ureg
, v
, 3 );
260 static INLINE
struct ureg_src
261 ureg_imm2f( struct ureg_program
*ureg
,
267 return ureg_DECL_immediate( ureg
, v
, 2 );
270 static INLINE
struct ureg_src
271 ureg_imm1f( struct ureg_program
*ureg
,
276 return ureg_DECL_immediate( ureg
, v
, 1 );
279 static INLINE
struct ureg_src
280 ureg_imm4u( struct ureg_program
*ureg
,
281 unsigned a
, unsigned b
,
282 unsigned c
, unsigned d
)
289 return ureg_DECL_immediate_uint( ureg
, v
, 4 );
292 static INLINE
struct ureg_src
293 ureg_imm3u( struct ureg_program
*ureg
,
294 unsigned a
, unsigned b
,
301 return ureg_DECL_immediate_uint( ureg
, v
, 3 );
304 static INLINE
struct ureg_src
305 ureg_imm2u( struct ureg_program
*ureg
,
306 unsigned a
, unsigned b
)
311 return ureg_DECL_immediate_uint( ureg
, v
, 2 );
314 static INLINE
struct ureg_src
315 ureg_imm1u( struct ureg_program
*ureg
,
318 return ureg_DECL_immediate_uint( ureg
, &a
, 1 );
321 static INLINE
struct ureg_src
322 ureg_imm4i( struct ureg_program
*ureg
,
331 return ureg_DECL_immediate_int( ureg
, v
, 4 );
334 static INLINE
struct ureg_src
335 ureg_imm3i( struct ureg_program
*ureg
,
343 return ureg_DECL_immediate_int( ureg
, v
, 3 );
346 static INLINE
struct ureg_src
347 ureg_imm2i( struct ureg_program
*ureg
,
353 return ureg_DECL_immediate_int( ureg
, v
, 2 );
356 static INLINE
struct ureg_src
357 ureg_imm1i( struct ureg_program
*ureg
,
360 return ureg_DECL_immediate_int( ureg
, &a
, 1 );
363 /***********************************************************************
364 * Functions for patching up labels
368 /* Will return a number which can be used in a label to point to the
369 * next instruction to be emitted.
372 ureg_get_instruction_number( struct ureg_program
*ureg
);
375 /* Patch a given label (expressed as a token number) to point to a
376 * given instruction (expressed as an instruction number).
378 * Labels are obtained from instruction emitters, eg ureg_CAL().
379 * Instruction numbers are obtained from ureg_get_instruction_number(),
383 ureg_fixup_label(struct ureg_program
*ureg
,
384 unsigned label_token
,
385 unsigned instruction_number
);
388 /* Generic instruction emitter. Use if you need to pass the opcode as
389 * a parameter, rather than using the emit_OP() varients below.
392 ureg_insn(struct ureg_program
*ureg
,
394 const struct ureg_dst
*dst
,
396 const struct ureg_src
*src
,
401 ureg_tex_insn(struct ureg_program
*ureg
,
403 const struct ureg_dst
*dst
,
406 const struct ureg_src
*src
,
411 ureg_label_insn(struct ureg_program
*ureg
,
413 const struct ureg_src
*src
,
418 /***********************************************************************
419 * Internal instruction helpers, don't call these directly:
422 struct ureg_emit_insn_result
{
423 unsigned insn_token
; /*< Used to fixup insn size. */
424 unsigned extended_token
; /*< Used to set the Extended bit, usually the same as insn_token. */
427 struct ureg_emit_insn_result
428 ureg_emit_insn(struct ureg_program
*ureg
,
433 unsigned pred_swizzle_x
,
434 unsigned pred_swizzle_y
,
435 unsigned pred_swizzle_z
,
436 unsigned pred_swizzle_w
,
441 ureg_emit_label(struct ureg_program
*ureg
,
443 unsigned *label_token
);
446 ureg_emit_texture(struct ureg_program
*ureg
,
451 ureg_emit_dst( struct ureg_program
*ureg
,
452 struct ureg_dst dst
);
455 ureg_emit_src( struct ureg_program
*ureg
,
456 struct ureg_src src
);
459 ureg_fixup_insn_size(struct ureg_program
*ureg
,
464 static INLINE void ureg_##op( struct ureg_program *ureg ) \
466 unsigned opcode = TGSI_OPCODE_##op; \
467 unsigned insn = ureg_emit_insn(ureg, \
478 ureg_fixup_insn_size( ureg, insn ); \
482 static INLINE void ureg_##op( struct ureg_program *ureg, \
483 struct ureg_src src ) \
485 unsigned opcode = TGSI_OPCODE_##op; \
486 unsigned insn = ureg_emit_insn(ureg, \
497 ureg_emit_src( ureg, src ); \
498 ureg_fixup_insn_size( ureg, insn ); \
501 #define OP00_LBL( op ) \
502 static INLINE void ureg_##op( struct ureg_program *ureg, \
503 unsigned *label_token ) \
505 unsigned opcode = TGSI_OPCODE_##op; \
506 struct ureg_emit_insn_result insn; \
507 insn = ureg_emit_insn(ureg, \
518 ureg_emit_label( ureg, insn.extended_token, label_token ); \
519 ureg_fixup_insn_size( ureg, insn.insn_token ); \
522 #define OP01_LBL( op ) \
523 static INLINE void ureg_##op( struct ureg_program *ureg, \
524 struct ureg_src src, \
525 unsigned *label_token ) \
527 unsigned opcode = TGSI_OPCODE_##op; \
528 struct ureg_emit_insn_result insn; \
529 insn = ureg_emit_insn(ureg, \
540 ureg_emit_label( ureg, insn.extended_token, label_token ); \
541 ureg_emit_src( ureg, src ); \
542 ureg_fixup_insn_size( ureg, insn.insn_token ); \
546 static INLINE void ureg_##op( struct ureg_program *ureg, \
547 struct ureg_dst dst ) \
549 unsigned opcode = TGSI_OPCODE_##op; \
550 unsigned insn = ureg_emit_insn(ureg, \
561 ureg_emit_dst( ureg, dst ); \
562 ureg_fixup_insn_size( ureg, insn ); \
567 static INLINE void ureg_##op( struct ureg_program *ureg, \
568 struct ureg_dst dst, \
569 struct ureg_src src ) \
571 unsigned opcode = TGSI_OPCODE_##op; \
572 unsigned insn = ureg_emit_insn(ureg, \
583 ureg_emit_dst( ureg, dst ); \
584 ureg_emit_src( ureg, src ); \
585 ureg_fixup_insn_size( ureg, insn ); \
589 static INLINE void ureg_##op( struct ureg_program *ureg, \
590 struct ureg_dst dst, \
591 struct ureg_src src0, \
592 struct ureg_src src1 ) \
594 unsigned opcode = TGSI_OPCODE_##op; \
595 unsigned insn = ureg_emit_insn(ureg, \
606 ureg_emit_dst( ureg, dst ); \
607 ureg_emit_src( ureg, src0 ); \
608 ureg_emit_src( ureg, src1 ); \
609 ureg_fixup_insn_size( ureg, insn ); \
612 #define OP12_TEX( op ) \
613 static INLINE void ureg_##op( struct ureg_program *ureg, \
614 struct ureg_dst dst, \
616 struct ureg_src src0, \
617 struct ureg_src src1 ) \
619 unsigned opcode = TGSI_OPCODE_##op; \
620 struct ureg_emit_insn_result insn; \
621 insn = ureg_emit_insn(ureg, \
632 ureg_emit_texture( ureg, insn.extended_token, target ); \
633 ureg_emit_dst( ureg, dst ); \
634 ureg_emit_src( ureg, src0 ); \
635 ureg_emit_src( ureg, src1 ); \
636 ureg_fixup_insn_size( ureg, insn.insn_token ); \
640 static INLINE void ureg_##op( struct ureg_program *ureg, \
641 struct ureg_dst dst, \
642 struct ureg_src src0, \
643 struct ureg_src src1, \
644 struct ureg_src src2 ) \
646 unsigned opcode = TGSI_OPCODE_##op; \
647 unsigned insn = ureg_emit_insn(ureg, \
658 ureg_emit_dst( ureg, dst ); \
659 ureg_emit_src( ureg, src0 ); \
660 ureg_emit_src( ureg, src1 ); \
661 ureg_emit_src( ureg, src2 ); \
662 ureg_fixup_insn_size( ureg, insn ); \
665 #define OP14_TEX( op ) \
666 static INLINE void ureg_##op( struct ureg_program *ureg, \
667 struct ureg_dst dst, \
669 struct ureg_src src0, \
670 struct ureg_src src1, \
671 struct ureg_src src2, \
672 struct ureg_src src3 ) \
674 unsigned opcode = TGSI_OPCODE_##op; \
675 struct ureg_emit_insn_result insn; \
676 insn = ureg_emit_insn(ureg, \
687 ureg_emit_texture( ureg, insn.extended_token, target ); \
688 ureg_emit_dst( ureg, dst ); \
689 ureg_emit_src( ureg, src0 ); \
690 ureg_emit_src( ureg, src1 ); \
691 ureg_emit_src( ureg, src2 ); \
692 ureg_emit_src( ureg, src3 ); \
693 ureg_fixup_insn_size( ureg, insn.insn_token ); \
697 /* Use a template include to generate a correctly-typed ureg_OP()
698 * function for each TGSI opcode:
700 #include "tgsi_opcode_tmp.h"
703 /***********************************************************************
704 * Inline helpers for manipulating register structs:
706 static INLINE
struct ureg_src
707 ureg_negate( struct ureg_src reg
)
709 assert(reg
.File
!= TGSI_FILE_NULL
);
714 static INLINE
struct ureg_src
715 ureg_abs( struct ureg_src reg
)
717 assert(reg
.File
!= TGSI_FILE_NULL
);
723 static INLINE
struct ureg_src
724 ureg_swizzle( struct ureg_src reg
,
725 int x
, int y
, int z
, int w
)
727 unsigned swz
= ( (reg
.SwizzleX
<< 0) |
728 (reg
.SwizzleY
<< 2) |
729 (reg
.SwizzleZ
<< 4) |
730 (reg
.SwizzleW
<< 6));
732 assert(reg
.File
!= TGSI_FILE_NULL
);
738 reg
.SwizzleX
= (swz
>> (x
*2)) & 0x3;
739 reg
.SwizzleY
= (swz
>> (y
*2)) & 0x3;
740 reg
.SwizzleZ
= (swz
>> (z
*2)) & 0x3;
741 reg
.SwizzleW
= (swz
>> (w
*2)) & 0x3;
745 static INLINE
struct ureg_src
746 ureg_scalar( struct ureg_src reg
, int x
)
748 return ureg_swizzle(reg
, x
, x
, x
, x
);
751 static INLINE
struct ureg_dst
752 ureg_writemask( struct ureg_dst reg
,
755 assert(reg
.File
!= TGSI_FILE_NULL
);
756 reg
.WriteMask
&= writemask
;
760 static INLINE
struct ureg_dst
761 ureg_saturate( struct ureg_dst reg
)
763 assert(reg
.File
!= TGSI_FILE_NULL
);
768 static INLINE
struct ureg_dst
769 ureg_predicate(struct ureg_dst reg
,
776 assert(reg
.File
!= TGSI_FILE_NULL
);
778 reg
.PredNegate
= negate
;
779 reg
.PredSwizzleX
= swizzle_x
;
780 reg
.PredSwizzleY
= swizzle_y
;
781 reg
.PredSwizzleZ
= swizzle_z
;
782 reg
.PredSwizzleW
= swizzle_w
;
786 static INLINE
struct ureg_dst
787 ureg_dst_indirect( struct ureg_dst reg
, struct ureg_src addr
)
789 assert(reg
.File
!= TGSI_FILE_NULL
);
790 assert(addr
.File
== TGSI_FILE_ADDRESS
);
792 reg
.IndirectIndex
= addr
.Index
;
793 reg
.IndirectSwizzle
= addr
.SwizzleX
;
797 static INLINE
struct ureg_src
798 ureg_src_indirect( struct ureg_src reg
, struct ureg_src addr
)
800 assert(reg
.File
!= TGSI_FILE_NULL
);
801 assert(addr
.File
== TGSI_FILE_ADDRESS
|| addr
.File
== TGSI_FILE_TEMPORARY
);
803 reg
.IndirectFile
= addr
.File
;
804 reg
.IndirectIndex
= addr
.Index
;
805 reg
.IndirectSwizzle
= addr
.SwizzleX
;
809 static INLINE
struct ureg_src
810 ureg_src_dimension( struct ureg_src reg
, int index
)
812 assert(reg
.File
!= TGSI_FILE_NULL
);
814 reg
.DimensionIndex
= index
;
818 static INLINE
struct ureg_dst
819 ureg_dst( struct ureg_src src
)
823 assert(!src
.Indirect
|| src
.IndirectFile
== TGSI_FILE_ADDRESS
);
826 dst
.WriteMask
= TGSI_WRITEMASK_XYZW
;
827 dst
.Indirect
= src
.Indirect
;
828 dst
.IndirectIndex
= src
.IndirectIndex
;
829 dst
.IndirectSwizzle
= src
.IndirectSwizzle
;
833 dst
.PredSwizzleX
= TGSI_SWIZZLE_X
;
834 dst
.PredSwizzleY
= TGSI_SWIZZLE_Y
;
835 dst
.PredSwizzleZ
= TGSI_SWIZZLE_Z
;
836 dst
.PredSwizzleW
= TGSI_SWIZZLE_W
;
837 dst
.Index
= src
.Index
;
842 static INLINE
struct ureg_src
843 ureg_src_register(unsigned file
,
849 src
.SwizzleX
= TGSI_SWIZZLE_X
;
850 src
.SwizzleY
= TGSI_SWIZZLE_Y
;
851 src
.SwizzleZ
= TGSI_SWIZZLE_Z
;
852 src
.SwizzleW
= TGSI_SWIZZLE_W
;
854 src
.IndirectFile
= TGSI_FILE_NULL
;
855 src
.IndirectIndex
= 0;
856 src
.IndirectSwizzle
= 0;
861 src
.DimensionIndex
= 0;
866 static INLINE
struct ureg_src
867 ureg_src( struct ureg_dst dst
)
872 src
.SwizzleX
= TGSI_SWIZZLE_X
;
873 src
.SwizzleY
= TGSI_SWIZZLE_Y
;
874 src
.SwizzleZ
= TGSI_SWIZZLE_Z
;
875 src
.SwizzleW
= TGSI_SWIZZLE_W
;
876 src
.Indirect
= dst
.Indirect
;
877 src
.IndirectFile
= TGSI_FILE_ADDRESS
;
878 src
.IndirectIndex
= dst
.IndirectIndex
;
879 src
.IndirectSwizzle
= dst
.IndirectSwizzle
;
881 src
.Index
= dst
.Index
;
884 src
.DimensionIndex
= 0;
891 static INLINE
struct ureg_dst
892 ureg_dst_undef( void )
896 dst
.File
= TGSI_FILE_NULL
;
899 dst
.IndirectIndex
= 0;
900 dst
.IndirectSwizzle
= 0;
904 dst
.PredSwizzleX
= TGSI_SWIZZLE_X
;
905 dst
.PredSwizzleY
= TGSI_SWIZZLE_Y
;
906 dst
.PredSwizzleZ
= TGSI_SWIZZLE_Z
;
907 dst
.PredSwizzleW
= TGSI_SWIZZLE_W
;
913 static INLINE
struct ureg_src
914 ureg_src_undef( void )
918 src
.File
= TGSI_FILE_NULL
;
924 src
.IndirectFile
= TGSI_FILE_NULL
;
925 src
.IndirectIndex
= 0;
926 src
.IndirectSwizzle
= 0;
931 src
.DimensionIndex
= 0;
936 static INLINE boolean
937 ureg_src_is_undef( struct ureg_src src
)
939 return src
.File
== TGSI_FILE_NULL
;
942 static INLINE boolean
943 ureg_dst_is_undef( struct ureg_dst dst
)
945 return dst
.File
== TGSI_FILE_NULL
;