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
* );
86 ureg_create_shader( struct ureg_program
*,
87 struct pipe_context
*pipe
);
90 ureg_destroy( struct ureg_program
* );
93 /***********************************************************************
94 * Convenience routine:
97 ureg_create_shader_and_destroy( struct ureg_program
*p
,
98 struct pipe_context
*pipe
)
100 void *result
= ureg_create_shader( p
, pipe
);
107 /***********************************************************************
108 * Build shader declarations:
112 ureg_DECL_fs_input( struct ureg_program
*,
113 unsigned semantic_name
,
114 unsigned semantic_index
,
115 unsigned interp_mode
);
118 ureg_DECL_vs_input( struct ureg_program
*,
119 unsigned semantic_name
,
120 unsigned semantic_index
);
123 ureg_DECL_output( struct ureg_program
*,
124 unsigned semantic_name
,
125 unsigned semantic_index
);
128 ureg_DECL_immediate( struct ureg_program
*,
133 ureg_DECL_constant( struct ureg_program
* );
136 ureg_DECL_temporary( struct ureg_program
* );
139 ureg_release_temporary( struct ureg_program
*ureg
,
140 struct ureg_dst tmp
);
143 ureg_DECL_address( struct ureg_program
* );
145 /* Supply an index to the sampler declaration as this is the hook to
146 * the external pipe_sampler state. Users of this function probably
147 * don't want just any sampler, but a specific one which they've set
148 * up state for in the context.
151 ureg_DECL_sampler( struct ureg_program
*,
155 static INLINE
struct ureg_src
156 ureg_imm4f( struct ureg_program
*ureg
,
165 return ureg_DECL_immediate( ureg
, v
, 4 );
168 static INLINE
struct ureg_src
169 ureg_imm3f( struct ureg_program
*ureg
,
177 return ureg_DECL_immediate( ureg
, v
, 3 );
180 static INLINE
struct ureg_src
181 ureg_imm2f( struct ureg_program
*ureg
,
187 return ureg_DECL_immediate( ureg
, v
, 2 );
190 static INLINE
struct ureg_src
191 ureg_imm1f( struct ureg_program
*ureg
,
196 return ureg_DECL_immediate( ureg
, v
, 1 );
199 /***********************************************************************
200 * Functions for patching up labels
204 /* Will return a number which can be used in a label to point to the
205 * next instruction to be emitted.
208 ureg_get_instruction_number( struct ureg_program
*ureg
);
211 /* Patch a given label (expressed as a token number) to point to a
212 * given instruction (expressed as an instruction number).
214 * Labels are obtained from instruction emitters, eg ureg_CAL().
215 * Instruction numbers are obtained from ureg_get_instruction_number(),
219 ureg_fixup_label(struct ureg_program
*ureg
,
220 unsigned label_token
,
221 unsigned instruction_number
);
224 /* Generic instruction emitter. Use if you need to pass the opcode as
225 * a parameter, rather than using the emit_OP() varients below.
228 ureg_insn(struct ureg_program
*ureg
,
230 const struct ureg_dst
*dst
,
232 const struct ureg_src
*src
,
236 /***********************************************************************
237 * Internal instruction helpers, don't call these directly:
241 ureg_emit_insn(struct ureg_program
*ureg
,
248 ureg_emit_label(struct ureg_program
*ureg
,
250 unsigned *label_token
);
253 ureg_emit_texture(struct ureg_program
*ureg
,
258 ureg_emit_dst( struct ureg_program
*ureg
,
259 struct ureg_dst dst
);
262 ureg_emit_src( struct ureg_program
*ureg
,
263 struct ureg_src src
);
266 ureg_fixup_insn_size(struct ureg_program
*ureg
,
271 static INLINE void ureg_##op( struct ureg_program *ureg ) \
273 unsigned opcode = TGSI_OPCODE_##op; \
274 unsigned insn = ureg_emit_insn( ureg, opcode, FALSE, 0, 0 ); \
275 ureg_fixup_insn_size( ureg, insn ); \
279 static INLINE void ureg_##op( struct ureg_program *ureg, \
280 struct ureg_src src ) \
282 unsigned opcode = TGSI_OPCODE_##op; \
283 unsigned insn = ureg_emit_insn( ureg, opcode, FALSE, 0, 1 ); \
284 ureg_emit_src( ureg, src ); \
285 ureg_fixup_insn_size( ureg, insn ); \
288 #define OP00_LBL( op ) \
289 static INLINE void ureg_##op( struct ureg_program *ureg, \
290 unsigned *label_token ) \
292 unsigned opcode = TGSI_OPCODE_##op; \
293 unsigned insn = ureg_emit_insn( ureg, opcode, FALSE, 0, 0 ); \
294 ureg_emit_label( ureg, insn, label_token ); \
295 ureg_fixup_insn_size( ureg, insn ); \
298 #define OP01_LBL( op ) \
299 static INLINE void ureg_##op( struct ureg_program *ureg, \
300 struct ureg_src src, \
301 unsigned *label_token ) \
303 unsigned opcode = TGSI_OPCODE_##op; \
304 unsigned insn = ureg_emit_insn( ureg, opcode, FALSE, 0, 1 ); \
305 ureg_emit_label( ureg, insn, label_token ); \
306 ureg_emit_src( ureg, src ); \
307 ureg_fixup_insn_size( ureg, insn ); \
311 static INLINE void ureg_##op( struct ureg_program *ureg, \
312 struct ureg_dst dst ) \
314 unsigned opcode = TGSI_OPCODE_##op; \
315 unsigned insn = ureg_emit_insn( ureg, opcode, dst.Saturate, 1, 0 ); \
316 ureg_emit_dst( ureg, dst ); \
317 ureg_fixup_insn_size( ureg, insn ); \
322 static INLINE void ureg_##op( struct ureg_program *ureg, \
323 struct ureg_dst dst, \
324 struct ureg_src src ) \
326 unsigned opcode = TGSI_OPCODE_##op; \
327 unsigned insn = ureg_emit_insn( ureg, opcode, dst.Saturate, 1, 1 ); \
328 ureg_emit_dst( ureg, dst ); \
329 ureg_emit_src( ureg, src ); \
330 ureg_fixup_insn_size( ureg, insn ); \
334 static INLINE void ureg_##op( struct ureg_program *ureg, \
335 struct ureg_dst dst, \
336 struct ureg_src src0, \
337 struct ureg_src src1 ) \
339 unsigned opcode = TGSI_OPCODE_##op; \
340 unsigned insn = ureg_emit_insn( ureg, opcode, dst.Saturate, 1, 2 ); \
341 ureg_emit_dst( ureg, dst ); \
342 ureg_emit_src( ureg, src0 ); \
343 ureg_emit_src( ureg, src1 ); \
344 ureg_fixup_insn_size( ureg, insn ); \
347 #define OP12_TEX( op ) \
348 static INLINE void ureg_##op( struct ureg_program *ureg, \
349 struct ureg_dst dst, \
351 struct ureg_src src0, \
352 struct ureg_src src1 ) \
354 unsigned opcode = TGSI_OPCODE_##op; \
355 unsigned insn = ureg_emit_insn( ureg, opcode, dst.Saturate, 1, 2 ); \
356 ureg_emit_texture( ureg, insn, target ); \
357 ureg_emit_dst( ureg, dst ); \
358 ureg_emit_src( ureg, src0 ); \
359 ureg_emit_src( ureg, src1 ); \
360 ureg_fixup_insn_size( ureg, insn ); \
364 static INLINE void ureg_##op( struct ureg_program *ureg, \
365 struct ureg_dst dst, \
366 struct ureg_src src0, \
367 struct ureg_src src1, \
368 struct ureg_src src2 ) \
370 unsigned opcode = TGSI_OPCODE_##op; \
371 unsigned insn = ureg_emit_insn( ureg, opcode, dst.Saturate, 1, 3 ); \
372 ureg_emit_dst( ureg, dst ); \
373 ureg_emit_src( ureg, src0 ); \
374 ureg_emit_src( ureg, src1 ); \
375 ureg_emit_src( ureg, src2 ); \
376 ureg_fixup_insn_size( ureg, insn ); \
379 #define OP14_TEX( op ) \
380 static INLINE void ureg_##op( struct ureg_program *ureg, \
381 struct ureg_dst dst, \
383 struct ureg_src src0, \
384 struct ureg_src src1, \
385 struct ureg_src src2, \
386 struct ureg_src src3 ) \
388 unsigned opcode = TGSI_OPCODE_##op; \
389 unsigned insn = ureg_emit_insn( ureg, opcode, dst.Saturate, 1, 4 ); \
390 ureg_emit_texture( ureg, insn, target ); \
391 ureg_emit_dst( ureg, dst ); \
392 ureg_emit_src( ureg, src0 ); \
393 ureg_emit_src( ureg, src1 ); \
394 ureg_emit_src( ureg, src2 ); \
395 ureg_emit_src( ureg, src3 ); \
396 ureg_fixup_insn_size( ureg, insn ); \
400 /* Use a template include to generate a correctly-typed ureg_OP()
401 * function for each TGSI opcode:
403 #include "tgsi_opcode_tmp.h"
406 /***********************************************************************
407 * Inline helpers for manipulating register structs:
409 static INLINE
struct ureg_src
410 ureg_negate( struct ureg_src reg
)
412 assert(reg
.File
!= TGSI_FILE_NULL
);
417 static INLINE
struct ureg_src
418 ureg_abs( struct ureg_src reg
)
420 assert(reg
.File
!= TGSI_FILE_NULL
);
426 static INLINE
struct ureg_src
427 ureg_swizzle( struct ureg_src reg
,
428 int x
, int y
, int z
, int w
)
430 unsigned swz
= ( (reg
.SwizzleX
<< 0) |
431 (reg
.SwizzleY
<< 2) |
432 (reg
.SwizzleZ
<< 4) |
433 (reg
.SwizzleW
<< 6));
435 assert(reg
.File
!= TGSI_FILE_NULL
);
441 reg
.SwizzleX
= (swz
>> (x
*2)) & 0x3;
442 reg
.SwizzleY
= (swz
>> (y
*2)) & 0x3;
443 reg
.SwizzleZ
= (swz
>> (z
*2)) & 0x3;
444 reg
.SwizzleW
= (swz
>> (w
*2)) & 0x3;
448 static INLINE
struct ureg_src
449 ureg_scalar( struct ureg_src reg
, int x
)
451 return ureg_swizzle(reg
, x
, x
, x
, x
);
454 static INLINE
struct ureg_dst
455 ureg_writemask( struct ureg_dst reg
,
458 assert(reg
.File
!= TGSI_FILE_NULL
);
459 reg
.WriteMask
&= writemask
;
463 static INLINE
struct ureg_dst
464 ureg_saturate( struct ureg_dst reg
)
466 assert(reg
.File
!= TGSI_FILE_NULL
);
471 static INLINE
struct ureg_dst
472 ureg_dst_indirect( struct ureg_dst reg
, struct ureg_src addr
)
474 assert(reg
.File
!= TGSI_FILE_NULL
);
475 assert(addr
.File
== TGSI_FILE_ADDRESS
);
477 reg
.IndirectIndex
= addr
.Index
;
478 reg
.IndirectSwizzle
= addr
.SwizzleX
;
482 static INLINE
struct ureg_src
483 ureg_src_indirect( struct ureg_src reg
, struct ureg_src addr
)
485 assert(reg
.File
!= TGSI_FILE_NULL
);
486 assert(addr
.File
== TGSI_FILE_ADDRESS
);
488 reg
.IndirectIndex
= addr
.Index
;
489 reg
.IndirectSwizzle
= addr
.SwizzleX
;
493 static INLINE
struct ureg_dst
494 ureg_dst( struct ureg_src src
)
499 dst
.WriteMask
= TGSI_WRITEMASK_XYZW
;
500 dst
.Indirect
= src
.Indirect
;
501 dst
.IndirectIndex
= src
.IndirectIndex
;
502 dst
.IndirectSwizzle
= src
.IndirectSwizzle
;
504 dst
.Index
= src
.Index
;
511 static INLINE
struct ureg_src
512 ureg_src( struct ureg_dst dst
)
517 src
.SwizzleX
= TGSI_SWIZZLE_X
;
518 src
.SwizzleY
= TGSI_SWIZZLE_Y
;
519 src
.SwizzleZ
= TGSI_SWIZZLE_Z
;
520 src
.SwizzleW
= TGSI_SWIZZLE_W
;
522 src
.Indirect
= dst
.Indirect
;
523 src
.IndirectIndex
= dst
.IndirectIndex
;
524 src
.IndirectSwizzle
= dst
.IndirectSwizzle
;
526 src
.Index
= dst
.Index
;
534 static INLINE
struct ureg_dst
535 ureg_dst_undef( void )
539 dst
.File
= TGSI_FILE_NULL
;
542 dst
.IndirectIndex
= 0;
543 dst
.IndirectSwizzle
= 0;
552 static INLINE
struct ureg_src
553 ureg_src_undef( void )
557 src
.File
= TGSI_FILE_NULL
;
564 src
.IndirectIndex
= 0;
565 src
.IndirectSwizzle
= 0;
573 static INLINE boolean
574 ureg_src_is_undef( struct ureg_src src
)
576 return src
.File
== TGSI_FILE_NULL
;
579 static INLINE boolean
580 ureg_dst_is_undef( struct ureg_dst dst
)
582 return dst
.File
== TGSI_FILE_NULL
;