c0dc722673f989fb20abe8c15428a617cd3374eb
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 Indirect
: 1; /* BOOL */
51 unsigned Dimension
: 1; /* BOOL */
52 unsigned Absolute
: 1; /* BOOL */
53 unsigned Negate
: 1; /* BOOL */
54 int Index
: 16; /* SINT */
55 unsigned IndirectFile
: 4; /* TGSI_FILE_ */
56 int IndirectIndex
: 16; /* SINT */
57 unsigned IndirectSwizzle
: 2; /* TGSI_SWIZZLE_ */
58 int DimensionIndex
: 16; /* SINT */
61 /* Very similar to a tgsi_dst_register, removing unsupported fields
62 * and adding a Saturate flag. It's easier to push saturate into the
63 * destination register than to try and create a _SAT varient of each
64 * instruction function.
68 unsigned File
: 4; /* TGSI_FILE_ */
69 unsigned WriteMask
: 4; /* TGSI_WRITEMASK_ */
70 unsigned Indirect
: 1; /* BOOL */
71 unsigned Saturate
: 1; /* BOOL */
72 unsigned Predicate
: 1;
73 unsigned PredNegate
: 1; /* BOOL */
74 unsigned PredSwizzleX
: 2; /* TGSI_SWIZZLE_ */
75 unsigned PredSwizzleY
: 2; /* TGSI_SWIZZLE_ */
76 unsigned PredSwizzleZ
: 2; /* TGSI_SWIZZLE_ */
77 unsigned PredSwizzleW
: 2; /* TGSI_SWIZZLE_ */
78 int Index
: 16; /* SINT */
79 int IndirectIndex
: 16; /* SINT */
80 int IndirectSwizzle
: 2; /* TGSI_SWIZZLE_ */
86 ureg_create( unsigned processor
);
88 const struct tgsi_token
*
89 ureg_finalize( struct ureg_program
* );
91 /* Create and return a shader:
94 ureg_create_shader( struct ureg_program
*,
95 struct pipe_context
*pipe
);
98 /* Alternately, return the built token stream and hand ownership of
99 * that memory to the caller:
101 const struct tgsi_token
*
102 ureg_get_tokens( struct ureg_program
*ureg
,
103 unsigned *nr_tokens
);
107 ureg_destroy( struct ureg_program
* );
110 /***********************************************************************
111 * Convenience routine:
114 ureg_create_shader_and_destroy( struct ureg_program
*p
,
115 struct pipe_context
*pipe
)
117 void *result
= ureg_create_shader( p
, pipe
);
123 /***********************************************************************
124 * Build shader properties:
128 ureg_property_gs_input_prim(struct ureg_program
*ureg
,
129 unsigned gs_input_prim
);
132 /***********************************************************************
133 * Build shader declarations:
137 ureg_DECL_fs_input( struct ureg_program
*,
138 unsigned semantic_name
,
139 unsigned semantic_index
,
140 unsigned interp_mode
);
143 ureg_DECL_vs_input( struct ureg_program
*,
147 ureg_DECL_gs_input(struct ureg_program
*,
151 ureg_DECL_system_value(struct ureg_program
*,
153 unsigned semantic_name
,
154 unsigned semantic_index
);
157 ureg_DECL_output( struct ureg_program
*,
158 unsigned semantic_name
,
159 unsigned semantic_index
);
162 ureg_DECL_immediate( struct ureg_program
*,
167 ureg_DECL_immediate_uint( struct ureg_program
*,
172 ureg_DECL_immediate_block_uint( struct ureg_program
*,
177 ureg_DECL_immediate_int( struct ureg_program
*,
182 ureg_DECL_constant2D(struct ureg_program
*ureg
,
188 ureg_DECL_constant( struct ureg_program
*,
192 ureg_DECL_temporary( struct ureg_program
* );
195 ureg_release_temporary( struct ureg_program
*ureg
,
196 struct ureg_dst tmp
);
199 ureg_DECL_address( struct ureg_program
* );
202 ureg_DECL_loop( struct ureg_program
* );
205 ureg_DECL_predicate(struct ureg_program
*);
207 /* Supply an index to the sampler declaration as this is the hook to
208 * the external pipe_sampler state. Users of this function probably
209 * don't want just any sampler, but a specific one which they've set
210 * up state for in the context.
213 ureg_DECL_sampler( struct ureg_program
*,
217 static INLINE
struct ureg_src
218 ureg_imm4f( struct ureg_program
*ureg
,
227 return ureg_DECL_immediate( ureg
, v
, 4 );
230 static INLINE
struct ureg_src
231 ureg_imm3f( struct ureg_program
*ureg
,
239 return ureg_DECL_immediate( ureg
, v
, 3 );
242 static INLINE
struct ureg_src
243 ureg_imm2f( struct ureg_program
*ureg
,
249 return ureg_DECL_immediate( ureg
, v
, 2 );
252 static INLINE
struct ureg_src
253 ureg_imm1f( struct ureg_program
*ureg
,
258 return ureg_DECL_immediate( ureg
, v
, 1 );
261 static INLINE
struct ureg_src
262 ureg_imm4u( struct ureg_program
*ureg
,
263 unsigned a
, unsigned b
,
264 unsigned c
, unsigned d
)
271 return ureg_DECL_immediate_uint( ureg
, v
, 4 );
274 static INLINE
struct ureg_src
275 ureg_imm3u( struct ureg_program
*ureg
,
276 unsigned a
, unsigned b
,
283 return ureg_DECL_immediate_uint( ureg
, v
, 3 );
286 static INLINE
struct ureg_src
287 ureg_imm2u( struct ureg_program
*ureg
,
288 unsigned a
, unsigned b
)
293 return ureg_DECL_immediate_uint( ureg
, v
, 2 );
296 static INLINE
struct ureg_src
297 ureg_imm1u( struct ureg_program
*ureg
,
300 return ureg_DECL_immediate_uint( ureg
, &a
, 1 );
303 static INLINE
struct ureg_src
304 ureg_imm4i( struct ureg_program
*ureg
,
313 return ureg_DECL_immediate_int( ureg
, v
, 4 );
316 static INLINE
struct ureg_src
317 ureg_imm3i( struct ureg_program
*ureg
,
325 return ureg_DECL_immediate_int( ureg
, v
, 3 );
328 static INLINE
struct ureg_src
329 ureg_imm2i( struct ureg_program
*ureg
,
335 return ureg_DECL_immediate_int( ureg
, v
, 2 );
338 static INLINE
struct ureg_src
339 ureg_imm1i( struct ureg_program
*ureg
,
342 return ureg_DECL_immediate_int( ureg
, &a
, 1 );
345 /***********************************************************************
346 * Functions for patching up labels
350 /* Will return a number which can be used in a label to point to the
351 * next instruction to be emitted.
354 ureg_get_instruction_number( struct ureg_program
*ureg
);
357 /* Patch a given label (expressed as a token number) to point to a
358 * given instruction (expressed as an instruction number).
360 * Labels are obtained from instruction emitters, eg ureg_CAL().
361 * Instruction numbers are obtained from ureg_get_instruction_number(),
365 ureg_fixup_label(struct ureg_program
*ureg
,
366 unsigned label_token
,
367 unsigned instruction_number
);
370 /* Generic instruction emitter. Use if you need to pass the opcode as
371 * a parameter, rather than using the emit_OP() varients below.
374 ureg_insn(struct ureg_program
*ureg
,
376 const struct ureg_dst
*dst
,
378 const struct ureg_src
*src
,
383 ureg_tex_insn(struct ureg_program
*ureg
,
385 const struct ureg_dst
*dst
,
388 const struct ureg_src
*src
,
393 ureg_label_insn(struct ureg_program
*ureg
,
395 const struct ureg_src
*src
,
400 /***********************************************************************
401 * Internal instruction helpers, don't call these directly:
404 struct ureg_emit_insn_result
{
405 unsigned insn_token
; /*< Used to fixup insn size. */
406 unsigned extended_token
; /*< Used to set the Extended bit, usually the same as insn_token. */
409 struct ureg_emit_insn_result
410 ureg_emit_insn(struct ureg_program
*ureg
,
415 unsigned pred_swizzle_x
,
416 unsigned pred_swizzle_y
,
417 unsigned pred_swizzle_z
,
418 unsigned pred_swizzle_w
,
423 ureg_emit_label(struct ureg_program
*ureg
,
425 unsigned *label_token
);
428 ureg_emit_texture(struct ureg_program
*ureg
,
433 ureg_emit_dst( struct ureg_program
*ureg
,
434 struct ureg_dst dst
);
437 ureg_emit_src( struct ureg_program
*ureg
,
438 struct ureg_src src
);
441 ureg_fixup_insn_size(struct ureg_program
*ureg
,
446 static INLINE void ureg_##op( struct ureg_program *ureg ) \
448 unsigned opcode = TGSI_OPCODE_##op; \
449 unsigned insn = ureg_emit_insn(ureg, \
460 ureg_fixup_insn_size( ureg, insn ); \
464 static INLINE void ureg_##op( struct ureg_program *ureg, \
465 struct ureg_src src ) \
467 unsigned opcode = TGSI_OPCODE_##op; \
468 unsigned insn = ureg_emit_insn(ureg, \
479 ureg_emit_src( ureg, src ); \
480 ureg_fixup_insn_size( ureg, insn ); \
483 #define OP00_LBL( op ) \
484 static INLINE void ureg_##op( struct ureg_program *ureg, \
485 unsigned *label_token ) \
487 unsigned opcode = TGSI_OPCODE_##op; \
488 struct ureg_emit_insn_result insn; \
489 insn = ureg_emit_insn(ureg, \
500 ureg_emit_label( ureg, insn.extended_token, label_token ); \
501 ureg_fixup_insn_size( ureg, insn.insn_token ); \
504 #define OP01_LBL( op ) \
505 static INLINE void ureg_##op( struct ureg_program *ureg, \
506 struct ureg_src src, \
507 unsigned *label_token ) \
509 unsigned opcode = TGSI_OPCODE_##op; \
510 struct ureg_emit_insn_result insn; \
511 insn = ureg_emit_insn(ureg, \
522 ureg_emit_label( ureg, insn.extended_token, label_token ); \
523 ureg_emit_src( ureg, src ); \
524 ureg_fixup_insn_size( ureg, insn.insn_token ); \
528 static INLINE void ureg_##op( struct ureg_program *ureg, \
529 struct ureg_dst dst ) \
531 unsigned opcode = TGSI_OPCODE_##op; \
532 unsigned insn = ureg_emit_insn(ureg, \
543 ureg_emit_dst( ureg, dst ); \
544 ureg_fixup_insn_size( ureg, insn ); \
549 static INLINE void ureg_##op( struct ureg_program *ureg, \
550 struct ureg_dst dst, \
551 struct ureg_src src ) \
553 unsigned opcode = TGSI_OPCODE_##op; \
554 unsigned insn = ureg_emit_insn(ureg, \
565 ureg_emit_dst( ureg, dst ); \
566 ureg_emit_src( ureg, src ); \
567 ureg_fixup_insn_size( ureg, insn ); \
571 static INLINE void ureg_##op( struct ureg_program *ureg, \
572 struct ureg_dst dst, \
573 struct ureg_src src0, \
574 struct ureg_src src1 ) \
576 unsigned opcode = TGSI_OPCODE_##op; \
577 unsigned insn = ureg_emit_insn(ureg, \
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 ); \
594 #define OP12_TEX( op ) \
595 static INLINE void ureg_##op( struct ureg_program *ureg, \
596 struct ureg_dst dst, \
598 struct ureg_src src0, \
599 struct ureg_src src1 ) \
601 unsigned opcode = TGSI_OPCODE_##op; \
602 struct ureg_emit_insn_result insn; \
603 insn = ureg_emit_insn(ureg, \
614 ureg_emit_texture( ureg, insn.extended_token, target ); \
615 ureg_emit_dst( ureg, dst ); \
616 ureg_emit_src( ureg, src0 ); \
617 ureg_emit_src( ureg, src1 ); \
618 ureg_fixup_insn_size( ureg, insn.insn_token ); \
622 static INLINE void ureg_##op( struct ureg_program *ureg, \
623 struct ureg_dst dst, \
624 struct ureg_src src0, \
625 struct ureg_src src1, \
626 struct ureg_src src2 ) \
628 unsigned opcode = TGSI_OPCODE_##op; \
629 unsigned insn = ureg_emit_insn(ureg, \
640 ureg_emit_dst( ureg, dst ); \
641 ureg_emit_src( ureg, src0 ); \
642 ureg_emit_src( ureg, src1 ); \
643 ureg_emit_src( ureg, src2 ); \
644 ureg_fixup_insn_size( ureg, insn ); \
647 #define OP14_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, \
653 struct ureg_src src2, \
654 struct ureg_src src3 ) \
656 unsigned opcode = TGSI_OPCODE_##op; \
657 struct ureg_emit_insn_result insn; \
658 insn = ureg_emit_insn(ureg, \
669 ureg_emit_texture( ureg, insn.extended_token, target ); \
670 ureg_emit_dst( ureg, dst ); \
671 ureg_emit_src( ureg, src0 ); \
672 ureg_emit_src( ureg, src1 ); \
673 ureg_emit_src( ureg, src2 ); \
674 ureg_emit_src( ureg, src3 ); \
675 ureg_fixup_insn_size( ureg, insn.insn_token ); \
679 /* Use a template include to generate a correctly-typed ureg_OP()
680 * function for each TGSI opcode:
682 #include "tgsi_opcode_tmp.h"
685 /***********************************************************************
686 * Inline helpers for manipulating register structs:
688 static INLINE
struct ureg_src
689 ureg_negate( struct ureg_src reg
)
691 assert(reg
.File
!= TGSI_FILE_NULL
);
696 static INLINE
struct ureg_src
697 ureg_abs( struct ureg_src reg
)
699 assert(reg
.File
!= TGSI_FILE_NULL
);
705 static INLINE
struct ureg_src
706 ureg_swizzle( struct ureg_src reg
,
707 int x
, int y
, int z
, int w
)
709 unsigned swz
= ( (reg
.SwizzleX
<< 0) |
710 (reg
.SwizzleY
<< 2) |
711 (reg
.SwizzleZ
<< 4) |
712 (reg
.SwizzleW
<< 6));
714 assert(reg
.File
!= TGSI_FILE_NULL
);
720 reg
.SwizzleX
= (swz
>> (x
*2)) & 0x3;
721 reg
.SwizzleY
= (swz
>> (y
*2)) & 0x3;
722 reg
.SwizzleZ
= (swz
>> (z
*2)) & 0x3;
723 reg
.SwizzleW
= (swz
>> (w
*2)) & 0x3;
727 static INLINE
struct ureg_src
728 ureg_scalar( struct ureg_src reg
, int x
)
730 return ureg_swizzle(reg
, x
, x
, x
, x
);
733 static INLINE
struct ureg_dst
734 ureg_writemask( struct ureg_dst reg
,
737 assert(reg
.File
!= TGSI_FILE_NULL
);
738 reg
.WriteMask
&= writemask
;
742 static INLINE
struct ureg_dst
743 ureg_saturate( struct ureg_dst reg
)
745 assert(reg
.File
!= TGSI_FILE_NULL
);
750 static INLINE
struct ureg_dst
751 ureg_predicate(struct ureg_dst reg
,
758 assert(reg
.File
!= TGSI_FILE_NULL
);
760 reg
.PredNegate
= negate
;
761 reg
.PredSwizzleX
= swizzle_x
;
762 reg
.PredSwizzleY
= swizzle_y
;
763 reg
.PredSwizzleZ
= swizzle_z
;
764 reg
.PredSwizzleW
= swizzle_w
;
768 static INLINE
struct ureg_dst
769 ureg_dst_indirect( struct ureg_dst reg
, struct ureg_src addr
)
771 assert(reg
.File
!= TGSI_FILE_NULL
);
772 assert(addr
.File
== TGSI_FILE_ADDRESS
);
774 reg
.IndirectIndex
= addr
.Index
;
775 reg
.IndirectSwizzle
= addr
.SwizzleX
;
779 static INLINE
struct ureg_src
780 ureg_src_indirect( struct ureg_src reg
, struct ureg_src addr
)
782 assert(reg
.File
!= TGSI_FILE_NULL
);
783 assert(addr
.File
== TGSI_FILE_ADDRESS
|| addr
.File
== TGSI_FILE_TEMPORARY
);
785 reg
.IndirectFile
= addr
.File
;
786 reg
.IndirectIndex
= addr
.Index
;
787 reg
.IndirectSwizzle
= addr
.SwizzleX
;
791 static INLINE
struct ureg_src
792 ureg_src_dimension( struct ureg_src reg
, int index
)
794 assert(reg
.File
!= TGSI_FILE_NULL
);
796 reg
.DimensionIndex
= index
;
800 static INLINE
struct ureg_dst
801 ureg_dst( struct ureg_src src
)
805 assert(!src
.Indirect
|| src
.IndirectFile
== TGSI_FILE_ADDRESS
);
808 dst
.WriteMask
= TGSI_WRITEMASK_XYZW
;
809 dst
.Indirect
= src
.Indirect
;
810 dst
.IndirectIndex
= src
.IndirectIndex
;
811 dst
.IndirectSwizzle
= src
.IndirectSwizzle
;
815 dst
.PredSwizzleX
= TGSI_SWIZZLE_X
;
816 dst
.PredSwizzleY
= TGSI_SWIZZLE_Y
;
817 dst
.PredSwizzleZ
= TGSI_SWIZZLE_Z
;
818 dst
.PredSwizzleW
= TGSI_SWIZZLE_W
;
819 dst
.Index
= src
.Index
;
824 static INLINE
struct ureg_src
825 ureg_src_register(unsigned file
,
831 src
.SwizzleX
= TGSI_SWIZZLE_X
;
832 src
.SwizzleY
= TGSI_SWIZZLE_Y
;
833 src
.SwizzleZ
= TGSI_SWIZZLE_Z
;
834 src
.SwizzleW
= TGSI_SWIZZLE_W
;
836 src
.IndirectFile
= TGSI_FILE_NULL
;
837 src
.IndirectIndex
= 0;
838 src
.IndirectSwizzle
= 0;
843 src
.DimensionIndex
= 0;
848 static INLINE
struct ureg_src
849 ureg_src( struct ureg_dst dst
)
854 src
.SwizzleX
= TGSI_SWIZZLE_X
;
855 src
.SwizzleY
= TGSI_SWIZZLE_Y
;
856 src
.SwizzleZ
= TGSI_SWIZZLE_Z
;
857 src
.SwizzleW
= TGSI_SWIZZLE_W
;
858 src
.Indirect
= dst
.Indirect
;
859 src
.IndirectFile
= TGSI_FILE_ADDRESS
;
860 src
.IndirectIndex
= dst
.IndirectIndex
;
861 src
.IndirectSwizzle
= dst
.IndirectSwizzle
;
863 src
.Index
= dst
.Index
;
866 src
.DimensionIndex
= 0;
873 static INLINE
struct ureg_dst
874 ureg_dst_undef( void )
878 dst
.File
= TGSI_FILE_NULL
;
881 dst
.IndirectIndex
= 0;
882 dst
.IndirectSwizzle
= 0;
886 dst
.PredSwizzleX
= TGSI_SWIZZLE_X
;
887 dst
.PredSwizzleY
= TGSI_SWIZZLE_Y
;
888 dst
.PredSwizzleZ
= TGSI_SWIZZLE_Z
;
889 dst
.PredSwizzleW
= TGSI_SWIZZLE_W
;
895 static INLINE
struct ureg_src
896 ureg_src_undef( void )
900 src
.File
= TGSI_FILE_NULL
;
906 src
.IndirectFile
= TGSI_FILE_NULL
;
907 src
.IndirectIndex
= 0;
908 src
.IndirectSwizzle
= 0;
913 src
.DimensionIndex
= 0;
918 static INLINE boolean
919 ureg_src_is_undef( struct ureg_src src
)
921 return src
.File
== TGSI_FILE_NULL
;
924 static INLINE boolean
925 ureg_dst_is_undef( struct ureg_dst dst
)
927 return dst
.File
== TGSI_FILE_NULL
;