| /************************************************************************** |
| * |
| * Copyright 2007-2008 Tungsten Graphics, Inc., Cedar Park, Texas. |
| * 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. |
| * |
| **************************************************************************/ |
| |
| #include "util/u_debug.h" |
| #include "util/u_string.h" |
| #include "tgsi_dump_c.h" |
| #include "tgsi_build.h" |
| #include "tgsi_info.h" |
| #include "tgsi_parse.h" |
| |
| static void |
| dump_enum( |
| const unsigned e, |
| const char **enums, |
| const unsigned enums_count ) |
| { |
| if (e >= enums_count) { |
| debug_printf( "%u", e ); |
| } |
| else { |
| debug_printf( "%s", enums[e] ); |
| } |
| } |
| |
| #define EOL() debug_printf( "\n" ) |
| #define TXT(S) debug_printf( "%s", S ) |
| #define CHR(C) debug_printf( "%c", C ) |
| #define UIX(I) debug_printf( "0x%x", I ) |
| #define UID(I) debug_printf( "%u", I ) |
| #define SID(I) debug_printf( "%d", I ) |
| #define FLT(F) debug_printf( "%10.4f", F ) |
| #define ENM(E,ENUMS) dump_enum( E, ENUMS, sizeof( ENUMS ) / sizeof( *ENUMS ) ) |
| |
| static const char *TGSI_PROCESSOR_TYPES[] = |
| { |
| "PROCESSOR_FRAGMENT", |
| "PROCESSOR_VERTEX", |
| "PROCESSOR_GEOMETRY" |
| }; |
| |
| static const char *TGSI_TOKEN_TYPES[] = |
| { |
| "TOKEN_TYPE_DECLARATION", |
| "TOKEN_TYPE_IMMEDIATE", |
| "TOKEN_TYPE_INSTRUCTION" |
| }; |
| |
| static const char *TGSI_FILES[TGSI_FILE_COUNT] = |
| { |
| "FILE_NULL", |
| "FILE_CONSTANT", |
| "FILE_INPUT", |
| "FILE_OUTPUT", |
| "FILE_TEMPORARY", |
| "FILE_SAMPLER", |
| "FILE_ADDRESS", |
| "FILE_IMMEDIATE", |
| "FILE_LOOP", |
| "FILE_PREDICATE" |
| }; |
| |
| static const char *TGSI_INTERPOLATES[] = |
| { |
| "INTERPOLATE_CONSTANT", |
| "INTERPOLATE_LINEAR", |
| "INTERPOLATE_PERSPECTIVE" |
| }; |
| |
| static const char *TGSI_SEMANTICS[] = |
| { |
| "SEMANTIC_POSITION", |
| "SEMANTIC_COLOR", |
| "SEMANTIC_BCOLOR", |
| "SEMANTIC_FOG", |
| "SEMANTIC_PSIZE", |
| "SEMANTIC_GENERIC", |
| "SEMANTIC_NORMAL" |
| }; |
| |
| static const char *TGSI_IMMS[] = |
| { |
| "IMM_FLOAT32" |
| }; |
| |
| static const char *TGSI_SATS[] = |
| { |
| "SAT_NONE", |
| "SAT_ZERO_ONE", |
| "SAT_MINUS_PLUS_ONE" |
| }; |
| |
| static const char *TGSI_INSTRUCTION_EXTS[] = |
| { |
| "", |
| "INSTRUCTION_EXT_TYPE_LABEL", |
| "INSTRUCTION_EXT_TYPE_TEXTURE" |
| }; |
| |
| static const char *TGSI_SWIZZLES[] = |
| { |
| "SWIZZLE_X", |
| "SWIZZLE_Y", |
| "SWIZZLE_Z", |
| "SWIZZLE_W" |
| }; |
| |
| static const char *TGSI_TEXTURES[] = |
| { |
| "TEXTURE_UNKNOWN", |
| "TEXTURE_1D", |
| "TEXTURE_2D", |
| "TEXTURE_3D", |
| "TEXTURE_CUBE", |
| "TEXTURE_RECT", |
| "TEXTURE_SHADOW1D", |
| "TEXTURE_SHADOW2D", |
| "TEXTURE_SHADOWRECT" |
| }; |
| |
| static const char *TGSI_SRC_REGISTER_EXTS[] = |
| { |
| "", |
| "SRC_REGISTER_EXT_TYPE_MOD" |
| }; |
| |
| static const char *TGSI_WRITEMASKS[] = |
| { |
| "0", |
| "WRITEMASK_X", |
| "WRITEMASK_Y", |
| "WRITEMASK_XY", |
| "WRITEMASK_Z", |
| "WRITEMASK_XZ", |
| "WRITEMASK_YZ", |
| "WRITEMASK_XYZ", |
| "WRITEMASK_W", |
| "WRITEMASK_XW", |
| "WRITEMASK_YW", |
| "WRITEMASK_XYW", |
| "WRITEMASK_ZW", |
| "WRITEMASK_XZW", |
| "WRITEMASK_YZW", |
| "WRITEMASK_XYZW" |
| }; |
| |
| static const char *TGSI_DST_REGISTER_EXTS[] = |
| { |
| "", |
| "DST_REGISTER_EXT_TYPE_MODULATE" |
| }; |
| |
| static const char *TGSI_MODULATES[] = |
| { |
| "MODULATE_1X", |
| "MODULATE_2X", |
| "MODULATE_4X", |
| "MODULATE_8X", |
| "MODULATE_HALF", |
| "MODULATE_QUARTER", |
| "MODULATE_EIGHTH" |
| }; |
| |
| static void |
| dump_declaration_verbose( |
| struct tgsi_full_declaration *decl, |
| unsigned ignored, |
| unsigned deflt, |
| struct tgsi_full_declaration *fd ) |
| { |
| TXT( "\nFile : " ); |
| ENM( decl->Declaration.File, TGSI_FILES ); |
| if( deflt || fd->Declaration.UsageMask != decl->Declaration.UsageMask ) { |
| TXT( "\nUsageMask : " ); |
| if( decl->Declaration.UsageMask & TGSI_WRITEMASK_X ) { |
| CHR( 'X' ); |
| } |
| if( decl->Declaration.UsageMask & TGSI_WRITEMASK_Y ) { |
| CHR( 'Y' ); |
| } |
| if( decl->Declaration.UsageMask & TGSI_WRITEMASK_Z ) { |
| CHR( 'Z' ); |
| } |
| if( decl->Declaration.UsageMask & TGSI_WRITEMASK_W ) { |
| CHR( 'W' ); |
| } |
| } |
| if( deflt || fd->Declaration.Interpolate != decl->Declaration.Interpolate ) { |
| TXT( "\nInterpolate: " ); |
| ENM( decl->Declaration.Interpolate, TGSI_INTERPOLATES ); |
| } |
| if( deflt || fd->Declaration.Semantic != decl->Declaration.Semantic ) { |
| TXT( "\nSemantic : " ); |
| UID( decl->Declaration.Semantic ); |
| } |
| if( ignored ) { |
| TXT( "\nPadding : " ); |
| UIX( decl->Declaration.Padding ); |
| } |
| |
| EOL(); |
| TXT( "\nFirst: " ); |
| UID( decl->DeclarationRange.First ); |
| TXT( "\nLast : " ); |
| UID( decl->DeclarationRange.Last ); |
| |
| if( decl->Declaration.Semantic ) { |
| EOL(); |
| TXT( "\nSemanticName : " ); |
| ENM( decl->Semantic.SemanticName, TGSI_SEMANTICS ); |
| TXT( "\nSemanticIndex: " ); |
| UID( decl->Semantic.SemanticIndex ); |
| if( ignored ) { |
| TXT( "\nPadding : " ); |
| UIX( decl->Semantic.Padding ); |
| } |
| } |
| } |
| |
| static void |
| dump_immediate_verbose( |
| struct tgsi_full_immediate *imm, |
| unsigned ignored ) |
| { |
| unsigned i; |
| |
| TXT( "\nDataType : " ); |
| ENM( imm->Immediate.DataType, TGSI_IMMS ); |
| if( ignored ) { |
| TXT( "\nPadding : " ); |
| UIX( imm->Immediate.Padding ); |
| } |
| |
| assert( imm->Immediate.NrTokens <= 4 + 1 ); |
| for( i = 0; i < imm->Immediate.NrTokens - 1; i++ ) { |
| EOL(); |
| switch( imm->Immediate.DataType ) { |
| case TGSI_IMM_FLOAT32: |
| TXT( "\nFloat: " ); |
| FLT( imm->u[i].Float ); |
| break; |
| |
| default: |
| assert( 0 ); |
| } |
| } |
| } |
| |
| static void |
| dump_instruction_verbose( |
| struct tgsi_full_instruction *inst, |
| unsigned ignored, |
| unsigned deflt, |
| struct tgsi_full_instruction *fi ) |
| { |
| unsigned i; |
| |
| TXT( "\nOpcode : OPCODE_" ); |
| TXT( tgsi_get_opcode_info( inst->Instruction.Opcode )->mnemonic ); |
| if( deflt || fi->Instruction.Saturate != inst->Instruction.Saturate ) { |
| TXT( "\nSaturate : " ); |
| ENM( inst->Instruction.Saturate, TGSI_SATS ); |
| } |
| if( deflt || fi->Instruction.NumDstRegs != inst->Instruction.NumDstRegs ) { |
| TXT( "\nNumDstRegs : " ); |
| UID( inst->Instruction.NumDstRegs ); |
| } |
| if( deflt || fi->Instruction.NumSrcRegs != inst->Instruction.NumSrcRegs ) { |
| TXT( "\nNumSrcRegs : " ); |
| UID( inst->Instruction.NumSrcRegs ); |
| } |
| if( ignored ) { |
| TXT( "\nPadding : " ); |
| UIX( inst->Instruction.Padding ); |
| } |
| |
| if( deflt || tgsi_compare_instruction_ext_label( inst->InstructionExtLabel, fi->InstructionExtLabel ) ) { |
| EOL(); |
| TXT( "\nType : " ); |
| ENM( inst->InstructionExtLabel.Type, TGSI_INSTRUCTION_EXTS ); |
| if( deflt || fi->InstructionExtLabel.Label != inst->InstructionExtLabel.Label ) { |
| TXT( "\nLabel : " ); |
| UID( inst->InstructionExtLabel.Label ); |
| } |
| if( ignored ) { |
| TXT( "\nPadding : " ); |
| UIX( inst->InstructionExtLabel.Padding ); |
| if( deflt || fi->InstructionExtLabel.Extended != inst->InstructionExtLabel.Extended ) { |
| TXT( "\nExtended: " ); |
| UID( inst->InstructionExtLabel.Extended ); |
| } |
| } |
| } |
| |
| if( deflt || tgsi_compare_instruction_ext_texture( inst->InstructionExtTexture, fi->InstructionExtTexture ) ) { |
| EOL(); |
| TXT( "\nType : " ); |
| ENM( inst->InstructionExtTexture.Type, TGSI_INSTRUCTION_EXTS ); |
| if( deflt || fi->InstructionExtTexture.Texture != inst->InstructionExtTexture.Texture ) { |
| TXT( "\nTexture : " ); |
| ENM( inst->InstructionExtTexture.Texture, TGSI_TEXTURES ); |
| } |
| if( ignored ) { |
| TXT( "\nPadding : " ); |
| UIX( inst->InstructionExtTexture.Padding ); |
| if( deflt || fi->InstructionExtTexture.Extended != inst->InstructionExtTexture.Extended ) { |
| TXT( "\nExtended: " ); |
| UID( inst->InstructionExtTexture.Extended ); |
| } |
| } |
| } |
| |
| for( i = 0; i < inst->Instruction.NumDstRegs; i++ ) { |
| struct tgsi_full_dst_register *dst = &inst->FullDstRegisters[i]; |
| struct tgsi_full_dst_register *fd = &fi->FullDstRegisters[i]; |
| |
| EOL(); |
| TXT( "\nFile : " ); |
| ENM( dst->DstRegister.File, TGSI_FILES ); |
| if( deflt || fd->DstRegister.WriteMask != dst->DstRegister.WriteMask ) { |
| TXT( "\nWriteMask: " ); |
| ENM( dst->DstRegister.WriteMask, TGSI_WRITEMASKS ); |
| } |
| if( ignored ) { |
| if( deflt || fd->DstRegister.Indirect != dst->DstRegister.Indirect ) { |
| TXT( "\nIndirect : " ); |
| UID( dst->DstRegister.Indirect ); |
| } |
| if( deflt || fd->DstRegister.Dimension != dst->DstRegister.Dimension ) { |
| TXT( "\nDimension: " ); |
| UID( dst->DstRegister.Dimension ); |
| } |
| } |
| if( deflt || fd->DstRegister.Index != dst->DstRegister.Index ) { |
| TXT( "\nIndex : " ); |
| SID( dst->DstRegister.Index ); |
| } |
| if( ignored ) { |
| TXT( "\nPadding : " ); |
| UIX( dst->DstRegister.Padding ); |
| if( deflt || fd->DstRegister.Extended != dst->DstRegister.Extended ) { |
| TXT( "\nExtended : " ); |
| UID( dst->DstRegister.Extended ); |
| } |
| } |
| |
| if( deflt || tgsi_compare_dst_register_ext_modulate( dst->DstRegisterExtModulate, fd->DstRegisterExtModulate ) ) { |
| EOL(); |
| TXT( "\nType : " ); |
| ENM( dst->DstRegisterExtModulate.Type, TGSI_DST_REGISTER_EXTS ); |
| if( deflt || fd->DstRegisterExtModulate.Modulate != dst->DstRegisterExtModulate.Modulate ) { |
| TXT( "\nModulate: " ); |
| ENM( dst->DstRegisterExtModulate.Modulate, TGSI_MODULATES ); |
| } |
| if( ignored ) { |
| TXT( "\nPadding : " ); |
| UIX( dst->DstRegisterExtModulate.Padding ); |
| if( deflt || fd->DstRegisterExtModulate.Extended != dst->DstRegisterExtModulate.Extended ) { |
| TXT( "\nExtended: " ); |
| UID( dst->DstRegisterExtModulate.Extended ); |
| } |
| } |
| } |
| } |
| |
| for( i = 0; i < inst->Instruction.NumSrcRegs; i++ ) { |
| struct tgsi_full_src_register *src = &inst->FullSrcRegisters[i]; |
| struct tgsi_full_src_register *fs = &fi->FullSrcRegisters[i]; |
| |
| EOL(); |
| TXT( "\nFile : "); |
| ENM( src->SrcRegister.File, TGSI_FILES ); |
| if( deflt || fs->SrcRegister.SwizzleX != src->SrcRegister.SwizzleX ) { |
| TXT( "\nSwizzleX : " ); |
| ENM( src->SrcRegister.SwizzleX, TGSI_SWIZZLES ); |
| } |
| if( deflt || fs->SrcRegister.SwizzleY != src->SrcRegister.SwizzleY ) { |
| TXT( "\nSwizzleY : " ); |
| ENM( src->SrcRegister.SwizzleY, TGSI_SWIZZLES ); |
| } |
| if( deflt || fs->SrcRegister.SwizzleZ != src->SrcRegister.SwizzleZ ) { |
| TXT( "\nSwizzleZ : " ); |
| ENM( src->SrcRegister.SwizzleZ, TGSI_SWIZZLES ); |
| } |
| if( deflt || fs->SrcRegister.SwizzleW != src->SrcRegister.SwizzleW ) { |
| TXT( "\nSwizzleW : " ); |
| ENM( src->SrcRegister.SwizzleW, TGSI_SWIZZLES ); |
| } |
| if( deflt || fs->SrcRegister.Negate != src->SrcRegister.Negate ) { |
| TXT( "\nNegate : " ); |
| UID( src->SrcRegister.Negate ); |
| } |
| if( ignored ) { |
| if( deflt || fs->SrcRegister.Indirect != src->SrcRegister.Indirect ) { |
| TXT( "\nIndirect : " ); |
| UID( src->SrcRegister.Indirect ); |
| } |
| if( deflt || fs->SrcRegister.Dimension != src->SrcRegister.Dimension ) { |
| TXT( "\nDimension: " ); |
| UID( src->SrcRegister.Dimension ); |
| } |
| } |
| if( deflt || fs->SrcRegister.Index != src->SrcRegister.Index ) { |
| TXT( "\nIndex : " ); |
| SID( src->SrcRegister.Index ); |
| } |
| if( ignored ) { |
| if( deflt || fs->SrcRegister.Extended != src->SrcRegister.Extended ) { |
| TXT( "\nExtended : " ); |
| UID( src->SrcRegister.Extended ); |
| } |
| } |
| |
| if( deflt || tgsi_compare_src_register_ext_mod( src->SrcRegisterExtMod, fs->SrcRegisterExtMod ) ) { |
| EOL(); |
| TXT( "\nType : " ); |
| ENM( src->SrcRegisterExtMod.Type, TGSI_SRC_REGISTER_EXTS ); |
| if( deflt || fs->SrcRegisterExtMod.Complement != src->SrcRegisterExtMod.Complement ) { |
| TXT( "\nComplement: " ); |
| UID( src->SrcRegisterExtMod.Complement ); |
| } |
| if( deflt || fs->SrcRegisterExtMod.Bias != src->SrcRegisterExtMod.Bias ) { |
| TXT( "\nBias : " ); |
| UID( src->SrcRegisterExtMod.Bias ); |
| } |
| if( deflt || fs->SrcRegisterExtMod.Scale2X != src->SrcRegisterExtMod.Scale2X ) { |
| TXT( "\nScale2X : " ); |
| UID( src->SrcRegisterExtMod.Scale2X ); |
| } |
| if( deflt || fs->SrcRegisterExtMod.Absolute != src->SrcRegisterExtMod.Absolute ) { |
| TXT( "\nAbsolute : " ); |
| UID( src->SrcRegisterExtMod.Absolute ); |
| } |
| if( deflt || fs->SrcRegisterExtMod.Negate != src->SrcRegisterExtMod.Negate ) { |
| TXT( "\nNegate : " ); |
| UID( src->SrcRegisterExtMod.Negate ); |
| } |
| if( ignored ) { |
| TXT( "\nPadding : " ); |
| UIX( src->SrcRegisterExtMod.Padding ); |
| if( deflt || fs->SrcRegisterExtMod.Extended != src->SrcRegisterExtMod.Extended ) { |
| TXT( "\nExtended : " ); |
| UID( src->SrcRegisterExtMod.Extended ); |
| } |
| } |
| } |
| } |
| } |
| |
| void |
| tgsi_dump_c( |
| const struct tgsi_token *tokens, |
| uint flags ) |
| { |
| struct tgsi_parse_context parse; |
| struct tgsi_full_instruction fi; |
| struct tgsi_full_declaration fd; |
| uint ignored = flags & TGSI_DUMP_C_IGNORED; |
| uint deflt = flags & TGSI_DUMP_C_DEFAULT; |
| |
| tgsi_parse_init( &parse, tokens ); |
| |
| TXT( "tgsi-dump begin -----------------" ); |
| |
| TXT( "\nMajorVersion: " ); |
| UID( parse.FullVersion.Version.MajorVersion ); |
| TXT( "\nMinorVersion: " ); |
| UID( parse.FullVersion.Version.MinorVersion ); |
| EOL(); |
| |
| TXT( "\nHeaderSize: " ); |
| UID( parse.FullHeader.Header.HeaderSize ); |
| TXT( "\nBodySize : " ); |
| UID( parse.FullHeader.Header.BodySize ); |
| TXT( "\nProcessor : " ); |
| ENM( parse.FullHeader.Processor.Processor, TGSI_PROCESSOR_TYPES ); |
| EOL(); |
| |
| fi = tgsi_default_full_instruction(); |
| fd = tgsi_default_full_declaration(); |
| |
| while( !tgsi_parse_end_of_tokens( &parse ) ) { |
| tgsi_parse_token( &parse ); |
| |
| TXT( "\nType : " ); |
| ENM( parse.FullToken.Token.Type, TGSI_TOKEN_TYPES ); |
| if( ignored ) { |
| TXT( "\nSize : " ); |
| UID( parse.FullToken.Token.NrTokens ); |
| if( deflt || parse.FullToken.Token.Extended ) { |
| TXT( "\nExtended : " ); |
| UID( parse.FullToken.Token.Extended ); |
| } |
| } |
| |
| switch( parse.FullToken.Token.Type ) { |
| case TGSI_TOKEN_TYPE_DECLARATION: |
| dump_declaration_verbose( |
| &parse.FullToken.FullDeclaration, |
| ignored, |
| deflt, |
| &fd ); |
| break; |
| |
| case TGSI_TOKEN_TYPE_IMMEDIATE: |
| dump_immediate_verbose( |
| &parse.FullToken.FullImmediate, |
| ignored ); |
| break; |
| |
| case TGSI_TOKEN_TYPE_INSTRUCTION: |
| dump_instruction_verbose( |
| &parse.FullToken.FullInstruction, |
| ignored, |
| deflt, |
| &fi ); |
| break; |
| |
| default: |
| assert( 0 ); |
| } |
| |
| EOL(); |
| } |
| |
| TXT( "\ntgsi-dump end -------------------\n" ); |
| |
| tgsi_parse_free( &parse ); |
| } |