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 Pad
: 1; /* BOOL */
51 unsigned Indirect
: 1; /* BOOL */
52 unsigned Absolute
: 1; /* BOOL */
53 int Index
: 16; /* SINT */
54 unsigned Negate
: 1; /* BOOL */
55 int IndirectIndex
: 16; /* SINT */
56 int IndirectSwizzle
: 2; /* TGSI_SWIZZLE_ */
59 /* Very similar to a tgsi_dst_register, removing unsupported fields
60 * and adding a Saturate flag. It's easier to push saturate into the
61 * destination register than to try and create a _SAT varient of each
62 * instruction function.
66 unsigned File
: 4; /* TGSI_FILE_ */
67 unsigned WriteMask
: 4; /* TGSI_WRITEMASK_ */
68 unsigned Indirect
: 1; /* BOOL */
69 unsigned Saturate
: 1; /* BOOL */
70 int Index
: 16; /* SINT */
72 unsigned Pad2
: 1; /* BOOL */
73 int IndirectIndex
: 16; /* SINT */
74 int IndirectSwizzle
: 2; /* TGSI_SWIZZLE_ */
80 ureg_create( unsigned processor
);
82 const struct tgsi_token
*
83 ureg_finalize( struct ureg_program
* );
85 /* Create and return a shader:
88 ureg_create_shader( struct ureg_program
*,
89 struct pipe_context
*pipe
);
92 /* Alternately, return the built token stream and hand ownership of
93 * that memory to the caller:
95 const struct tgsi_token
*
96 ureg_get_tokens( struct ureg_program
*ureg
,
97 unsigned *nr_tokens
);
101 ureg_destroy( struct ureg_program
* );
104 /***********************************************************************
105 * Convenience routine:
108 ureg_create_shader_and_destroy( struct ureg_program
*p
,
109 struct pipe_context
*pipe
)
111 void *result
= ureg_create_shader( p
, pipe
);
118 /***********************************************************************
119 * Build shader declarations:
123 ureg_DECL_fs_input( struct ureg_program
*,
124 unsigned semantic_name
,
125 unsigned semantic_index
,
126 unsigned interp_mode
);
129 ureg_DECL_vs_input( struct ureg_program
*,
133 ureg_DECL_output( struct ureg_program
*,
134 unsigned semantic_name
,
135 unsigned semantic_index
);
138 ureg_DECL_immediate( struct ureg_program
*,
143 ureg_DECL_constant( struct ureg_program
*,
147 ureg_DECL_temporary( struct ureg_program
* );
150 ureg_release_temporary( struct ureg_program
*ureg
,
151 struct ureg_dst tmp
);
154 ureg_DECL_address( struct ureg_program
* );
156 /* Supply an index to the sampler declaration as this is the hook to
157 * the external pipe_sampler state. Users of this function probably
158 * don't want just any sampler, but a specific one which they've set
159 * up state for in the context.
162 ureg_DECL_sampler( struct ureg_program
*,
166 static INLINE
struct ureg_src
167 ureg_imm4f( struct ureg_program
*ureg
,
176 return ureg_DECL_immediate( ureg
, v
, 4 );
179 static INLINE
struct ureg_src
180 ureg_imm3f( struct ureg_program
*ureg
,
188 return ureg_DECL_immediate( ureg
, v
, 3 );
191 static INLINE
struct ureg_src
192 ureg_imm2f( struct ureg_program
*ureg
,
198 return ureg_DECL_immediate( ureg
, v
, 2 );
201 static INLINE
struct ureg_src
202 ureg_imm1f( struct ureg_program
*ureg
,
207 return ureg_DECL_immediate( ureg
, v
, 1 );
210 /***********************************************************************
211 * Functions for patching up labels
215 /* Will return a number which can be used in a label to point to the
216 * next instruction to be emitted.
219 ureg_get_instruction_number( struct ureg_program
*ureg
);
222 /* Patch a given label (expressed as a token number) to point to a
223 * given instruction (expressed as an instruction number).
225 * Labels are obtained from instruction emitters, eg ureg_CAL().
226 * Instruction numbers are obtained from ureg_get_instruction_number(),
230 ureg_fixup_label(struct ureg_program
*ureg
,
231 unsigned label_token
,
232 unsigned instruction_number
);
235 /* Generic instruction emitter. Use if you need to pass the opcode as
236 * a parameter, rather than using the emit_OP() varients below.
239 ureg_insn(struct ureg_program
*ureg
,
241 const struct ureg_dst
*dst
,
243 const struct ureg_src
*src
,
248 ureg_tex_insn(struct ureg_program
*ureg
,
250 const struct ureg_dst
*dst
,
253 const struct ureg_src
*src
,
258 ureg_label_insn(struct ureg_program
*ureg
,
260 const struct ureg_src
*src
,
265 /***********************************************************************
266 * Internal instruction helpers, don't call these directly:
270 ureg_emit_insn(struct ureg_program
*ureg
,
277 ureg_emit_label(struct ureg_program
*ureg
,
279 unsigned *label_token
);
282 ureg_emit_texture(struct ureg_program
*ureg
,
287 ureg_emit_dst( struct ureg_program
*ureg
,
288 struct ureg_dst dst
);
291 ureg_emit_src( struct ureg_program
*ureg
,
292 struct ureg_src src
);
295 ureg_fixup_insn_size(struct ureg_program
*ureg
,
300 static INLINE void ureg_##op( struct ureg_program *ureg ) \
302 unsigned opcode = TGSI_OPCODE_##op; \
303 unsigned insn = ureg_emit_insn( ureg, opcode, FALSE, 0, 0 ); \
304 ureg_fixup_insn_size( ureg, insn ); \
308 static INLINE void ureg_##op( struct ureg_program *ureg, \
309 struct ureg_src src ) \
311 unsigned opcode = TGSI_OPCODE_##op; \
312 unsigned insn = ureg_emit_insn( ureg, opcode, FALSE, 0, 1 ); \
313 ureg_emit_src( ureg, src ); \
314 ureg_fixup_insn_size( ureg, insn ); \
317 #define OP00_LBL( op ) \
318 static INLINE void ureg_##op( struct ureg_program *ureg, \
319 unsigned *label_token ) \
321 unsigned opcode = TGSI_OPCODE_##op; \
322 unsigned insn = ureg_emit_insn( ureg, opcode, FALSE, 0, 0 ); \
323 ureg_emit_label( ureg, insn, label_token ); \
324 ureg_fixup_insn_size( ureg, insn ); \
327 #define OP01_LBL( op ) \
328 static INLINE void ureg_##op( struct ureg_program *ureg, \
329 struct ureg_src src, \
330 unsigned *label_token ) \
332 unsigned opcode = TGSI_OPCODE_##op; \
333 unsigned insn = ureg_emit_insn( ureg, opcode, FALSE, 0, 1 ); \
334 ureg_emit_label( ureg, insn, label_token ); \
335 ureg_emit_src( ureg, src ); \
336 ureg_fixup_insn_size( ureg, insn ); \
340 static INLINE void ureg_##op( struct ureg_program *ureg, \
341 struct ureg_dst dst ) \
343 unsigned opcode = TGSI_OPCODE_##op; \
344 unsigned insn = ureg_emit_insn( ureg, opcode, dst.Saturate, 1, 0 ); \
345 ureg_emit_dst( ureg, dst ); \
346 ureg_fixup_insn_size( ureg, insn ); \
351 static INLINE void ureg_##op( struct ureg_program *ureg, \
352 struct ureg_dst dst, \
353 struct ureg_src src ) \
355 unsigned opcode = TGSI_OPCODE_##op; \
356 unsigned insn = ureg_emit_insn( ureg, opcode, dst.Saturate, 1, 1 ); \
357 ureg_emit_dst( ureg, dst ); \
358 ureg_emit_src( ureg, src ); \
359 ureg_fixup_insn_size( ureg, insn ); \
363 static INLINE void ureg_##op( struct ureg_program *ureg, \
364 struct ureg_dst dst, \
365 struct ureg_src src0, \
366 struct ureg_src src1 ) \
368 unsigned opcode = TGSI_OPCODE_##op; \
369 unsigned insn = ureg_emit_insn( ureg, opcode, dst.Saturate, 1, 2 ); \
370 ureg_emit_dst( ureg, dst ); \
371 ureg_emit_src( ureg, src0 ); \
372 ureg_emit_src( ureg, src1 ); \
373 ureg_fixup_insn_size( ureg, insn ); \
376 #define OP12_TEX( op ) \
377 static INLINE void ureg_##op( struct ureg_program *ureg, \
378 struct ureg_dst dst, \
380 struct ureg_src src0, \
381 struct ureg_src src1 ) \
383 unsigned opcode = TGSI_OPCODE_##op; \
384 unsigned insn = ureg_emit_insn( ureg, opcode, dst.Saturate, 1, 2 ); \
385 ureg_emit_texture( ureg, insn, target ); \
386 ureg_emit_dst( ureg, dst ); \
387 ureg_emit_src( ureg, src0 ); \
388 ureg_emit_src( ureg, src1 ); \
389 ureg_fixup_insn_size( ureg, insn ); \
393 static INLINE void ureg_##op( struct ureg_program *ureg, \
394 struct ureg_dst dst, \
395 struct ureg_src src0, \
396 struct ureg_src src1, \
397 struct ureg_src src2 ) \
399 unsigned opcode = TGSI_OPCODE_##op; \
400 unsigned insn = ureg_emit_insn( ureg, opcode, dst.Saturate, 1, 3 ); \
401 ureg_emit_dst( ureg, dst ); \
402 ureg_emit_src( ureg, src0 ); \
403 ureg_emit_src( ureg, src1 ); \
404 ureg_emit_src( ureg, src2 ); \
405 ureg_fixup_insn_size( ureg, insn ); \
408 #define OP14_TEX( op ) \
409 static INLINE void ureg_##op( struct ureg_program *ureg, \
410 struct ureg_dst dst, \
412 struct ureg_src src0, \
413 struct ureg_src src1, \
414 struct ureg_src src2, \
415 struct ureg_src src3 ) \
417 unsigned opcode = TGSI_OPCODE_##op; \
418 unsigned insn = ureg_emit_insn( ureg, opcode, dst.Saturate, 1, 4 ); \
419 ureg_emit_texture( ureg, insn, target ); \
420 ureg_emit_dst( ureg, dst ); \
421 ureg_emit_src( ureg, src0 ); \
422 ureg_emit_src( ureg, src1 ); \
423 ureg_emit_src( ureg, src2 ); \
424 ureg_emit_src( ureg, src3 ); \
425 ureg_fixup_insn_size( ureg, insn ); \
429 /* Use a template include to generate a correctly-typed ureg_OP()
430 * function for each TGSI opcode:
432 #include "tgsi_opcode_tmp.h"
435 /***********************************************************************
436 * Inline helpers for manipulating register structs:
438 static INLINE
struct ureg_src
439 ureg_negate( struct ureg_src reg
)
441 assert(reg
.File
!= TGSI_FILE_NULL
);
446 static INLINE
struct ureg_src
447 ureg_abs( struct ureg_src reg
)
449 assert(reg
.File
!= TGSI_FILE_NULL
);
455 static INLINE
struct ureg_src
456 ureg_swizzle( struct ureg_src reg
,
457 int x
, int y
, int z
, int w
)
459 unsigned swz
= ( (reg
.SwizzleX
<< 0) |
460 (reg
.SwizzleY
<< 2) |
461 (reg
.SwizzleZ
<< 4) |
462 (reg
.SwizzleW
<< 6));
464 assert(reg
.File
!= TGSI_FILE_NULL
);
470 reg
.SwizzleX
= (swz
>> (x
*2)) & 0x3;
471 reg
.SwizzleY
= (swz
>> (y
*2)) & 0x3;
472 reg
.SwizzleZ
= (swz
>> (z
*2)) & 0x3;
473 reg
.SwizzleW
= (swz
>> (w
*2)) & 0x3;
477 static INLINE
struct ureg_src
478 ureg_scalar( struct ureg_src reg
, int x
)
480 return ureg_swizzle(reg
, x
, x
, x
, x
);
483 static INLINE
struct ureg_dst
484 ureg_writemask( struct ureg_dst reg
,
487 assert(reg
.File
!= TGSI_FILE_NULL
);
488 reg
.WriteMask
&= writemask
;
492 static INLINE
struct ureg_dst
493 ureg_saturate( struct ureg_dst reg
)
495 assert(reg
.File
!= TGSI_FILE_NULL
);
500 static INLINE
struct ureg_dst
501 ureg_dst_indirect( struct ureg_dst reg
, struct ureg_src addr
)
503 assert(reg
.File
!= TGSI_FILE_NULL
);
504 assert(addr
.File
== TGSI_FILE_ADDRESS
);
506 reg
.IndirectIndex
= addr
.Index
;
507 reg
.IndirectSwizzle
= addr
.SwizzleX
;
511 static INLINE
struct ureg_src
512 ureg_src_indirect( struct ureg_src reg
, struct ureg_src addr
)
514 assert(reg
.File
!= TGSI_FILE_NULL
);
515 assert(addr
.File
== TGSI_FILE_ADDRESS
);
517 reg
.IndirectIndex
= addr
.Index
;
518 reg
.IndirectSwizzle
= addr
.SwizzleX
;
522 static INLINE
struct ureg_dst
523 ureg_dst( struct ureg_src src
)
528 dst
.WriteMask
= TGSI_WRITEMASK_XYZW
;
529 dst
.Indirect
= src
.Indirect
;
530 dst
.IndirectIndex
= src
.IndirectIndex
;
531 dst
.IndirectSwizzle
= src
.IndirectSwizzle
;
533 dst
.Index
= src
.Index
;
540 static INLINE
struct ureg_src
541 ureg_src( struct ureg_dst dst
)
546 src
.SwizzleX
= TGSI_SWIZZLE_X
;
547 src
.SwizzleY
= TGSI_SWIZZLE_Y
;
548 src
.SwizzleZ
= TGSI_SWIZZLE_Z
;
549 src
.SwizzleW
= TGSI_SWIZZLE_W
;
551 src
.Indirect
= dst
.Indirect
;
552 src
.IndirectIndex
= dst
.IndirectIndex
;
553 src
.IndirectSwizzle
= dst
.IndirectSwizzle
;
555 src
.Index
= dst
.Index
;
563 static INLINE
struct ureg_dst
564 ureg_dst_undef( void )
568 dst
.File
= TGSI_FILE_NULL
;
571 dst
.IndirectIndex
= 0;
572 dst
.IndirectSwizzle
= 0;
581 static INLINE
struct ureg_src
582 ureg_src_undef( void )
586 src
.File
= TGSI_FILE_NULL
;
593 src
.IndirectIndex
= 0;
594 src
.IndirectSwizzle
= 0;
602 static INLINE boolean
603 ureg_src_is_undef( struct ureg_src src
)
605 return src
.File
== TGSI_FILE_NULL
;
608 static INLINE boolean
609 ureg_dst_is_undef( struct ureg_dst dst
)
611 return dst
.File
== TGSI_FILE_NULL
;