tgsi_scan.c revision c8c2fc9a7a029bb61520973e55fb3cec18f13e20
12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)/**************************************************************************
22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *
32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * All Rights Reserved.
52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * Copyright 2008 VMware, Inc.  All rights Reserved.
62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *
72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * Permission is hereby granted, free of charge, to any person obtaining a
82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * copy of this software and associated documentation files (the
92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * "Software"), to deal in the Software without restriction, including
102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * without limitation the rights to use, copy, modify, merge, publish,
112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * distribute, sub license, and/or sell copies of the Software, and to
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * permit persons to whom the Software is furnished to do so, subject to
13868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) * the following conditions:
14c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) *
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * The above copyright notice and this permission notice (including the
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * next paragraph) shall be included in all copies or substantial portions
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * of the Software.
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) **************************************************************************/
28c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
29c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)/**
30c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * TGSI program scan utility.
31c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * Used to determine which registers and instructions are used by a shader.
32c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) *
33868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) * Authors:  Brian Paul
34868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) */
35868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
36868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
37868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "util/u_math.h"
38868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "tgsi/tgsi_parse.h"
39868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "tgsi/tgsi_util.h"
40868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "tgsi/tgsi_scan.h"
41868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
42868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
43868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
44868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
45868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)/**
46868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) * Scan the given TGSI shader to collect information such as number of
47868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) * registers used, special instructions used, etc.
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * \return info  the result of the scan
49868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) */
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void
51c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochtgsi_scan_shader(const struct tgsi_token *tokens,
52c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                 struct tgsi_shader_info *info)
53c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch{
54c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch   uint procType, i;
55c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch   struct tgsi_parse_context parse;
56a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
57a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)   memset(info, 0, sizeof(*info));
58a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)   for (i = 0; i < TGSI_FILE_COUNT; i++)
59a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      info->file_max[i] = -1;
60a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
61a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)   /**
62a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    ** Setup to begin parsing input shader
63a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    **/
64a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)   if (tgsi_parse_init( &parse, tokens ) != TGSI_PARSE_OK) {
65a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      debug_printf("tgsi_parse_init() failed in tgsi_scan_shader()!\n");
66a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      return;
67a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)   }
68a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)   procType = parse.FullHeader.Processor.Processor;
69a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)   assert(procType == TGSI_PROCESSOR_FRAGMENT ||
70a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)          procType == TGSI_PROCESSOR_VERTEX ||
71a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)          procType == TGSI_PROCESSOR_GEOMETRY);
72a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
73a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
74a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)   /**
75a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    ** Loop over incoming program tokens/instructions
76a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    */
77a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)   while( !tgsi_parse_end_of_tokens( &parse ) ) {
785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      info->num_tokens++;
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      tgsi_parse_token( &parse );
822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      switch( parse.FullToken.Token.Type ) {
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      case TGSI_TOKEN_TYPE_INSTRUCTION:
852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)         {
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            const struct tgsi_full_instruction *fullinst
872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)               = &parse.FullToken.FullInstruction;
882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            uint i;
892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            assert(fullinst->Instruction.Opcode < TGSI_OPCODE_LAST);
912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            info->opcode_count[fullinst->Instruction.Opcode]++;
922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            for (i = 0; i < fullinst->Instruction.NumSrcRegs; i++) {
942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)               const struct tgsi_full_src_register *src =
952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                  &fullinst->Src[i];
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)               int ind = src->Register.Index;
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)               /* Mark which inputs are effectively used */
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)               if (src->Register.File == TGSI_FILE_INPUT) {
1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                  unsigned usage_mask;
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                  usage_mask = tgsi_util_get_inst_usage_mask(fullinst, i);
1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                  if (src->Register.Indirect) {
1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     for (ind = 0; ind < info->num_inputs; ++ind) {
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                        info->input_usage_mask[ind] |= usage_mask;
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     }
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                  } else {
1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     assert(ind >= 0);
1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     assert(ind < PIPE_MAX_SHADER_INPUTS);
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     info->input_usage_mask[ind] |= usage_mask;
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                  }
1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                  if (procType == TGSI_PROCESSOR_FRAGMENT &&
113c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                      src->Register.File == TGSI_FILE_INPUT &&
114868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                      info->reads_position &&
115868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                      src->Register.Index == 0 &&
116868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                      (src->Register.SwizzleX == TGSI_SWIZZLE_Z ||
117868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                       src->Register.SwizzleY == TGSI_SWIZZLE_Z ||
1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                       src->Register.SwizzleZ == TGSI_SWIZZLE_Z ||
1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                       src->Register.SwizzleW == TGSI_SWIZZLE_Z)) {
1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     info->reads_z = TRUE;
1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                  }
122c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch               }
1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
124c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch               /* check for indirect register reads */
125a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)               if (src->Register.Indirect) {
1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                  info->indirect_files |= (1 << src->Register.File);
127a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)               }
1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            }
129c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
130c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch            /* check for indirect register writes */
131a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)            for (i = 0; i < fullinst->Instruction.NumDstRegs; i++) {
132a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)               const struct tgsi_full_dst_register *dst = &fullinst->Dst[i];
1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)               if (dst->Register.Indirect) {
1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                  info->indirect_files |= (1 << dst->Register.File);
1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)               }
136868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)            }
1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            info->num_instructions++;
1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)         }
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)         break;
141868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
142868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      case TGSI_TOKEN_TYPE_DECLARATION:
1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)         {
1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            const struct tgsi_full_declaration *fulldecl
1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)               = &parse.FullToken.FullDeclaration;
1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            const uint file = fulldecl->Declaration.File;
147c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch            uint reg;
148c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch            for (reg = fulldecl->Range.First;
149c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                 reg <= fulldecl->Range.Last;
150c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                 reg++) {
151c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
152c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch               /* only first 32 regs will appear in this bitfield */
153c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch               info->file_mask[file] |= (1 << reg);
154c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch               info->file_count[file]++;
155a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)               info->file_max[file] = MAX2(info->file_max[file], (int)reg);
1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
157a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)               if (file == TGSI_FILE_INPUT) {
1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                  info->input_semantic_name[reg] = (ubyte)fulldecl->Semantic.Name;
1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                  info->input_semantic_index[reg] = (ubyte)fulldecl->Semantic.Index;
1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                  info->input_interpolate[reg] = (ubyte)fulldecl->Declaration.Interpolate;
161a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)                  info->input_centroid[reg] = (ubyte)fulldecl->Declaration.Centroid;
162a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)                  info->input_cylindrical_wrap[reg] = (ubyte)fulldecl->Declaration.CylindricalWrap;
1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                  info->num_inputs++;
164a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                  if (procType == TGSI_PROCESSOR_FRAGMENT &&
1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                      fulldecl->Semantic.Name == TGSI_SEMANTIC_POSITION)
1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                        info->reads_position = TRUE;
1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)               }
1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)               else if (file == TGSI_FILE_SYSTEM_VALUE) {
1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                  unsigned index = fulldecl->Range.First;
1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                  unsigned semName = fulldecl->Semantic.Name;
1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                  info->system_value_semantic_name[index] = semName;
1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                  info->num_system_values = MAX2(info->num_system_values,
1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                                 index + 1);
1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                  /*
1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                  info->system_value_semantic_name[info->num_system_values++] =
1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     fulldecl->Semantic.Name;
1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                  */
181868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
182868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                  if (fulldecl->Semantic.Name == TGSI_SEMANTIC_INSTANCEID) {
183868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                     info->uses_instanceid = TRUE;
184868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                  }
185868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)               }
1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)               else if (file == TGSI_FILE_OUTPUT) {
1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                  info->output_semantic_name[reg] = (ubyte)fulldecl->Semantic.Name;
1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                  info->output_semantic_index[reg] = (ubyte)fulldecl->Semantic.Index;
1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                  info->num_outputs++;
1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                  /* extra info for special outputs */
192a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)                  if (procType == TGSI_PROCESSOR_FRAGMENT &&
193a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)                      fulldecl->Semantic.Name == TGSI_SEMANTIC_POSITION)
1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                        info->writes_z = TRUE;
195a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)                  if (procType == TGSI_PROCESSOR_FRAGMENT &&
1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                      fulldecl->Semantic.Name == TGSI_SEMANTIC_STENCIL)
197c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                        info->writes_stencil = TRUE;
198c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                  if (procType == TGSI_PROCESSOR_VERTEX &&
199a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)                      fulldecl->Semantic.Name == TGSI_SEMANTIC_EDGEFLAG) {
2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     info->writes_edgeflag = TRUE;
2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                  }
2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)               }
203c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
204c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch             }
205c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch         }
206c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch         break;
2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      case TGSI_TOKEN_TYPE_IMMEDIATE:
2095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)         {
210            uint reg = info->immediate_count++;
211            uint file = TGSI_FILE_IMMEDIATE;
212
213            info->file_mask[file] |= (1 << reg);
214            info->file_count[file]++;
215            info->file_max[file] = MAX2(info->file_max[file], (int)reg);
216         }
217         break;
218
219      case TGSI_TOKEN_TYPE_PROPERTY:
220         {
221            const struct tgsi_full_property *fullprop
222               = &parse.FullToken.FullProperty;
223
224            info->properties[info->num_properties].name =
225               fullprop->Property.PropertyName;
226            memcpy(info->properties[info->num_properties].data,
227                   fullprop->u, 8 * sizeof(unsigned));;
228
229            ++info->num_properties;
230         }
231         break;
232
233      default:
234         assert( 0 );
235      }
236   }
237
238   info->uses_kill = (info->opcode_count[TGSI_OPCODE_KIL] ||
239                      info->opcode_count[TGSI_OPCODE_KILP]);
240
241   /* extract simple properties */
242   for (i = 0; i < info->num_properties; ++i) {
243      switch (info->properties[i].name) {
244      case TGSI_PROPERTY_FS_COORD_ORIGIN:
245         info->origin_lower_left = info->properties[i].data[0];
246         break;
247      case TGSI_PROPERTY_FS_COORD_PIXEL_CENTER:
248         info->pixel_center_integer = info->properties[i].data[0];
249         break;
250      case TGSI_PROPERTY_FS_COLOR0_WRITES_ALL_CBUFS:
251         info->color0_writes_all_cbufs = info->properties[i].data[0];
252         break;
253      default:
254         ;
255      }
256   }
257
258   tgsi_parse_free (&parse);
259}
260
261
262
263/**
264 * Check if the given shader is a "passthrough" shader consisting of only
265 * MOV instructions of the form:  MOV OUT[n], IN[n]
266 *
267 */
268boolean
269tgsi_is_passthrough_shader(const struct tgsi_token *tokens)
270{
271   struct tgsi_parse_context parse;
272
273   /**
274    ** Setup to begin parsing input shader
275    **/
276   if (tgsi_parse_init(&parse, tokens) != TGSI_PARSE_OK) {
277      debug_printf("tgsi_parse_init() failed in tgsi_is_passthrough_shader()!\n");
278      return FALSE;
279   }
280
281   /**
282    ** Loop over incoming program tokens/instructions
283    */
284   while (!tgsi_parse_end_of_tokens(&parse)) {
285
286      tgsi_parse_token(&parse);
287
288      switch (parse.FullToken.Token.Type) {
289      case TGSI_TOKEN_TYPE_INSTRUCTION:
290         {
291            struct tgsi_full_instruction *fullinst =
292               &parse.FullToken.FullInstruction;
293            const struct tgsi_full_src_register *src =
294               &fullinst->Src[0];
295            const struct tgsi_full_dst_register *dst =
296               &fullinst->Dst[0];
297
298            /* Do a whole bunch of checks for a simple move */
299            if (fullinst->Instruction.Opcode != TGSI_OPCODE_MOV ||
300                (src->Register.File != TGSI_FILE_INPUT &&
301                 src->Register.File != TGSI_FILE_SYSTEM_VALUE) ||
302                dst->Register.File != TGSI_FILE_OUTPUT ||
303                src->Register.Index != dst->Register.Index ||
304
305                src->Register.Negate ||
306                src->Register.Absolute ||
307
308                src->Register.SwizzleX != TGSI_SWIZZLE_X ||
309                src->Register.SwizzleY != TGSI_SWIZZLE_Y ||
310                src->Register.SwizzleZ != TGSI_SWIZZLE_Z ||
311                src->Register.SwizzleW != TGSI_SWIZZLE_W ||
312
313                dst->Register.WriteMask != TGSI_WRITEMASK_XYZW)
314            {
315               tgsi_parse_free(&parse);
316               return FALSE;
317            }
318         }
319         break;
320
321      case TGSI_TOKEN_TYPE_DECLARATION:
322         /* fall-through */
323      case TGSI_TOKEN_TYPE_IMMEDIATE:
324         /* fall-through */
325      case TGSI_TOKEN_TYPE_PROPERTY:
326         /* fall-through */
327      default:
328         ; /* no-op */
329      }
330   }
331
332   tgsi_parse_free(&parse);
333
334   /* if we get here, it's a pass-through shader */
335   return TRUE;
336}
337