tgsi_dump.c

Go to the documentation of this file.
00001 /**************************************************************************
00002  * 
00003  * Copyright 2007-2008 Tungsten Graphics, Inc., Cedar Park, Texas.
00004  * All Rights Reserved.
00005  * 
00006  * Permission is hereby granted, free of charge, to any person obtaining a
00007  * copy of this software and associated documentation files (the
00008  * "Software"), to deal in the Software without restriction, including
00009  * without limitation the rights to use, copy, modify, merge, publish,
00010  * distribute, sub license, and/or sell copies of the Software, and to
00011  * permit persons to whom the Software is furnished to do so, subject to
00012  * the following conditions:
00013  * 
00014  * The above copyright notice and this permission notice (including the
00015  * next paragraph) shall be included in all copies or substantial portions
00016  * of the Software.
00017  * 
00018  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
00019  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00020  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
00021  * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
00022  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
00023  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
00024  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00025  * 
00026  **************************************************************************/
00027 
00028 #include "pipe/p_debug.h"
00029 #include "util/u_string.h"
00030 #include "util/u_math.h"
00031 #include "tgsi_dump.h"
00032 #include "tgsi_info.h"
00033 #include "tgsi_iterate.h"
00034 
00035 struct dump_ctx
00036 {
00037    struct tgsi_iterate_context iter;
00038 
00039    uint instno;
00040    int indent;
00041    
00042    void (*printf)(struct dump_ctx *ctx, const char *format, ...);
00043 };
00044 
00045 static void 
00046 dump_ctx_printf(struct dump_ctx *ctx, const char *format, ...)
00047 {
00048    va_list ap;
00049    (void)ctx;
00050    va_start(ap, format);
00051    debug_vprintf(format, ap);
00052    va_end(ap);
00053 }
00054 
00055 static void
00056 dump_enum(
00057    struct dump_ctx *ctx,
00058    uint e,
00059    const char **enums,
00060    uint enum_count )
00061 {
00062    if (e >= enum_count)
00063       ctx->printf( ctx, "%u", e );
00064    else
00065       ctx->printf( ctx, "%s", enums[e] );
00066 }
00067 
00068 #define EOL()           ctx->printf( ctx, "\n" )
00069 #define TXT(S)          ctx->printf( ctx, "%s", S )
00070 #define CHR(C)          ctx->printf( ctx, "%c", C )
00071 #define UIX(I)          ctx->printf( ctx, "0x%x", I )
00072 #define UID(I)          ctx->printf( ctx, "%u", I )
00073 #define INSTID(I)          ctx->printf( ctx, "% 3u", I )
00074 #define SID(I)          ctx->printf( ctx, "%d", I )
00075 #define FLT(F)          ctx->printf( ctx, "%10.4f", F )
00076 #define ENM(E,ENUMS)    dump_enum( ctx, E, ENUMS, sizeof( ENUMS ) / sizeof( *ENUMS ) )
00077 
00078 static const char *processor_type_names[] =
00079 {
00080    "FRAG",
00081    "VERT",
00082    "GEOM"
00083 };
00084 
00085 static const char *file_names[TGSI_FILE_COUNT] =
00086 {
00087    "NULL",
00088    "CONST",
00089    "IN",
00090    "OUT",
00091    "TEMP",
00092    "SAMP",
00093    "ADDR",
00094    "IMM",
00095    "LOOP"
00096 };
00097 
00098 static const char *interpolate_names[] =
00099 {
00100    "CONSTANT",
00101    "LINEAR",
00102    "PERSPECTIVE"
00103 };
00104 
00105 static const char *semantic_names[] =
00106 {
00107    "POSITION",
00108    "COLOR",
00109    "BCOLOR",
00110    "FOG",
00111    "PSIZE",
00112    "GENERIC",
00113    "NORMAL"
00114 };
00115 
00116 static const char *immediate_type_names[] =
00117 {
00118    "FLT32"
00119 };
00120 
00121 static const char *swizzle_names[] =
00122 {
00123    "x",
00124    "y",
00125    "z",
00126    "w"
00127 };
00128 
00129 static const char *texture_names[] =
00130 {
00131    "UNKNOWN",
00132    "1D",
00133    "2D",
00134    "3D",
00135    "CUBE",
00136    "RECT",
00137    "SHADOW1D",
00138    "SHADOW2D",
00139    "SHADOWRECT"
00140 };
00141 
00142 static const char *extswizzle_names[] =
00143 {
00144    "x",
00145    "y",
00146    "z",
00147    "w",
00148    "0",
00149    "1"
00150 };
00151 
00152 static const char *modulate_names[TGSI_MODULATE_COUNT] =
00153 {
00154    "",
00155    "_2X",
00156    "_4X",
00157    "_8X",
00158    "_D2",
00159    "_D4",
00160    "_D8"
00161 };
00162 
00163 static void
00164 _dump_register(
00165    struct dump_ctx *ctx,
00166    uint file,
00167    int first,
00168    int last )
00169 {
00170    ENM( file, file_names );
00171    CHR( '[' );
00172    SID( first );
00173    if (first != last) {
00174       TXT( ".." );
00175       SID( last );
00176    }
00177    CHR( ']' );
00178 }
00179 
00180 static void
00181 _dump_register_ind(
00182    struct dump_ctx *ctx,
00183    uint file,
00184    int index,
00185    uint ind_file,
00186    int ind_index,
00187    uint ind_swizzle )
00188 {
00189    ENM( file, file_names );
00190    CHR( '[' );
00191    ENM( ind_file, file_names );
00192    CHR( '[' );
00193    SID( ind_index );
00194    TXT( "]." );
00195    ENM( ind_swizzle, swizzle_names );
00196    if (index != 0) {
00197       if (index > 0)
00198          CHR( '+' );
00199       SID( index );
00200    }
00201    CHR( ']' );
00202 }
00203 
00204 static void
00205 _dump_writemask(
00206    struct dump_ctx *ctx,
00207    uint writemask )
00208 {
00209    if (writemask != TGSI_WRITEMASK_XYZW) {
00210       CHR( '.' );
00211       if (writemask & TGSI_WRITEMASK_X)
00212          CHR( 'x' );
00213       if (writemask & TGSI_WRITEMASK_Y)
00214          CHR( 'y' );
00215       if (writemask & TGSI_WRITEMASK_Z)
00216          CHR( 'z' );
00217       if (writemask & TGSI_WRITEMASK_W)
00218          CHR( 'w' );
00219    }
00220 }
00221 
00222 static boolean
00223 iter_declaration(
00224    struct tgsi_iterate_context *iter,
00225    struct tgsi_full_declaration *decl )
00226 {
00227    struct dump_ctx *ctx = (struct dump_ctx *)iter;
00228 
00229    TXT( "DCL " );
00230 
00231    _dump_register(
00232       ctx,
00233       decl->Declaration.File,
00234       decl->DeclarationRange.First,
00235       decl->DeclarationRange.Last );
00236    _dump_writemask(
00237       ctx,
00238       decl->Declaration.UsageMask );
00239 
00240    if (decl->Declaration.Semantic) {
00241       TXT( ", " );
00242       ENM( decl->Semantic.SemanticName, semantic_names );
00243       if (decl->Semantic.SemanticIndex != 0 ||
00244           decl->Semantic.SemanticName == TGSI_SEMANTIC_GENERIC) {
00245          CHR( '[' );
00246          UID( decl->Semantic.SemanticIndex );
00247          CHR( ']' );
00248       }
00249    }
00250 
00251    if (iter->processor.Processor == TGSI_PROCESSOR_FRAGMENT &&
00252        decl->Declaration.File == TGSI_FILE_INPUT)
00253    {
00254       TXT( ", " );
00255       ENM( decl->Declaration.Interpolate, interpolate_names );
00256    }
00257 
00258    if (decl->Declaration.Centroid) {
00259       TXT( ", CENTROID" );
00260    }
00261 
00262    if (decl->Declaration.Invariant) {
00263       TXT( ", INVARIANT" );
00264    }
00265 
00266    EOL();
00267 
00268    return TRUE;
00269 }
00270 
00271 void
00272 tgsi_dump_declaration(
00273    const struct tgsi_full_declaration *decl )
00274 {
00275    struct dump_ctx ctx;
00276 
00277    ctx.printf = dump_ctx_printf;
00278 
00279    iter_declaration( &ctx.iter, (struct tgsi_full_declaration *)decl );
00280 }
00281 
00282 static boolean
00283 iter_immediate(
00284    struct tgsi_iterate_context *iter,
00285    struct tgsi_full_immediate *imm )
00286 {
00287    struct dump_ctx *ctx = (struct dump_ctx *) iter;
00288 
00289    uint i;
00290 
00291    TXT( "IMM " );
00292    ENM( imm->Immediate.DataType, immediate_type_names );
00293 
00294    TXT( " { " );
00295    for (i = 0; i < imm->Immediate.Size - 1; i++) {
00296       switch (imm->Immediate.DataType) {
00297       case TGSI_IMM_FLOAT32:
00298          FLT( imm->u.ImmediateFloat32[i].Float );
00299          break;
00300       default:
00301          assert( 0 );
00302       }
00303 
00304       if (i < imm->Immediate.Size - 2)
00305          TXT( ", " );
00306    }
00307    TXT( " }" );
00308 
00309    EOL();
00310 
00311    return TRUE;
00312 }
00313 
00314 void
00315 tgsi_dump_immediate(
00316    const struct tgsi_full_immediate *imm )
00317 {
00318    struct dump_ctx ctx;
00319 
00320    ctx.printf = dump_ctx_printf;
00321 
00322    iter_immediate( &ctx.iter, (struct tgsi_full_immediate *)imm );
00323 }
00324 
00325 static boolean
00326 iter_instruction(
00327    struct tgsi_iterate_context *iter,
00328    struct tgsi_full_instruction *inst )
00329 {
00330    struct dump_ctx *ctx = (struct dump_ctx *) iter;
00331    uint instno = ctx->instno++;
00332    const struct tgsi_opcode_info *info = tgsi_get_opcode_info( inst->Instruction.Opcode );
00333    uint i;
00334    boolean first_reg = TRUE;
00335 
00336    INSTID( instno );
00337    TXT( ": " );
00338    
00339    ctx->indent -= info->pre_dedent;
00340    for(i = 0; (int)i < ctx->indent; ++i)
00341       TXT( "  " );
00342    ctx->indent += info->post_indent;
00343    
00344    TXT( info->mnemonic );
00345 
00346    switch (inst->Instruction.Saturate) {
00347    case TGSI_SAT_NONE:
00348       break;
00349    case TGSI_SAT_ZERO_ONE:
00350       TXT( "_SAT" );
00351       break;
00352    case TGSI_SAT_MINUS_PLUS_ONE:
00353       TXT( "_SATNV" );
00354       break;
00355    default:
00356       assert( 0 );
00357    }
00358 
00359    for (i = 0; i < inst->Instruction.NumDstRegs; i++) {
00360       const struct tgsi_full_dst_register *dst = &inst->FullDstRegisters[i];
00361 
00362       if (!first_reg)
00363          CHR( ',' );
00364       CHR( ' ' );
00365 
00366       _dump_register(
00367          ctx,
00368          dst->DstRegister.File,
00369          dst->DstRegister.Index,
00370          dst->DstRegister.Index );
00371       ENM( dst->DstRegisterExtModulate.Modulate, modulate_names );
00372       _dump_writemask( ctx, dst->DstRegister.WriteMask );
00373 
00374       first_reg = FALSE;
00375    }
00376 
00377    for (i = 0; i < inst->Instruction.NumSrcRegs; i++) {
00378       const struct tgsi_full_src_register *src = &inst->FullSrcRegisters[i];
00379 
00380       if (!first_reg)
00381          CHR( ',' );
00382       CHR( ' ' );
00383 
00384       if (src->SrcRegisterExtMod.Negate)
00385          TXT( "-(" );
00386       if (src->SrcRegisterExtMod.Absolute)
00387          CHR( '|' );
00388       if (src->SrcRegisterExtMod.Scale2X)
00389          TXT( "2*(" );
00390       if (src->SrcRegisterExtMod.Bias)
00391          CHR( '(' );
00392       if (src->SrcRegisterExtMod.Complement)
00393          TXT( "1-(" );
00394       if (src->SrcRegister.Negate)
00395          CHR( '-' );
00396 
00397       if (src->SrcRegister.Indirect) {
00398          _dump_register_ind(
00399             ctx,
00400             src->SrcRegister.File,
00401             src->SrcRegister.Index,
00402             src->SrcRegisterInd.File,
00403             src->SrcRegisterInd.Index,
00404             src->SrcRegisterInd.SwizzleX );
00405       }
00406       else {
00407          _dump_register(
00408             ctx,
00409             src->SrcRegister.File,
00410             src->SrcRegister.Index,
00411             src->SrcRegister.Index );
00412       }
00413 
00414       if (src->SrcRegister.SwizzleX != TGSI_SWIZZLE_X ||
00415           src->SrcRegister.SwizzleY != TGSI_SWIZZLE_Y ||
00416           src->SrcRegister.SwizzleZ != TGSI_SWIZZLE_Z ||
00417           src->SrcRegister.SwizzleW != TGSI_SWIZZLE_W) {
00418          CHR( '.' );
00419          ENM( src->SrcRegister.SwizzleX, swizzle_names );
00420          ENM( src->SrcRegister.SwizzleY, swizzle_names );
00421          ENM( src->SrcRegister.SwizzleZ, swizzle_names );
00422          ENM( src->SrcRegister.SwizzleW, swizzle_names );
00423       }
00424       if (src->SrcRegisterExtSwz.ExtSwizzleX != TGSI_EXTSWIZZLE_X ||
00425           src->SrcRegisterExtSwz.ExtSwizzleY != TGSI_EXTSWIZZLE_Y ||
00426           src->SrcRegisterExtSwz.ExtSwizzleZ != TGSI_EXTSWIZZLE_Z ||
00427           src->SrcRegisterExtSwz.ExtSwizzleW != TGSI_EXTSWIZZLE_W) {
00428          CHR( '.' );
00429          if (src->SrcRegisterExtSwz.NegateX)
00430             TXT("-");
00431          ENM( src->SrcRegisterExtSwz.ExtSwizzleX, extswizzle_names );
00432          if (src->SrcRegisterExtSwz.NegateY)
00433             TXT("-");
00434          ENM( src->SrcRegisterExtSwz.ExtSwizzleY, extswizzle_names );
00435          if (src->SrcRegisterExtSwz.NegateZ)
00436             TXT("-");
00437          ENM( src->SrcRegisterExtSwz.ExtSwizzleZ, extswizzle_names );
00438          if (src->SrcRegisterExtSwz.NegateW)
00439             TXT("-");
00440          ENM( src->SrcRegisterExtSwz.ExtSwizzleW, extswizzle_names );
00441       }
00442 
00443       if (src->SrcRegisterExtMod.Complement)
00444          CHR( ')' );
00445       if (src->SrcRegisterExtMod.Bias)
00446          TXT( ")-.5" );
00447       if (src->SrcRegisterExtMod.Scale2X)
00448          CHR( ')' );
00449       if (src->SrcRegisterExtMod.Absolute)
00450          CHR( '|' );
00451       if (src->SrcRegisterExtMod.Negate)
00452          CHR( ')' );
00453 
00454       first_reg = FALSE;
00455    }
00456 
00457    if (inst->InstructionExtTexture.Texture != TGSI_TEXTURE_UNKNOWN) {
00458       TXT( ", " );
00459       ENM( inst->InstructionExtTexture.Texture, texture_names );
00460    }
00461 
00462    switch (inst->Instruction.Opcode) {
00463    case TGSI_OPCODE_IF:
00464    case TGSI_OPCODE_ELSE:
00465    case TGSI_OPCODE_BGNLOOP2:
00466    case TGSI_OPCODE_ENDLOOP2:
00467    case TGSI_OPCODE_CAL:
00468       TXT( " :" );
00469       UID( inst->InstructionExtLabel.Label );
00470       break;
00471    }
00472 
00473    EOL();
00474 
00475    return TRUE;
00476 }
00477 
00478 void
00479 tgsi_dump_instruction(
00480    const struct tgsi_full_instruction *inst,
00481    uint instno )
00482 {
00483    struct dump_ctx ctx;
00484 
00485    ctx.instno = instno;
00486    ctx.indent = 0;
00487    ctx.printf = dump_ctx_printf;
00488 
00489    iter_instruction( &ctx.iter, (struct tgsi_full_instruction *)inst );
00490 }
00491 
00492 static boolean
00493 prolog(
00494    struct tgsi_iterate_context *iter )
00495 {
00496    struct dump_ctx *ctx = (struct dump_ctx *) iter;
00497    ENM( iter->processor.Processor, processor_type_names );
00498    UID( iter->version.MajorVersion );
00499    CHR( '.' );
00500    UID( iter->version.MinorVersion );
00501    EOL();
00502    return TRUE;
00503 }
00504 
00505 void
00506 tgsi_dump(
00507    const struct tgsi_token *tokens,
00508    uint flags )
00509 {
00510    struct dump_ctx ctx;
00511 
00512    ctx.iter.prolog = prolog;
00513    ctx.iter.iterate_instruction = iter_instruction;
00514    ctx.iter.iterate_declaration = iter_declaration;
00515    ctx.iter.iterate_immediate = iter_immediate;
00516    ctx.iter.epilog = NULL;
00517 
00518    ctx.instno = 0;
00519    ctx.indent = 0;
00520    ctx.printf = dump_ctx_printf;
00521 
00522    tgsi_iterate_shader( tokens, &ctx.iter );
00523 }
00524 
00525 struct str_dump_ctx
00526 {
00527    struct dump_ctx base;
00528    char *str;
00529    char *ptr;
00530    int left;
00531 };
00532 
00533 static void
00534 str_dump_ctx_printf(struct dump_ctx *ctx, const char *format, ...)
00535 {
00536    struct str_dump_ctx *sctx = (struct str_dump_ctx *)ctx;
00537    
00538    if(sctx->left > 1) {
00539       int written;
00540       va_list ap;
00541       va_start(ap, format);
00542       written = util_vsnprintf(sctx->ptr, sctx->left, format, ap);
00543       va_end(ap);
00544 
00545       /* Some complicated logic needed to handle the return value of
00546        * vsnprintf:
00547        */
00548       if (written > 0) {
00549          written = MIN2(sctx->left, written);
00550          sctx->ptr += written;
00551          sctx->left -= written;
00552       }
00553    }
00554 }
00555 
00556 void
00557 tgsi_dump_str(
00558    const struct tgsi_token *tokens,
00559    uint flags,
00560    char *str,
00561    size_t size)
00562 {
00563    struct str_dump_ctx ctx;
00564 
00565    ctx.base.iter.prolog = prolog;
00566    ctx.base.iter.iterate_instruction = iter_instruction;
00567    ctx.base.iter.iterate_declaration = iter_declaration;
00568    ctx.base.iter.iterate_immediate = iter_immediate;
00569    ctx.base.iter.epilog = NULL;
00570 
00571    ctx.base.instno = 0;
00572    ctx.base.indent = 0;
00573    ctx.base.printf = &str_dump_ctx_printf;
00574 
00575    ctx.str = str;
00576    ctx.str[0] = 0;
00577    ctx.ptr = str;
00578    ctx.left = (int)size;
00579 
00580    tgsi_iterate_shader( tokens, &ctx.base.iter );
00581 }

Generated on Tue Sep 29 06:25:15 2009 for Gallium3D by  doxygen 1.5.4