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"
36 /* Almost a tgsi_src_register, but we need to pull in the Absolute
37 * flag from the _ext token. Indirect flag always implies ADDR[0].
41 unsigned File
: 4; /* TGSI_FILE_ */
42 unsigned SwizzleX
: 2; /* TGSI_SWIZZLE_ */
43 unsigned SwizzleY
: 2; /* TGSI_SWIZZLE_ */
44 unsigned SwizzleZ
: 2; /* TGSI_SWIZZLE_ */
45 unsigned SwizzleW
: 2; /* TGSI_SWIZZLE_ */
46 unsigned Pad
: 1; /* BOOL */
47 unsigned Indirect
: 1; /* BOOL */
48 unsigned Absolute
: 1; /* BOOL */
49 int Index
: 16; /* SINT */
50 unsigned Negate
: 1; /* BOOL */
53 /* Very similar to a tgsi_dst_register, removing unsupported fields
54 * and adding a Saturate flag. It's easier to push saturate into the
55 * destination register than to try and create a _SAT varient of each
56 * instruction function.
60 unsigned File
: 4; /* TGSI_FILE_ */
61 unsigned WriteMask
: 4; /* TGSI_WRITEMASK_ */
62 unsigned Indirect
: 1; /* BOOL */
63 unsigned Saturate
: 1; /* BOOL */
64 int Index
: 16; /* SINT */
66 unsigned Pad2
: 1; /* BOOL */
72 ureg_create( struct pipe_context
*pipe
,
76 ureg_create_shader( struct ureg_program
* );
79 ureg_destroy( struct ureg_program
* );
82 /***********************************************************************
83 * Convenience routine:
85 static INLINE
void *ureg_create_shader_and_destroy( struct ureg_program
*p
)
87 void *result
= ureg_create_shader( p
);
94 /***********************************************************************
95 * Build shader declarations:
99 ureg_DECL_fs_input( struct ureg_program
*,
100 unsigned semantic_name
,
101 unsigned semantic_index
,
102 unsigned interp_mode
);
105 ureg_DECL_vs_input( struct ureg_program
*,
106 unsigned semantic_name
,
107 unsigned semantic_index
);
110 ureg_DECL_output( struct ureg_program
*,
111 unsigned semantic_name
,
112 unsigned semantic_index
);
115 ureg_DECL_immediate( struct ureg_program
*,
120 ureg_DECL_constant( struct ureg_program
* );
123 ureg_DECL_temporary( struct ureg_program
* );
126 ureg_release_temporary( struct ureg_program
*ureg
,
127 struct ureg_dst tmp
);
130 ureg_DECL_sampler( struct ureg_program
* );
133 static INLINE
struct ureg_src
134 ureg_DECL_immediate4f( struct ureg_program
*ureg
,
143 return ureg_DECL_immediate( ureg
, v
, 4 );
146 static INLINE
struct ureg_src
147 ureg_DECL_immediate3f( struct ureg_program
*ureg
,
155 return ureg_DECL_immediate( ureg
, v
, 3 );
158 static INLINE
struct ureg_src
159 ureg_DECL_immediate2f( struct ureg_program
*ureg
,
165 return ureg_DECL_immediate( ureg
, v
, 2 );
168 static INLINE
struct ureg_src
169 ureg_DECL_immediate1f( struct ureg_program
*ureg
,
174 return ureg_DECL_immediate( ureg
, v
, 1 );
177 /***********************************************************************
178 * Internal instruction helpers, don't call these directly:
182 ureg_emit_insn(struct ureg_program
*ureg
,
189 ureg_emit_label(struct ureg_program
*ureg
,
191 unsigned *label_token
);
194 ureg_emit_texture(struct ureg_program
*ureg
,
199 ureg_emit_dst( struct ureg_program
*ureg
,
200 struct ureg_dst dst
);
203 ureg_emit_src( struct ureg_program
*ureg
,
204 struct ureg_src src
);
207 ureg_fixup_insn_size(struct ureg_program
*ureg
,
212 static INLINE void ureg_##op( struct ureg_program *ureg ) \
214 unsigned opcode = TGSI_OPCODE_##op; \
215 unsigned insn = ureg_emit_insn( ureg, opcode, FALSE, 0, 0 ); \
216 ureg_fixup_insn_size( ureg, insn ); \
220 static INLINE void ureg_##op( struct ureg_program *ureg, \
221 struct ureg_src src ) \
223 unsigned opcode = TGSI_OPCODE_##op; \
224 unsigned insn = ureg_emit_insn( ureg, opcode, FALSE, 0, 1 ); \
225 ureg_emit_src( ureg, src ); \
226 ureg_fixup_insn_size( ureg, insn ); \
229 #define OP00_LBL( op ) \
230 static INLINE void ureg_##op( struct ureg_program *ureg, \
231 unsigned *label_token ) \
233 unsigned opcode = TGSI_OPCODE_##op; \
234 unsigned insn = ureg_emit_insn( ureg, opcode, FALSE, 0, 0 ); \
235 ureg_emit_label( ureg, insn, label_token ); \
236 ureg_fixup_insn_size( ureg, insn ); \
239 #define OP01_LBL( op ) \
240 static INLINE void ureg_##op( struct ureg_program *ureg, \
241 struct ureg_src src, \
242 unsigned *label_token ) \
244 unsigned opcode = TGSI_OPCODE_##op; \
245 unsigned insn = ureg_emit_insn( ureg, opcode, FALSE, 0, 1 ); \
246 ureg_emit_label( ureg, insn, label_token ); \
247 ureg_emit_src( ureg, src ); \
248 ureg_fixup_insn_size( ureg, insn ); \
252 static INLINE void ureg_##op( struct ureg_program *ureg, \
253 struct ureg_dst dst ) \
255 unsigned opcode = TGSI_OPCODE_##op; \
256 unsigned insn = ureg_emit_insn( ureg, opcode, dst.Saturate, 1, 0 ); \
257 ureg_emit_dst( ureg, dst ); \
258 ureg_fixup_insn_size( ureg, insn ); \
263 static INLINE void ureg_##op( struct ureg_program *ureg, \
264 struct ureg_dst dst, \
265 struct ureg_src src ) \
267 unsigned opcode = TGSI_OPCODE_##op; \
268 unsigned insn = ureg_emit_insn( ureg, opcode, dst.Saturate, 1, 1 ); \
269 ureg_emit_dst( ureg, dst ); \
270 ureg_emit_src( ureg, src ); \
271 ureg_fixup_insn_size( ureg, insn ); \
275 static INLINE void ureg_##op( struct ureg_program *ureg, \
276 struct ureg_dst dst, \
277 struct ureg_src src0, \
278 struct ureg_src src1 ) \
280 unsigned opcode = TGSI_OPCODE_##op; \
281 unsigned insn = ureg_emit_insn( ureg, opcode, dst.Saturate, 1, 2 ); \
282 ureg_emit_dst( ureg, dst ); \
283 ureg_emit_src( ureg, src0 ); \
284 ureg_emit_src( ureg, src1 ); \
285 ureg_fixup_insn_size( ureg, insn ); \
288 #define OP12_TEX( op ) \
289 static INLINE void ureg_##op( struct ureg_program *ureg, \
290 struct ureg_dst dst, \
292 struct ureg_src src0, \
293 struct ureg_src src1 ) \
295 unsigned opcode = TGSI_OPCODE_##op; \
296 unsigned insn = ureg_emit_insn( ureg, opcode, dst.Saturate, 1, 2 ); \
297 ureg_emit_texture( ureg, insn, target ); \
298 ureg_emit_dst( ureg, dst ); \
299 ureg_emit_src( ureg, src0 ); \
300 ureg_emit_src( ureg, src1 ); \
301 ureg_fixup_insn_size( ureg, insn ); \
305 static INLINE void ureg_##op( struct ureg_program *ureg, \
306 struct ureg_dst dst, \
307 struct ureg_src src0, \
308 struct ureg_src src1, \
309 struct ureg_src src2 ) \
311 unsigned opcode = TGSI_OPCODE_##op; \
312 unsigned insn = ureg_emit_insn( ureg, opcode, dst.Saturate, 1, 3 ); \
313 ureg_emit_dst( ureg, dst ); \
314 ureg_emit_src( ureg, src0 ); \
315 ureg_emit_src( ureg, src1 ); \
316 ureg_emit_src( ureg, src2 ); \
317 ureg_fixup_insn_size( ureg, insn ); \
320 #define OP14_TEX( op ) \
321 static INLINE void ureg_##op( struct ureg_program *ureg, \
322 struct ureg_dst dst, \
324 struct ureg_src src0, \
325 struct ureg_src src1, \
326 struct ureg_src src2, \
327 struct ureg_src src3 ) \
329 unsigned opcode = TGSI_OPCODE_##op; \
330 unsigned insn = ureg_emit_insn( ureg, opcode, dst.Saturate, 1, 4 ); \
331 ureg_emit_texture( ureg, insn, target ); \
332 ureg_emit_dst( ureg, dst ); \
333 ureg_emit_src( ureg, src0 ); \
334 ureg_emit_src( ureg, src1 ); \
335 ureg_emit_src( ureg, src2 ); \
336 ureg_emit_src( ureg, src3 ); \
337 ureg_fixup_insn_size( ureg, insn ); \
341 /* Use a template include to generate a correctly-typed ureg_OP()
342 * function for each TGSI opcode:
344 #include "tgsi_opcode_tmp.h"
347 /***********************************************************************
348 * Inline helpers for manipulating register structs:
350 static INLINE
struct ureg_src
351 ureg_negate( struct ureg_src reg
)
357 static INLINE
struct ureg_src
358 ureg_abs( struct ureg_src reg
)
365 static INLINE
struct ureg_src
366 ureg_swizzle( struct ureg_src reg
,
367 int x
, int y
, int z
, int w
)
369 unsigned swz
= ( (reg
.SwizzleX
<< 0) |
370 (reg
.SwizzleY
<< 2) |
371 (reg
.SwizzleZ
<< 4) |
372 (reg
.SwizzleW
<< 6));
374 reg
.SwizzleX
= (swz
>> (x
*2)) & 0x3;
375 reg
.SwizzleY
= (swz
>> (y
*2)) & 0x3;
376 reg
.SwizzleZ
= (swz
>> (z
*2)) & 0x3;
377 reg
.SwizzleW
= (swz
>> (w
*2)) & 0x3;
381 static INLINE
struct ureg_src
382 ureg_scalar( struct ureg_src reg
, int x
)
384 return ureg_swizzle(reg
, x
, x
, x
, x
);
387 static INLINE
struct ureg_dst
388 ureg_writemask( struct ureg_dst reg
,
391 reg
.WriteMask
&= writemask
;
395 static INLINE
struct ureg_dst
396 ureg_saturate( struct ureg_dst reg
)
402 static INLINE
struct ureg_dst
403 ureg_dst( struct ureg_src src
)
408 dst
.WriteMask
= TGSI_WRITEMASK_XYZW
;
409 dst
.Indirect
= src
.Indirect
;
411 dst
.Index
= src
.Index
;
418 static INLINE
struct ureg_src
419 ureg_src( struct ureg_dst dst
)
424 src
.SwizzleX
= TGSI_SWIZZLE_X
;
425 src
.SwizzleY
= TGSI_SWIZZLE_Y
;
426 src
.SwizzleZ
= TGSI_SWIZZLE_Z
;
427 src
.SwizzleW
= TGSI_SWIZZLE_W
;
429 src
.Indirect
= dst
.Indirect
;
431 src
.Index
= dst
.Index
;