summaryrefslogtreecommitdiffstats
path: root/src/gallium/auxiliary/tgsi/tgsi_exec.h
blob: c009a97c5743b00f2d55b2789219932084d226ad (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
/**************************************************************************
 * 
 * Copyright 2007-2008 Tungsten Graphics, Inc., Cedar Park, Texas.
 * All Rights Reserved.
 * Copyright 2009-2010 VMware, Inc.  All rights Reserved.
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the
 * "Software"), to deal in the Software without restriction, including
 * without limitation the rights to use, copy, modify, merge, publish,
 * distribute, sub license, and/or sell copies of the Software, and to
 * permit persons to whom the Software is furnished to do so, subject to
 * the following conditions:
 * 
 * The above copyright notice and this permission notice (including the
 * next paragraph) shall be included in all copies or substantial portions
 * of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 * 
 **************************************************************************/

#ifndef TGSI_EXEC_H
#define TGSI_EXEC_H

#include "pipe/p_compiler.h"
#include "pipe/p_state.h"
#include "pipe/p_shader_tokens.h"

#if defined __cplusplus
extern "C" {
#endif

#define TGSI_CHAN_X 0
#define TGSI_CHAN_Y 1
#define TGSI_CHAN_Z 2
#define TGSI_CHAN_W 3

#define TGSI_NUM_CHANNELS 4  /* R,G,B,A */
#define TGSI_QUAD_SIZE    4  /* 4 pixel/quad */

#define TGSI_FOR_EACH_CHANNEL( CHAN )\
   for (CHAN = 0; CHAN < TGSI_NUM_CHANNELS; CHAN++)

#define TGSI_IS_DST0_CHANNEL_ENABLED( INST, CHAN )\
   ((INST)->Dst[0].Register.WriteMask & (1 << (CHAN)))

#define TGSI_IF_IS_DST0_CHANNEL_ENABLED( INST, CHAN )\
   if (TGSI_IS_DST0_CHANNEL_ENABLED( INST, CHAN ))

#define TGSI_FOR_EACH_DST0_ENABLED_CHANNEL( INST, CHAN )\
   TGSI_FOR_EACH_CHANNEL( CHAN )\
      TGSI_IF_IS_DST0_CHANNEL_ENABLED( INST, CHAN )


/**
  * Registers may be treated as float, signed int or unsigned int.
  */
union tgsi_exec_channel
{
   float    f[TGSI_QUAD_SIZE];
   int      i[TGSI_QUAD_SIZE];
   unsigned u[TGSI_QUAD_SIZE];
};

/**
  * A vector[RGBA] of channels[4 pixels]
  */
struct tgsi_exec_vector
{
   union tgsi_exec_channel xyzw[TGSI_NUM_CHANNELS];
};

/**
 * For fragment programs, information for computing fragment input
 * values from plane equation of the triangle/line.
 */
struct tgsi_interp_coef
{
   float a0[TGSI_NUM_CHANNELS];	/* in an xyzw layout */
   float dadx[TGSI_NUM_CHANNELS];
   float dady[TGSI_NUM_CHANNELS];
};

enum tgsi_sampler_control {
   tgsi_sampler_lod_none,
   tgsi_sampler_lod_bias,
   tgsi_sampler_lod_explicit,
   tgsi_sampler_lod_zero
   /* FIXME: tgsi_sampler_derivs_explicit */
};

/**
 * Information for sampling textures, which must be implemented
 * by code outside the TGSI executor.
 */
struct tgsi_sampler
{
   /** Get samples for four fragments in a quad */
   /* this interface contains 5 sets of channels that vary
    * depending on the sampler.
    * s - the first texture coordinate for sampling.
    * t - the second texture coordinate for sampling - unused for 1D,
          layer for 1D arrays.
    * p - the third coordinate for sampling for 3D, cube, cube arrays,
    *     layer for 2D arrays. Compare value for 1D/2D shadows.
    * c0 - Compare value for shadow cube and shadow 2d arrays,
    *      layer for cube arrays.
    * lod - lod value, except for shadow cube arrays (compare value there).
    */
   void (*get_samples)(struct tgsi_sampler *sampler,
                       const unsigned sview_index,
                       const unsigned sampler_index,
                       const float s[TGSI_QUAD_SIZE],
                       const float t[TGSI_QUAD_SIZE],
                       const float r[TGSI_QUAD_SIZE],
                       const float c0[TGSI_QUAD_SIZE],
                       const float c1[TGSI_QUAD_SIZE],
                       enum tgsi_sampler_control control,
                       float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE]);
   void (*get_dims)(struct tgsi_sampler *sampler,
                    const unsigned sview_index,
                    int level, int dims[4]);
   void (*get_texel)(struct tgsi_sampler *sampler,
                     const unsigned sview_index,
                     const int i[TGSI_QUAD_SIZE],
                     const int j[TGSI_QUAD_SIZE], const int k[TGSI_QUAD_SIZE],
                     const int lod[TGSI_QUAD_SIZE], const int8_t offset[3],
                     float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE]);
};

#define TGSI_EXEC_NUM_TEMPS       4096
#define TGSI_EXEC_NUM_IMMEDIATES  256
#define TGSI_EXEC_NUM_TEMP_ARRAYS 8

/*
 * Locations of various utility registers (_I = Index, _C = Channel)
 */
#define TGSI_EXEC_TEMP_00000000_I   (TGSI_EXEC_NUM_TEMPS + 0)
#define TGSI_EXEC_TEMP_00000000_C   0

#define TGSI_EXEC_TEMP_7FFFFFFF_I   (TGSI_EXEC_NUM_TEMPS + 0)
#define TGSI_EXEC_TEMP_7FFFFFFF_C   1

#define TGSI_EXEC_TEMP_80000000_I   (TGSI_EXEC_NUM_TEMPS + 0)
#define TGSI_EXEC_TEMP_80000000_C   2

#define TGSI_EXEC_TEMP_FFFFFFFF_I   (TGSI_EXEC_NUM_TEMPS + 0)
#define TGSI_EXEC_TEMP_FFFFFFFF_C   3

#define TGSI_EXEC_TEMP_ONE_I        (TGSI_EXEC_NUM_TEMPS + 1)
#define TGSI_EXEC_TEMP_ONE_C        0

#define TGSI_EXEC_TEMP_TWO_I        (TGSI_EXEC_NUM_TEMPS + 1)
#define TGSI_EXEC_TEMP_TWO_C        1

#define TGSI_EXEC_TEMP_128_I        (TGSI_EXEC_NUM_TEMPS + 1)
#define TGSI_EXEC_TEMP_128_C        2

#define TGSI_EXEC_TEMP_MINUS_128_I  (TGSI_EXEC_NUM_TEMPS + 1)
#define TGSI_EXEC_TEMP_MINUS_128_C  3

#define TGSI_EXEC_TEMP_KILMASK_I    (TGSI_EXEC_NUM_TEMPS + 2)
#define TGSI_EXEC_TEMP_KILMASK_C    0

#define TGSI_EXEC_TEMP_OUTPUT_I     (TGSI_EXEC_NUM_TEMPS + 2)
#define TGSI_EXEC_TEMP_OUTPUT_C     1

#define TGSI_EXEC_TEMP_PRIMITIVE_I  (TGSI_EXEC_NUM_TEMPS + 2)
#define TGSI_EXEC_TEMP_PRIMITIVE_C  2

#define TGSI_EXEC_TEMP_THREE_I      (TGSI_EXEC_NUM_TEMPS + 2)
#define TGSI_EXEC_TEMP_THREE_C      3

#define TGSI_EXEC_TEMP_HALF_I       (TGSI_EXEC_NUM_TEMPS + 3)
#define TGSI_EXEC_TEMP_HALF_C       0

/* execution mask, each value is either 0 or ~0 */
#define TGSI_EXEC_MASK_I            (TGSI_EXEC_NUM_TEMPS + 3)
#define TGSI_EXEC_MASK_C            1

/* 4 register buffer for various purposes */
#define TGSI_EXEC_TEMP_R0           (TGSI_EXEC_NUM_TEMPS + 4)
#define TGSI_EXEC_NUM_TEMP_R        4

#define TGSI_EXEC_TEMP_ADDR         (TGSI_EXEC_NUM_TEMPS + 8)
#define TGSI_EXEC_NUM_ADDRS         1

/* predicate register */
#define TGSI_EXEC_TEMP_P0           (TGSI_EXEC_NUM_TEMPS + 9)
#define TGSI_EXEC_NUM_PREDS         1

#define TGSI_EXEC_NUM_TEMP_EXTRAS   10



#define TGSI_EXEC_MAX_NESTING  32
#define TGSI_EXEC_MAX_COND_NESTING  TGSI_EXEC_MAX_NESTING
#define TGSI_EXEC_MAX_LOOP_NESTING  TGSI_EXEC_MAX_NESTING
#define TGSI_EXEC_MAX_SWITCH_NESTING TGSI_EXEC_MAX_NESTING
#define TGSI_EXEC_MAX_CALL_NESTING  TGSI_EXEC_MAX_NESTING

/* The maximum number of input attributes per vertex. For 2D
 * input register files, this is the stride between two 1D
 * arrays.
 */
#define TGSI_EXEC_MAX_INPUT_ATTRIBS 17

/* The maximum number of constant vectors per constant buffer.
 */
#define TGSI_EXEC_MAX_CONST_BUFFER  4096

/* The maximum number of vertices per primitive */
#define TGSI_MAX_PRIM_VERTICES 6

/* The maximum number of primitives to be generated */
#define TGSI_MAX_PRIMITIVES 64

/* The maximum total number of vertices */
#define TGSI_MAX_TOTAL_VERTICES (TGSI_MAX_PRIM_VERTICES * TGSI_MAX_PRIMITIVES * PIPE_MAX_ATTRIBS)

#define TGSI_MAX_MISC_INPUTS 8

/** function call/activation record */
struct tgsi_call_record
{
   uint CondStackTop;
   uint LoopStackTop;
   uint ContStackTop;
   int SwitchStackTop;
   int BreakStackTop;
   uint ReturnAddr;
};


/* Switch-case block state. */
struct tgsi_switch_record {
   uint mask;                          /**< execution mask */
   union tgsi_exec_channel selector;   /**< a value case statements are compared to */
   uint defaultMask;                   /**< non-execute mask for default case */
};


enum tgsi_break_type {
   TGSI_EXEC_BREAK_INSIDE_LOOP,
   TGSI_EXEC_BREAK_INSIDE_SWITCH
};


#define TGSI_EXEC_MAX_BREAK_STACK (TGSI_EXEC_MAX_LOOP_NESTING + TGSI_EXEC_MAX_SWITCH_NESTING)


/**
 * Run-time virtual machine state for executing TGSI shader.
 */
struct tgsi_exec_machine
{
   /* Total = program temporaries + internal temporaries
    */
   struct tgsi_exec_vector       Temps[TGSI_EXEC_NUM_TEMPS +
                                       TGSI_EXEC_NUM_TEMP_EXTRAS];
   struct tgsi_exec_vector       TempArray[TGSI_EXEC_NUM_TEMP_ARRAYS][TGSI_EXEC_NUM_TEMPS];

   float                         Imms[TGSI_EXEC_NUM_IMMEDIATES][4];

   float                         ImmArray[TGSI_EXEC_NUM_IMMEDIATES][4];

   struct tgsi_exec_vector       *Inputs;
   struct tgsi_exec_vector       *Outputs;

   /* System values */
   unsigned                      SysSemanticToIndex[TGSI_SEMANTIC_COUNT];
   union tgsi_exec_channel       SystemValue[TGSI_MAX_MISC_INPUTS];

   struct tgsi_exec_vector       *Addrs;
   struct tgsi_exec_vector       *Predicates;

   struct tgsi_sampler           *Sampler;

   unsigned                      ImmLimit;

   const void *Consts[PIPE_MAX_CONSTANT_BUFFERS];
   unsigned ConstsSize[PIPE_MAX_CONSTANT_BUFFERS];

   const struct tgsi_token       *Tokens;   /**< Declarations, instructions */
   unsigned                      Processor; /**< TGSI_PROCESSOR_x */

   /* GEOMETRY processor only. */
   unsigned                      *Primitives;
   unsigned                       NumOutputs;
   unsigned                       MaxGeometryShaderOutputs;

   /* FRAGMENT processor only. */
   const struct tgsi_interp_coef *InterpCoefs;
   struct tgsi_exec_vector       QuadPos;
   float                         Face;    /**< +1 if front facing, -1 if back facing */
   bool                          flatshade_color;
   /* Conditional execution masks */
   uint CondMask;  /**< For IF/ELSE/ENDIF */
   uint LoopMask;  /**< For BGNLOOP/ENDLOOP */
   uint ContMask;  /**< For loop CONT statements */
   uint FuncMask;  /**< For function calls */
   uint ExecMask;  /**< = CondMask & LoopMask */

   /* Current switch-case state. */
   struct tgsi_switch_record Switch;

   /* Current break type. */
   enum tgsi_break_type BreakType;

   /** Condition mask stack (for nested conditionals) */
   uint CondStack[TGSI_EXEC_MAX_COND_NESTING];
   int CondStackTop;

   /** Loop mask stack (for nested loops) */
   uint LoopStack[TGSI_EXEC_MAX_LOOP_NESTING];
   int LoopStackTop;

   /** Loop label stack */
   uint LoopLabelStack[TGSI_EXEC_MAX_LOOP_NESTING];
   int LoopLabelStackTop;

   /** Loop continue mask stack (see comments in tgsi_exec.c) */
   uint ContStack[TGSI_EXEC_MAX_LOOP_NESTING];
   int ContStackTop;

   /** Switch case stack */
   struct tgsi_switch_record SwitchStack[TGSI_EXEC_MAX_SWITCH_NESTING];
   int SwitchStackTop;

   enum tgsi_break_type BreakStack[TGSI_EXEC_MAX_BREAK_STACK];
   int BreakStackTop;

   /** Function execution mask stack (for executing subroutine code) */
   uint FuncStack[TGSI_EXEC_MAX_CALL_NESTING];
   int FuncStackTop;

   /** Function call stack for saving/restoring the program counter */
   struct tgsi_call_record CallStack[TGSI_EXEC_MAX_CALL_NESTING];
   int CallStackTop;

   struct tgsi_full_instruction *Instructions;
   uint NumInstructions;

   struct tgsi_full_declaration *Declarations;
   uint NumDeclarations;

   struct tgsi_declaration_sampler_view
      SamplerViews[PIPE_MAX_SHADER_SAMPLER_VIEWS];

   boolean UsedGeometryShader;
};

struct tgsi_exec_machine *
tgsi_exec_machine_create( void );

void
tgsi_exec_machine_destroy(struct tgsi_exec_machine *mach);


void 
tgsi_exec_machine_bind_shader(
   struct tgsi_exec_machine *mach,
   const struct tgsi_token *tokens,
   struct tgsi_sampler *sampler);

uint
tgsi_exec_machine_run(
   struct tgsi_exec_machine *mach );


void
tgsi_exec_machine_free_data(struct tgsi_exec_machine *mach);


boolean
tgsi_check_soa_dependencies(const struct tgsi_full_instruction *inst);


static INLINE void
tgsi_set_kill_mask(struct tgsi_exec_machine *mach, unsigned mask)
{
   mach->Temps[TGSI_EXEC_TEMP_KILMASK_I].xyzw[TGSI_EXEC_TEMP_KILMASK_C].u[0] =
      mask;
}


/** Set execution mask values prior to executing the shader */
static INLINE void
tgsi_set_exec_mask(struct tgsi_exec_machine *mach,
                   boolean ch0, boolean ch1, boolean ch2, boolean ch3)
{
   int *mask = mach->Temps[TGSI_EXEC_MASK_I].xyzw[TGSI_EXEC_MASK_C].i;
   mask[0] = ch0 ? ~0 : 0;
   mask[1] = ch1 ? ~0 : 0;
   mask[2] = ch2 ? ~0 : 0;
   mask[3] = ch3 ? ~0 : 0;
}


extern void
tgsi_exec_set_constant_buffers(struct tgsi_exec_machine *mach,
                               unsigned num_bufs,
                               const void **bufs,
                               const unsigned *buf_sizes);


static INLINE int
tgsi_exec_get_shader_param(enum pipe_shader_cap param)
{
   switch(param) {
   case PIPE_SHADER_CAP_MAX_INSTRUCTIONS:
   case PIPE_SHADER_CAP_MAX_ALU_INSTRUCTIONS:
   case PIPE_SHADER_CAP_MAX_TEX_INSTRUCTIONS:
   case PIPE_SHADER_CAP_MAX_TEX_INDIRECTIONS:
      return INT_MAX;
   case PIPE_SHADER_CAP_MAX_CONTROL_FLOW_DEPTH:
      return TGSI_EXEC_MAX_NESTING;
   case PIPE_SHADER_CAP_MAX_INPUTS:
      return TGSI_EXEC_MAX_INPUT_ATTRIBS;
   case PIPE_SHADER_CAP_MAX_CONSTS:
      return TGSI_EXEC_MAX_CONST_BUFFER;
   case PIPE_SHADER_CAP_MAX_CONST_BUFFERS:
      return PIPE_MAX_CONSTANT_BUFFERS;
   case PIPE_SHADER_CAP_MAX_TEMPS:
      return TGSI_EXEC_NUM_TEMPS;
   case PIPE_SHADER_CAP_MAX_ADDRS:
      return TGSI_EXEC_NUM_ADDRS;
   case PIPE_SHADER_CAP_MAX_PREDS:
      return TGSI_EXEC_NUM_PREDS;
   case PIPE_SHADER_CAP_TGSI_CONT_SUPPORTED:
      return 1;
   case PIPE_SHADER_CAP_INDIRECT_INPUT_ADDR:
   case PIPE_SHADER_CAP_INDIRECT_OUTPUT_ADDR:
   case PIPE_SHADER_CAP_INDIRECT_TEMP_ADDR:
   case PIPE_SHADER_CAP_INDIRECT_CONST_ADDR:
      return 1;
   case PIPE_SHADER_CAP_SUBROUTINES:
      return 1;
   case PIPE_SHADER_CAP_INTEGERS:
      return 1;
   case PIPE_SHADER_CAP_MAX_TEXTURE_SAMPLERS:
      return PIPE_MAX_SAMPLERS;
   case PIPE_SHADER_CAP_TGSI_SQRT_SUPPORTED:
      return 1;
   default:
      return 0;
   }
}

#if defined __cplusplus
} /* extern "C" */
#endif

#endif /* TGSI_EXEC_H */