00001 /************************************************************************** 00002 * 00003 * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. 00004 * All Rights Reserved. 00005 * Copyright 2008 VMware, Inc. All rights Reserved. 00006 * 00007 * Permission is hereby granted, free of charge, to any person obtaining a 00008 * copy of this software and associated documentation files (the 00009 * "Software"), to deal in the Software without restriction, including 00010 * without limitation the rights to use, copy, modify, merge, publish, 00011 * distribute, sub license, and/or sell copies of the Software, and to 00012 * permit persons to whom the Software is furnished to do so, subject to 00013 * the following conditions: 00014 * 00015 * The above copyright notice and this permission notice (including the 00016 * next paragraph) shall be included in all copies or substantial portions 00017 * of the Software. 00018 * 00019 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 00020 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 00021 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 00022 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR 00023 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 00024 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 00025 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 00026 * 00027 **************************************************************************/ 00028 00037 #include "util/u_math.h" 00038 #include "tgsi/tgsi_build.h" 00039 #include "tgsi/tgsi_parse.h" 00040 #include "tgsi/tgsi_scan.h" 00041 00042 00043 00044 00047 void 00048 tgsi_scan_shader(const struct tgsi_token *tokens, 00049 struct tgsi_shader_info *info) 00050 { 00051 uint procType, i; 00052 struct tgsi_parse_context parse; 00053 00054 memset(info, 0, sizeof(*info)); 00055 for (i = 0; i < TGSI_FILE_COUNT; i++) 00056 info->file_max[i] = -1; 00057 00061 if (tgsi_parse_init( &parse, tokens ) != TGSI_PARSE_OK) { 00062 debug_printf("tgsi_parse_init() failed in tgsi_scan_shader()!\n"); 00063 return; 00064 } 00065 procType = parse.FullHeader.Processor.Processor; 00066 assert(procType == TGSI_PROCESSOR_FRAGMENT || 00067 procType == TGSI_PROCESSOR_VERTEX || 00068 procType == TGSI_PROCESSOR_GEOMETRY); 00069 00070 00074 while( !tgsi_parse_end_of_tokens( &parse ) ) { 00075 00076 info->num_tokens++; 00077 00078 tgsi_parse_token( &parse ); 00079 00080 switch( parse.FullToken.Token.Type ) { 00081 case TGSI_TOKEN_TYPE_INSTRUCTION: 00082 { 00083 const struct tgsi_full_instruction *fullinst 00084 = &parse.FullToken.FullInstruction; 00085 00086 assert(fullinst->Instruction.Opcode < TGSI_OPCODE_LAST); 00087 info->opcode_count[fullinst->Instruction.Opcode]++; 00088 00089 /* special case: scan fragment shaders for use of the fog 00090 * input/attribute. The X component is fog, the Y component 00091 * is the front/back-face flag. 00092 */ 00093 if (procType == TGSI_PROCESSOR_FRAGMENT) { 00094 uint i; 00095 for (i = 0; i < fullinst->Instruction.NumSrcRegs; i++) { 00096 const struct tgsi_full_src_register *src = 00097 &fullinst->FullSrcRegisters[i]; 00098 if (src->SrcRegister.File == TGSI_FILE_INPUT) { 00099 const int ind = src->SrcRegister.Index; 00100 if (info->input_semantic_name[ind] == TGSI_SEMANTIC_FOG) { 00101 if (src->SrcRegister.SwizzleX == TGSI_SWIZZLE_X) { 00102 info->uses_fogcoord = TRUE; 00103 } 00104 else if (src->SrcRegister.SwizzleX == TGSI_SWIZZLE_Y) { 00105 info->uses_frontfacing = TRUE; 00106 } 00107 } 00108 } 00109 } 00110 } 00111 } 00112 break; 00113 00114 case TGSI_TOKEN_TYPE_DECLARATION: 00115 { 00116 const struct tgsi_full_declaration *fulldecl 00117 = &parse.FullToken.FullDeclaration; 00118 uint file = fulldecl->Declaration.File; 00119 uint reg; 00120 for (reg = fulldecl->DeclarationRange.First; 00121 reg <= fulldecl->DeclarationRange.Last; 00122 reg++) { 00123 00124 /* only first 32 regs will appear in this bitfield */ 00125 info->file_mask[file] |= (1 << reg); 00126 info->file_count[file]++; 00127 info->file_max[file] = MAX2(info->file_max[file], (int)reg); 00128 00129 if (file == TGSI_FILE_INPUT) { 00130 info->input_semantic_name[reg] = (ubyte)fulldecl->Semantic.SemanticName; 00131 info->input_semantic_index[reg] = (ubyte)fulldecl->Semantic.SemanticIndex; 00132 info->num_inputs++; 00133 } 00134 00135 if (file == TGSI_FILE_OUTPUT) { 00136 info->output_semantic_name[reg] = (ubyte)fulldecl->Semantic.SemanticName; 00137 info->output_semantic_index[reg] = (ubyte)fulldecl->Semantic.SemanticIndex; 00138 info->num_outputs++; 00139 } 00140 00141 /* special case */ 00142 if (procType == TGSI_PROCESSOR_FRAGMENT && 00143 file == TGSI_FILE_OUTPUT && 00144 fulldecl->Semantic.SemanticName == TGSI_SEMANTIC_POSITION) { 00145 info->writes_z = TRUE; 00146 } 00147 } 00148 } 00149 break; 00150 00151 case TGSI_TOKEN_TYPE_IMMEDIATE: 00152 info->immediate_count++; 00153 break; 00154 00155 default: 00156 assert( 0 ); 00157 } 00158 } 00159 00160 info->uses_kill = (info->opcode_count[TGSI_OPCODE_KIL] || 00161 info->opcode_count[TGSI_OPCODE_KILP]); 00162 00163 tgsi_parse_free (&parse); 00164 } 00165 00166 00167 00173 boolean 00174 tgsi_is_passthrough_shader(const struct tgsi_token *tokens) 00175 { 00176 struct tgsi_parse_context parse; 00177 00181 if (tgsi_parse_init(&parse, tokens) != TGSI_PARSE_OK) { 00182 debug_printf("tgsi_parse_init() failed in tgsi_is_passthrough_shader()!\n"); 00183 return FALSE; 00184 } 00185 00189 while (!tgsi_parse_end_of_tokens(&parse)) { 00190 00191 tgsi_parse_token(&parse); 00192 00193 switch (parse.FullToken.Token.Type) { 00194 case TGSI_TOKEN_TYPE_INSTRUCTION: 00195 { 00196 struct tgsi_full_instruction *fullinst = 00197 &parse.FullToken.FullInstruction; 00198 const struct tgsi_full_src_register *src = 00199 &fullinst->FullSrcRegisters[0]; 00200 const struct tgsi_full_dst_register *dst = 00201 &fullinst->FullDstRegisters[0]; 00202 00203 /* Do a whole bunch of checks for a simple move */ 00204 if (fullinst->Instruction.Opcode != TGSI_OPCODE_MOV || 00205 src->SrcRegister.File != TGSI_FILE_INPUT || 00206 dst->DstRegister.File != TGSI_FILE_OUTPUT || 00207 src->SrcRegister.Index != dst->DstRegister.Index || 00208 00209 src->SrcRegister.Negate || 00210 src->SrcRegisterExtMod.Negate || 00211 src->SrcRegisterExtMod.Absolute || 00212 src->SrcRegisterExtMod.Scale2X || 00213 src->SrcRegisterExtMod.Bias || 00214 src->SrcRegisterExtMod.Complement || 00215 00216 src->SrcRegister.SwizzleX != TGSI_SWIZZLE_X || 00217 src->SrcRegister.SwizzleY != TGSI_SWIZZLE_Y || 00218 src->SrcRegister.SwizzleZ != TGSI_SWIZZLE_Z || 00219 src->SrcRegister.SwizzleW != TGSI_SWIZZLE_W || 00220 00221 src->SrcRegisterExtSwz.ExtSwizzleX != TGSI_EXTSWIZZLE_X || 00222 src->SrcRegisterExtSwz.ExtSwizzleY != TGSI_EXTSWIZZLE_Y || 00223 src->SrcRegisterExtSwz.ExtSwizzleZ != TGSI_EXTSWIZZLE_Z || 00224 src->SrcRegisterExtSwz.ExtSwizzleW != TGSI_EXTSWIZZLE_W || 00225 00226 dst->DstRegister.WriteMask != TGSI_WRITEMASK_XYZW) 00227 { 00228 tgsi_parse_free(&parse); 00229 return FALSE; 00230 } 00231 } 00232 break; 00233 00234 case TGSI_TOKEN_TYPE_DECLARATION: 00235 /* fall-through */ 00236 case TGSI_TOKEN_TYPE_IMMEDIATE: 00237 /* fall-through */ 00238 default: 00239 ; /* no-op */ 00240 } 00241 } 00242 00243 tgsi_parse_free(&parse); 00244 00245 /* if we get here, it's a pass-through shader */ 00246 return TRUE; 00247 }