9.3 Using `lib3delight' to Interrogate Shaders
Shader interrogation is possible by using the shaderinfo command line tool (see section Using shaderinfo to Interrogate Shaders). It is also possible to "manually" interrogate shaders by using a number of calls implemented in `lib3delight'. The interrogating application should include `slo.h' (found in `$DELIGHT/include') and link with `lib3delight' (see section Linking with 3Delight).
Here is the complete list for shader interrogation calls:
- void Slo_SetPath ( char* i_path )
Set the paths where the library looks for shaders. It accepts a colon separated list of paths. Refer to Search Paths Options for more information on search paths which also applies to this function.
- int Slo_SetShader ( char* i_name )
Find and open the shader named i_name. Close any shader that was previously opened by
Slo_SetShader. Returns 0 when the shader was successfully loaded.
- SLO_TYPE Slo_GetType ( void )
Return the type of the currently opened shader. See the file `slo.h' for details about
SLO_TYPE.
- SLO_VISSYMDEF* Slo_GetArgById ( int i )
Return information about the i-th parameter of the shader. The first parameter has an id of 1. See `slo.h' for details about
SLO_VISSYMDEFstructure.
- SLO_VISSYMDEF* Slo_GetArgByName ( char *i_name )
Return information about the parameter named i_name. See the file `slo.h' for details about
SLO_VISSYMDEF.
- SLO_VISSYMDEF* Slo_GetArrayArgElement ( SLO_VISSYMDEF *i_array, int i_index )
If a parameter is an array (as specified by
Slo_GetArgById()orSlo_GetArgByName), each of its element should be accessed using this function.
- int Slo_GetNAnnotations ( void )
Return the number of annotations contained in this shader. Annotations are further discussed in Attaching annotations to shaders.
- char* Slo_GetAnnotationKeyById ( int i_id )
Returns an annotation key by it's index i_id. Acceptable indexes range from 1 to n, where n is the number of annotations available. Any index outside this range returns 0x0 (null pointer).
- char* Slo_GetAnnotationByKey ( const char *i_key )
Returns an annotation specified by it's key. If i_key doesn't refer to any annotation, 0 (null pointer) is returned. It is possible to retrieve the different possible keys with
Slo_GetAnnotationKeyById.
- char* Slo_StortoStr ( SLO_STORAGE i_storage )
Get a string representation of storage class i_storage.
- char* Slo_DetailtoStr ( SLO_DETAIL i_detail )
Get a string representation of variable detail i_detail.
Next is the complete source code of the shaderinfo utility, it is compilable on all supported platforms, see Linking with 3Delight.
/******************************************************************************/
/* */
/* Copyright (c)The 3Delight Team. */
/* All Rights Reserved. */
/* */
/******************************************************************************/
// ===========================================================================
// = VERSION
// $Revision$
// = DATE RELEASED
// $Date: 2009-01-07 22:54:15 -0500 (Wed, 07 Jan 2009) $
// = RCSID
// $Id: shaderinfo.cpp 11807 2009-01-08 03:54:15Z olivier $
// ===========================================================================
#include "slo.h"
#include "dlMsgShaderInfo.h"
#include "dlVersion.h"
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
typedef enum
{
e_prman = 1,
e_ribout,
e_table,
e_source,
e_annotations
} Format;
void PrintDefaultValue( SLO_VISSYMDEF* arg )
{
switch(arg->svd_type)
{
case SLO_TYPE_SCALAR:
printf( "%g", *arg->svd_default.scalarval );
break;
case SLO_TYPE_STRING:
printf( "%s", arg->svd_default.stringval );
break;
case SLO_TYPE_POINT:
case SLO_TYPE_COLOR:
case SLO_TYPE_VECTOR:
case SLO_TYPE_NORMAL:
printf( "%g %g %g",
arg->svd_default.pointval->xval,
arg->svd_default.pointval->yval,
arg->svd_default.pointval->zval );
break;
case SLO_TYPE_MATRIX:
{
unsigned i=0;
for( ; i < 15; ++i )
printf( "%g ", arg->svd_default.matrixval[i] );
printf( "%g", arg->svd_default.matrixval[i] );
break;
}
}
}
void printArgs( const Format i_format )
{
int j, k, kk;
if( i_format == e_table )
{
printf( "%d\n", Slo_GetNArgs() );
}
for( j = 0; j < Slo_GetNArgs(); j++ )
{
SLO_VISSYMDEF *parameter = Slo_GetArgById( j+1 );
if( !parameter || !parameter->svd_valisvalid )
{
fprintf( stderr, DlGetText(DlText_2259_param), j );
continue;
}
const char *storage = Slo_StortoStr( parameter->svd_storage );
const char *name = parameter->svd_name;
const char *detail = Slo_DetailtoStr( parameter->svd_detail );
const char *type = Slo_TypetoStr( parameter->svd_type );
unsigned arraylen = parameter->svd_arraylen;
bool is_array = arraylen > 0 || parameter->svd_default.scalarval == 0x0;
if( i_format == e_ribout )
{
/* Output a string suitable for RIB syntax */
if( !is_array )
printf( "Declare \"%s\" \"%s %s\"\n", name, detail, type );
else
printf( "Declare \"%s\" \"%s %s[%d]\"\n",
name, detail, type, arraylen );
continue;
}
else if( i_format == e_table )
{
printf( "%s,%s,%s,%s,%s,%d,",
name, storage, detail, type,
parameter->svd_spacename[0] ?
parameter->svd_spacename : "<none>",
arraylen );
/* Print all default values */
if( !is_array )
{
PrintDefaultValue( parameter );
}
else
{
for( int i = 0; i < parameter->svd_arraylen; i++ )
{
if( i != 0 )
{
printf( " " );
}
PrintDefaultValue( Slo_GetArrayArgElement(parameter, i) );
}
}
printf( "\n" );
continue;
}
assert( i_format == e_prman );
printf( " \"%s\" \"%s %s %s", name, storage, detail, type );
if( is_array )
{
if( arraylen == 0 )
printf( "[]" );
else
printf( "[%d]", arraylen );
}
printf( "\"\n" );
printf( "\t\t%s", DlGetText(DlText_1725_default) );
switch( parameter->svd_type )
{
case SLO_TYPE_COLOR:
// Even if color has a different spacename,
// it has been converted by evaluation.
printf( "\"rgb\" ");
break;
case SLO_TYPE_POINT:
case SLO_TYPE_VECTOR:
case SLO_TYPE_NORMAL:
case SLO_TYPE_MATRIX:
if( parameter->svd_spacename[0] != (char)0 )
printf( "\"%s\" ", parameter->svd_spacename );
break;
default:
break;
}
if( is_array )
{
printf( "{" );
}
int num_elements = is_array ? arraylen : 1;
for( k=0; k<num_elements; k++ )
{
SLO_VISSYMDEF *elem = Slo_GetArrayArgElement( parameter, k );
if( !elem )
{
printf( "<error>" );
continue;
}
switch( parameter->svd_type )
{
case SLO_TYPE_SCALAR:
printf( "%g", *elem->svd_default.scalarval );
break;
case SLO_TYPE_POINT:
case SLO_TYPE_VECTOR:
case SLO_TYPE_NORMAL:
case SLO_TYPE_COLOR:
printf( "[%g %g %g]",
elem->svd_default.pointval->xval,
elem->svd_default.pointval->yval,
elem->svd_default.pointval->zval );
break;
case SLO_TYPE_MATRIX:
printf( "[%g ", elem->svd_default.matrixval[0] );
for( kk = 1; kk < 15; kk++ )
printf( "%g ", elem->svd_default.matrixval[kk] );
printf( "%g]", elem->svd_default.matrixval[15] );
break;
case SLO_TYPE_STRING:
printf( "\"%s\"", elem->svd_default.stringval );
break;
default:
break;
}
if( k != (num_elements-1) )
{
printf( ", " );
}
}
if( is_array )
printf( "}" );
printf( "\n" );
}
if( i_format == e_prman )
{
printf( "\n" );
}
}
int main( int argc, char ** argv )
{
int i;
int exitCode = 0;
Format format = e_prman;
int start = 1;
/* DlDebug::InitErrorSignalsHandling(); */
if ( argc <= 1 || !strcmp(argv[1], "-h") || !strcmp(argv[1], "--help") )
{
printf(
"Usage: shaderinfo [<option>] [file1 ... fileN]\n"
"Options\n"
" -d : Outputs declarations in RIB format\n"
" -t : Outputs declarations in parsable table format\n"
" -a : Outputs available annotation keys\n"
" -source : Outputs shader's source (if embedded)\n"
" -v : Shows version to console\n"
" --version : Same as -v\n"
" -h : Shows this help\n\n"
"Notes:\n"
"- No arguments is the equivalent of passing -h\n"
"- All options are exclusive. Use no more than one\n"
"- The options -h, -v, and --version should not be used with shader names\n"
);
return 0;
}
if( argc == 2 && (!strcmp(argv[1], "-v") || !strcmp(argv[1], "--version")) )
{
const char* v = DlGetVersionString();
const char* copyright = DlGetCopyrightString();
fprintf(stderr, "shaderinfo version %s.\n%s\n", v, copyright);
return 0;
}
if ( argc == 1 )
{
start++;
}
else if (!strcmp(argv[1], "-d"))
{
format = e_ribout;
start++;
}
else if( !strcmp(argv[1], "-t") )
{
format = e_table;
start++;
}
else if (!strcmp(argv[1], "-a"))
{
format = e_annotations;
start++;
}
else if (!strcmp(argv[1], "-source"))
{
format = e_source;
start ++;
}
/*
Add '.' to the default path so shaders are still found in the current
directory even if the default path is modified not to include '.'
*/
Slo_SetPath( ".:@" );
for( i = start; i < argc; i++ )
{
int err = Slo_SetShader( argv[i] );
if( err != 0 )
{
fprintf( stderr, DlGetText(DlText_2260_open), argv[i], err );
exitCode = 1;
continue;
}
/* Print a header indicating which shader this is */
if( format == e_table )
{
printf( "%s\n%s\n",
Slo_GetName(), Slo_TypetoStr(Slo_GetType()) );
}
else if( format == e_prman )
{
printf( "\n%s \"%s\"\n",
Slo_TypetoStr(Slo_GetType()), Slo_GetName() );
}
else
{
printf( "%s %s\n",
Slo_TypetoStr(Slo_GetType()), Slo_GetName() );
}
if( format == e_annotations )
{
if( Slo_GetNAnnotations() == 0 )
{
fprintf( stderr, DlGetText(DlText_2261_nokey), argv[i] );
continue;
}
printf( "%d\n", Slo_GetNAnnotations() );
for( int id=0; id<Slo_GetNAnnotations(); id++ )
{
const char *key = Slo_GetAnnotationKeyById( id+1 );
if( !key )
{
assert( false );
fprintf(stderr, DlGetText(DlText_1727_nokey), id, argv[i]);
return 1;
}
const char *annotation = Slo_GetAnnotationByKey(key);
printf( "\"%s\" \"%s\"\n", key, annotation );
}
}
else if ( format == e_source )
{
const char *value = Slo_GetAnnotationByKey( "source" );
if( value )
{
printf( "%s\n", value );
}
else
{
fprintf( stderr, DlGetText(DlText_1796_no_source) );
}
}
else
{
printArgs( format );
}
Slo_EndShader();
}
return exitCode;
}
3Delight 8.5. Copyright 2000-2009 The 3Delight Team. All Rights Reserved.