tgsi_ureg.h revision ae4704eabc237e13c9b06df9c44f31c9baca6208
1/**************************************************************************
2 *
3 * Copyright 2009 VMware, Inc.
4 * All Rights Reserved.
5 *
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:
13 *
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
16 * of the Software.
17 *
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.
25 *
26 **************************************************************************/
27
28#ifndef TGSI_UREG_H
29#define TGSI_UREG_H
30
31#include "pipe/p_compiler.h"
32#include "pipe/p_shader_tokens.h"
33
34#ifdef __cplusplus
35extern "C" {
36#endif
37
38struct ureg_program;
39
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].
42 */
43struct ureg_src
44{
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_ */
57};
58
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.
63 */
64struct ureg_dst
65{
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 */
71   unsigned Pad1        : 5;
72   unsigned Pad2        : 1;  /* BOOL */
73   int      IndirectIndex   : 16; /* SINT */
74   int      IndirectSwizzle : 2;  /* TGSI_SWIZZLE_ */
75};
76
77struct pipe_context;
78
79struct ureg_program *
80ureg_create( unsigned processor );
81
82const struct tgsi_token *
83ureg_finalize( struct ureg_program * );
84
85void *
86ureg_create_shader( struct ureg_program *,
87                    struct pipe_context *pipe );
88
89void
90ureg_destroy( struct ureg_program * );
91
92
93/***********************************************************************
94 * Convenience routine:
95 */
96static INLINE void *
97ureg_create_shader_and_destroy( struct ureg_program *p,
98                                struct pipe_context *pipe )
99{
100   void *result = ureg_create_shader( p, pipe );
101   ureg_destroy( p );
102   return result;
103}
104
105
106
107/***********************************************************************
108 * Build shader declarations:
109 */
110
111struct ureg_src
112ureg_DECL_fs_input( struct ureg_program *,
113                    unsigned semantic_name,
114                    unsigned semantic_index,
115                    unsigned interp_mode );
116
117struct ureg_src
118ureg_DECL_vs_input( struct ureg_program *,
119                    unsigned index );
120
121struct ureg_dst
122ureg_DECL_output( struct ureg_program *,
123                  unsigned semantic_name,
124                  unsigned semantic_index );
125
126struct ureg_src
127ureg_DECL_immediate( struct ureg_program *,
128                     const float *v,
129                     unsigned nr );
130
131struct ureg_src
132ureg_DECL_constant( struct ureg_program *,
133                    unsigned index );
134
135struct ureg_dst
136ureg_DECL_temporary( struct ureg_program * );
137
138void
139ureg_release_temporary( struct ureg_program *ureg,
140                        struct ureg_dst tmp );
141
142struct ureg_dst
143ureg_DECL_address( struct ureg_program * );
144
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.
149 */
150struct ureg_src
151ureg_DECL_sampler( struct ureg_program *,
152                   unsigned index );
153
154
155static INLINE struct ureg_src
156ureg_imm4f( struct ureg_program *ureg,
157                       float a, float b,
158                       float c, float d)
159{
160   float v[4];
161   v[0] = a;
162   v[1] = b;
163   v[2] = c;
164   v[3] = d;
165   return ureg_DECL_immediate( ureg, v, 4 );
166}
167
168static INLINE struct ureg_src
169ureg_imm3f( struct ureg_program *ureg,
170                       float a, float b,
171                       float c)
172{
173   float v[3];
174   v[0] = a;
175   v[1] = b;
176   v[2] = c;
177   return ureg_DECL_immediate( ureg, v, 3 );
178}
179
180static INLINE struct ureg_src
181ureg_imm2f( struct ureg_program *ureg,
182                       float a, float b)
183{
184   float v[2];
185   v[0] = a;
186   v[1] = b;
187   return ureg_DECL_immediate( ureg, v, 2 );
188}
189
190static INLINE struct ureg_src
191ureg_imm1f( struct ureg_program *ureg,
192                       float a)
193{
194   float v[1];
195   v[0] = a;
196   return ureg_DECL_immediate( ureg, v, 1 );
197}
198
199/***********************************************************************
200 * Functions for patching up labels
201 */
202
203
204/* Will return a number which can be used in a label to point to the
205 * next instruction to be emitted.
206 */
207unsigned
208ureg_get_instruction_number( struct ureg_program *ureg );
209
210
211/* Patch a given label (expressed as a token number) to point to a
212 * given instruction (expressed as an instruction number).
213 *
214 * Labels are obtained from instruction emitters, eg ureg_CAL().
215 * Instruction numbers are obtained from ureg_get_instruction_number(),
216 * above.
217 */
218void
219ureg_fixup_label(struct ureg_program *ureg,
220                 unsigned label_token,
221                 unsigned instruction_number );
222
223
224/* Generic instruction emitter.  Use if you need to pass the opcode as
225 * a parameter, rather than using the emit_OP() varients below.
226 */
227void
228ureg_insn(struct ureg_program *ureg,
229          unsigned opcode,
230          const struct ureg_dst *dst,
231          unsigned nr_dst,
232          const struct ureg_src *src,
233          unsigned nr_src );
234
235
236/***********************************************************************
237 * Internal instruction helpers, don't call these directly:
238 */
239
240unsigned
241ureg_emit_insn(struct ureg_program *ureg,
242               unsigned opcode,
243               boolean saturate,
244               unsigned num_dst,
245               unsigned num_src );
246
247void
248ureg_emit_label(struct ureg_program *ureg,
249                unsigned insn_token,
250                unsigned *label_token );
251
252void
253ureg_emit_texture(struct ureg_program *ureg,
254                  unsigned insn_token,
255                  unsigned target );
256
257void
258ureg_emit_dst( struct ureg_program *ureg,
259               struct ureg_dst dst );
260
261void
262ureg_emit_src( struct ureg_program *ureg,
263               struct ureg_src src );
264
265void
266ureg_fixup_insn_size(struct ureg_program *ureg,
267                     unsigned insn );
268
269
270#define OP00( op )                                              \
271static INLINE void ureg_##op( struct ureg_program *ureg )       \
272{                                                               \
273   unsigned opcode = TGSI_OPCODE_##op;                          \
274   unsigned insn = ureg_emit_insn( ureg, opcode, FALSE, 0, 0 ); \
275   ureg_fixup_insn_size( ureg, insn );                          \
276}
277
278#define OP01( op )                                              \
279static INLINE void ureg_##op( struct ureg_program *ureg,        \
280                              struct ureg_src src )             \
281{                                                               \
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 );                          \
286}
287
288#define OP00_LBL( op )                                          \
289static INLINE void ureg_##op( struct ureg_program *ureg,        \
290                              unsigned *label_token )           \
291{                                                               \
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 );                          \
296}
297
298#define OP01_LBL( op )                                          \
299static INLINE void ureg_##op( struct ureg_program *ureg,        \
300                              struct ureg_src src,              \
301                              unsigned *label_token )          \
302{                                                               \
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 );                          \
308}
309
310#define OP10( op )                                                      \
311static INLINE void ureg_##op( struct ureg_program *ureg,                \
312                              struct ureg_dst dst )                     \
313{                                                                       \
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 );                                  \
318}
319
320
321#define OP11( op )                                                      \
322static INLINE void ureg_##op( struct ureg_program *ureg,                \
323                              struct ureg_dst dst,                      \
324                              struct ureg_src src )                     \
325{                                                                       \
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 );                                  \
331}
332
333#define OP12( op )                                                      \
334static INLINE void ureg_##op( struct ureg_program *ureg,                \
335                              struct ureg_dst dst,                      \
336                              struct ureg_src src0,                     \
337                              struct ureg_src src1 )                    \
338{                                                                       \
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 );                                  \
345}
346
347#define OP12_TEX( op )                                                  \
348static INLINE void ureg_##op( struct ureg_program *ureg,                \
349                              struct ureg_dst dst,                      \
350                              unsigned target,                          \
351                              struct ureg_src src0,                     \
352                              struct ureg_src src1 )                    \
353{                                                                       \
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 );                                  \
361}
362
363#define OP13( op )                                                      \
364static 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 )                    \
369{                                                                       \
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 );                                  \
377}
378
379#define OP14_TEX( op )                                                  \
380static INLINE void ureg_##op( struct ureg_program *ureg,                \
381                              struct ureg_dst dst,                      \
382                              unsigned target,                          \
383                              struct ureg_src src0,                     \
384                              struct ureg_src src1,                     \
385                              struct ureg_src src2,                     \
386                              struct ureg_src src3 )                    \
387{                                                                       \
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 );                                  \
397}
398
399
400/* Use a template include to generate a correctly-typed ureg_OP()
401 * function for each TGSI opcode:
402 */
403#include "tgsi_opcode_tmp.h"
404
405
406/***********************************************************************
407 * Inline helpers for manipulating register structs:
408 */
409static INLINE struct ureg_src
410ureg_negate( struct ureg_src reg )
411{
412   assert(reg.File != TGSI_FILE_NULL);
413   reg.Negate ^= 1;
414   return reg;
415}
416
417static INLINE struct ureg_src
418ureg_abs( struct ureg_src reg )
419{
420   assert(reg.File != TGSI_FILE_NULL);
421   reg.Absolute = 1;
422   reg.Negate = 0;
423   return reg;
424}
425
426static INLINE struct ureg_src
427ureg_swizzle( struct ureg_src reg,
428              int x, int y, int z, int w )
429{
430   unsigned swz = ( (reg.SwizzleX << 0) |
431                    (reg.SwizzleY << 2) |
432                    (reg.SwizzleZ << 4) |
433                    (reg.SwizzleW << 6));
434
435   assert(reg.File != TGSI_FILE_NULL);
436   assert(x < 4);
437   assert(y < 4);
438   assert(z < 4);
439   assert(w < 4);
440
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;
445   return reg;
446}
447
448static INLINE struct ureg_src
449ureg_scalar( struct ureg_src reg, int x )
450{
451   return ureg_swizzle(reg, x, x, x, x);
452}
453
454static INLINE struct ureg_dst
455ureg_writemask( struct ureg_dst reg,
456                unsigned writemask )
457{
458   assert(reg.File != TGSI_FILE_NULL);
459   reg.WriteMask &= writemask;
460   return reg;
461}
462
463static INLINE struct ureg_dst
464ureg_saturate( struct ureg_dst reg )
465{
466   assert(reg.File != TGSI_FILE_NULL);
467   reg.Saturate = 1;
468   return reg;
469}
470
471static INLINE struct ureg_dst
472ureg_dst_indirect( struct ureg_dst reg, struct ureg_src addr )
473{
474   assert(reg.File != TGSI_FILE_NULL);
475   assert(addr.File == TGSI_FILE_ADDRESS);
476   reg.Indirect = 1;
477   reg.IndirectIndex = addr.Index;
478   reg.IndirectSwizzle = addr.SwizzleX;
479   return reg;
480}
481
482static INLINE struct ureg_src
483ureg_src_indirect( struct ureg_src reg, struct ureg_src addr )
484{
485   assert(reg.File != TGSI_FILE_NULL);
486   assert(addr.File == TGSI_FILE_ADDRESS);
487   reg.Indirect = 1;
488   reg.IndirectIndex = addr.Index;
489   reg.IndirectSwizzle = addr.SwizzleX;
490   return reg;
491}
492
493static INLINE struct ureg_dst
494ureg_dst( struct ureg_src src )
495{
496   struct ureg_dst dst;
497
498   dst.File      = src.File;
499   dst.WriteMask = TGSI_WRITEMASK_XYZW;
500   dst.Indirect  = src.Indirect;
501   dst.IndirectIndex = src.IndirectIndex;
502   dst.IndirectSwizzle = src.IndirectSwizzle;
503   dst.Saturate  = 0;
504   dst.Index     = src.Index;
505   dst.Pad1      = 0;
506   dst.Pad2      = 0;
507
508   return dst;
509}
510
511static INLINE struct ureg_src
512ureg_src( struct ureg_dst dst )
513{
514   struct ureg_src src;
515
516   src.File      = dst.File;
517   src.SwizzleX  = TGSI_SWIZZLE_X;
518   src.SwizzleY  = TGSI_SWIZZLE_Y;
519   src.SwizzleZ  = TGSI_SWIZZLE_Z;
520   src.SwizzleW  = TGSI_SWIZZLE_W;
521   src.Pad       = 0;
522   src.Indirect  = dst.Indirect;
523   src.IndirectIndex = dst.IndirectIndex;
524   src.IndirectSwizzle = dst.IndirectSwizzle;
525   src.Absolute  = 0;
526   src.Index     = dst.Index;
527   src.Negate    = 0;
528
529   return src;
530}
531
532
533
534static INLINE struct ureg_dst
535ureg_dst_undef( void )
536{
537   struct ureg_dst dst;
538
539   dst.File      = TGSI_FILE_NULL;
540   dst.WriteMask = 0;
541   dst.Indirect  = 0;
542   dst.IndirectIndex = 0;
543   dst.IndirectSwizzle = 0;
544   dst.Saturate  = 0;
545   dst.Index     = 0;
546   dst.Pad1      = 0;
547   dst.Pad2      = 0;
548
549   return dst;
550}
551
552static INLINE struct ureg_src
553ureg_src_undef( void )
554{
555   struct ureg_src src;
556
557   src.File      = TGSI_FILE_NULL;
558   src.SwizzleX  = 0;
559   src.SwizzleY  = 0;
560   src.SwizzleZ  = 0;
561   src.SwizzleW  = 0;
562   src.Pad       = 0;
563   src.Indirect  = 0;
564   src.IndirectIndex = 0;
565   src.IndirectSwizzle = 0;
566   src.Absolute  = 0;
567   src.Index     = 0;
568   src.Negate    = 0;
569
570   return src;
571}
572
573static INLINE boolean
574ureg_src_is_undef( struct ureg_src src )
575{
576   return src.File == TGSI_FILE_NULL;
577}
578
579static INLINE boolean
580ureg_dst_is_undef( struct ureg_dst dst )
581{
582   return dst.File == TGSI_FILE_NULL;
583}
584
585
586#ifdef __cplusplus
587}
588#endif
589
590#endif
591