e25f35c6dc3bae182a917ece3e78830c0c2d9ddd
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 input_prim
);
132 ureg_property_gs_output_prim(struct ureg_program
*ureg
,
133 unsigned output_prim
);
136 ureg_property_gs_max_vertices(struct ureg_program
*ureg
,
137 unsigned max_vertices
);
140 ureg_property_fs_coord_origin(struct ureg_program
*ureg
,
141 unsigned fs_coord_origin
);
144 ureg_property_fs_coord_pixel_center(struct ureg_program
*ureg
,
145 unsigned fs_coord_pixel_center
);
147 /***********************************************************************
148 * Build shader declarations:
152 ureg_DECL_fs_input( struct ureg_program
*,
153 unsigned semantic_name
,
154 unsigned semantic_index
,
155 unsigned interp_mode
);
158 ureg_DECL_vs_input( struct ureg_program
*,
162 ureg_DECL_gs_input(struct ureg_program
*,
166 ureg_DECL_system_value(struct ureg_program
*,
168 unsigned semantic_name
,
169 unsigned semantic_index
);
172 ureg_DECL_output( struct ureg_program
*,
173 unsigned semantic_name
,
174 unsigned semantic_index
);
177 ureg_DECL_immediate( struct ureg_program
*,
182 ureg_DECL_immediate_uint( struct ureg_program
*,
187 ureg_DECL_immediate_block_uint( struct ureg_program
*,
192 ureg_DECL_immediate_int( struct ureg_program
*,
197 ureg_DECL_constant2D(struct ureg_program
*ureg
,
203 ureg_DECL_constant( struct ureg_program
*,
207 ureg_DECL_temporary( struct ureg_program
* );
210 ureg_release_temporary( struct ureg_program
*ureg
,
211 struct ureg_dst tmp
);
214 ureg_DECL_address( struct ureg_program
* );
217 ureg_DECL_loop( struct ureg_program
* );
220 ureg_DECL_predicate(struct ureg_program
*);
222 /* Supply an index to the sampler declaration as this is the hook to
223 * the external pipe_sampler state. Users of this function probably
224 * don't want just any sampler, but a specific one which they've set
225 * up state for in the context.
228 ureg_DECL_sampler( struct ureg_program
*,
232 static INLINE
struct ureg_src
233 ureg_imm4f( struct ureg_program
*ureg
,
242 return ureg_DECL_immediate( ureg
, v
, 4 );
245 static INLINE
struct ureg_src
246 ureg_imm3f( struct ureg_program
*ureg
,
254 return ureg_DECL_immediate( ureg
, v
, 3 );
257 static INLINE
struct ureg_src
258 ureg_imm2f( struct ureg_program
*ureg
,
264 return ureg_DECL_immediate( ureg
, v
, 2 );
267 static INLINE
struct ureg_src
268 ureg_imm1f( struct ureg_program
*ureg
,
273 return ureg_DECL_immediate( ureg
, v
, 1 );
276 static INLINE
struct ureg_src
277 ureg_imm4u( struct ureg_program
*ureg
,
278 unsigned a
, unsigned b
,
279 unsigned c
, unsigned d
)
286 return ureg_DECL_immediate_uint( ureg
, v
, 4 );
289 static INLINE
struct ureg_src
290 ureg_imm3u( struct ureg_program
*ureg
,
291 unsigned a
, unsigned b
,
298 return ureg_DECL_immediate_uint( ureg
, v
, 3 );
301 static INLINE
struct ureg_src
302 ureg_imm2u( struct ureg_program
*ureg
,
303 unsigned a
, unsigned b
)
308 return ureg_DECL_immediate_uint( ureg
, v
, 2 );
311 static INLINE
struct ureg_src
312 ureg_imm1u( struct ureg_program
*ureg
,
315 return ureg_DECL_immediate_uint( ureg
, &a
, 1 );
318 static INLINE
struct ureg_src
319 ureg_imm4i( struct ureg_program
*ureg
,
328 return ureg_DECL_immediate_int( ureg
, v
, 4 );
331 static INLINE
struct ureg_src
332 ureg_imm3i( struct ureg_program
*ureg
,
340 return ureg_DECL_immediate_int( ureg
, v
, 3 );
343 static INLINE
struct ureg_src
344 ureg_imm2i( struct ureg_program
*ureg
,
350 return ureg_DECL_immediate_int( ureg
, v
, 2 );
353 static INLINE
struct ureg_src
354 ureg_imm1i( struct ureg_program
*ureg
,
357 return ureg_DECL_immediate_int( ureg
, &a
, 1 );
360 /***********************************************************************
361 * Functions for patching up labels
365 /* Will return a number which can be used in a label to point to the
366 * next instruction to be emitted.
369 ureg_get_instruction_number( struct ureg_program
*ureg
);
372 /* Patch a given label (expressed as a token number) to point to a
373 * given instruction (expressed as an instruction number).
375 * Labels are obtained from instruction emitters, eg ureg_CAL().
376 * Instruction numbers are obtained from ureg_get_instruction_number(),
380 ureg_fixup_label(struct ureg_program
*ureg
,
381 unsigned label_token
,
382 unsigned instruction_number
);
385 /* Generic instruction emitter. Use if you need to pass the opcode as
386 * a parameter, rather than using the emit_OP() varients below.
389 ureg_insn(struct ureg_program
*ureg
,
391 const struct ureg_dst
*dst
,
393 const struct ureg_src
*src
,
398 ureg_tex_insn(struct ureg_program
*ureg
,
400 const struct ureg_dst
*dst
,
403 const struct ureg_src
*src
,
408 ureg_label_insn(struct ureg_program
*ureg
,
410 const struct ureg_src
*src
,
415 /***********************************************************************
416 * Internal instruction helpers, don't call these directly:
419 struct ureg_emit_insn_result
{
420 unsigned insn_token
; /*< Used to fixup insn size. */
421 unsigned extended_token
; /*< Used to set the Extended bit, usually the same as insn_token. */
424 struct ureg_emit_insn_result
425 ureg_emit_insn(struct ureg_program
*ureg
,
430 unsigned pred_swizzle_x
,
431 unsigned pred_swizzle_y
,
432 unsigned pred_swizzle_z
,
433 unsigned pred_swizzle_w
,
438 ureg_emit_label(struct ureg_program
*ureg
,
440 unsigned *label_token
);
443 ureg_emit_texture(struct ureg_program
*ureg
,
448 ureg_emit_dst( struct ureg_program
*ureg
,
449 struct ureg_dst dst
);
452 ureg_emit_src( struct ureg_program
*ureg
,
453 struct ureg_src src
);
456 ureg_fixup_insn_size(struct ureg_program
*ureg
,
461 static INLINE void ureg_##op( struct ureg_program *ureg ) \
463 unsigned opcode = TGSI_OPCODE_##op; \
464 unsigned insn = ureg_emit_insn(ureg, \
475 ureg_fixup_insn_size( ureg, insn ); \
479 static INLINE void ureg_##op( struct ureg_program *ureg, \
480 struct ureg_src src ) \
482 unsigned opcode = TGSI_OPCODE_##op; \
483 unsigned insn = ureg_emit_insn(ureg, \
494 ureg_emit_src( ureg, src ); \
495 ureg_fixup_insn_size( ureg, insn ); \
498 #define OP00_LBL( op ) \
499 static INLINE void ureg_##op( struct ureg_program *ureg, \
500 unsigned *label_token ) \
502 unsigned opcode = TGSI_OPCODE_##op; \
503 struct ureg_emit_insn_result insn; \
504 insn = ureg_emit_insn(ureg, \
515 ureg_emit_label( ureg, insn.extended_token, label_token ); \
516 ureg_fixup_insn_size( ureg, insn.insn_token ); \
519 #define OP01_LBL( op ) \
520 static INLINE void ureg_##op( struct ureg_program *ureg, \
521 struct ureg_src src, \
522 unsigned *label_token ) \
524 unsigned opcode = TGSI_OPCODE_##op; \
525 struct ureg_emit_insn_result insn; \
526 insn = ureg_emit_insn(ureg, \
537 ureg_emit_label( ureg, insn.extended_token, label_token ); \
538 ureg_emit_src( ureg, src ); \
539 ureg_fixup_insn_size( ureg, insn.insn_token ); \
543 static INLINE void ureg_##op( struct ureg_program *ureg, \
544 struct ureg_dst dst ) \
546 unsigned opcode = TGSI_OPCODE_##op; \
547 unsigned insn = ureg_emit_insn(ureg, \
558 ureg_emit_dst( ureg, dst ); \
559 ureg_fixup_insn_size( ureg, insn ); \
564 static INLINE void ureg_##op( struct ureg_program *ureg, \
565 struct ureg_dst dst, \
566 struct ureg_src src ) \
568 unsigned opcode = TGSI_OPCODE_##op; \
569 unsigned insn = ureg_emit_insn(ureg, \
580 ureg_emit_dst( ureg, dst ); \
581 ureg_emit_src( ureg, src ); \
582 ureg_fixup_insn_size( ureg, insn ); \
586 static INLINE void ureg_##op( struct ureg_program *ureg, \
587 struct ureg_dst dst, \
588 struct ureg_src src0, \
589 struct ureg_src src1 ) \
591 unsigned opcode = TGSI_OPCODE_##op; \
592 unsigned insn = ureg_emit_insn(ureg, \
603 ureg_emit_dst( ureg, dst ); \
604 ureg_emit_src( ureg, src0 ); \
605 ureg_emit_src( ureg, src1 ); \
606 ureg_fixup_insn_size( ureg, insn ); \
609 #define OP12_TEX( op ) \
610 static INLINE void ureg_##op( struct ureg_program *ureg, \
611 struct ureg_dst dst, \
613 struct ureg_src src0, \
614 struct ureg_src src1 ) \
616 unsigned opcode = TGSI_OPCODE_##op; \
617 struct ureg_emit_insn_result insn; \
618 insn = ureg_emit_insn(ureg, \
629 ureg_emit_texture( ureg, insn.extended_token, target ); \
630 ureg_emit_dst( ureg, dst ); \
631 ureg_emit_src( ureg, src0 ); \
632 ureg_emit_src( ureg, src1 ); \
633 ureg_fixup_insn_size( ureg, insn.insn_token ); \
637 static INLINE void ureg_##op( struct ureg_program *ureg, \
638 struct ureg_dst dst, \
639 struct ureg_src src0, \
640 struct ureg_src src1, \
641 struct ureg_src src2 ) \
643 unsigned opcode = TGSI_OPCODE_##op; \
644 unsigned insn = ureg_emit_insn(ureg, \
655 ureg_emit_dst( ureg, dst ); \
656 ureg_emit_src( ureg, src0 ); \
657 ureg_emit_src( ureg, src1 ); \
658 ureg_emit_src( ureg, src2 ); \
659 ureg_fixup_insn_size( ureg, insn ); \
662 #define OP14_TEX( op ) \
663 static INLINE void ureg_##op( struct ureg_program *ureg, \
664 struct ureg_dst dst, \
666 struct ureg_src src0, \
667 struct ureg_src src1, \
668 struct ureg_src src2, \
669 struct ureg_src src3 ) \
671 unsigned opcode = TGSI_OPCODE_##op; \
672 struct ureg_emit_insn_result insn; \
673 insn = ureg_emit_insn(ureg, \
684 ureg_emit_texture( ureg, insn.extended_token, target ); \
685 ureg_emit_dst( ureg, dst ); \
686 ureg_emit_src( ureg, src0 ); \
687 ureg_emit_src( ureg, src1 ); \
688 ureg_emit_src( ureg, src2 ); \
689 ureg_emit_src( ureg, src3 ); \
690 ureg_fixup_insn_size( ureg, insn.insn_token ); \
694 /* Use a template include to generate a correctly-typed ureg_OP()
695 * function for each TGSI opcode:
697 #include "tgsi_opcode_tmp.h"
700 /***********************************************************************
701 * Inline helpers for manipulating register structs:
703 static INLINE
struct ureg_src
704 ureg_negate( struct ureg_src reg
)
706 assert(reg
.File
!= TGSI_FILE_NULL
);
711 static INLINE
struct ureg_src
712 ureg_abs( struct ureg_src reg
)
714 assert(reg
.File
!= TGSI_FILE_NULL
);
720 static INLINE
struct ureg_src
721 ureg_swizzle( struct ureg_src reg
,
722 int x
, int y
, int z
, int w
)
724 unsigned swz
= ( (reg
.SwizzleX
<< 0) |
725 (reg
.SwizzleY
<< 2) |
726 (reg
.SwizzleZ
<< 4) |
727 (reg
.SwizzleW
<< 6));
729 assert(reg
.File
!= TGSI_FILE_NULL
);
735 reg
.SwizzleX
= (swz
>> (x
*2)) & 0x3;
736 reg
.SwizzleY
= (swz
>> (y
*2)) & 0x3;
737 reg
.SwizzleZ
= (swz
>> (z
*2)) & 0x3;
738 reg
.SwizzleW
= (swz
>> (w
*2)) & 0x3;
742 static INLINE
struct ureg_src
743 ureg_scalar( struct ureg_src reg
, int x
)
745 return ureg_swizzle(reg
, x
, x
, x
, x
);
748 static INLINE
struct ureg_dst
749 ureg_writemask( struct ureg_dst reg
,
752 assert(reg
.File
!= TGSI_FILE_NULL
);
753 reg
.WriteMask
&= writemask
;
757 static INLINE
struct ureg_dst
758 ureg_saturate( struct ureg_dst reg
)
760 assert(reg
.File
!= TGSI_FILE_NULL
);
765 static INLINE
struct ureg_dst
766 ureg_predicate(struct ureg_dst reg
,
773 assert(reg
.File
!= TGSI_FILE_NULL
);
775 reg
.PredNegate
= negate
;
776 reg
.PredSwizzleX
= swizzle_x
;
777 reg
.PredSwizzleY
= swizzle_y
;
778 reg
.PredSwizzleZ
= swizzle_z
;
779 reg
.PredSwizzleW
= swizzle_w
;
783 static INLINE
struct ureg_dst
784 ureg_dst_indirect( struct ureg_dst reg
, struct ureg_src addr
)
786 assert(reg
.File
!= TGSI_FILE_NULL
);
787 assert(addr
.File
== TGSI_FILE_ADDRESS
);
789 reg
.IndirectIndex
= addr
.Index
;
790 reg
.IndirectSwizzle
= addr
.SwizzleX
;
794 static INLINE
struct ureg_src
795 ureg_src_indirect( struct ureg_src reg
, struct ureg_src addr
)
797 assert(reg
.File
!= TGSI_FILE_NULL
);
798 assert(addr
.File
== TGSI_FILE_ADDRESS
|| addr
.File
== TGSI_FILE_TEMPORARY
);
800 reg
.IndirectFile
= addr
.File
;
801 reg
.IndirectIndex
= addr
.Index
;
802 reg
.IndirectSwizzle
= addr
.SwizzleX
;
806 static INLINE
struct ureg_src
807 ureg_src_dimension( struct ureg_src reg
, int index
)
809 assert(reg
.File
!= TGSI_FILE_NULL
);
811 reg
.DimensionIndex
= index
;
815 static INLINE
struct ureg_dst
816 ureg_dst( struct ureg_src src
)
820 assert(!src
.Indirect
|| src
.IndirectFile
== TGSI_FILE_ADDRESS
);
823 dst
.WriteMask
= TGSI_WRITEMASK_XYZW
;
824 dst
.Indirect
= src
.Indirect
;
825 dst
.IndirectIndex
= src
.IndirectIndex
;
826 dst
.IndirectSwizzle
= src
.IndirectSwizzle
;
830 dst
.PredSwizzleX
= TGSI_SWIZZLE_X
;
831 dst
.PredSwizzleY
= TGSI_SWIZZLE_Y
;
832 dst
.PredSwizzleZ
= TGSI_SWIZZLE_Z
;
833 dst
.PredSwizzleW
= TGSI_SWIZZLE_W
;
834 dst
.Index
= src
.Index
;
839 static INLINE
struct ureg_src
840 ureg_src_register(unsigned file
,
846 src
.SwizzleX
= TGSI_SWIZZLE_X
;
847 src
.SwizzleY
= TGSI_SWIZZLE_Y
;
848 src
.SwizzleZ
= TGSI_SWIZZLE_Z
;
849 src
.SwizzleW
= TGSI_SWIZZLE_W
;
851 src
.IndirectFile
= TGSI_FILE_NULL
;
852 src
.IndirectIndex
= 0;
853 src
.IndirectSwizzle
= 0;
858 src
.DimensionIndex
= 0;
863 static INLINE
struct ureg_src
864 ureg_src( struct ureg_dst dst
)
869 src
.SwizzleX
= TGSI_SWIZZLE_X
;
870 src
.SwizzleY
= TGSI_SWIZZLE_Y
;
871 src
.SwizzleZ
= TGSI_SWIZZLE_Z
;
872 src
.SwizzleW
= TGSI_SWIZZLE_W
;
873 src
.Indirect
= dst
.Indirect
;
874 src
.IndirectFile
= TGSI_FILE_ADDRESS
;
875 src
.IndirectIndex
= dst
.IndirectIndex
;
876 src
.IndirectSwizzle
= dst
.IndirectSwizzle
;
878 src
.Index
= dst
.Index
;
881 src
.DimensionIndex
= 0;
888 static INLINE
struct ureg_dst
889 ureg_dst_undef( void )
893 dst
.File
= TGSI_FILE_NULL
;
896 dst
.IndirectIndex
= 0;
897 dst
.IndirectSwizzle
= 0;
901 dst
.PredSwizzleX
= TGSI_SWIZZLE_X
;
902 dst
.PredSwizzleY
= TGSI_SWIZZLE_Y
;
903 dst
.PredSwizzleZ
= TGSI_SWIZZLE_Z
;
904 dst
.PredSwizzleW
= TGSI_SWIZZLE_W
;
910 static INLINE
struct ureg_src
911 ureg_src_undef( void )
915 src
.File
= TGSI_FILE_NULL
;
921 src
.IndirectFile
= TGSI_FILE_NULL
;
922 src
.IndirectIndex
= 0;
923 src
.IndirectSwizzle
= 0;
928 src
.DimensionIndex
= 0;
933 static INLINE boolean
934 ureg_src_is_undef( struct ureg_src src
)
936 return src
.File
== TGSI_FILE_NULL
;
939 static INLINE boolean
940 ureg_dst_is_undef( struct ureg_dst dst
)
942 return dst
.File
== TGSI_FILE_NULL
;