Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
4358 Serge 1
/**************************************************************************
2
 *
3
 * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
4
 * All Rights Reserved.
5
 * Copyright 2008 VMware, Inc.  All rights Reserved.
6
 *
7
 * Permission is hereby granted, free of charge, to any person obtaining a
8
 * copy of this software and associated documentation files (the
9
 * "Software"), to deal in the Software without restriction, including
10
 * without limitation the rights to use, copy, modify, merge, publish,
11
 * distribute, sub license, and/or sell copies of the Software, and to
12
 * permit persons to whom the Software is furnished to do so, subject to
13
 * the following conditions:
14
 *
15
 * The above copyright notice and this permission notice (including the
16
 * next paragraph) shall be included in all copies or substantial portions
17
 * of the Software.
18
 *
19
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
22
 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
23
 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
24
 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
25
 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26
 *
27
 **************************************************************************/
28
 
29
/**
30
 * TGSI program scan utility.
31
 * Used to determine which registers and instructions are used by a shader.
32
 *
33
 * Authors:  Brian Paul
34
 */
35
 
36
 
37
#include "util/u_debug.h"
38
#include "util/u_math.h"
39
#include "util/u_prim.h"
40
#include "tgsi/tgsi_parse.h"
41
#include "tgsi/tgsi_util.h"
42
#include "tgsi/tgsi_scan.h"
43
 
44
 
45
 
46
 
47
/**
48
 * Scan the given TGSI shader to collect information such as number of
49
 * registers used, special instructions used, etc.
50
 * \return info  the result of the scan
51
 */
52
void
53
tgsi_scan_shader(const struct tgsi_token *tokens,
54
                 struct tgsi_shader_info *info)
55
{
56
   uint procType, i;
57
   struct tgsi_parse_context parse;
58
 
59
   memset(info, 0, sizeof(*info));
60
   for (i = 0; i < TGSI_FILE_COUNT; i++)
61
      info->file_max[i] = -1;
62
 
63
   /**
64
    ** Setup to begin parsing input shader
65
    **/
66
   if (tgsi_parse_init( &parse, tokens ) != TGSI_PARSE_OK) {
67
      debug_printf("tgsi_parse_init() failed in tgsi_scan_shader()!\n");
68
      return;
69
   }
70
   procType = parse.FullHeader.Processor.Processor;
71
   assert(procType == TGSI_PROCESSOR_FRAGMENT ||
72
          procType == TGSI_PROCESSOR_VERTEX ||
73
          procType == TGSI_PROCESSOR_GEOMETRY ||
74
          procType == TGSI_PROCESSOR_COMPUTE);
75
   info->processor = procType;
76
 
77
 
78
   /**
79
    ** Loop over incoming program tokens/instructions
80
    */
81
   while( !tgsi_parse_end_of_tokens( &parse ) ) {
82
 
83
      info->num_tokens++;
84
 
85
      tgsi_parse_token( &parse );
86
 
87
      switch( parse.FullToken.Token.Type ) {
88
      case TGSI_TOKEN_TYPE_INSTRUCTION:
89
         {
90
            const struct tgsi_full_instruction *fullinst
91
               = &parse.FullToken.FullInstruction;
92
            uint i;
93
 
94
            assert(fullinst->Instruction.Opcode < TGSI_OPCODE_LAST);
95
            info->opcode_count[fullinst->Instruction.Opcode]++;
96
 
97
            for (i = 0; i < fullinst->Instruction.NumSrcRegs; i++) {
98
               const struct tgsi_full_src_register *src =
99
                  &fullinst->Src[i];
100
               int ind = src->Register.Index;
101
 
102
               /* Mark which inputs are effectively used */
103
               if (src->Register.File == TGSI_FILE_INPUT) {
104
                  unsigned usage_mask;
105
                  usage_mask = tgsi_util_get_inst_usage_mask(fullinst, i);
106
                  if (src->Register.Indirect) {
107
                     for (ind = 0; ind < info->num_inputs; ++ind) {
108
                        info->input_usage_mask[ind] |= usage_mask;
109
                     }
110
                  } else {
111
                     assert(ind >= 0);
112
                     assert(ind < PIPE_MAX_SHADER_INPUTS);
113
                     info->input_usage_mask[ind] |= usage_mask;
114
                  }
115
 
116
                  if (procType == TGSI_PROCESSOR_FRAGMENT &&
117
                      src->Register.File == TGSI_FILE_INPUT &&
118
                      info->reads_position &&
119
                      src->Register.Index == 0 &&
120
                      (src->Register.SwizzleX == TGSI_SWIZZLE_Z ||
121
                       src->Register.SwizzleY == TGSI_SWIZZLE_Z ||
122
                       src->Register.SwizzleZ == TGSI_SWIZZLE_Z ||
123
                       src->Register.SwizzleW == TGSI_SWIZZLE_Z)) {
124
                     info->reads_z = TRUE;
125
                  }
126
               }
127
 
128
               /* check for indirect register reads */
129
               if (src->Register.Indirect) {
130
                  info->indirect_files |= (1 << src->Register.File);
131
               }
132
            }
133
 
134
            /* check for indirect register writes */
135
            for (i = 0; i < fullinst->Instruction.NumDstRegs; i++) {
136
               const struct tgsi_full_dst_register *dst = &fullinst->Dst[i];
137
               if (dst->Register.Indirect) {
138
                  info->indirect_files |= (1 << dst->Register.File);
139
               }
140
            }
141
 
142
            info->num_instructions++;
143
         }
144
         break;
145
 
146
      case TGSI_TOKEN_TYPE_DECLARATION:
147
         {
148
            const struct tgsi_full_declaration *fulldecl
149
               = &parse.FullToken.FullDeclaration;
150
            const uint file = fulldecl->Declaration.File;
151
            uint reg;
152
            for (reg = fulldecl->Range.First;
153
                 reg <= fulldecl->Range.Last;
154
                 reg++) {
155
 
156
               /* only first 32 regs will appear in this bitfield */
157
               info->file_mask[file] |= (1 << reg);
158
               info->file_count[file]++;
159
               info->file_max[file] = MAX2(info->file_max[file], (int)reg);
160
 
161
               if (file == TGSI_FILE_INPUT) {
162
                  info->input_semantic_name[reg] = (ubyte)fulldecl->Semantic.Name;
163
                  info->input_semantic_index[reg] = (ubyte)fulldecl->Semantic.Index;
164
                  info->input_interpolate[reg] = (ubyte)fulldecl->Interp.Interpolate;
165
                  info->input_centroid[reg] = (ubyte)fulldecl->Interp.Centroid;
166
                  info->input_cylindrical_wrap[reg] = (ubyte)fulldecl->Interp.CylindricalWrap;
167
                  info->num_inputs++;
168
 
169
                  if (procType == TGSI_PROCESSOR_FRAGMENT &&
170
                      fulldecl->Semantic.Name == TGSI_SEMANTIC_POSITION)
171
                        info->reads_position = TRUE;
172
               }
173
               else if (file == TGSI_FILE_SYSTEM_VALUE) {
174
                  unsigned index = fulldecl->Range.First;
175
                  unsigned semName = fulldecl->Semantic.Name;
176
 
177
                  info->system_value_semantic_name[index] = semName;
178
                  info->num_system_values = MAX2(info->num_system_values,
179
                                                 index + 1);
180
 
181
                  /*
182
                  info->system_value_semantic_name[info->num_system_values++] =
183
                     fulldecl->Semantic.Name;
184
                  */
185
 
186
                  if (fulldecl->Semantic.Name == TGSI_SEMANTIC_INSTANCEID) {
187
                     info->uses_instanceid = TRUE;
188
                  }
189
                  else if (fulldecl->Semantic.Name == TGSI_SEMANTIC_VERTEXID) {
190
                     info->uses_vertexid = TRUE;
191
                  } else if (fulldecl->Semantic.Name == TGSI_SEMANTIC_PRIMID) {
192
                     info->uses_primid = TRUE;
193
                  }
194
               }
195
               else if (file == TGSI_FILE_OUTPUT) {
196
                  info->output_semantic_name[reg] = (ubyte)fulldecl->Semantic.Name;
197
                  info->output_semantic_index[reg] = (ubyte)fulldecl->Semantic.Index;
198
                  info->num_outputs++;
199
 
200
                  if ((procType == TGSI_PROCESSOR_VERTEX || procType == TGSI_PROCESSOR_GEOMETRY) &&
201
                      fulldecl->Semantic.Name == TGSI_SEMANTIC_CLIPDIST) {
202
                     info->num_written_clipdistance += util_bitcount(fulldecl->Declaration.UsageMask);
203
                  }
204
                  if ((procType == TGSI_PROCESSOR_VERTEX || procType == TGSI_PROCESSOR_GEOMETRY) &&
205
                      fulldecl->Semantic.Name == TGSI_SEMANTIC_CULLDIST) {
206
                     info->num_written_culldistance += util_bitcount(fulldecl->Declaration.UsageMask);
207
                  }
208
                  /* extra info for special outputs */
209
                  if (procType == TGSI_PROCESSOR_FRAGMENT &&
210
                      fulldecl->Semantic.Name == TGSI_SEMANTIC_POSITION)
211
                        info->writes_z = TRUE;
212
                  if (procType == TGSI_PROCESSOR_FRAGMENT &&
213
                      fulldecl->Semantic.Name == TGSI_SEMANTIC_STENCIL)
214
                        info->writes_stencil = TRUE;
215
                  if (procType == TGSI_PROCESSOR_VERTEX &&
216
                      fulldecl->Semantic.Name == TGSI_SEMANTIC_EDGEFLAG) {
217
                     info->writes_edgeflag = TRUE;
218
                  }
219
 
220
                  if (procType == TGSI_PROCESSOR_GEOMETRY &&
221
                      fulldecl->Semantic.Name ==
222
                      TGSI_SEMANTIC_VIEWPORT_INDEX) {
223
                     info->writes_viewport_index = TRUE;
224
                  }
225
                  if (procType == TGSI_PROCESSOR_GEOMETRY &&
226
                      fulldecl->Semantic.Name ==
227
                      TGSI_SEMANTIC_LAYER) {
228
                     info->writes_layer = TRUE;
229
                  }
230
               }
231
 
232
             }
233
         }
234
         break;
235
 
236
      case TGSI_TOKEN_TYPE_IMMEDIATE:
237
         {
238
            uint reg = info->immediate_count++;
239
            uint file = TGSI_FILE_IMMEDIATE;
240
 
241
            info->file_mask[file] |= (1 << reg);
242
            info->file_count[file]++;
243
            info->file_max[file] = MAX2(info->file_max[file], (int)reg);
244
         }
245
         break;
246
 
247
      case TGSI_TOKEN_TYPE_PROPERTY:
248
         {
249
            const struct tgsi_full_property *fullprop
250
               = &parse.FullToken.FullProperty;
251
 
252
            info->properties[info->num_properties].name =
253
               fullprop->Property.PropertyName;
254
            memcpy(info->properties[info->num_properties].data,
255
                   fullprop->u, 8 * sizeof(unsigned));;
256
 
257
            ++info->num_properties;
258
         }
259
         break;
260
 
261
      default:
262
         assert( 0 );
263
      }
264
   }
265
 
266
   info->uses_kill = (info->opcode_count[TGSI_OPCODE_KILL_IF] ||
267
                      info->opcode_count[TGSI_OPCODE_KILL]);
268
 
269
   /* extract simple properties */
270
   for (i = 0; i < info->num_properties; ++i) {
271
      switch (info->properties[i].name) {
272
      case TGSI_PROPERTY_FS_COORD_ORIGIN:
273
         info->origin_lower_left = info->properties[i].data[0];
274
         break;
275
      case TGSI_PROPERTY_FS_COORD_PIXEL_CENTER:
276
         info->pixel_center_integer = info->properties[i].data[0];
277
         break;
278
      case TGSI_PROPERTY_FS_COLOR0_WRITES_ALL_CBUFS:
279
         info->color0_writes_all_cbufs = info->properties[i].data[0];
280
         break;
281
      case TGSI_PROPERTY_GS_INPUT_PRIM:
282
         /* The dimensions of the IN decleration in geometry shader have
283
          * to be deduced from the type of the input primitive.
284
          */
285
         if (procType == TGSI_PROCESSOR_GEOMETRY) {
286
            unsigned input_primitive = info->properties[i].data[0];
287
            int num_verts = u_vertices_per_prim(input_primitive);
288
            int j;
289
            info->file_count[TGSI_FILE_INPUT] = num_verts;
290
            info->file_max[TGSI_FILE_INPUT] =
291
               MAX2(info->file_max[TGSI_FILE_INPUT], num_verts - 1);
292
            for (j = 0; j < num_verts; ++j) {
293
               info->file_mask[TGSI_FILE_INPUT] |= (1 << j);
294
            }
295
         }
296
         break;
297
      default:
298
         ;
299
      }
300
   }
301
 
302
   tgsi_parse_free (&parse);
303
}
304
 
305
 
306
 
307
/**
308
 * Check if the given shader is a "passthrough" shader consisting of only
309
 * MOV instructions of the form:  MOV OUT[n], IN[n]
310
 *
311
 */
312
boolean
313
tgsi_is_passthrough_shader(const struct tgsi_token *tokens)
314
{
315
   struct tgsi_parse_context parse;
316
 
317
   /**
318
    ** Setup to begin parsing input shader
319
    **/
320
   if (tgsi_parse_init(&parse, tokens) != TGSI_PARSE_OK) {
321
      debug_printf("tgsi_parse_init() failed in tgsi_is_passthrough_shader()!\n");
322
      return FALSE;
323
   }
324
 
325
   /**
326
    ** Loop over incoming program tokens/instructions
327
    */
328
   while (!tgsi_parse_end_of_tokens(&parse)) {
329
 
330
      tgsi_parse_token(&parse);
331
 
332
      switch (parse.FullToken.Token.Type) {
333
      case TGSI_TOKEN_TYPE_INSTRUCTION:
334
         {
335
            struct tgsi_full_instruction *fullinst =
336
               &parse.FullToken.FullInstruction;
337
            const struct tgsi_full_src_register *src =
338
               &fullinst->Src[0];
339
            const struct tgsi_full_dst_register *dst =
340
               &fullinst->Dst[0];
341
 
342
            /* Do a whole bunch of checks for a simple move */
343
            if (fullinst->Instruction.Opcode != TGSI_OPCODE_MOV ||
344
                (src->Register.File != TGSI_FILE_INPUT &&
345
                 src->Register.File != TGSI_FILE_SYSTEM_VALUE) ||
346
                dst->Register.File != TGSI_FILE_OUTPUT ||
347
                src->Register.Index != dst->Register.Index ||
348
 
349
                src->Register.Negate ||
350
                src->Register.Absolute ||
351
 
352
                src->Register.SwizzleX != TGSI_SWIZZLE_X ||
353
                src->Register.SwizzleY != TGSI_SWIZZLE_Y ||
354
                src->Register.SwizzleZ != TGSI_SWIZZLE_Z ||
355
                src->Register.SwizzleW != TGSI_SWIZZLE_W ||
356
 
357
                dst->Register.WriteMask != TGSI_WRITEMASK_XYZW)
358
            {
359
               tgsi_parse_free(&parse);
360
               return FALSE;
361
            }
362
         }
363
         break;
364
 
365
      case TGSI_TOKEN_TYPE_DECLARATION:
366
         /* fall-through */
367
      case TGSI_TOKEN_TYPE_IMMEDIATE:
368
         /* fall-through */
369
      case TGSI_TOKEN_TYPE_PROPERTY:
370
         /* fall-through */
371
      default:
372
         ; /* no-op */
373
      }
374
   }
375
 
376
   tgsi_parse_free(&parse);
377
 
378
   /* if we get here, it's a pass-through shader */
379
   return TRUE;
380
}