Show More
Commit Description:
Various UI improvements.
Commit Description:
Various UI improvements.
References:
File last commit:
Show/Diff file:
Action:
FNA/lib/MojoShader/utils/testparse.c
827 lines | 26.4 KiB | text/x-c | CLexer
827 lines | 26.4 KiB | text/x-c | CLexer
r0 | /** | |||
* MojoShader; generate shader programs from bytecode of compiled | ||||
* Direct3D shaders. | ||||
* | ||||
* Please see the file LICENSE.txt in the source's root directory. | ||||
* | ||||
* This file written by Ryan C. Gordon. | ||||
*/ | ||||
#include <stdio.h> | ||||
#include <stdlib.h> | ||||
#include <string.h> | ||||
#include <assert.h> | ||||
#include "../mojoshader.h" | ||||
#define __MOJOSHADER_INTERNAL__ 1 | ||||
#include "../mojoshader_internal.h" | ||||
#ifdef MOJOSHADER_HAS_SPIRV_TOOLS | ||||
#include "spirv-tools/libspirv.h" | ||||
#endif | ||||
#ifdef _MSC_VER | ||||
#define snprintf _snprintf | ||||
#endif | ||||
#if MOJOSHADER_DEBUG_MALLOC | ||||
static void *Malloc(int len) | ||||
{ | ||||
void *ptr = malloc(len + sizeof (int)); | ||||
int *store = (int *) ptr; | ||||
printf("malloc() %d bytes (%p)\n", len, ptr); | ||||
if (ptr == NULL) return NULL; | ||||
*store = len; | ||||
return (void *) (store + 1); | ||||
} // Malloc | ||||
static void Free(void *_ptr) | ||||
{ | ||||
int *ptr = (((int *) _ptr) - 1); | ||||
int len = *ptr; | ||||
printf("free() %d bytes (%p)\n", len, ptr); | ||||
free(ptr); | ||||
} // Free | ||||
#else | ||||
#define Malloc NULL | ||||
#define Free NULL | ||||
#endif | ||||
static inline void do_indent(const unsigned int indent) | ||||
{ | ||||
unsigned int i; | ||||
for (i = 0; i < indent; i++) | ||||
printf(" "); | ||||
} | ||||
#define INDENT() do { if (indent) { do_indent(indent); } } while (0) | ||||
static const char *shader_type(const MOJOSHADER_shaderType s) | ||||
{ | ||||
switch (s) | ||||
{ | ||||
case MOJOSHADER_TYPE_UNKNOWN: return "unknown"; | ||||
case MOJOSHADER_TYPE_PIXEL: return "pixel"; | ||||
case MOJOSHADER_TYPE_VERTEX: return "vertex"; | ||||
case MOJOSHADER_TYPE_GEOMETRY: return "geometry"; | ||||
default: return "(bogus value?)"; | ||||
} // switch | ||||
return NULL; // shouldn't hit this. | ||||
} // shader_type | ||||
static void print_typeinfo(const MOJOSHADER_symbolTypeInfo *info, | ||||
unsigned int indent) | ||||
{ | ||||
static const char *symclasses[] = { | ||||
"scalar", "vector", "row-major matrix", | ||||
"column-major matrix", "object", "struct" | ||||
}; | ||||
static const char *symtypes[] = { | ||||
"void", "bool", "int", "float", "string", "texture", | ||||
"texture1d", "texture2d", "texture3d", "texturecube", | ||||
"sampler", "sampler1d", "sampler2d", "sampler3d", | ||||
"samplercube", "pixelshader", "vertexshader", "unsupported" | ||||
}; | ||||
INDENT(); | ||||
printf(" symbol class %s\n", symclasses[info->parameter_class]); | ||||
INDENT(); | ||||
printf(" symbol type %s\n", symtypes[info->parameter_type]); | ||||
INDENT(); | ||||
printf(" rows %u\n", info->rows); | ||||
INDENT(); | ||||
printf(" columns %u\n", info->columns); | ||||
INDENT(); | ||||
printf(" elements %u\n", info->elements); | ||||
if (info->member_count > 0) | ||||
{ | ||||
int i; | ||||
INDENT(); printf(" MEMBERS:\n"); | ||||
for (i = 0; i < info->member_count; i++) | ||||
{ | ||||
const MOJOSHADER_symbolStructMember *member = &info->members[i]; | ||||
INDENT(); printf(" MEMBERS:\n"); | ||||
indent++; | ||||
INDENT(); printf(" * %d: \"%s\"\n", i, member->name); | ||||
print_typeinfo(&member->info, indent); | ||||
indent--; | ||||
} // for | ||||
} // if | ||||
} // print_typeinfo | ||||
static void print_symbols(const MOJOSHADER_symbol *sym, | ||||
const unsigned int symbol_count, | ||||
const unsigned int indent) | ||||
{ | ||||
INDENT(); printf("SYMBOLS:"); | ||||
if (symbol_count == 0) | ||||
printf(" (none.)\n"); | ||||
else | ||||
{ | ||||
int i; | ||||
printf("\n"); | ||||
for (i = 0; i < symbol_count; i++, sym++) | ||||
{ | ||||
static const char *regsets[] = { | ||||
"bool", "int4", "float4", "sampler" | ||||
}; | ||||
INDENT(); printf(" * %d: \"%s\"\n", i, sym->name); | ||||
INDENT(); printf(" register set %s\n", regsets[sym->register_set]); | ||||
INDENT(); printf(" register index %u\n", sym->register_index); | ||||
INDENT(); printf(" register count %u\n", sym->register_count); | ||||
print_typeinfo(&sym->info, indent); | ||||
} // for | ||||
printf("\n"); | ||||
} // else | ||||
} // print_symbols | ||||
static void print_preshader_operand(const MOJOSHADER_preshader *preshader, | ||||
const int instidx, const int opidx) | ||||
{ | ||||
static char mask[] = { 'x', 'y', 'z', 'w' }; | ||||
const MOJOSHADER_preshaderInstruction *inst = &preshader->instructions[instidx]; | ||||
const MOJOSHADER_preshaderOperand *operand = &inst->operands[opidx]; | ||||
const int elems = inst->element_count; | ||||
const int isscalarop = (inst->opcode >= MOJOSHADER_PRESHADEROP_SCALAR_OPS); | ||||
const int isscalar = ((isscalarop) && (opidx == 0)); // probably wrong. | ||||
int i; | ||||
switch (operand->type) | ||||
{ | ||||
case MOJOSHADER_PRESHADEROPERAND_LITERAL: | ||||
{ | ||||
const double *lit = &preshader->literals[operand->index]; | ||||
printf("("); | ||||
if (isscalar) | ||||
{ | ||||
const double val = *lit; | ||||
for (i = 0; i < elems-1; i++) | ||||
printf("%g, ", val); | ||||
printf("%g)", val); | ||||
} // if | ||||
else | ||||
{ | ||||
for (i = 0; i < elems-1; i++, lit++) | ||||
printf("%g, ", *lit); | ||||
printf("%g)", *lit); | ||||
} // else | ||||
break; | ||||
} // case | ||||
case MOJOSHADER_PRESHADEROPERAND_INPUT: | ||||
case MOJOSHADER_PRESHADEROPERAND_OUTPUT: | ||||
case MOJOSHADER_PRESHADEROPERAND_TEMP: | ||||
{ | ||||
int idx = operand->index % 4; | ||||
char regch = 'c'; | ||||
if (operand->type == MOJOSHADER_PRESHADEROPERAND_TEMP) | ||||
regch = 'r'; | ||||
if (operand->array_register_count > 0) | ||||
{ | ||||
for (i = operand->array_register_count - 1; i >= 0; i--) | ||||
printf("c%d[", operand->array_registers[i]); | ||||
printf("%c%d.%c", regch, operand->index / 4, mask[idx]); | ||||
for (i = 0; i < operand->array_register_count; i++) | ||||
printf("]"); | ||||
break; | ||||
} // if | ||||
printf("%c%d", regch, operand->index / 4); | ||||
if (isscalar) | ||||
printf(".%c", mask[idx]); | ||||
else if (elems != 4) | ||||
{ | ||||
printf("."); | ||||
for (i = 0; i < elems; i++) | ||||
printf("%c", mask[idx++]); | ||||
} // else if | ||||
break; | ||||
} // case | ||||
default: | ||||
printf("[???{%d, %u}???]", (int) operand->type, operand->index); | ||||
break; | ||||
} // switch | ||||
} // print_preshader_operand | ||||
static void print_preshader(const MOJOSHADER_preshader *preshader, | ||||
const int indent) | ||||
{ | ||||
MOJOSHADER_preshaderInstruction *inst = preshader->instructions; | ||||
int i, j; | ||||
static const char *opcodestr[] = { | ||||
"nop", "mov", "neg", "rcp", "frc", "exp", "log", "rsq", "sin", "cos", | ||||
"asin", "acos", "atan", "min", "max", "lt", "ge", "add", "mul", | ||||
"atan2", "div", "cmp", "movc", "dot", "noise", "min", "max", "lt", | ||||
"ge", "add", "mul", "atan2", "div", "dot", "noise" | ||||
}; | ||||
INDENT(); printf("PRESHADER:\n"); | ||||
print_symbols(preshader->symbols, preshader->symbol_count, indent + 1); | ||||
for (i = 0; i < preshader->instruction_count; i++, inst++) | ||||
{ | ||||
INDENT(); printf(" %s ", opcodestr[inst->opcode]); | ||||
// print dest register first... | ||||
print_preshader_operand(preshader, i, inst->operand_count - 1); | ||||
// ...then the source registers. | ||||
for (j = 0; j < inst->operand_count - 1; j++) | ||||
{ | ||||
printf(", "); | ||||
print_preshader_operand(preshader, i, j); | ||||
} // for | ||||
printf("\n"); | ||||
} // for | ||||
printf("\n"); | ||||
} // print_preshader | ||||
static void print_attrs(const char *category, const int count, | ||||
const MOJOSHADER_attribute *attributes, | ||||
const int indent) | ||||
{ | ||||
INDENT(); printf("%s:", category); | ||||
if (count == 0) | ||||
printf(" (none.)\n"); | ||||
else | ||||
{ | ||||
int i; | ||||
printf("\n"); | ||||
for (i = 0; i < count; i++) | ||||
{ | ||||
static const char *usagenames[] = { | ||||
"<unknown>", | ||||
"position", "blendweight", "blendindices", "normal", | ||||
"psize", "texcoord", "tangent", "binormal", "tessfactor", | ||||
"positiont", "color", "fog", "depth", "sample" | ||||
}; | ||||
const MOJOSHADER_attribute *a = &attributes[i]; | ||||
char numstr[16] = { 0 }; | ||||
if (a->index != 0) | ||||
snprintf(numstr, sizeof (numstr), "%d", a->index); | ||||
INDENT(); | ||||
printf(" * %s%s", usagenames[1 + (int) a->usage], numstr); | ||||
if (a->name != NULL) | ||||
printf(" (\"%s\")", a->name); | ||||
printf("\n"); | ||||
} // for | ||||
} // else | ||||
} // print_attrs | ||||
static void print_shader(const char *fname, const MOJOSHADER_parseData *pd, | ||||
unsigned int indent) | ||||
{ | ||||
INDENT(); printf("PROFILE: %s\n", pd->profile); | ||||
if (pd->error_count > 0) | ||||
{ | ||||
int i; | ||||
for (i = 0; i < pd->error_count; i++) | ||||
{ | ||||
const MOJOSHADER_error *err = &pd->errors[i]; | ||||
INDENT(); | ||||
printf("%s:%d: ERROR: %s\n", | ||||
err->filename ? err->filename : fname, | ||||
err->error_position, err->error); | ||||
} // for | ||||
} // if | ||||
else | ||||
{ | ||||
INDENT(); printf("SHADER TYPE: %s\n", shader_type(pd->shader_type)); | ||||
INDENT(); printf("VERSION: %d.%d\n", pd->major_ver, pd->minor_ver); | ||||
INDENT(); printf("INSTRUCTION COUNT: %d\n", (int) pd->instruction_count); | ||||
INDENT(); printf("MAIN FUNCTION: %s\n", pd->mainfn); | ||||
print_attrs("INPUTS", pd->attribute_count, pd->attributes, indent); | ||||
print_attrs("OUTPUTS", pd->output_count, pd->outputs, indent); | ||||
INDENT(); printf("CONSTANTS:"); | ||||
if (pd->constant_count == 0) | ||||
printf(" (none.)\n"); | ||||
else | ||||
{ | ||||
int i; | ||||
printf("\n"); | ||||
for (i = 0; i < pd->constant_count; i++) | ||||
{ | ||||
static const char *typenames[] = { "float", "int", "bool" }; | ||||
const MOJOSHADER_constant *c = &pd->constants[i]; | ||||
INDENT(); | ||||
printf(" * %d: %s (", c->index, typenames[(int) c->type]); | ||||
if (c->type == MOJOSHADER_UNIFORM_FLOAT) | ||||
{ | ||||
printf("%f %f %f %f", c->value.f[0], c->value.f[1], | ||||
c->value.f[2], c->value.f[3]); | ||||
} // if | ||||
else if (c->type == MOJOSHADER_UNIFORM_INT) | ||||
{ | ||||
printf("%d %d %d %d", c->value.i[0], c->value.i[1], | ||||
c->value.i[2], c->value.i[3]); | ||||
} // else if | ||||
else if (c->type == MOJOSHADER_UNIFORM_BOOL) | ||||
{ | ||||
printf("%s", c->value.b ? "true" : "false"); | ||||
} // else if | ||||
else | ||||
{ | ||||
printf("???"); | ||||
} // else | ||||
printf(")\n"); | ||||
} // for | ||||
} // else | ||||
INDENT(); printf("UNIFORMS:"); | ||||
if (pd->uniform_count == 0) | ||||
printf(" (none.)\n"); | ||||
else | ||||
{ | ||||
int i; | ||||
printf("\n"); | ||||
for (i = 0; i < pd->uniform_count; i++) | ||||
{ | ||||
static const char *typenames[] = { "float", "int", "bool" }; | ||||
const MOJOSHADER_uniform *u = &pd->uniforms[i]; | ||||
const char *arrayof = ""; | ||||
const char *constant = u->constant ? "const " : ""; | ||||
char arrayrange[64] = { '\0' }; | ||||
if (u->array_count > 0) | ||||
{ | ||||
arrayof = "array["; | ||||
snprintf(arrayrange, sizeof (arrayrange), "%d] ", | ||||
u->array_count); | ||||
} // if | ||||
INDENT(); | ||||
printf(" * %d: %s%s%s%s", u->index, constant, arrayof, | ||||
arrayrange, typenames[(int) u->type]); | ||||
if (u->name != NULL) | ||||
printf(" (\"%s\")", u->name); | ||||
printf("\n"); | ||||
} // for | ||||
} // else | ||||
INDENT(); printf("SAMPLERS:"); | ||||
if (pd->sampler_count == 0) | ||||
printf(" (none.)\n"); | ||||
else | ||||
{ | ||||
int i; | ||||
printf("\n"); | ||||
for (i = 0; i < pd->sampler_count; i++) | ||||
{ | ||||
static const char *typenames[] = { "2d", "cube", "volume" }; | ||||
const MOJOSHADER_sampler *s = &pd->samplers[i]; | ||||
INDENT(); | ||||
printf(" * %d: %s", s->index, typenames[(int) s->type]); | ||||
if (s->name != NULL) | ||||
printf(" (\"%s\")", s->name); | ||||
if (s->texbem) | ||||
printf(" [TEXBEM]"); | ||||
printf("\n"); | ||||
} // for | ||||
} // else | ||||
print_symbols(pd->symbols, pd->symbol_count, indent); | ||||
if (pd->preshader != NULL) | ||||
print_preshader(pd->preshader, indent); | ||||
if (pd->output != NULL) | ||||
{ | ||||
const char *output; | ||||
int output_len; | ||||
int i; | ||||
if (strcmp(pd->profile, "spirv") == 0) | ||||
{ | ||||
#if SUPPORT_PROFILE_SPIRV && defined(MOJOSHADER_HAS_SPIRV_TOOLS) | ||||
int binary_len = pd->output_len - sizeof(SpirvPatchTable); | ||||
uint32_t *words = (uint32_t *) pd->output; | ||||
size_t word_count = binary_len / 4; | ||||
spv_text text; | ||||
spv_diagnostic diagnostic; | ||||
spv_context ctx = spvContextCreate(SPV_ENV_UNIVERSAL_1_0); | ||||
int options = /*SPV_BINARY_TO_TEXT_OPTION_COLOR |*/ SPV_BINARY_TO_TEXT_OPTION_FRIENDLY_NAMES; | ||||
spv_result_t disResult = spvBinaryToText(ctx, words, word_count, options, &text, &diagnostic); | ||||
if (disResult == SPV_SUCCESS) | ||||
{ | ||||
output = text->str; | ||||
output_len = text->length; | ||||
} // if | ||||
else | ||||
{ | ||||
fprintf(stderr, "\nERROR DIAGNOSTIC: %s\n\n", diagnostic->error); | ||||
} // else | ||||
spv_result_t validateResult = spvValidateBinary(ctx, words, word_count, &diagnostic); | ||||
if (validateResult != SPV_SUCCESS) | ||||
{ | ||||
fprintf(stderr, "\nVALIDATION FAILURE: %s\n\n", diagnostic->error); | ||||
} // if | ||||
if (disResult != SPV_SUCCESS || validateResult != SPV_SUCCESS) | ||||
{ | ||||
exit(EXIT_FAILURE); | ||||
} // if | ||||
// FIXME: we're currently just leaking this disassembly... | ||||
#else | ||||
output = pd->output; | ||||
output_len = pd->output_len; | ||||
#endif | ||||
} // if | ||||
else | ||||
{ | ||||
output = pd->output; | ||||
output_len = pd->output_len; | ||||
} // else | ||||
INDENT(); | ||||
printf("OUTPUT:\n"); | ||||
indent++; | ||||
INDENT(); | ||||
for (i = 0; i < output_len; i++) | ||||
{ | ||||
putchar((int) output[i]); | ||||
if (output[i] == '\n') | ||||
INDENT(); | ||||
} // for | ||||
printf("\n"); | ||||
indent--; | ||||
} // if | ||||
} // else | ||||
printf("\n\n"); | ||||
} // print_shader | ||||
#ifdef MOJOSHADER_EFFECT_SUPPORT | ||||
static void print_value(const MOJOSHADER_effectValue *value, | ||||
const unsigned int indent) | ||||
{ | ||||
int i, r, c; | ||||
INDENT(); | ||||
printf("VALUE: %s -> %s\n", value->name, value->semantic); | ||||
static const char *classes[] = | ||||
{ | ||||
"SCALAR", | ||||
"VECTOR", | ||||
"ROW-MAJOR MATRIX", | ||||
"COLUMN-MAJOR MATRIX", | ||||
"OBJECT", | ||||
"STRUCT" | ||||
}; | ||||
static const char *types[] = | ||||
{ | ||||
"VOID", | ||||
"BOOL", | ||||
"INT", | ||||
"FLOAT", | ||||
"STRING", | ||||
"TEXTURE", | ||||
"TEXTURE1D", | ||||
"TEXTURE2D", | ||||
"TEXTURE3D", | ||||
"TEXTURECUBE", | ||||
"SAMPLER", | ||||
"SAMPLER1D", | ||||
"SAMPLER2D", | ||||
"SAMPLER3D", | ||||
"SAMPLERCUBE", | ||||
"PIXELSHADER", | ||||
"VERTEXSHADER", | ||||
"UNSUPPORTED" | ||||
}; | ||||
do_indent(indent + 1); | ||||
printf("CLASS: %s\n", classes[value->type.parameter_class]); | ||||
do_indent(indent + 1); | ||||
printf("TYPE: %s\n", types[value->type.parameter_type]); | ||||
do_indent(indent + 1); | ||||
printf("ROWS/COLUMNS/ELEMENTS: %d, %d, %d\n", | ||||
value->type.rows, value->type.columns, value->type.elements); | ||||
do_indent(indent + 1); | ||||
printf("TOTAL VALUES: %d\n", value->value_count); | ||||
if (value->type.parameter_type == MOJOSHADER_SYMTYPE_SAMPLER | ||||
|| value->type.parameter_type == MOJOSHADER_SYMTYPE_SAMPLER1D | ||||
|| value->type.parameter_type == MOJOSHADER_SYMTYPE_SAMPLER2D | ||||
|| value->type.parameter_type == MOJOSHADER_SYMTYPE_SAMPLER3D | ||||
|| value->type.parameter_type == MOJOSHADER_SYMTYPE_SAMPLERCUBE) | ||||
{ | ||||
do_indent(indent + 1); | ||||
printf("SAMPLER VALUES:\n"); | ||||
for (i = 0; i < value->value_count; i++) | ||||
{ | ||||
MOJOSHADER_effectSamplerState *state = &value->valuesSS[i]; | ||||
static const char *samplerstatetypes[] = | ||||
{ | ||||
"UNKNOWN0", | ||||
"UNKNOWN1", | ||||
"UNKNOWN2", | ||||
"UNKNOWN3", | ||||
"TEXTURE", | ||||
"ADDRESSU", | ||||
"ADDRESSV", | ||||
"ADDRESSW", | ||||
"BORDERCOLOR", | ||||
"MAGFILTER", | ||||
"MINFILTER", | ||||
"MIPFILTER", | ||||
"MIPMAPLODBIAS", | ||||
"MAXMIPLEVEL", | ||||
"MAXANISOTROPY", | ||||
"SRGBTEXTURE", | ||||
"ELEMENTINDEX", | ||||
"DMAPOFFSET", | ||||
}; | ||||
do_indent(indent + 2); | ||||
printf("TYPE: %s -> ", samplerstatetypes[state->type]); | ||||
/* Assuming only one value per state! */ | ||||
if (state->type == MOJOSHADER_SAMP_MIPMAPLODBIAS) | ||||
{ | ||||
/* float types */ | ||||
printf("%.2f\n", *state->value.valuesF); | ||||
} // if | ||||
else | ||||
{ | ||||
/* int/enum types */ | ||||
printf("%d\n", *state->value.valuesI); | ||||
} // else | ||||
} // for | ||||
} // if | ||||
else | ||||
{ | ||||
do_indent(indent + 1); | ||||
printf("%s VALUES:\n", types[value->type.parameter_type]); | ||||
i = 0; | ||||
do | ||||
{ | ||||
static const char *prints[] = | ||||
{ | ||||
"%X ", | ||||
"%d ", | ||||
"%d ", | ||||
"%.2f ", | ||||
"%d ", | ||||
"%d ", | ||||
"%d ", | ||||
"%d ", | ||||
"%d ", | ||||
"%d ", | ||||
"SAMPLER?! ", | ||||
"SAMPLER?! ", | ||||
"SAMPLER?! ", | ||||
"SAMPLER?! ", | ||||
"SAMPLER?! ", | ||||
"%d ", | ||||
"%d ", | ||||
"%X " | ||||
}; | ||||
for (r = 0; r < value->type.rows; r++) | ||||
{ | ||||
do_indent(indent + 2); | ||||
for (c = 0; c < value->type.columns; c++) | ||||
{ | ||||
const int offset = (i * value->type.rows * 4) + (r * 4) + c; | ||||
if (value->type.parameter_type == MOJOSHADER_SYMTYPE_FLOAT) | ||||
printf(prints[value->type.parameter_type], value->valuesF[offset]); | ||||
else | ||||
printf(prints[value->type.parameter_type], value->valuesI[offset]); | ||||
} // for | ||||
printf("\n"); | ||||
} // for | ||||
} while (++i < value->type.elements); | ||||
} // else | ||||
} // print_value | ||||
static void print_effect(const char *fname, const MOJOSHADER_effect *effect, | ||||
const unsigned int indent) | ||||
{ | ||||
INDENT(); | ||||
printf("PROFILE: %s\n", effect->profile); | ||||
printf("\n"); | ||||
if (effect->error_count > 0) | ||||
{ | ||||
int i; | ||||
for (i = 0; i < effect->error_count; i++) | ||||
{ | ||||
const MOJOSHADER_error *err = &effect->errors[i]; | ||||
INDENT(); | ||||
printf("%s:%d: ERROR: %s\n", | ||||
err->filename ? err->filename : fname, | ||||
err->error_position, err->error); | ||||
} // for | ||||
} // if | ||||
else | ||||
{ | ||||
int i, j, k; | ||||
const MOJOSHADER_effectTechnique *technique = effect->techniques; | ||||
const MOJOSHADER_effectObject *object = effect->objects; | ||||
const MOJOSHADER_effectParam *param = effect->params; | ||||
for (i = 0; i < effect->param_count; i++, param++) | ||||
{ | ||||
INDENT(); | ||||
printf("PARAM #%d\n", i); | ||||
print_value(¶m->value, indent + 1); | ||||
if (param->annotation_count > 0) | ||||
{ | ||||
do_indent(indent + 1); | ||||
printf("ANNOTATIONS:\n"); | ||||
} // if | ||||
for (j = 0; j < param->annotation_count; j++) | ||||
{ | ||||
print_value(¶m->annotations[j], indent + 2); | ||||
} // for | ||||
} // for | ||||
printf("\n"); | ||||
for (i = 0; i < effect->technique_count; i++, technique++) | ||||
{ | ||||
const MOJOSHADER_effectPass *pass = technique->passes; | ||||
INDENT(); | ||||
printf("TECHNIQUE #%d ('%s'):\n", i, technique->name); | ||||
for (j = 0; j < technique->pass_count; j++, pass++) | ||||
{ | ||||
const MOJOSHADER_effectState *state = pass->states; | ||||
do_indent(indent + 1); | ||||
printf("PASS #%d ('%s'):\n", j, pass->name); | ||||
for (k = 0; k < pass->state_count; k++, state++) | ||||
{ | ||||
do_indent(indent + 2); | ||||
printf("STATE %d:\n", state->type); | ||||
print_value(&state->value, indent + 3); | ||||
} // for | ||||
} // for | ||||
} // for | ||||
printf("\n"); | ||||
/* Start at index 1, 0 is always empty (thanks Microsoft!) */ | ||||
object++; | ||||
for (i = 1; i < effect->object_count; i++, object++) | ||||
{ | ||||
INDENT(); | ||||
if (object->type == MOJOSHADER_SYMTYPE_PIXELSHADER | ||||
|| object->type == MOJOSHADER_SYMTYPE_VERTEXSHADER) | ||||
{ | ||||
if (object->shader.is_preshader) | ||||
{ | ||||
printf("OBJECT #%d: PRESHADER, technique %u, pass %u, param %s\n", i, | ||||
object->shader.technique, object->shader.pass, | ||||
effect->params[object->shader.params[0]].value.name); | ||||
print_preshader(object->shader.preshader, indent + 1); | ||||
} // if | ||||
else | ||||
{ | ||||
printf("OBJECT #%d: SHADER, technique %u, pass %u\n", i, | ||||
object->shader.technique, object->shader.pass); | ||||
print_shader(fname, object->shader.shader, indent + 1); | ||||
} // else | ||||
} // if | ||||
else if (object->type == MOJOSHADER_SYMTYPE_STRING) | ||||
printf("OBJECT #%d: STRING, '%s'\n", i, | ||||
object->string.string); | ||||
else if (object->type == MOJOSHADER_SYMTYPE_SAMPLER | ||||
|| object->type == MOJOSHADER_SYMTYPE_SAMPLER1D | ||||
|| object->type == MOJOSHADER_SYMTYPE_SAMPLER2D | ||||
|| object->type == MOJOSHADER_SYMTYPE_SAMPLER3D | ||||
|| object->type == MOJOSHADER_SYMTYPE_SAMPLERCUBE) | ||||
printf("OBJECT #%d: MAPPING, '%s'\n", i, | ||||
object->mapping.name); | ||||
else if (object->type == MOJOSHADER_SYMTYPE_TEXTURE | ||||
|| object->type == MOJOSHADER_SYMTYPE_TEXTURE1D | ||||
|| object->type == MOJOSHADER_SYMTYPE_TEXTURE2D | ||||
|| object->type == MOJOSHADER_SYMTYPE_TEXTURE3D | ||||
|| object->type == MOJOSHADER_SYMTYPE_TEXTURECUBE) | ||||
printf("OBJECT #%d: TEXTURE\n", i); | ||||
else | ||||
printf("UNKNOWN OBJECT: #%d\n", i); | ||||
} // for | ||||
} // else | ||||
} // print_effect | ||||
#endif // MOJOSHADER_EFFECT_SUPPORT | ||||
static int do_parse(const char *fname, const unsigned char *buf, | ||||
const int len, const char *prof) | ||||
{ | ||||
int i; | ||||
int retval = 0; | ||||
// magic for an effects file (!!! FIXME: I _think_). | ||||
if ( ((buf[0] == 0x01) && (buf[1] == 0x09) && | ||||
(buf[2] == 0xFF) && (buf[3] == 0xFE)) || | ||||
((buf[0] == 0xCF) && (buf[1] == 0x0B) && | ||||
(buf[2] == 0xF0) && (buf[3] == 0xBC)) ) | ||||
{ | ||||
#ifdef MOJOSHADER_EFFECT_SUPPORT | ||||
const MOJOSHADER_effect *effect; | ||||
effect = MOJOSHADER_parseEffect(prof, buf, len, NULL, 0, | ||||
NULL, 0, Malloc, Free, 0); | ||||
int error_count = effect->error_count; | ||||
for (i = 0; i < effect->object_count; i++) | ||||
{ | ||||
MOJOSHADER_effectObject *object = &effect->objects[i]; | ||||
switch (object->type) | ||||
{ | ||||
case MOJOSHADER_SYMTYPE_VERTEXSHADER: | ||||
case MOJOSHADER_SYMTYPE_PIXELSHADER: | ||||
if (!object->shader.is_preshader) | ||||
{ | ||||
const MOJOSHADER_parseData *shader = object->shader.shader; | ||||
if (shader) | ||||
error_count += shader->error_count; | ||||
} // if | ||||
break; | ||||
default: | ||||
break; | ||||
} | ||||
} | ||||
retval = (error_count == 0); | ||||
printf("EFFECT: %s\n", fname); | ||||
print_effect(fname, effect, 1); | ||||
MOJOSHADER_freeEffect(effect); | ||||
#else | ||||
printf("Is an effect, but effect support is disabled!\n"); | ||||
#endif | ||||
} // if | ||||
else // do it as a regular compiled shader. | ||||
{ | ||||
const MOJOSHADER_parseData *pd; | ||||
pd = MOJOSHADER_parse(prof, NULL, buf, len, NULL, 0, | ||||
NULL, 0, Malloc, Free, NULL); | ||||
retval = (pd->error_count == 0); | ||||
printf("SHADER: %s\n", fname); | ||||
print_shader(fname, pd, 1); | ||||
MOJOSHADER_freeParseData(pd); | ||||
} // else | ||||
return retval; | ||||
} // do_parse | ||||
int main(int argc, char **argv) | ||||
{ | ||||
int retval = 0; | ||||
printf("MojoShader testparse\n"); | ||||
printf("Compiled against changeset %s\n", MOJOSHADER_CHANGESET); | ||||
printf("Linked against changeset %s\n", MOJOSHADER_changeset()); | ||||
printf("\n"); | ||||
if (argc <= 2) | ||||
printf("\n\nUSAGE: %s <profile> [file1] ... [fileN]\n\n", argv[0]); | ||||
else | ||||
{ | ||||
const char *profile = argv[1]; | ||||
int i; | ||||
for (i = 2; i < argc; i++) | ||||
{ | ||||
FILE *io = fopen(argv[i], "rb"); | ||||
if (io == NULL) | ||||
printf(" ... fopen('%s') failed.\n", argv[i]); | ||||
else | ||||
{ | ||||
unsigned char *buf = (unsigned char *) malloc(1000000); | ||||
int rc = fread(buf, 1, 1000000, io); | ||||
fclose(io); | ||||
if (!do_parse(argv[i], buf, rc, profile)) | ||||
retval = 1; | ||||
free(buf); | ||||
} // else | ||||
} // for | ||||
} // else | ||||
return retval; | ||||
} // main | ||||
// end of testparse.c ... | ||||