mojoshader.h
author Ryan C. Gordon <icculus@icculus.org>
Fri, 13 Oct 2017 00:47:22 -0400
changeset 1181 b873f3b0f838
parent 1180 8abc040525ed
permissions -rw-r--r--
Count constant arrays for the uniform_count. Fixes buffer overflow.

This one got found by AFL, too, but it's a legit bug that can happen with
legit shaders.
icculus@7
     1
/**
icculus@35
     2
 * MojoShader; generate shader programs from bytecode of compiled
icculus@35
     3
 *  Direct3D shaders.
icculus@7
     4
 *
icculus@7
     5
 * Please see the file LICENSE.txt in the source's root directory.
icculus@7
     6
 *
icculus@7
     7
 *  This file written by Ryan C. Gordon.
icculus@7
     8
 */
icculus@7
     9
icculus@592
    10
#ifndef _INCL_MOJOSHADER_H_
icculus@592
    11
#define _INCL_MOJOSHADER_H_
icculus@7
    12
icculus@7
    13
#ifdef __cplusplus
icculus@7
    14
extern "C" {
icculus@7
    15
#endif
icculus@7
    16
icculus@455
    17
/* You can define this if you aren't generating mojoshader_version.h */
icculus@455
    18
#ifndef MOJOSHADER_NO_VERSION_INCLUDE
icculus@455
    19
#include "mojoshader_version.h"
icculus@461
    20
#endif
icculus@461
    21
icculus@461
    22
#ifndef MOJOSHADER_VERSION
icculus@455
    23
#define MOJOSHADER_VERSION -1
icculus@461
    24
#endif
icculus@461
    25
icculus@461
    26
#ifndef MOJOSHADER_CHANGESET
icculus@455
    27
#define MOJOSHADER_CHANGESET "???"
icculus@455
    28
#endif
icculus@455
    29
flibitijibibo@1150
    30
#ifndef DECLSPEC
flibitijibibo@1150
    31
#ifdef _WIN32
flibitijibibo@1150
    32
#define DECLSPEC __declspec(dllexport)
flibitijibibo@1150
    33
#else
flibitijibibo@1150
    34
#define DECLSPEC
flibitijibibo@1150
    35
#endif
flibitijibibo@1150
    36
#endif
flibitijibibo@1150
    37
flibitijibibo@1150
    38
#ifndef MOJOSHADERCALL
flibitijibibo@1150
    39
#ifdef _WIN32
flibitijibibo@1150
    40
#define MOJOSHADERCALL __stdcall
flibitijibibo@1150
    41
#else
flibitijibibo@1150
    42
#define MOJOSHADERCALL
flibitijibibo@1150
    43
#endif
flibitijibibo@1150
    44
#endif
flibitijibibo@1150
    45
icculus@20
    46
/*
icculus@46
    47
 * For determining the version of MojoShader you are using:
icculus@46
    48
 *    const int compiled_against = MOJOSHADER_VERSION;
icculus@46
    49
 *    const int linked_against = MOJOSHADER_version();
icculus@46
    50
 *
icculus@46
    51
 * The version is a single integer that increments, not a major/minor value.
icculus@20
    52
 */
flibitijibibo@1150
    53
DECLSPEC int MOJOSHADER_version(void);
icculus@20
    54
icculus@20
    55
/*
icculus@552
    56
 * For determining the revision control changeset of MojoShader you are using:
icculus@1017
    57
 *    const char *compiled_against = MOJOSHADER_CHANGESET;
icculus@455
    58
 *    const char *linked_against = MOJOSHADER_changeset();
icculus@455
    59
 *
icculus@455
    60
 * The version is an arbitrary, null-terminated ASCII string. It is probably
icculus@455
    61
 *  a hash that represents a revision control changeset, and can't be
icculus@455
    62
 *  compared to any other string to determine chronology.
icculus@455
    63
 *
icculus@455
    64
 * Do not attempt to free this string; it's statically allocated.
icculus@455
    65
 */
flibitijibibo@1150
    66
DECLSPEC const char *MOJOSHADER_changeset(void);
icculus@455
    67
icculus@455
    68
/*
icculus@20
    69
 * These allocators work just like the C runtime's malloc() and free()
icculus@46
    70
 *  (in fact, they probably use malloc() and free() internally if you don't
icculus@46
    71
 *  specify your own allocator, but don't rely on that behaviour).
icculus@97
    72
 * (data) is the pointer you supplied when specifying these allocator
icculus@97
    73
 *  callbacks, in case you need instance-specific data...it is passed through
icculus@97
    74
 *  to your allocator unmolested, and can be NULL if you like.
icculus@20
    75
 */
flibitijibibo@1150
    76
typedef void *(MOJOSHADERCALL *MOJOSHADER_malloc)(int bytes, void *data);
flibitijibibo@1150
    77
typedef void (MOJOSHADERCALL *MOJOSHADER_free)(void *ptr, void *data);
icculus@18
    78
icculus@46
    79
icculus@46
    80
/*
icculus@46
    81
 * These are enum values, but they also can be used in bitmasks, so we can
icculus@46
    82
 *  test if an opcode is acceptable: if (op->shader_types & ourtype) {} ...
icculus@46
    83
 */
icculus@46
    84
typedef enum
icculus@46
    85
{
icculus@46
    86
    MOJOSHADER_TYPE_UNKNOWN  = 0,
icculus@46
    87
    MOJOSHADER_TYPE_PIXEL    = (1 << 0),
icculus@46
    88
    MOJOSHADER_TYPE_VERTEX   = (1 << 1),
icculus@46
    89
    MOJOSHADER_TYPE_GEOMETRY = (1 << 2),  /* (not supported yet.) */
icculus@46
    90
    MOJOSHADER_TYPE_ANY = 0xFFFFFFFF   /* used for bitmasks */
icculus@46
    91
} MOJOSHADER_shaderType;
icculus@46
    92
icculus@94
    93
/*
icculus@196
    94
 * Data types for vertex attribute streams.
icculus@196
    95
 */
icculus@196
    96
typedef enum
icculus@196
    97
{
icculus@240
    98
    MOJOSHADER_ATTRIBUTE_UNKNOWN = -1,  /* housekeeping; not returned. */
icculus@196
    99
    MOJOSHADER_ATTRIBUTE_BYTE,
icculus@196
   100
    MOJOSHADER_ATTRIBUTE_UBYTE,
icculus@196
   101
    MOJOSHADER_ATTRIBUTE_SHORT,
icculus@196
   102
    MOJOSHADER_ATTRIBUTE_USHORT,
icculus@196
   103
    MOJOSHADER_ATTRIBUTE_INT,
icculus@196
   104
    MOJOSHADER_ATTRIBUTE_UINT,
icculus@196
   105
    MOJOSHADER_ATTRIBUTE_FLOAT,
icculus@236
   106
    MOJOSHADER_ATTRIBUTE_DOUBLE,
icculus@236
   107
    MOJOSHADER_ATTRIBUTE_HALF_FLOAT,  /* MAYBE available in your OpenGL! */
icculus@196
   108
} MOJOSHADER_attributeType;
icculus@196
   109
icculus@196
   110
/*
icculus@94
   111
 * Data types for uniforms. See MOJOSHADER_uniform for more information.
icculus@94
   112
 */
icculus@92
   113
typedef enum
icculus@92
   114
{
icculus@240
   115
    MOJOSHADER_UNIFORM_UNKNOWN = -1, /* housekeeping value; never returned. */
icculus@147
   116
    MOJOSHADER_UNIFORM_FLOAT,
icculus@147
   117
    MOJOSHADER_UNIFORM_INT,
icculus@147
   118
    MOJOSHADER_UNIFORM_BOOL,
icculus@94
   119
} MOJOSHADER_uniformType;
icculus@92
   120
icculus@94
   121
/*
icculus@94
   122
 * These are the uniforms to be set for a shader. "Uniforms" are what Direct3D
icculus@94
   123
 *  calls "Constants" ... IDirect3DDevice::SetVertexShaderConstantF() would
icculus@94
   124
 *  need this data, for example. These integers are register indexes. So if
icculus@94
   125
 *  index==6 and type==MOJOSHADER_UNIFORM_FLOAT, that means we'd expect a
icculus@94
   126
 *  4-float vector to be specified for what would be register "c6" in D3D
icculus@94
   127
 *  assembly language, before drawing with the shader.
icculus@280
   128
 * (array_count) means this is an array of uniforms...this happens in some
icculus@280
   129
 *  profiles when we see a relative address ("c0[a0.x]", not the usual "c0").
icculus@280
   130
 *  In those cases, the shader was built to set some range of constant
icculus@280
   131
 *  registers as an array. You should set this array with (array_count)
icculus@280
   132
 *  elements from the constant register file, starting at (index) instead of
icculus@280
   133
 *  just a single uniform. To be extra difficult, you'll need to fill in the
icculus@280
   134
 *  correct values from the MOJOSHADER_constant data into the appropriate
icculus@280
   135
 *  parts of the array, overriding the constant register file. Fun!
icculus@438
   136
 * (constant) says whether this is a constant array; these need to be loaded
icculus@438
   137
 *  once at creation time, from the constant list and not ever updated from
icculus@438
   138
 *  the constant register file. This is a workaround for limitations in some
icculus@438
   139
 *  profiles.
icculus@190
   140
 * (name) is a profile-specific variable name; it may be NULL if it isn't
icculus@190
   141
 *  applicable to the requested profile.
icculus@94
   142
 */
icculus@462
   143
typedef struct MOJOSHADER_uniform
icculus@92
   144
{
icculus@100
   145
    MOJOSHADER_uniformType type;
icculus@92
   146
    int index;
icculus@280
   147
    int array_count;
icculus@438
   148
    int constant;
icculus@190
   149
    const char *name;
icculus@92
   150
} MOJOSHADER_uniform;
icculus@92
   151
icculus@100
   152
/*
icculus@278
   153
 * These are the constants defined in a shader. These are data values
icculus@278
   154
 *  hardcoded in a shader (with the DEF, DEFI, DEFB instructions), which
icculus@278
   155
 *  override your Uniforms. This data is largely for informational purposes,
icculus@278
   156
 *  since they are compiled in and can't be changed, like Uniforms can be.
icculus@278
   157
 * These integers are register indexes. So if index==6 and
icculus@278
   158
 *  type==MOJOSHADER_UNIFORM_FLOAT, that means we'd expect a 4-float vector
icculus@278
   159
 *  to be specified for what would be register "c6" in D3D assembly language,
icculus@278
   160
 *  before drawing with the shader.
icculus@278
   161
 * (value) is the value of the constant, unioned by type.
icculus@278
   162
 */
icculus@462
   163
typedef struct MOJOSHADER_constant
icculus@278
   164
{
icculus@278
   165
    MOJOSHADER_uniformType type;
icculus@278
   166
    int index;
icculus@278
   167
    union
icculus@278
   168
    {
icculus@278
   169
        float f[4];  /* if type==MOJOSHADER_UNIFORM_FLOAT */
icculus@278
   170
        int i[4];    /* if type==MOJOSHADER_UNIFORM_INT */
icculus@278
   171
        int b;       /* if type==MOJOSHADER_UNIFORM_BOOL */
icculus@278
   172
    } value;
icculus@278
   173
} MOJOSHADER_constant;
icculus@278
   174
icculus@278
   175
/*
icculus@148
   176
 * Data types for samplers. See MOJOSHADER_sampler for more information.
icculus@148
   177
 */
icculus@148
   178
typedef enum
icculus@148
   179
{
icculus@240
   180
    MOJOSHADER_SAMPLER_UNKNOWN = -1, /* housekeeping value; never returned. */
icculus@148
   181
    MOJOSHADER_SAMPLER_2D,
icculus@148
   182
    MOJOSHADER_SAMPLER_CUBE,
icculus@148
   183
    MOJOSHADER_SAMPLER_VOLUME,
icculus@148
   184
} MOJOSHADER_samplerType;
icculus@148
   185
icculus@148
   186
/*
icculus@148
   187
 * These are the samplers to be set for a shader. ...
icculus@148
   188
 *  IDirect3DDevice::SetTexture() would need this data, for example.
icculus@148
   189
 * These integers are the sampler "stage". So if index==6 and
icculus@148
   190
 *  type==MOJOSHADER_SAMPLER_2D, that means we'd expect a regular 2D texture
icculus@148
   191
 *  to be specified for what would be register "s6" in D3D assembly language,
icculus@148
   192
 *  before drawing with the shader.
icculus@190
   193
 * (name) is a profile-specific variable name; it may be NULL if it isn't
icculus@190
   194
 *  applicable to the requested profile.
icculus@1090
   195
 * (texbem) will be non-zero if a TEXBEM opcode references this sampler. This
icculus@1090
   196
 *  is only used in legacy shaders (ps_1_1 through ps_1_3), but it needs some
icculus@1090
   197
 *  special support to work, as we have to load a magic uniform behind the
icculus@1090
   198
 *  scenes to support it. Most code can ignore this field in general, and no
icculus@1090
   199
 *  one has to touch it unless they really know what they're doing.
icculus@148
   200
 */
icculus@462
   201
typedef struct MOJOSHADER_sampler
icculus@148
   202
{
icculus@148
   203
    MOJOSHADER_samplerType type;
icculus@148
   204
    int index;
icculus@190
   205
    const char *name;
icculus@1090
   206
    int texbem;
icculus@148
   207
} MOJOSHADER_sampler;
icculus@148
   208
icculus@1104
   209
icculus@1104
   210
/*
icculus@1104
   211
 * This struct is used if you have to force a sampler to a specific type.
icculus@1104
   212
 *  Generally, you can ignore this, but if you have, say, a ps_1_1
icculus@1104
   213
 *  shader, you might need to specify what the samplers are meant to be
icculus@1104
   214
 *  to get correct results, as Shader Model 1 samples textures according
icculus@1104
   215
 *  to what is bound to a sampler at the moment instead of what the shader
icculus@1104
   216
 *  is hardcoded to expect.
icculus@1104
   217
 */
icculus@1104
   218
typedef struct MOJOSHADER_samplerMap
icculus@1104
   219
{
icculus@1104
   220
    int index;
icculus@1104
   221
    MOJOSHADER_samplerType type;
icculus@1104
   222
} MOJOSHADER_samplerMap;
icculus@1104
   223
icculus@148
   224
/*
icculus@100
   225
 * Data types for attributes. See MOJOSHADER_attribute for more information.
icculus@100
   226
 */
icculus@100
   227
typedef enum
icculus@100
   228
{
icculus@240
   229
    MOJOSHADER_USAGE_UNKNOWN = -1,  /* housekeeping value; never returned. */
icculus@147
   230
    MOJOSHADER_USAGE_POSITION,
icculus@147
   231
    MOJOSHADER_USAGE_BLENDWEIGHT,
icculus@147
   232
    MOJOSHADER_USAGE_BLENDINDICES,
icculus@147
   233
    MOJOSHADER_USAGE_NORMAL,
icculus@147
   234
    MOJOSHADER_USAGE_POINTSIZE,
icculus@147
   235
    MOJOSHADER_USAGE_TEXCOORD,
icculus@147
   236
    MOJOSHADER_USAGE_TANGENT,
icculus@147
   237
    MOJOSHADER_USAGE_BINORMAL,
icculus@147
   238
    MOJOSHADER_USAGE_TESSFACTOR,
icculus@147
   239
    MOJOSHADER_USAGE_POSITIONT,
icculus@147
   240
    MOJOSHADER_USAGE_COLOR,
icculus@147
   241
    MOJOSHADER_USAGE_FOG,
icculus@147
   242
    MOJOSHADER_USAGE_DEPTH,
icculus@147
   243
    MOJOSHADER_USAGE_SAMPLE,
icculus@1180
   244
    MOJOSHADER_USAGE_TOTAL   /* housekeeping value; never returned. */
icculus@100
   245
} MOJOSHADER_usage;
icculus@100
   246
icculus@100
   247
/*
icculus@100
   248
 * These are the attributes to be set for a shader. "Attributes" are what
icculus@100
   249
 *  Direct3D calls "Vertex Declarations Usages" ...
icculus@100
   250
 *  IDirect3DDevice::CreateVertexDeclaration() would need this data, for
icculus@100
   251
 *  example. Each attribute is associated with an array of data that uses one
icculus@100
   252
 *  element per-vertex. So if usage==MOJOSHADER_USAGE_COLOR and index==1, that
icculus@100
   253
 *  means we'd expect a secondary color array to be bound to this shader
icculus@100
   254
 *  before drawing.
icculus@190
   255
 * (name) is a profile-specific variable name; it may be NULL if it isn't
icculus@190
   256
 *  applicable to the requested profile.
icculus@100
   257
 */
icculus@462
   258
typedef struct MOJOSHADER_attribute
icculus@100
   259
{
icculus@100
   260
    MOJOSHADER_usage usage;
icculus@100
   261
    int index;
icculus@190
   262
    const char *name;
icculus@100
   263
} MOJOSHADER_attribute;
icculus@46
   264
icculus@46
   265
/*
icculus@450
   266
 * Use this if you want to specify newly-parsed code to swizzle incoming
icculus@450
   267
 *  data. This can be useful if you know, at parse time, that a shader
icculus@450
   268
 *  will be processing data on COLOR0 that should be RGBA, but you'll
icculus@450
   269
 *  be passing it a vertex array full of ARGB instead.
icculus@450
   270
 */
icculus@462
   271
typedef struct MOJOSHADER_swizzle
icculus@450
   272
{
icculus@450
   273
    MOJOSHADER_usage usage;
icculus@450
   274
    unsigned int index;
icculus@450
   275
    unsigned char swizzles[4];  /* {0,1,2,3} == .xyzw, {2,2,2,2} == .zzzz */
icculus@450
   276
} MOJOSHADER_swizzle;
icculus@450
   277
icculus@450
   278
icculus@450
   279
/*
icculus@524
   280
 * MOJOSHADER_symbol data.
icculus@524
   281
 *
icculus@524
   282
 * These are used to expose high-level information in shader bytecode.
icculus@524
   283
 *  They associate HLSL variables with registers. This data is used for both
icculus@524
   284
 *  debugging and optimization.
icculus@524
   285
 */
icculus@524
   286
icculus@524
   287
typedef enum
icculus@524
   288
{
icculus@1180
   289
    MOJOSHADER_SYMREGSET_BOOL=0,
icculus@524
   290
    MOJOSHADER_SYMREGSET_INT4,
icculus@524
   291
    MOJOSHADER_SYMREGSET_FLOAT4,
icculus@524
   292
    MOJOSHADER_SYMREGSET_SAMPLER,
icculus@1180
   293
    MOJOSHADER_SYMREGSET_TOTAL    /* housekeeping value; never returned. */
icculus@524
   294
} MOJOSHADER_symbolRegisterSet;
icculus@524
   295
icculus@524
   296
typedef enum
icculus@524
   297
{
icculus@1180
   298
    MOJOSHADER_SYMCLASS_SCALAR=0,
icculus@524
   299
    MOJOSHADER_SYMCLASS_VECTOR,
icculus@524
   300
    MOJOSHADER_SYMCLASS_MATRIX_ROWS,
icculus@524
   301
    MOJOSHADER_SYMCLASS_MATRIX_COLUMNS,
icculus@524
   302
    MOJOSHADER_SYMCLASS_OBJECT,
icculus@524
   303
    MOJOSHADER_SYMCLASS_STRUCT,
icculus@1180
   304
    MOJOSHADER_SYMCLASS_TOTAL    /* housekeeping value; never returned. */
icculus@524
   305
} MOJOSHADER_symbolClass;
icculus@524
   306
icculus@524
   307
typedef enum
icculus@524
   308
{
icculus@1180
   309
    MOJOSHADER_SYMTYPE_VOID=0,
icculus@524
   310
    MOJOSHADER_SYMTYPE_BOOL,
icculus@524
   311
    MOJOSHADER_SYMTYPE_INT,
icculus@524
   312
    MOJOSHADER_SYMTYPE_FLOAT,
icculus@524
   313
    MOJOSHADER_SYMTYPE_STRING,
icculus@524
   314
    MOJOSHADER_SYMTYPE_TEXTURE,
icculus@524
   315
    MOJOSHADER_SYMTYPE_TEXTURE1D,
icculus@524
   316
    MOJOSHADER_SYMTYPE_TEXTURE2D,
icculus@524
   317
    MOJOSHADER_SYMTYPE_TEXTURE3D,
icculus@524
   318
    MOJOSHADER_SYMTYPE_TEXTURECUBE,
icculus@524
   319
    MOJOSHADER_SYMTYPE_SAMPLER,
icculus@524
   320
    MOJOSHADER_SYMTYPE_SAMPLER1D,
icculus@524
   321
    MOJOSHADER_SYMTYPE_SAMPLER2D,
icculus@524
   322
    MOJOSHADER_SYMTYPE_SAMPLER3D,
icculus@524
   323
    MOJOSHADER_SYMTYPE_SAMPLERCUBE,
icculus@524
   324
    MOJOSHADER_SYMTYPE_PIXELSHADER,
icculus@524
   325
    MOJOSHADER_SYMTYPE_VERTEXSHADER,
icculus@524
   326
    MOJOSHADER_SYMTYPE_PIXELFRAGMENT,
icculus@524
   327
    MOJOSHADER_SYMTYPE_VERTEXFRAGMENT,
icculus@524
   328
    MOJOSHADER_SYMTYPE_UNSUPPORTED,
icculus@1180
   329
    MOJOSHADER_SYMTYPE_TOTAL    /* housekeeping value; never returned. */
icculus@524
   330
} MOJOSHADER_symbolType;
icculus@524
   331
icculus@524
   332
typedef struct MOJOSHADER_symbolStructMember MOJOSHADER_symbolStructMember;
icculus@524
   333
icculus@524
   334
typedef struct MOJOSHADER_symbolTypeInfo
icculus@524
   335
{
icculus@524
   336
    MOJOSHADER_symbolClass parameter_class;
icculus@524
   337
    MOJOSHADER_symbolType parameter_type;
icculus@524
   338
    unsigned int rows;
icculus@524
   339
    unsigned int columns;
icculus@524
   340
    unsigned int elements;
icculus@524
   341
    unsigned int member_count;
icculus@524
   342
    MOJOSHADER_symbolStructMember *members;
icculus@524
   343
} MOJOSHADER_symbolTypeInfo;
icculus@524
   344
icculus@524
   345
struct MOJOSHADER_symbolStructMember
icculus@524
   346
{
icculus@524
   347
    const char *name;
icculus@524
   348
    MOJOSHADER_symbolTypeInfo info;
icculus@524
   349
};
icculus@524
   350
icculus@524
   351
typedef struct MOJOSHADER_symbol
icculus@524
   352
{
icculus@524
   353
    const char *name;
icculus@524
   354
    MOJOSHADER_symbolRegisterSet register_set;
icculus@524
   355
    unsigned int register_index;
icculus@524
   356
    unsigned int register_count;
icculus@524
   357
    MOJOSHADER_symbolTypeInfo info;
icculus@524
   358
} MOJOSHADER_symbol;
icculus@524
   359
icculus@524
   360
icculus@947
   361
/*
icculus@947
   362
 * These are used with MOJOSHADER_error as special case positions.
icculus@947
   363
 */
icculus@947
   364
#define MOJOSHADER_POSITION_NONE (-3)
icculus@947
   365
#define MOJOSHADER_POSITION_BEFORE (-2)
icculus@947
   366
#define MOJOSHADER_POSITION_AFTER (-1)
icculus@947
   367
icculus@536
   368
typedef struct MOJOSHADER_error
icculus@46
   369
{
icculus@46
   370
    /*
icculus@46
   371
     * Human-readable error, if there is one. Will be NULL if there was no
icculus@46
   372
     *  error. The string will be UTF-8 encoded, and English only. Most of
icculus@46
   373
     *  these shouldn't be shown to the end-user anyhow.
icculus@46
   374
     */
icculus@46
   375
    const char *error;
icculus@46
   376
icculus@523
   377
    /*
icculus@578
   378
     * Filename where error happened. This can be NULL if the information
icculus@578
   379
     *  isn't available.
icculus@536
   380
     */
icculus@536
   381
    const char *filename;
icculus@536
   382
icculus@536
   383
    /*
icculus@947
   384
     * Position of error, if there is one. Will be MOJOSHADER_POSITION_NONE if
icculus@947
   385
     *  there was no error, MOJOSHADER_POSITION_BEFORE if there was an error
icculus@947
   386
     *  before processing started, and MOJOSHADER_POSITION_AFTER if there was
icculus@947
   387
     *  an error during final processing. If >= 0, MOJOSHADER_parse() sets
icculus@947
   388
     *  this to the byte offset (starting at zero) into the bytecode you
icculus@947
   389
     *  supplied, and MOJOSHADER_assemble(), MOJOSHADER_parseAst(), and
icculus@947
   390
     *  MOJOSHADER_compile() sets this to a a line number in the source code
icculus@947
   391
     *  you supplied (starting at one).
icculus@475
   392
     */
icculus@475
   393
    int error_position;
icculus@536
   394
} MOJOSHADER_error;
icculus@536
   395
icculus@1030
   396
icculus@1030
   397
/* !!! FIXME: document me. */
icculus@1030
   398
typedef enum MOJOSHADER_preshaderOpcode
icculus@1030
   399
{
icculus@1030
   400
    MOJOSHADER_PRESHADEROP_NOP,
icculus@1030
   401
    MOJOSHADER_PRESHADEROP_MOV,
icculus@1030
   402
    MOJOSHADER_PRESHADEROP_NEG,
icculus@1030
   403
    MOJOSHADER_PRESHADEROP_RCP,
icculus@1030
   404
    MOJOSHADER_PRESHADEROP_FRC,
icculus@1030
   405
    MOJOSHADER_PRESHADEROP_EXP,
icculus@1030
   406
    MOJOSHADER_PRESHADEROP_LOG,
icculus@1030
   407
    MOJOSHADER_PRESHADEROP_RSQ,
icculus@1030
   408
    MOJOSHADER_PRESHADEROP_SIN,
icculus@1030
   409
    MOJOSHADER_PRESHADEROP_COS,
icculus@1032
   410
    MOJOSHADER_PRESHADEROP_ASIN,
icculus@1032
   411
    MOJOSHADER_PRESHADEROP_ACOS,
icculus@1032
   412
    MOJOSHADER_PRESHADEROP_ATAN,
icculus@1032
   413
    MOJOSHADER_PRESHADEROP_MIN,
icculus@1032
   414
    MOJOSHADER_PRESHADEROP_MAX,
icculus@1035
   415
    MOJOSHADER_PRESHADEROP_LT,
icculus@1035
   416
    MOJOSHADER_PRESHADEROP_GE,
icculus@1032
   417
    MOJOSHADER_PRESHADEROP_ADD,
icculus@1032
   418
    MOJOSHADER_PRESHADEROP_MUL,
icculus@1032
   419
    MOJOSHADER_PRESHADEROP_ATAN2,
icculus@1033
   420
    MOJOSHADER_PRESHADEROP_DIV,
icculus@1032
   421
    MOJOSHADER_PRESHADEROP_CMP,
icculus@1034
   422
    MOJOSHADER_PRESHADEROP_MOVC,
icculus@1032
   423
    MOJOSHADER_PRESHADEROP_DOT,
icculus@1034
   424
    MOJOSHADER_PRESHADEROP_NOISE,
icculus@1032
   425
    MOJOSHADER_PRESHADEROP_SCALAR_OPS,
icculus@1032
   426
    MOJOSHADER_PRESHADEROP_MIN_SCALAR = MOJOSHADER_PRESHADEROP_SCALAR_OPS,
icculus@1032
   427
    MOJOSHADER_PRESHADEROP_MAX_SCALAR,
icculus@1035
   428
    MOJOSHADER_PRESHADEROP_LT_SCALAR,
icculus@1035
   429
    MOJOSHADER_PRESHADEROP_GE_SCALAR,
icculus@1032
   430
    MOJOSHADER_PRESHADEROP_ADD_SCALAR,
icculus@1032
   431
    MOJOSHADER_PRESHADEROP_MUL_SCALAR,
icculus@1032
   432
    MOJOSHADER_PRESHADEROP_ATAN2_SCALAR,
icculus@1033
   433
    MOJOSHADER_PRESHADEROP_DIV_SCALAR,
icculus@1032
   434
    MOJOSHADER_PRESHADEROP_DOT_SCALAR,
icculus@1034
   435
    MOJOSHADER_PRESHADEROP_NOISE_SCALAR,
icculus@1030
   436
} MOJOSHADER_preshaderOpcode;
icculus@1030
   437
icculus@1030
   438
typedef enum MOJOSHADER_preshaderOperandType
icculus@1030
   439
{
icculus@1030
   440
    MOJOSHADER_PRESHADEROPERAND_INPUT,
icculus@1030
   441
    MOJOSHADER_PRESHADEROPERAND_OUTPUT,
icculus@1030
   442
    MOJOSHADER_PRESHADEROPERAND_LITERAL,
icculus@1030
   443
    MOJOSHADER_PRESHADEROPERAND_TEMP,
icculus@1030
   444
} MOJOSHADER_preshaderOperandType;
icculus@1030
   445
icculus@1030
   446
typedef struct MOJOSHADER_preshaderOperand
icculus@1030
   447
{
icculus@1030
   448
    MOJOSHADER_preshaderOperandType type;
icculus@1030
   449
    unsigned int index;
flibitijibibo@1150
   450
    unsigned int array_register_count;
flibitijibibo@1150
   451
    unsigned int *array_registers;
icculus@1030
   452
} MOJOSHADER_preshaderOperand;
icculus@1030
   453
icculus@1030
   454
typedef struct MOJOSHADER_preshaderInstruction
icculus@1030
   455
{
icculus@1030
   456
    MOJOSHADER_preshaderOpcode opcode;
icculus@1030
   457
    unsigned int element_count;
icculus@1030
   458
    unsigned int operand_count;
flibitijibibo@1150
   459
    MOJOSHADER_preshaderOperand operands[4];
icculus@1030
   460
} MOJOSHADER_preshaderInstruction;
icculus@1030
   461
icculus@1030
   462
typedef struct MOJOSHADER_preshader
icculus@1030
   463
{
icculus@1030
   464
    unsigned int literal_count;
icculus@1030
   465
    double *literals;
icculus@1030
   466
    unsigned int temp_count;  /* scalar, not vector! */
icculus@1042
   467
    unsigned int symbol_count;
icculus@1042
   468
    MOJOSHADER_symbol *symbols;
icculus@1030
   469
    unsigned int instruction_count;
icculus@1030
   470
    MOJOSHADER_preshaderInstruction *instructions;
flibitijibibo@1150
   471
    unsigned int register_count;
flibitijibibo@1150
   472
    float *registers;
icculus@1164
   473
    MOJOSHADER_malloc malloc;
icculus@1164
   474
    MOJOSHADER_free free;
icculus@1164
   475
    void *malloc_data;
icculus@1030
   476
} MOJOSHADER_preshader;
icculus@1030
   477
icculus@536
   478
/*
icculus@536
   479
 * Structure used to return data from parsing of a shader...
icculus@536
   480
 */
icculus@536
   481
/* !!! FIXME: most of these ints should be unsigned. */
icculus@536
   482
typedef struct MOJOSHADER_parseData
icculus@536
   483
{
icculus@536
   484
    /*
icculus@536
   485
     * The number of elements pointed to by (errors).
icculus@536
   486
     */
icculus@536
   487
    int error_count;
icculus@536
   488
icculus@536
   489
    /*
icculus@536
   490
     * (error_count) elements of data that specify errors that were generated
icculus@536
   491
     *  by parsing this shader.
icculus@536
   492
     * This can be NULL if there were no errors or if (error_count) is zero.
icculus@536
   493
     */
icculus@536
   494
    MOJOSHADER_error *errors;
icculus@475
   495
icculus@475
   496
    /*
icculus@187
   497
     * The name of the profile used to parse the shader. Will be NULL on error.
icculus@187
   498
     */
icculus@187
   499
    const char *profile;
icculus@187
   500
icculus@187
   501
    /*
icculus@46
   502
     * Bytes of output from parsing. Most profiles produce a string of source
icculus@46
   503
     *  code, but profiles that do binary output may not be text at all.
icculus@46
   504
     *  Will be NULL on error.
icculus@46
   505
     */
icculus@46
   506
    const char *output;
icculus@46
   507
icculus@46
   508
    /*
icculus@46
   509
     * Byte count for output, not counting any null terminator. Most profiles
icculus@113
   510
     *  produce an ASCII string of source code (which will be null-terminated
icculus@113
   511
     *  even though that null char isn't included in output_len), but profiles
icculus@113
   512
     *  that do binary output may not be text at all. Will be 0 on error.
icculus@46
   513
     */
icculus@46
   514
    int output_len;
icculus@46
   515
icculus@46
   516
    /*
icculus@356
   517
     * Count of Direct3D instruction slots used. This is meaningless in terms
icculus@46
   518
     *  of the actual output, as the profile will probably grow or reduce
icculus@46
   519
     *  the count (or for high-level languages, not have that information at
icculus@356
   520
     *  all). Also, as with Microsoft's own assembler, this value is just a
icculus@356
   521
     *  rough estimate, as unpredicable real-world factors make the actual
icculus@356
   522
     *  value vary at least a little from this count. Still, it can give you
icculus@356
   523
     *  a rough idea of the size of your shader. Will be zero on error.
icculus@46
   524
     */
icculus@46
   525
    int instruction_count;
icculus@46
   526
icculus@46
   527
    /*
icculus@46
   528
     * The type of shader we parsed. Will be MOJOSHADER_TYPE_UNKNOWN on error.
icculus@46
   529
     */
icculus@46
   530
    MOJOSHADER_shaderType shader_type;
icculus@46
   531
icculus@46
   532
    /*
icculus@46
   533
     * The shader's major version. If this was a "vs_3_0", this would be 3.
icculus@46
   534
     */
icculus@46
   535
    int major_ver;
icculus@46
   536
icculus@46
   537
    /*
icculus@46
   538
     * The shader's minor version. If this was a "ps_1_4", this would be 4.
icculus@46
   539
     *  Two notes: for "vs_2_x", this is 1, and for "vs_3_sw", this is 255.
icculus@46
   540
     */
icculus@46
   541
    int minor_ver;
icculus@46
   542
icculus@46
   543
    /*
icculus@1171
   544
     * This is the main function name of the shader. This will be the
icculus@1171
   545
     *  caller-supplied string even if a given profile ignores it (GLSL,
icculus@1171
   546
     *  for example, always uses "main" in the shader output out of necessity,
icculus@1171
   547
     *  and Direct3D assembly has no concept of a "main function", etc).
icculus@1171
   548
     *  Otherwise, it'll be a default name chosen by the profile ("main") or
icculus@1156
   549
     *  whatnot.
icculus@1156
   550
     */
icculus@1156
   551
    const char *mainfn;
icculus@1156
   552
icculus@1156
   553
    /*
icculus@92
   554
     * The number of elements pointed to by (uniforms).
icculus@92
   555
     */
icculus@92
   556
    int uniform_count;
icculus@92
   557
icculus@92
   558
    /*
icculus@94
   559
     * (uniform_count) elements of data that specify Uniforms to be set for
icculus@94
   560
     *  this shader. See discussion on MOJOSHADER_uniform for details.
icculus@145
   561
     * This can be NULL on error or if (uniform_count) is zero.
icculus@92
   562
     */
icculus@92
   563
    MOJOSHADER_uniform *uniforms;
icculus@92
   564
icculus@100
   565
    /*
icculus@278
   566
     * The number of elements pointed to by (constants).
icculus@278
   567
     */
icculus@278
   568
    int constant_count;
icculus@278
   569
icculus@278
   570
    /*
icculus@278
   571
     * (constant_count) elements of data that specify constants used in
icculus@278
   572
     *  this shader. See discussion on MOJOSHADER_constant for details.
icculus@278
   573
     * This can be NULL on error or if (constant_count) is zero.
icculus@278
   574
     *  This is largely informational: constants are hardcoded into a shader.
icculus@278
   575
     *  The constants that you can set like parameters are in the "uniforms"
icculus@278
   576
     *  list.
icculus@278
   577
     */
icculus@278
   578
    MOJOSHADER_constant *constants;
icculus@278
   579
icculus@278
   580
    /*
icculus@148
   581
     * The number of elements pointed to by (samplers).
icculus@148
   582
     */
icculus@148
   583
    int sampler_count;
icculus@148
   584
icculus@148
   585
    /*
icculus@148
   586
     * (sampler_count) elements of data that specify Samplers to be set for
icculus@148
   587
     *  this shader. See discussion on MOJOSHADER_sampler for details.
icculus@148
   588
     * This can be NULL on error or if (sampler_count) is zero.
icculus@148
   589
     */
icculus@148
   590
    MOJOSHADER_sampler *samplers;
icculus@148
   591
icculus@1055
   592
    /* !!! FIXME: this should probably be "input" and not "attribute" */
icculus@148
   593
    /*
icculus@100
   594
     * The number of elements pointed to by (attributes).
icculus@100
   595
     */
icculus@100
   596
    int attribute_count;
icculus@100
   597
icculus@1055
   598
    /* !!! FIXME: this should probably be "input" and not "attribute" */
icculus@100
   599
    /*
icculus@100
   600
     * (attribute_count) elements of data that specify Attributes to be set
icculus@100
   601
     *  for this shader. See discussion on MOJOSHADER_attribute for details.
icculus@145
   602
     * This can be NULL on error or if (attribute_count) is zero.
icculus@100
   603
     */
icculus@100
   604
    MOJOSHADER_attribute *attributes;
icculus@100
   605
icculus@92
   606
    /*
icculus@1055
   607
     * The number of elements pointed to by (outputs).
icculus@1055
   608
     */
icculus@1055
   609
    int output_count;
icculus@1055
   610
icculus@1055
   611
    /*
icculus@1055
   612
     * (output_count) elements of data that specify outputs this shader
icculus@1055
   613
     *  writes to. See discussion on MOJOSHADER_attribute for details.
icculus@1055
   614
     * This can be NULL on error or if (output_count) is zero.
icculus@1055
   615
     */
icculus@1055
   616
    MOJOSHADER_attribute *outputs;
icculus@1055
   617
icculus@1055
   618
    /*
icculus@450
   619
     * The number of elements pointed to by (swizzles).
icculus@450
   620
     */
icculus@450
   621
    int swizzle_count;
icculus@450
   622
icculus@1055
   623
    /* !!! FIXME: this should probably be "input" and not "attribute" */
icculus@450
   624
    /*
icculus@450
   625
     * (swizzle_count) elements of data that specify swizzles the shader will
icculus@450
   626
     *  apply to incoming attributes. This is a copy of what was passed to
icculus@450
   627
     *  MOJOSHADER_parseData().
icculus@450
   628
     * This can be NULL on error or if (swizzle_count) is zero.
icculus@450
   629
     */
icculus@450
   630
    MOJOSHADER_swizzle *swizzles;
icculus@450
   631
icculus@450
   632
    /*
icculus@524
   633
     * The number of elements pointed to by (symbols).
icculus@524
   634
     */
icculus@524
   635
    int symbol_count;
icculus@524
   636
icculus@524
   637
    /*
icculus@524
   638
     * (symbol_count) elements of data that specify high-level symbol data
icculus@524
   639
     *  for the shader. This will be parsed from the CTAB section
icculus@524
   640
     *  in bytecode, and will be a copy of what you provide to
icculus@524
   641
     *  MOJOSHADER_assemble(). This data is optional.
icculus@524
   642
     * This can be NULL on error or if (symbol_count) is zero.
icculus@524
   643
     */
icculus@524
   644
    MOJOSHADER_symbol *symbols;
icculus@524
   645
icculus@524
   646
    /*
icculus@1030
   647
     * !!! FIXME: document me.
icculus@1030
   648
     * This can be NULL on error or if no preshader was available.
icculus@1030
   649
     */
icculus@1030
   650
    MOJOSHADER_preshader *preshader;
icculus@1030
   651
icculus@1030
   652
    /*
icculus@46
   653
     * This is the malloc implementation you passed to MOJOSHADER_parse().
icculus@46
   654
     */
icculus@46
   655
    MOJOSHADER_malloc malloc;
icculus@46
   656
icculus@46
   657
    /*
icculus@46
   658
     * This is the free implementation you passed to MOJOSHADER_parse().
icculus@46
   659
     */
icculus@46
   660
    MOJOSHADER_free free;
icculus@97
   661
icculus@97
   662
    /*
icculus@97
   663
     * This is the pointer you passed as opaque data for your allocator.
icculus@97
   664
     */
icculus@97
   665
    void *malloc_data;
icculus@46
   666
} MOJOSHADER_parseData;
icculus@46
   667
icculus@46
   668
icculus@46
   669
/*
icculus@46
   670
 * Profile string for Direct3D assembly language output.
icculus@46
   671
 */
icculus@46
   672
#define MOJOSHADER_PROFILE_D3D "d3d"
icculus@46
   673
icculus@46
   674
/*
icculus@109
   675
 * Profile string for passthrough of the original bytecode, unchanged.
icculus@109
   676
 */
icculus@469
   677
#define MOJOSHADER_PROFILE_BYTECODE "bytecode"
icculus@109
   678
icculus@109
   679
/*
icculus@46
   680
 * Profile string for GLSL: OpenGL high-level shader language output.
icculus@46
   681
 */
icculus@46
   682
#define MOJOSHADER_PROFILE_GLSL "glsl"
icculus@46
   683
icculus@323
   684
/*
icculus@407
   685
 * Profile string for GLSL 1.20: minor improvements to base GLSL spec.
icculus@407
   686
 */
icculus@407
   687
#define MOJOSHADER_PROFILE_GLSL120 "glsl120"
icculus@407
   688
icculus@407
   689
/*
flibitijibibo@1150
   690
 * Profile string for GLSL ES: minor changes to GLSL output for ES compliance.
flibitijibibo@1150
   691
 */
flibitijibibo@1150
   692
#define MOJOSHADER_PROFILE_GLSLES "glsles"
flibitijibibo@1150
   693
flibitijibibo@1150
   694
/*
icculus@323
   695
 * Profile string for OpenGL ARB 1.0 shaders: GL_ARB_(vertex|fragment)_program.
icculus@323
   696
 */
icculus@323
   697
#define MOJOSHADER_PROFILE_ARB1 "arb1"
icculus@323
   698
icculus@361
   699
/*
icculus@361
   700
 * Profile string for OpenGL ARB 1.0 shaders with Nvidia 2.0 extensions:
icculus@361
   701
 *  GL_NV_vertex_program2_option and GL_NV_fragment_program2
icculus@361
   702
 */
icculus@361
   703
#define MOJOSHADER_PROFILE_NV2 "nv2"
icculus@361
   704
icculus@361
   705
/*
icculus@361
   706
 * Profile string for OpenGL ARB 1.0 shaders with Nvidia 3.0 extensions:
icculus@361
   707
 *  GL_NV_vertex_program3 and GL_NV_fragment_program2
icculus@361
   708
 */
icculus@421
   709
#define MOJOSHADER_PROFILE_NV3 "nv3"
icculus@361
   710
icculus@361
   711
/*
icculus@361
   712
 * Profile string for OpenGL ARB 1.0 shaders with Nvidia 4.0 extensions:
icculus@454
   713
 *  GL_NV_gpu_program4
icculus@361
   714
 */
icculus@431
   715
#define MOJOSHADER_PROFILE_NV4 "nv4"
icculus@361
   716
icculus@458
   717
/*
icculus@1156
   718
 * Profile string for Metal: Apple's lowlevel API's high-level shader language.
icculus@1156
   719
 */
icculus@1156
   720
#define MOJOSHADER_PROFILE_METAL "metal"
icculus@1156
   721
icculus@1156
   722
/*
icculus@458
   723
 * Determine the highest supported Shader Model for a profile.
icculus@458
   724
 */
flibitijibibo@1150
   725
DECLSPEC int MOJOSHADER_maxShaderModel(const char *profile);
icculus@458
   726
icculus@97
   727
icculus@46
   728
/*
icculus@46
   729
 * Parse a compiled Direct3D shader's bytecode.
icculus@46
   730
 *
icculus@46
   731
 * This is your primary entry point into MojoShader. You need to pass it
icculus@46
   732
 *  a compiled D3D shader and tell it which "profile" you want to use to
icculus@46
   733
 *  convert it into useful data.
icculus@46
   734
 *
icculus@46
   735
 * The available profiles are the set of MOJOSHADER_PROFILE_* defines.
icculus@46
   736
 *  Note that MojoShader may be built without support for all listed
icculus@46
   737
 *  profiles (in which case using one here will return with an error).
icculus@46
   738
 *
icculus@46
   739
 * As parsing requires some memory to be allocated, you may provide a custom
icculus@46
   740
 *  allocator to this function, which will be used to allocate/free memory.
icculus@46
   741
 *  They function just like malloc() and free(). We do not use realloc().
icculus@97
   742
 *  If you don't care, pass NULL in for the allocator functions. If your
icculus@97
   743
 *  allocator needs instance-specific data, you may supply it with the
icculus@97
   744
 *  (d) parameter. This pointer is passed as-is to your (m) and (f) functions.
icculus@46
   745
 *
icculus@97
   746
 * This function returns a MOJOSHADER_parseData.
icculus@46
   747
 *
icculus@46
   748
 * This function will never return NULL, even if the system is completely
icculus@46
   749
 *  out of memory upon entry (in which case, this function returns a static
icculus@46
   750
 *  MOJOSHADER_parseData object, which is still safe to pass to
icculus@46
   751
 *  MOJOSHADER_freeParseData()).
icculus@46
   752
 *
icculus@450
   753
 * You can tell the generated program to swizzle certain inputs. If you know
icculus@450
   754
 *  that COLOR0 should be RGBA but you're passing in ARGB, you can specify
icculus@450
   755
 *  a swizzle of { MOJOSHADER_USAGE_COLOR, 0, {1,2,3,0} } to (swiz). If the
icculus@450
   756
 *  input register in the code would produce reg.ywzx, that swizzle would
icculus@450
   757
 *  change it to reg.wzxy ... (swiz) can be NULL.
icculus@450
   758
 *
icculus@1104
   759
 * You can force the shader to expect samplers of certain types. Generally
icculus@1104
   760
 *  you don't need this, as Shader Model 2 and later always specify what they
icculus@1104
   761
 *  expect samplers to be (2D, cubemap, etc). Shader Model 1, however, just
icculus@1104
   762
 *  uses whatever is bound to a given sampler at draw time, but this doesn't
icculus@1104
   763
 *  work in OpenGL, etc. In these cases, MojoShader will default to
icculus@1106
   764
 *  2D texture sampling (or cubemap sampling, in cases where it makes sense,
icculus@1106
   765
 *  like the TEXM3X3TEX opcode), which works 75% of the time, but if you
icculus@1106
   766
 *  really needed something else, you'll need to specify it here. This can
icculus@1106
   767
 *  also be used, at your own risk, to override DCL opcodes in shaders: if
icculus@1106
   768
 *  the shader explicit says 2D, but you want Cubemap, for example, you can
icculus@1106
   769
 *  use this to override. If you aren't sure about any of this stuff, you can
icculus@1106
   770
 *  (and should) almost certainly ignore it: (smap) can be NULL.
icculus@1104
   771
 *
icculus@1143
   772
 * (bufsize) is the size in bytes of (tokenbuf). If (bufsize) is zero,
icculus@1143
   773
 *  MojoShader will attempt to figure out the size of the buffer, but you
icculus@1143
   774
 *  risk a buffer overflow if you have corrupt data, etc. Supply the value
icculus@1143
   775
 *  if you can.
icculus@1143
   776
 *
icculus@1156
   777
 * You should pass a name for your shader's main function in here, via the
icculus@1156
   778
 *  (mainfn) param. Some profiles need this name to be unique. Passing a NULL
icculus@1156
   779
 *  here will pick a reasonable default, and most profiles will ignore it
icculus@1156
   780
 *  anyhow. As the name of the shader's main function, etc, so make it a
icculus@1156
   781
 *  simple name that would match C's identifier rules. Keep it simple!
icculus@1156
   782
 *
icculus@187
   783
 * This function is thread safe, so long as (m) and (f) are too, and that
icculus@46
   784
 *  (tokenbuf) remains intact for the duration of the call. This allows you
icculus@46
   785
 *  to parse several shaders on separate CPU cores at the same time.
icculus@46
   786
 */
flibitijibibo@1150
   787
DECLSPEC const MOJOSHADER_parseData *MOJOSHADER_parse(const char *profile,
icculus@1156
   788
                                                      const char *mainfn,
flibitijibibo@1150
   789
                                                      const unsigned char *tokenbuf,
flibitijibibo@1150
   790
                                                      const unsigned int bufsize,
flibitijibibo@1150
   791
                                                      const MOJOSHADER_swizzle *swiz,
flibitijibibo@1150
   792
                                                      const unsigned int swizcount,
flibitijibibo@1150
   793
                                                      const MOJOSHADER_samplerMap *smap,
flibitijibibo@1150
   794
                                                      const unsigned int smapcount,
flibitijibibo@1150
   795
                                                      MOJOSHADER_malloc m,
flibitijibibo@1150
   796
                                                      MOJOSHADER_free f,
flibitijibibo@1150
   797
                                                      void *d);
flibitijibibo@1150
   798
icculus@46
   799
icculus@46
   800
/*
icculus@46
   801
 * Call this to dispose of parsing results when you are done with them.
icculus@46
   802
 *  This will call the MOJOSHADER_free function you provided to
icculus@46
   803
 *  MOJOSHADER_parse multiple times, if you provided one.
icculus@46
   804
 *  Passing a NULL here is a safe no-op.
icculus@46
   805
 *
icculus@46
   806
 * This function is thread safe, so long as any allocator you passed into
icculus@46
   807
 *  MOJOSHADER_parse() is, too.
icculus@46
   808
 */
flibitijibibo@1150
   809
DECLSPEC void MOJOSHADER_freeParseData(const MOJOSHADER_parseData *data);
icculus@7
   810
icculus@196
   811
icculus@1164
   812
/*
icculus@1164
   813
 * You almost certainly don't need this function, unless you absolutely know
icculus@1164
   814
 *  why you need it without hesitation. This is useful if you're doing
icculus@1164
   815
 *  extremely low-level shader work or building specialized tools.
icculus@1164
   816
 *
icculus@1164
   817
 * Parse a preshader structure. This expects a buffer of bytes that represents
icculus@1164
   818
 *  the preshader data starting with its magic number token and ending at
icculus@1164
   819
 *  the end of the comment tokens that contain this preshader. Note that it
icculus@1164
   820
 *  does _not_ start at the beginning of the comment tokens.
icculus@1164
   821
 *
icculus@1164
   822
 * On success, this will return a MOJOSHADER_preshader. This can be
icculus@1164
   823
 *  deallocated later by calling MOJOSHADER_freePreshader(). On failure,
icculus@1164
   824
 *  this will return NULL. Unlike other MojoShader APIs, this assumes you
icculus@1164
   825
 *  either have a complete and valid buffer of preshader tokens or you have
icculus@1164
   826
 *  incomplete/corrupted data, so there is no explicit error reporting. Please
icculus@1164
   827
 *  note that if the system runs out of memory, this function will also return
icculus@1164
   828
 *  NULL without distinction.
icculus@1164
   829
 *
icculus@1164
   830
 * This function is thread safe, so long as any allocator you passed into
icculus@1164
   831
 *  MOJOSHADER_parsePreshader() is, too.
icculus@1164
   832
 */
flibitijibibo@1150
   833
DECLSPEC const MOJOSHADER_preshader *MOJOSHADER_parsePreshader(const unsigned char *buf,
flibitijibibo@1150
   834
                                                               const unsigned int len,
flibitijibibo@1150
   835
                                                               MOJOSHADER_malloc m,
flibitijibibo@1150
   836
                                                               MOJOSHADER_free f,
flibitijibibo@1150
   837
                                                               void *d);
icculus@1019
   838
icculus@1019
   839
icculus@1164
   840
/*
icculus@1164
   841
 * You almost certainly don't need this function, unless you absolutely know
icculus@1164
   842
 *  why you need it without hesitation. This is useful if you're doing
icculus@1164
   843
 *  extremely low-level shader work or building specialized tools.
icculus@1164
   844
 *
icculus@1164
   845
 * Call this to dispose of preshader parsing results when you are done with
icculus@1164
   846
 *  them. This will call the MOJOSHADER_free function you provided to
icculus@1164
   847
 *  MOJOSHADER_parsePreshader() multiple times, if you provided one.
icculus@1164
   848
 *  Passing a NULL here is a safe no-op.
icculus@1164
   849
 *
icculus@1164
   850
 * You only need to call this function for results from a call to
icculus@1164
   851
 *  MOJOSHADER_parsePreshader(). Other MojoShader structures with a preshader
icculus@1164
   852
 *  field, such as MOJOSHADER_parseData(), should not use this function, as
icculus@1164
   853
 *  the preshader will be deallocated with everything else in
icculus@1164
   854
 *  MOJOSHADER_freeParseData(), etc.
icculus@1164
   855
 *
icculus@1164
   856
 * This function is thread safe, so long as any allocator you passed into
icculus@1164
   857
 *  MOJOSHADER_parsePreshader() is, too.
icculus@1164
   858
 */
icculus@1164
   859
DECLSPEC void MOJOSHADER_freePreshader(const MOJOSHADER_preshader *preshader);
flibitijibibo@1150
   860
flibitijibibo@1150
   861
flibitijibibo@1150
   862
/* Effects interface... */
flibitijibibo@1150
   863
#include "mojoshader_effects.h"
icculus@1019
   864
icculus@218
   865
icculus@555
   866
/* Preprocessor interface... */
icculus@555
   867
icculus@555
   868
/*
icculus@555
   869
 * Structure used to pass predefined macros. Maps to D3DXMACRO.
icculus@675
   870
 *  You can have macro arguments: set identifier to "a(b, c)" or whatever.
icculus@555
   871
 */
icculus@555
   872
typedef struct MOJOSHADER_preprocessorDefine
icculus@555
   873
{
icculus@555
   874
    const char *identifier;
icculus@555
   875
    const char *definition;
icculus@555
   876
} MOJOSHADER_preprocessorDefine;
icculus@555
   877
icculus@555
   878
/*
icculus@555
   879
 * Used with the MOJOSHADER_includeOpen callback. Maps to D3DXINCLUDE_TYPE.
icculus@555
   880
 */
icculus@555
   881
typedef enum
icculus@555
   882
{
icculus@555
   883
    MOJOSHADER_INCLUDETYPE_LOCAL,   /* local header: #include "blah.h" */
icculus@555
   884
    MOJOSHADER_INCLUDETYPE_SYSTEM   /* system header: #include <blah.h> */
icculus@555
   885
} MOJOSHADER_includeType;
icculus@555
   886
icculus@555
   887
icculus@555
   888
/*
icculus@555
   889
 * Structure used to return data from preprocessing of a shader...
icculus@555
   890
 */
icculus@555
   891
/* !!! FIXME: most of these ints should be unsigned. */
icculus@555
   892
typedef struct MOJOSHADER_preprocessData
icculus@555
   893
{
icculus@555
   894
    /*
icculus@555
   895
     * The number of elements pointed to by (errors).
icculus@555
   896
     */
icculus@555
   897
    int error_count;
icculus@555
   898
icculus@555
   899
    /*
icculus@555
   900
     * (error_count) elements of data that specify errors that were generated
icculus@555
   901
     *  by parsing this shader.
icculus@555
   902
     * This can be NULL if there were no errors or if (error_count) is zero.
icculus@555
   903
     */
icculus@555
   904
    MOJOSHADER_error *errors;
icculus@555
   905
icculus@555
   906
    /*
icculus@579
   907
     * Bytes of output from preprocessing. This is a UTF-8 string. We
icculus@555
   908
     *  guarantee it to be NULL-terminated. Will be NULL on error.
icculus@555
   909
     */
icculus@555
   910
    const char *output;
icculus@555
   911
icculus@555
   912
    /*
icculus@555
   913
     * Byte count for output, not counting any null terminator.
icculus@555
   914
     *  Will be 0 on error.
icculus@555
   915
     */
icculus@555
   916
    int output_len;
icculus@555
   917
icculus@555
   918
    /*
icculus@555
   919
     * This is the malloc implementation you passed to MOJOSHADER_parse().
icculus@555
   920
     */
icculus@555
   921
    MOJOSHADER_malloc malloc;
icculus@555
   922
icculus@555
   923
    /*
icculus@555
   924
     * This is the free implementation you passed to MOJOSHADER_parse().
icculus@555
   925
     */
icculus@555
   926
    MOJOSHADER_free free;
icculus@555
   927
icculus@555
   928
    /*
icculus@555
   929
     * This is the pointer you passed as opaque data for your allocator.
icculus@555
   930
     */
icculus@555
   931
    void *malloc_data;
icculus@555
   932
} MOJOSHADER_preprocessData;
icculus@555
   933
icculus@555
   934
icculus@555
   935
/*
icculus@555
   936
 * This callback allows an app to handle #include statements for the
icculus@555
   937
 *  preprocessor. When the preprocessor sees an #include, it will call this
icculus@555
   938
 *  function to obtain the contents of the requested file. This is optional;
icculus@728
   939
 *  the preprocessor will open files directly if no callback is supplied, but
icculus@555
   940
 *  this allows an app to retrieve data from something other than the
icculus@555
   941
 *  traditional filesystem (for example, headers packed in a .zip file or
icculus@555
   942
 *  headers generated on-the-fly).
icculus@555
   943
 *
icculus@555
   944
 * This function maps to ID3DXInclude::Open()
icculus@555
   945
 *
icculus@555
   946
 * (inctype) specifies the type of header we wish to include.
icculus@555
   947
 * (fname) specifies the name of the file specified on the #include line.
icculus@555
   948
 * (parent) is a string of the entire source file containing the include, in
icculus@555
   949
 *  its original, not-yet-preprocessed state. Note that this is just the
icculus@555
   950
 *  contents of the specific file, not all source code that the preprocessor
icculus@555
   951
 *  has seen through other includes, etc.
icculus@555
   952
 * (outdata) will be set by the callback to a pointer to the included file's
icculus@555
   953
 *  contents. The callback is responsible for allocating this however they
icculus@555
   954
 *  see fit (we provide allocator functions, but you may ignore them). This
icculus@555
   955
 *  pointer must remain valid until the includeClose callback runs. This
icculus@555
   956
 *  string does not need to be NULL-terminated.
icculus@555
   957
 * (outbytes) will be set by the callback to the number of bytes pointed to
icculus@555
   958
 *  by (outdata).
icculus@555
   959
 * (m),(f), and (d) are the allocator details that the application passed to
icculus@555
   960
 *  MojoShader. If these were NULL, MojoShader may have replaced them with its
icculus@555
   961
 *  own internal allocators.
icculus@555
   962
 *
icculus@555
   963
 * The callback returns zero on error, non-zero on success.
icculus@555
   964
 *
icculus@555
   965
 * If you supply an includeOpen callback, you must supply includeClose, too.
icculus@555
   966
 */
flibitijibibo@1150
   967
typedef int (MOJOSHADERCALL *MOJOSHADER_includeOpen)(MOJOSHADER_includeType inctype,
icculus@555
   968
                            const char *fname, const char *parent,
icculus@555
   969
                            const char **outdata, unsigned int *outbytes,
icculus@555
   970
                            MOJOSHADER_malloc m, MOJOSHADER_free f, void *d);
icculus@555
   971
icculus@555
   972
/*
icculus@555
   973
 * This callback allows an app to clean up the results of a previous
icculus@555
   974
 *  includeOpen callback.
icculus@555
   975
 *
icculus@555
   976
 * This function maps to ID3DXInclude::Close()
icculus@555
   977
 *
icculus@555
   978
 * (data) is the data that was returned from a previous call to includeOpen.
icculus@555
   979
 *  It is now safe to deallocate this data.
icculus@555
   980
 * (m),(f), and (d) are the same allocator details that were passed to your
icculus@555
   981
 *  includeOpen callback.
icculus@555
   982
 *
icculus@555
   983
 * If you supply an includeClose callback, you must supply includeOpen, too.
icculus@555
   984
 */
flibitijibibo@1150
   985
typedef void (MOJOSHADERCALL *MOJOSHADER_includeClose)(const char *data,
icculus@555
   986
                            MOJOSHADER_malloc m, MOJOSHADER_free f, void *d);
icculus@555
   987
icculus@555
   988
icculus@555
   989
/*
icculus@555
   990
 * This function is optional. Even if you are dealing with shader source
icculus@555
   991
 *  code, you don't need to explicitly use the preprocessor, as the compiler
icculus@555
   992
 *  and assembler will use it behind the scenes. In fact, you probably never
icculus@555
   993
 *  need this function unless you are debugging a custom tool (or debugging
icculus@555
   994
 *  MojoShader itself).
icculus@555
   995
 *
icculus@555
   996
 * Preprocessing roughly follows the syntax of an ANSI C preprocessor, as
icculus@555
   997
 *  Microsoft's Direct3D assembler and HLSL compiler use this syntax. Please
icculus@555
   998
 *  note that we try to match the output you'd get from Direct3D's
icculus@555
   999
 *  preprocessor, which has some quirks if you're expecting output that matches
icculus@555
  1000
 *  a generic C preprocessor.
icculus@555
  1001
 *
icculus@555
  1002
 * This function maps to D3DXPreprocessShader().
icculus@555
  1003
 *
icculus@578
  1004
 * (filename) is a NULL-terminated UTF-8 filename. It can be NULL. We do not
icculus@578
  1005
 *  actually access this file, as we obtain our data from (source). This
icculus@578
  1006
 *  string is copied when we need to report errors while processing (source),
icculus@578
  1007
 *  as opposed to errors in a file referenced via the #include directive in
icculus@578
  1008
 *  (source). If this is NULL, then errors will report the filename as NULL,
icculus@578
  1009
 *  too.
icculus@578
  1010
 *
icculus@578
  1011
 * (source) is an string of UTF-8 text to preprocess. It does not need to be
icculus@555
  1012
 *  NULL-terminated.
icculus@555
  1013
 *
icculus@555
  1014
 * (sourcelen) is the length of the string pointed to by (source), in bytes.
icculus@555
  1015
 *
icculus@555
  1016
 * (defines) points to (define_count) preprocessor definitions, and can be
icculus@555
  1017
 *  NULL. These are treated by the preprocessor as if the source code started
icculus@555
  1018
 *  with one #define for each entry you pass in here.
icculus@555
  1019
 *
icculus@555
  1020
 * (include_open) and (include_close) let the app control the preprocessor's
icculus@555
  1021
 *  behaviour for #include statements. Both are optional and can be NULL, but
icculus@555
  1022
 *  both must be specified if either is specified.
icculus@555
  1023
 *
icculus@555
  1024
 * This will return a MOJOSHADER_preprocessorData. You should pass this
icculus@555
  1025
 *  return value to MOJOSHADER_freePreprocessData() when you are done with
icculus@555
  1026
 *  it.
icculus@555
  1027
 *
icculus@555
  1028
 * This function will never return NULL, even if the system is completely
icculus@555
  1029
 *  out of memory upon entry (in which case, this function returns a static
icculus@555
  1030
 *  MOJOSHADER_preprocessData object, which is still safe to pass to
icculus@555
  1031
 *  MOJOSHADER_freePreprocessData()).
icculus@555
  1032
 *
icculus@555
  1033
 * As preprocessing requires some memory to be allocated, you may provide a
icculus@555
  1034
 *  custom allocator to this function, which will be used to allocate/free
icculus@555
  1035
 *  memory. They function just like malloc() and free(). We do not use
icculus@555
  1036
 *  realloc(). If you don't care, pass NULL in for the allocator functions.
icculus@555
  1037
 *  If your allocator needs instance-specific data, you may supply it with the
icculus@555
  1038
 *  (d) parameter. This pointer is passed as-is to your (m) and (f) functions.
icculus@555
  1039
 *
icculus@555
  1040
 * This function is thread safe, so long as the various callback functions
icculus@555
  1041
 *  are, too, and that the parameters remains intact for the duration of the
icculus@555
  1042
 *  call. This allows you to preprocess several shaders on separate CPU cores
icculus@555
  1043
 *  at the same time.
icculus@555
  1044
 */
flibitijibibo@1150
  1045
DECLSPEC const MOJOSHADER_preprocessData *MOJOSHADER_preprocess(const char *filename,
icculus@578
  1046
                             const char *source, unsigned int sourcelen,
icculus@658
  1047
                             const MOJOSHADER_preprocessorDefine *defines,
icculus@555
  1048
                             unsigned int define_count,
icculus@555
  1049
                             MOJOSHADER_includeOpen include_open,
icculus@555
  1050
                             MOJOSHADER_includeClose include_close,
icculus@555
  1051
                             MOJOSHADER_malloc m, MOJOSHADER_free f, void *d);
icculus@555
  1052
icculus@555
  1053
icculus@555
  1054
/*
icculus@555
  1055
 * Call this to dispose of preprocessing results when you are done with them.
icculus@555
  1056
 *  This will call the MOJOSHADER_free function you provided to
icculus@555
  1057
 *  MOJOSHADER_preprocess() multiple times, if you provided one.
icculus@555
  1058
 *  Passing a NULL here is a safe no-op.
icculus@555
  1059
 *
icculus@555
  1060
 * This function is thread safe, so long as any allocator you passed into
icculus@555
  1061
 *  MOJOSHADER_preprocess() is, too.
icculus@555
  1062
 */
flibitijibibo@1150
  1063
DECLSPEC void MOJOSHADER_freePreprocessData(const MOJOSHADER_preprocessData *data);
icculus@555
  1064
icculus@555
  1065
icculus@465
  1066
/* Assembler interface... */
icculus@465
  1067
icculus@465
  1068
/*
icculus@465
  1069
 * This function is optional. Use this to convert Direct3D shader assembly
icculus@465
  1070
 *  language into bytecode, which can be handled by MOJOSHADER_parse().
icculus@465
  1071
 *
icculus@578
  1072
 * (filename) is a NULL-terminated UTF-8 filename. It can be NULL. We do not
icculus@578
  1073
 *  actually access this file, as we obtain our data from (source). This
icculus@578
  1074
 *  string is copied when we need to report errors while processing (source),
icculus@578
  1075
 *  as opposed to errors in a file referenced via the #include directive in
icculus@578
  1076
 *  (source). If this is NULL, then errors will report the filename as NULL,
icculus@578
  1077
 *  too.
icculus@578
  1078
 *
icculus@578
  1079
 * (source) is an UTF-8 string of valid Direct3D shader assembly source code.
icculus@562
  1080
 *  It does not need to be NULL-terminated.
icculus@562
  1081
 *
icculus@562
  1082
 * (sourcelen) is the length of the string pointed to by (source), in bytes.
icculus@465
  1083
 *
icculus@579
  1084
 * (comments) points to (comment_count) NULL-terminated UTF-8 strings, and
icculus@524
  1085
 *  can be NULL. These strings are inserted as comments in the bytecode.
icculus@524
  1086
 *
icculus@524
  1087
 * (symbols) points to (symbol_count) symbol structs, and can be NULL. These
icculus@524
  1088
 *  become a CTAB field in the bytecode. This is optional, but
icculus@524
  1089
 *  MOJOSHADER_parse() needs CTAB data for all arrays used in a program, or
icculus@524
  1090
 *  relative addressing will not be permitted, so you'll want to at least
icculus@524
  1091
 *  provide symbol information for those. The symbol data is 100% trusted
icculus@524
  1092
 *  at this time; it will not be checked to see if it matches what was
icculus@524
  1093
 *  assembled in any way whatsoever.
icculus@524
  1094
 *
icculus@562
  1095
 * (defines) points to (define_count) preprocessor definitions, and can be
icculus@562
  1096
 *  NULL. These are treated by the preprocessor as if the source code started
icculus@562
  1097
 *  with one #define for each entry you pass in here.
icculus@562
  1098
 *
icculus@562
  1099
 * (include_open) and (include_close) let the app control the preprocessor's
icculus@562
  1100
 *  behaviour for #include statements. Both are optional and can be NULL, but
icculus@562
  1101
 *  both must be specified if either is specified.
icculus@562
  1102
 *
icculus@562
  1103
 * This will return a MOJOSHADER_parseData, like MOJOSHADER_parse() would,
icculus@470
  1104
 *  except the profile will be MOJOSHADER_PROFILE_BYTECODE and the output
icculus@470
  1105
 *  will be the assembled bytecode instead of some other language. This output
icculus@470
  1106
 *  can be pushed back through MOJOSHADER_parseData() with a different profile.
icculus@470
  1107
 *
icculus@470
  1108
 * This function will never return NULL, even if the system is completely
icculus@470
  1109
 *  out of memory upon entry (in which case, this function returns a static
icculus@470
  1110
 *  MOJOSHADER_parseData object, which is still safe to pass to
icculus@470
  1111
 *  MOJOSHADER_freeParseData()).
icculus@470
  1112
 *
icculus@465
  1113
 * As assembling requires some memory to be allocated, you may provide a
icculus@465
  1114
 *  custom allocator to this function, which will be used to allocate/free
icculus@465
  1115
 *  memory. They function just like malloc() and free(). We do not use
icculus@465
  1116
 *  realloc(). If you don't care, pass NULL in for the allocator functions.
icculus@465
  1117
 *  If your allocator needs instance-specific data, you may supply it with the
icculus@465
  1118
 *  (d) parameter. This pointer is passed as-is to your (m) and (f) functions.
icculus@465
  1119
 *
icculus@562
  1120
 * This function is thread safe, so long as the various callback functions
icculus@562
  1121
 *  are, too, and that the parameters remains intact for the duration of the
icculus@562
  1122
 *  call. This allows you to assemble several shaders on separate CPU cores
icculus@562
  1123
 *  at the same time.
icculus@465
  1124
 */
flibitijibibo@1150
  1125
DECLSPEC const MOJOSHADER_parseData *MOJOSHADER_assemble(const char *filename,
icculus@578
  1126
                             const char *source, unsigned int sourcelen,
icculus@524
  1127
                             const char **comments, unsigned int comment_count,
icculus@524
  1128
                             const MOJOSHADER_symbol *symbols,
icculus@524
  1129
                             unsigned int symbol_count,
icculus@658
  1130
                             const MOJOSHADER_preprocessorDefine *defines,
icculus@562
  1131
                             unsigned int define_count,
icculus@562
  1132
                             MOJOSHADER_includeOpen include_open,
icculus@562
  1133
                             MOJOSHADER_includeClose include_close,
icculus@524
  1134
                             MOJOSHADER_malloc m, MOJOSHADER_free f, void *d);
icculus@465
  1135
icculus@465
  1136
icculus@931
  1137
/* High level shading language support... */
icculus@931
  1138
icculus@931
  1139
/*
icculus@931
  1140
 * Source profile strings for HLSL: Direct3D High Level Shading Language.
icculus@931
  1141
 */
icculus@931
  1142
#define MOJOSHADER_SRC_PROFILE_HLSL_VS_1_1 "hlsl_vs_1_1"
icculus@931
  1143
#define MOJOSHADER_SRC_PROFILE_HLSL_VS_2_0 "hlsl_vs_2_0"
icculus@931
  1144
#define MOJOSHADER_SRC_PROFILE_HLSL_VS_3_0 "hlsl_vs_3_0"
icculus@931
  1145
#define MOJOSHADER_SRC_PROFILE_HLSL_PS_1_1 "hlsl_ps_1_1"
icculus@931
  1146
#define MOJOSHADER_SRC_PROFILE_HLSL_PS_1_2 "hlsl_ps_1_2"
icculus@931
  1147
#define MOJOSHADER_SRC_PROFILE_HLSL_PS_1_3 "hlsl_ps_1_3"
icculus@931
  1148
#define MOJOSHADER_SRC_PROFILE_HLSL_PS_1_4 "hlsl_ps_1_4"
icculus@931
  1149
#define MOJOSHADER_SRC_PROFILE_HLSL_PS_2_0 "hlsl_ps_2_0"
icculus@931
  1150
#define MOJOSHADER_SRC_PROFILE_HLSL_PS_3_0 "hlsl_ps_3_0"
icculus@931
  1151
icculus@931
  1152
icculus@931
  1153
/* Abstract Syntax Tree interface... */
icculus@931
  1154
icculus@931
  1155
/*
icculus@931
  1156
 * ATTENTION: This adds a lot of stuff to the API, but almost everyone can
icculus@931
  1157
 *  ignore this section. Seriously, go ahead and skip over anything that has
icculus@931
  1158
 *  "AST" in it, unless you know why you'd want to use it.
icculus@931
  1159
 *
icculus@931
  1160
 * ALSO: This API is still evolving! We make no promises at this time to keep
icculus@931
  1161
 *  source or binary compatibility for the AST pieces.
icculus@964
  1162
 *
icculus@964
  1163
 * Important notes:
icculus@964
  1164
 *  - ASTs are the result of parsing the source code: a program that fails to
icculus@964
  1165
 *    compile will often parse successfully. Undeclared variables,
icculus@964
  1166
 *    type incompatibilities, etc, aren't detected at this point.
icculus@964
  1167
 *  - Vector swizzles (the ".xyzw" part of "MyVec4.xyzw") will look like
icculus@964
  1168
 *    structure dereferences. We don't realize these are actually swizzles
icculus@964
  1169
 *    until semantic analysis.
icculus@964
  1170
 *  - MOJOSHADER_astDataType info is not reliable when returned from
icculus@964
  1171
 *    MOJOSHADER_parseAst()! Most of the datatype info will be missing or have
icculus@964
  1172
 *    inaccurate data types. We sort these out during semantic analysis, which
icculus@964
  1173
 *    happens after the AST parsing is complete. A few are filled in, or can
icculus@964
  1174
 *    be deduced fairly trivially by processing several pieces into one.
icculus@964
  1175
 *    It's enough that you can reproduce the original source code, more or
icculus@964
  1176
 *    less, from the AST.
icculus@931
  1177
 */
icculus@931
  1178
icculus@964
  1179
/* High-level datatypes for AST nodes. */
icculus@964
  1180
typedef enum MOJOSHADER_astDataTypeType
icculus@964
  1181
{
icculus@964
  1182
    MOJOSHADER_AST_DATATYPE_NONE,
icculus@964
  1183
    MOJOSHADER_AST_DATATYPE_BOOL,
icculus@964
  1184
    MOJOSHADER_AST_DATATYPE_INT,
icculus@964
  1185
    MOJOSHADER_AST_DATATYPE_UINT,
icculus@964
  1186
    MOJOSHADER_AST_DATATYPE_FLOAT,
icculus@964
  1187
    MOJOSHADER_AST_DATATYPE_FLOAT_SNORM,
icculus@964
  1188
    MOJOSHADER_AST_DATATYPE_FLOAT_UNORM,
icculus@964
  1189
    MOJOSHADER_AST_DATATYPE_HALF,
icculus@964
  1190
    MOJOSHADER_AST_DATATYPE_DOUBLE,
icculus@964
  1191
    MOJOSHADER_AST_DATATYPE_STRING,
icculus@964
  1192
    MOJOSHADER_AST_DATATYPE_SAMPLER_1D,
icculus@964
  1193
    MOJOSHADER_AST_DATATYPE_SAMPLER_2D,
icculus@964
  1194
    MOJOSHADER_AST_DATATYPE_SAMPLER_3D,
icculus@964
  1195
    MOJOSHADER_AST_DATATYPE_SAMPLER_CUBE,
icculus@964
  1196
    MOJOSHADER_AST_DATATYPE_SAMPLER_STATE,
icculus@964
  1197
    MOJOSHADER_AST_DATATYPE_SAMPLER_COMPARISON_STATE,
icculus@964
  1198
    MOJOSHADER_AST_DATATYPE_STRUCT,
icculus@964
  1199
    MOJOSHADER_AST_DATATYPE_ARRAY,
icculus@964
  1200
    MOJOSHADER_AST_DATATYPE_VECTOR,
icculus@964
  1201
    MOJOSHADER_AST_DATATYPE_MATRIX,
icculus@964
  1202
    MOJOSHADER_AST_DATATYPE_BUFFER,
icculus@964
  1203
    MOJOSHADER_AST_DATATYPE_FUNCTION,
icculus@964
  1204
    MOJOSHADER_AST_DATATYPE_USER,
icculus@964
  1205
} MOJOSHADER_astDataTypeType;
icculus@964
  1206
#define MOJOSHADER_AST_DATATYPE_CONST (1 << 31)
icculus@964
  1207
icculus@964
  1208
typedef union MOJOSHADER_astDataType MOJOSHADER_astDataType;
icculus@964
  1209
icculus@964
  1210
// This is just part of DataTypeStruct, never appears outside of it.
icculus@964
  1211
typedef struct MOJOSHADER_astDataTypeStructMember
icculus@964
  1212
{
icculus@964
  1213
    const MOJOSHADER_astDataType *datatype;
icculus@964
  1214
    const char *identifier;
icculus@964
  1215
} MOJOSHADER_astDataTypeStructMember;
icculus@964
  1216
icculus@964
  1217
typedef struct MOJOSHADER_astDataTypeStruct
icculus@964
  1218
{
icculus@964
  1219
    MOJOSHADER_astDataTypeType type;
icculus@964
  1220
    const MOJOSHADER_astDataTypeStructMember *members;
icculus@964
  1221
    int member_count;
icculus@964
  1222
} MOJOSHADER_astDataTypeStruct;
icculus@964
  1223
icculus@964
  1224
typedef struct MOJOSHADER_astDataTypeArray
icculus@964
  1225
{
icculus@964
  1226
    MOJOSHADER_astDataTypeType type;
icculus@964
  1227
    const MOJOSHADER_astDataType *base;
icculus@964
  1228
    int elements;
icculus@964
  1229
} MOJOSHADER_astDataTypeArray;
icculus@964
  1230
icculus@964
  1231
typedef MOJOSHADER_astDataTypeArray MOJOSHADER_astDataTypeVector;
icculus@964
  1232
icculus@964
  1233
typedef struct MOJOSHADER_astDataTypeMatrix
icculus@964
  1234
{
icculus@964
  1235
    MOJOSHADER_astDataTypeType type;
icculus@964
  1236
    const MOJOSHADER_astDataType *base;
icculus@964
  1237
    int rows;
icculus@964
  1238
    int columns;
icculus@964
  1239
} MOJOSHADER_astDataTypeMatrix;
icculus@964
  1240
icculus@964
  1241
typedef struct MOJOSHADER_astDataTypeBuffer
icculus@964
  1242
{
icculus@964
  1243
    MOJOSHADER_astDataTypeType type;
icculus@964
  1244
    const MOJOSHADER_astDataType *base;
icculus@964
  1245
} MOJOSHADER_astDataTypeBuffer;
icculus@964
  1246
icculus@964
  1247
typedef struct MOJOSHADER_astDataTypeFunction
icculus@964
  1248
{
icculus@964
  1249
    MOJOSHADER_astDataTypeType type;
icculus@964
  1250
    const MOJOSHADER_astDataType *retval;
icculus@973
  1251
    const MOJOSHADER_astDataType **params;
icculus@964
  1252
    int num_params;
icculus@973
  1253
    int intrinsic;  /* non-zero for built-in functions */
icculus@964
  1254
} MOJOSHADER_astDataTypeFunction;
icculus@964
  1255
icculus@964
  1256
typedef struct MOJOSHADER_astDataTypeUser
icculus@964
  1257
{
icculus@964
  1258
    MOJOSHADER_astDataTypeType type;
icculus@964
  1259
    const MOJOSHADER_astDataType *details;
icculus@964
  1260
    const char *name;
icculus@964
  1261
} MOJOSHADER_astDataTypeUser;
icculus@964
  1262
icculus@964
  1263
union MOJOSHADER_astDataType
icculus@964
  1264
{
icculus@964
  1265
    MOJOSHADER_astDataTypeType type;
icculus@964
  1266
    MOJOSHADER_astDataTypeArray array;
icculus@964
  1267
    MOJOSHADER_astDataTypeStruct structure;
icculus@964
  1268
    MOJOSHADER_astDataTypeVector vector;
icculus@964
  1269
    MOJOSHADER_astDataTypeMatrix matrix;
icculus@964
  1270
    MOJOSHADER_astDataTypeBuffer buffer;
icculus@964
  1271
    MOJOSHADER_astDataTypeUser user;
icculus@964
  1272
    MOJOSHADER_astDataTypeFunction function;
icculus@964
  1273
};
icculus@964
  1274
icculus@931
  1275
/* Structures that make up the parse tree... */
icculus@931
  1276
icculus@931
  1277
typedef enum MOJOSHADER_astNodeType
icculus@931
  1278
{
icculus@931
  1279
    MOJOSHADER_AST_OP_START_RANGE,         /* expression operators. */
icculus@931
  1280
icculus@931
  1281
    MOJOSHADER_AST_OP_START_RANGE_UNARY,   /* unary operators. */
icculus@931
  1282
    MOJOSHADER_AST_OP_PREINCREMENT,
icculus@931
  1283
    MOJOSHADER_AST_OP_PREDECREMENT,
icculus@931
  1284
    MOJOSHADER_AST_OP_NEGATE,
icculus@931
  1285
    MOJOSHADER_AST_OP_COMPLEMENT,
icculus@931
  1286
    MOJOSHADER_AST_OP_NOT,
icculus@931
  1287
    MOJOSHADER_AST_OP_POSTINCREMENT,
icculus@931
  1288
    MOJOSHADER_AST_OP_POSTDECREMENT,
icculus@962
  1289
    MOJOSHADER_AST_OP_CAST,
icculus@931
  1290
    MOJOSHADER_AST_OP_END_RANGE_UNARY,
icculus@931
  1291
icculus@931
  1292
    MOJOSHADER_AST_OP_START_RANGE_BINARY,  /* binary operators. */
icculus@931
  1293
    MOJOSHADER_AST_OP_COMMA,
icculus@931
  1294
    MOJOSHADER_AST_OP_MULTIPLY,
icculus@931
  1295
    MOJOSHADER_AST_OP_DIVIDE,
icculus@931
  1296
    MOJOSHADER_AST_OP_MODULO,
icculus@931
  1297
    MOJOSHADER_AST_OP_ADD,
icculus@931
  1298
    MOJOSHADER_AST_OP_SUBTRACT,
icculus@931
  1299
    MOJOSHADER_AST_OP_LSHIFT,
icculus@931
  1300
    MOJOSHADER_AST_OP_RSHIFT,
icculus@931
  1301
    MOJOSHADER_AST_OP_LESSTHAN,
icculus@931
  1302
    MOJOSHADER_AST_OP_GREATERTHAN,
icculus@931
  1303
    MOJOSHADER_AST_OP_LESSTHANOREQUAL,
icculus@931
  1304
    MOJOSHADER_AST_OP_GREATERTHANOREQUAL,
icculus@931
  1305
    MOJOSHADER_AST_OP_EQUAL,
icculus@931
  1306
    MOJOSHADER_AST_OP_NOTEQUAL,
icculus@931
  1307
    MOJOSHADER_AST_OP_BINARYAND,
icculus@931
  1308
    MOJOSHADER_AST_OP_BINARYXOR,
icculus@931
  1309
    MOJOSHADER_AST_OP_BINARYOR,
icculus@931
  1310
    MOJOSHADER_AST_OP_LOGICALAND,
icculus@931
  1311
    MOJOSHADER_AST_OP_LOGICALOR,
icculus@931
  1312
    MOJOSHADER_AST_OP_ASSIGN,
icculus@931
  1313
    MOJOSHADER_AST_OP_MULASSIGN,
icculus@931
  1314
    MOJOSHADER_AST_OP_DIVASSIGN,
icculus@931
  1315
    MOJOSHADER_AST_OP_MODASSIGN,
icculus@931
  1316
    MOJOSHADER_AST_OP_ADDASSIGN,
icculus@931
  1317
    MOJOSHADER_AST_OP_SUBASSIGN,
icculus@931
  1318
    MOJOSHADER_AST_OP_LSHIFTASSIGN,
icculus@931
  1319
    MOJOSHADER_AST_OP_RSHIFTASSIGN,
icculus@931
  1320
    MOJOSHADER_AST_OP_ANDASSIGN,
icculus@931
  1321
    MOJOSHADER_AST_OP_XORASSIGN,
icculus@931
  1322
    MOJOSHADER_AST_OP_ORASSIGN,
icculus@931
  1323
    MOJOSHADER_AST_OP_DEREF_ARRAY,
icculus@931
  1324
    MOJOSHADER_AST_OP_END_RANGE_BINARY,
icculus@931
  1325
icculus@931
  1326
    MOJOSHADER_AST_OP_START_RANGE_TERNARY,  /* ternary operators. */
icculus@931
  1327
    MOJOSHADER_AST_OP_CONDITIONAL,
icculus@931
  1328
    MOJOSHADER_AST_OP_END_RANGE_TERNARY,
icculus@931
  1329
icculus@931
  1330
    MOJOSHADER_AST_OP_START_RANGE_DATA,     /* expression operands. */
icculus@931
  1331
    MOJOSHADER_AST_OP_IDENTIFIER,
icculus@931
  1332
    MOJOSHADER_AST_OP_INT_LITERAL,
icculus@931
  1333
    MOJOSHADER_AST_OP_FLOAT_LITERAL,
icculus@931
  1334
    MOJOSHADER_AST_OP_STRING_LITERAL,
icculus@931
  1335
    MOJOSHADER_AST_OP_BOOLEAN_LITERAL,
icculus@931
  1336
    MOJOSHADER_AST_OP_END_RANGE_DATA,
icculus@931
  1337
icculus@931
  1338
    MOJOSHADER_AST_OP_START_RANGE_MISC,     /* other expression things. */
icculus@931
  1339
    MOJOSHADER_AST_OP_DEREF_STRUCT,
icculus@931
  1340
    MOJOSHADER_AST_OP_CALLFUNC,
icculus@931
  1341
    MOJOSHADER_AST_OP_CONSTRUCTOR,
icculus@931
  1342
    MOJOSHADER_AST_OP_END_RANGE_MISC,
icculus@931
  1343
    MOJOSHADER_AST_OP_END_RANGE,
icculus@931
  1344
icculus@931
  1345
    MOJOSHADER_AST_COMPUNIT_START_RANGE,    /* things in global scope. */
icculus@931
  1346
    MOJOSHADER_AST_COMPUNIT_FUNCTION,
icculus@931
  1347
    MOJOSHADER_AST_COMPUNIT_TYPEDEF,
icculus@931
  1348
    MOJOSHADER_AST_COMPUNIT_STRUCT,
icculus@931
  1349
    MOJOSHADER_AST_COMPUNIT_VARIABLE,
icculus@931
  1350
    MOJOSHADER_AST_COMPUNIT_END_RANGE,
icculus@931
  1351
icculus@931
  1352
    MOJOSHADER_AST_STATEMENT_START_RANGE,   /* statements in function scope. */
icculus@931
  1353
    MOJOSHADER_AST_STATEMENT_EMPTY,
icculus@931
  1354
    MOJOSHADER_AST_STATEMENT_BREAK,
icculus@931
  1355
    MOJOSHADER_AST_STATEMENT_CONTINUE,
icculus@931
  1356
    MOJOSHADER_AST_STATEMENT_DISCARD,
icculus@931
  1357
    MOJOSHADER_AST_STATEMENT_BLOCK,
icculus@931
  1358
    MOJOSHADER_AST_STATEMENT_EXPRESSION,
icculus@931
  1359
    MOJOSHADER_AST_STATEMENT_IF,
icculus@931
  1360
    MOJOSHADER_AST_STATEMENT_SWITCH,
icculus@931
  1361
    MOJOSHADER_AST_STATEMENT_FOR,
icculus@931
  1362
    MOJOSHADER_AST_STATEMENT_DO,
icculus@931
  1363
    MOJOSHADER_AST_STATEMENT_WHILE,
icculus@931
  1364
    MOJOSHADER_AST_STATEMENT_RETURN,
icculus@931
  1365
    MOJOSHADER_AST_STATEMENT_TYPEDEF,
icculus@931
  1366
    MOJOSHADER_AST_STATEMENT_STRUCT,
icculus@931
  1367
    MOJOSHADER_AST_STATEMENT_VARDECL,
icculus@931
  1368
    MOJOSHADER_AST_STATEMENT_END_RANGE,
icculus@931
  1369
icculus@931
  1370
    MOJOSHADER_AST_MISC_START_RANGE,        /* misc. syntactic glue. */
icculus@931
  1371
    MOJOSHADER_AST_FUNCTION_PARAMS,
icculus@931
  1372
    MOJOSHADER_AST_FUNCTION_SIGNATURE,
icculus@931
  1373
    MOJOSHADER_AST_SCALAR_OR_ARRAY,
icculus@931
  1374
    MOJOSHADER_AST_TYPEDEF,
icculus@931
  1375
    MOJOSHADER_AST_PACK_OFFSET,
icculus@931
  1376
    MOJOSHADER_AST_VARIABLE_LOWLEVEL,
icculus@931
  1377
    MOJOSHADER_AST_ANNOTATION,
icculus@931
  1378
    MOJOSHADER_AST_VARIABLE_DECLARATION,
icculus@931
  1379
    MOJOSHADER_AST_STRUCT_DECLARATION,
icculus@931
  1380
    MOJOSHADER_AST_STRUCT_MEMBER,
icculus@931
  1381
    MOJOSHADER_AST_SWITCH_CASE,
icculus@931
  1382
    MOJOSHADER_AST_ARGUMENTS,
icculus@931
  1383
    MOJOSHADER_AST_MISC_END_RANGE,
icculus@931
  1384
icculus@931
  1385
    MOJOSHADER_AST_END_RANGE
icculus@931
  1386
} MOJOSHADER_astNodeType;
icculus@931
  1387
icculus@931
  1388
typedef struct MOJOSHADER_astNodeInfo
icculus@931
  1389
{
icculus@931
  1390
    MOJOSHADER_astNodeType type;
icculus@931
  1391
    const char *filename;
icculus@931
  1392
    unsigned int line;
icculus@931
  1393
} MOJOSHADER_astNodeInfo;
icculus@931
  1394
icculus@931
  1395
typedef enum MOJOSHADER_astVariableAttributes
icculus@931
  1396
{
icculus@931
  1397
    MOJOSHADER_AST_VARATTR_EXTERN = (1 << 0),
icculus@931
  1398
    MOJOSHADER_AST_VARATTR_NOINTERPOLATION = (1 << 1),
icculus@931
  1399
    MOJOSHADER_AST_VARATTR_SHARED = (1 << 2),
icculus@931
  1400
    MOJOSHADER_AST_VARATTR_STATIC = (1 << 3),
icculus@931
  1401
    MOJOSHADER_AST_VARATTR_UNIFORM = (1 << 4),
icculus@931
  1402
    MOJOSHADER_AST_VARATTR_VOLATILE = (1 << 5),
icculus@931
  1403
    MOJOSHADER_AST_VARATTR_CONST = (1 << 6),
icculus@931
  1404
    MOJOSHADER_AST_VARATTR_ROWMAJOR = (1 << 7),
icculus@931
  1405
    MOJOSHADER_AST_VARATTR_COLUMNMAJOR = (1 << 8)
icculus@931
  1406
} MOJOSHADER_astVariableAttributes;
icculus@931
  1407
icculus@931
  1408
typedef enum MOJOSHADER_astIfAttributes
icculus@931
  1409
{
icculus@931
  1410
    MOJOSHADER_AST_IFATTR_NONE,
icculus@931
  1411
    MOJOSHADER_AST_IFATTR_BRANCH,
icculus@931
  1412
    MOJOSHADER_AST_IFATTR_FLATTEN,
icculus@931
  1413
    MOJOSHADER_AST_IFATTR_IFALL,
icculus@931
  1414
    MOJOSHADER_AST_IFATTR_IFANY,
icculus@931
  1415
    MOJOSHADER_AST_IFATTR_PREDICATE,
icculus@931
  1416
    MOJOSHADER_AST_IFATTR_PREDICATEBLOCK,
icculus@931
  1417
} MOJOSHADER_astIfAttributes;
icculus@931
  1418
icculus@931
  1419
typedef enum MOJOSHADER_astSwitchAttributes
icculus@931
  1420
{
icculus@931
  1421
    MOJOSHADER_AST_SWITCHATTR_NONE,
icculus@931
  1422
    MOJOSHADER_AST_SWITCHATTR_FLATTEN,
icculus@931
  1423
    MOJOSHADER_AST_SWITCHATTR_BRANCH,
icculus@931
  1424
    MOJOSHADER_AST_SWITCHATTR_FORCECASE,
icculus@931
  1425
    MOJOSHADER_AST_SWITCHATTR_CALL
icculus@931
  1426
} MOJOSHADER_astSwitchAttributes;
icculus@931
  1427
icculus@931
  1428
/* You can cast any AST node pointer to this. */
icculus@931
  1429
typedef struct MOJOSHADER_astGeneric
icculus@931
  1430
{
icculus@931
  1431
    MOJOSHADER_astNodeInfo ast;
icculus@931
  1432
} MOJOSHADER_astGeneric;
icculus@931
  1433
icculus@964
  1434
typedef struct MOJOSHADER_astExpression
icculus@964
  1435
{
icculus@964
  1436
    MOJOSHADER_astNodeInfo ast;
icculus@964
  1437
    const MOJOSHADER_astDataType *datatype;
icculus@964
  1438
} MOJOSHADER_astExpression;
icculus@931
  1439
icculus@931
  1440
typedef struct MOJOSHADER_astArguments
icculus@931
  1441
{
icculus@931
  1442
    MOJOSHADER_astNodeInfo ast;  /* Always MOJOSHADER_AST_ARGUMENTS */
icculus@931
  1443
    MOJOSHADER_astExpression *argument;
icculus@931
  1444
    struct MOJOSHADER_astArguments *next;
icculus@931
  1445
} MOJOSHADER_astArguments;
icculus@931
  1446
icculus@931
  1447
typedef struct MOJOSHADER_astExpressionUnary
icculus@931
  1448
{
icculus@931
  1449
    MOJOSHADER_astNodeInfo ast;
icculus@964
  1450
    const MOJOSHADER_astDataType *datatype;
icculus@931
  1451
    MOJOSHADER_astExpression *operand;
icculus@931
  1452
} MOJOSHADER_astExpressionUnary;
icculus@931
  1453
icculus@931
  1454
typedef struct MOJOSHADER_astExpressionBinary
icculus@931
  1455
{
icculus@931
  1456
    MOJOSHADER_astNodeInfo ast;
icculus@964
  1457
    const MOJOSHADER_astDataType *datatype;
icculus@931
  1458
    MOJOSHADER_astExpression *left;
icculus@931
  1459
    MOJOSHADER_astExpression *right;
icculus@931
  1460
} MOJOSHADER_astExpressionBinary;
icculus@931
  1461
icculus@931
  1462
typedef struct MOJOSHADER_astExpressionTernary
icculus@931
  1463
{
icculus@931
  1464
    MOJOSHADER_astNodeInfo ast;
icculus@964
  1465
    const MOJOSHADER_astDataType *datatype;
icculus@931
  1466
    MOJOSHADER_astExpression *left;
icculus@931
  1467
    MOJOSHADER_astExpression *center;
icculus@931
  1468
    MOJOSHADER_astExpression *right;
icculus@931
  1469
} MOJOSHADER_astExpressionTernary;
icculus@931
  1470
icculus@966
  1471
/* Identifier indexes aren't available until semantic analysis phase completes.
icculus@966
  1472
 *  It provides a unique id for this identifier's variable.
icculus@966
  1473
 *  It will be negative for global scope, positive for function scope
icculus@966
  1474
 *  (global values are globally unique, function values are only
icculus@973
  1475
 *  unique within the scope of the given function). There's a different
icculus@973
  1476
 *  set of indices if this identifier is a function (positive for
icculus@973
  1477
 *  user-defined functions, negative for intrinsics).
icculus@973
  1478
 *  May be zero for various reasons (unknown identifier, etc).
icculus@966
  1479
 */
icculus@931
  1480
typedef struct MOJOSHADER_astExpressionIdentifier
icculus@931
  1481
{
icculus@931
  1482
    MOJOSHADER_astNodeInfo ast;  /* Always MOJOSHADER_AST_OP_IDENTIFIER */
icculus@964
  1483
    const MOJOSHADER_astDataType *datatype;
icculus@931
  1484
    const char *identifier;
icculus@966
  1485
    int index;
icculus@931
  1486
} MOJOSHADER_astExpressionIdentifier;
icculus@931
  1487
icculus@931
  1488
typedef struct MOJOSHADER_astExpressionIntLiteral
icculus@931
  1489
{
icculus@931
  1490
    MOJOSHADER_astNodeInfo ast;  /* Always MOJOSHADER_AST_OP_INT_LITERAL */
icculus@964
  1491
    const MOJOSHADER_astDataType *datatype;  /* always AST_DATATYPE_INT */
icculus@931
  1492
    int value;
icculus@931
  1493
} MOJOSHADER_astExpressionIntLiteral;
icculus@931
  1494
icculus@931
  1495
typedef struct MOJOSHADER_astExpressionFloatLiteral
icculus@931
  1496
{
icculus@931
  1497
    MOJOSHADER_astNodeInfo ast;  /* Always MOJOSHADER_AST_OP_FLOAT_LITERAL */
icculus@964
  1498
    const MOJOSHADER_astDataType *datatype;  /* always AST_DATATYPE_FLOAT */
icculus@931
  1499
    double value;
icculus@931
  1500
} MOJOSHADER_astExpressionFloatLiteral;
icculus@931
  1501
icculus@931
  1502
typedef struct MOJOSHADER_astExpressionStringLiteral
icculus@931
  1503
{
icculus@931
  1504
    MOJOSHADER_astNodeInfo ast;  /* Always MOJOSHADER_AST_OP_STRING_LITERAL */
icculus@964
  1505
    const MOJOSHADER_astDataType *datatype;  /* always AST_DATATYPE_STRING */
icculus@931
  1506
    const char *string;
icculus@931
  1507
} MOJOSHADER_astExpressionStringLiteral;
icculus@931
  1508
icculus@931
  1509
typedef struct MOJOSHADER_astExpressionBooleanLiteral
icculus@931
  1510
{
icculus@931
  1511
    MOJOSHADER_astNodeInfo ast;  /* Always MOJOSHADER_AST_OP_BOOLEAN_LITERAL */
icculus@964
  1512
    const MOJOSHADER_astDataType *datatype;  /* always AST_DATATYPE_BOOL */
icculus@931
  1513
    int value;  /* Always 1 or 0. */
icculus@931
  1514
} MOJOSHADER_astExpressionBooleanLiteral;
icculus@931
  1515
icculus@931
  1516
typedef struct MOJOSHADER_astExpressionConstructor
icculus@931
  1517
{
icculus@931
  1518
    MOJOSHADER_astNodeInfo ast;  /* Always MOJOSHADER_AST_OP_CONSTRUCTOR */
icculus@964
  1519
    const MOJOSHADER_astDataType *datatype;
icculus@931
  1520
    MOJOSHADER_astArguments *args;
icculus@931
  1521
} MOJOSHADER_astExpressionConstructor;
icculus@931
  1522
icculus@931
  1523
typedef struct MOJOSHADER_astExpressionDerefStruct
icculus@931
  1524
{
icculus@931
  1525
    MOJOSHADER_astNodeInfo ast;  /* Always MOJOSHADER_AST_OP_DEREF_STRUCT */
icculus@964
  1526
    const MOJOSHADER_astDataType *datatype;
icculus@1008
  1527
    /* !!! FIXME:
icculus@1008
  1528
     *  "identifier" is misnamed; this might not be an identifier at all:
icculus@1008
  1529
     *    x = FunctionThatReturnsAStruct().SomeMember;
icculus@1008
  1530
     */
icculus@931
  1531
    MOJOSHADER_astExpression *identifier;
icculus@931
  1532
    const char *member;
icculus@964
  1533
    int isswizzle;  /* Always 1 or 0. Never set by parseAst()! */
icculus@1009
  1534
    int member_index;  /* Never set by parseAst()! */
icculus@931
  1535
} MOJOSHADER_astExpressionDerefStruct;
icculus@931
  1536
icculus@931
  1537
typedef struct MOJOSHADER_astExpressionCallFunction
icculus@931
  1538
{
icculus@931
  1539
    MOJOSHADER_astNodeInfo ast;  /* Always MOJOSHADER_AST_OP_CALLFUNC */
icculus@964
  1540
    const MOJOSHADER_astDataType *datatype;
icculus@973
  1541
    MOJOSHADER_astExpressionIdentifier *identifier;
icculus@931
  1542
    MOJOSHADER_astArguments *args;
icculus@931
  1543
} MOJOSHADER_astExpressionCallFunction;
icculus@931
  1544
icculus@931
  1545
typedef struct MOJOSHADER_astExpressionCast
icculus@931
  1546
{
icculus@931
  1547
    MOJOSHADER_astNodeInfo ast;  /* Always MOJOSHADER_AST_OP_CAST */
icculus@964
  1548
    const MOJOSHADER_astDataType *datatype;
icculus@931
  1549
    MOJOSHADER_astExpression *operand;
icculus@931
  1550
} MOJOSHADER_astExpressionCast;
icculus@931
  1551
icculus@931
  1552
typedef struct MOJOSHADER_astCompilationUnit
icculus@931
  1553
{
icculus@931
  1554
    MOJOSHADER_astNodeInfo ast;
icculus@931
  1555
    struct MOJOSHADER_astCompilationUnit *next;
icculus@931
  1556
} MOJOSHADER_astCompilationUnit;
icculus@931
  1557
icculus@931
  1558
typedef enum MOJOSHADER_astFunctionStorageClass
icculus@931
  1559
{
icculus@931
  1560
    MOJOSHADER_AST_FNSTORECLS_NONE,
icculus@931
  1561
    MOJOSHADER_AST_FNSTORECLS_INLINE
icculus@931
  1562
} MOJOSHADER_astFunctionStorageClass;
icculus@931
  1563
icculus@931
  1564
typedef enum MOJOSHADER_astInputModifier
icculus@931
  1565
{
icculus@931
  1566
    MOJOSHADER_AST_INPUTMOD_NONE,
icculus@931
  1567
    MOJOSHADER_AST_INPUTMOD_IN,
icculus@931
  1568
    MOJOSHADER_AST_INPUTMOD_OUT,
icculus@931
  1569
    MOJOSHADER_AST_INPUTMOD_INOUT,
icculus@931
  1570
    MOJOSHADER_AST_INPUTMOD_UNIFORM
icculus@931
  1571
} MOJOSHADER_astInputModifier;
icculus@931
  1572
icculus@931
  1573
typedef enum MOJOSHADER_astInterpolationModifier
icculus@931
  1574
{
icculus@931
  1575
    MOJOSHADER_AST_INTERPMOD_NONE,
icculus@931
  1576
    MOJOSHADER_AST_INTERPMOD_LINEAR,
icculus@931
  1577
    MOJOSHADER_AST_INTERPMOD_CENTROID,
icculus@931
  1578
    MOJOSHADER_AST_INTERPMOD_NOINTERPOLATION,
icculus@931
  1579
    MOJOSHADER_AST_INTERPMOD_NOPERSPECTIVE,
icculus@931
  1580
    MOJOSHADER_AST_INTERPMOD_SAMPLE
icculus@931
  1581
} MOJOSHADER_astInterpolationModifier;
icculus@931
  1582
icculus@931
  1583
typedef struct MOJOSHADER_astFunctionParameters
icculus@931
  1584
{
icculus@931
  1585
    MOJOSHADER_astNodeInfo ast;
icculus@964
  1586
    const MOJOSHADER_astDataType *datatype;
icculus@931
  1587
    MOJOSHADER_astInputModifier input_modifier;
icculus@931
  1588
    const char *identifier;
icculus@931
  1589
    const char *semantic;
icculus@931
  1590
    MOJOSHADER_astInterpolationModifier interpolation_modifier;
icculus@931
  1591
    MOJOSHADER_astExpression *initializer;
icculus@931
  1592
    struct MOJOSHADER_astFunctionParameters *next;
icculus@931
  1593
} MOJOSHADER_astFunctionParameters;
icculus@931
  1594
icculus@931
  1595
typedef struct MOJOSHADER_astFunctionSignature
icculus@931
  1596
{
icculus@931
  1597
    MOJOSHADER_astNodeInfo ast;
icculus@964
  1598
    const MOJOSHADER_astDataType *datatype;
icculus@931
  1599
    const char *identifier;
icculus@931
  1600
    MOJOSHADER_astFunctionParameters *params;
icculus@931
  1601
    MOJOSHADER_astFunctionStorageClass storage_class;
icculus@931
  1602
    const char *semantic;
icculus@931
  1603
} MOJOSHADER_astFunctionSignature;
icculus@931
  1604
icculus@931
  1605
typedef struct MOJOSHADER_astScalarOrArray
icculus@931
  1606
{
icculus@931
  1607
    MOJOSHADER_astNodeInfo ast;
icculus@931
  1608
    const char *identifier;
icculus@931
  1609
    int isarray;  /* boolean: 1 or 0 */
icculus@931
  1610
    MOJOSHADER_astExpression *dimension;
icculus@931
  1611
} MOJOSHADER_astScalarOrArray;
icculus@931
  1612
icculus@931
  1613
typedef struct MOJOSHADER_astAnnotations
icculus@931
  1614
{
icculus@931
  1615
    MOJOSHADER_astNodeInfo ast;
icculus@964
  1616
    const MOJOSHADER_astDataType *datatype;
icculus@931
  1617
    MOJOSHADER_astExpression *initializer;
icculus@931
  1618
    struct MOJOSHADER_astAnnotations *next;
icculus@931
  1619
} MOJOSHADER_astAnnotations;
icculus@931
  1620
icculus@931
  1621
typedef struct MOJOSHADER_astPackOffset
icculus@931
  1622
{
icculus@931
  1623
    MOJOSHADER_astNodeInfo ast;
icculus@931
  1624
    const char *ident1;   /* !!! FIXME: rename this. */
icculus@931
  1625
    const char *ident2;
icculus@931
  1626
} MOJOSHADER_astPackOffset;
icculus@931
  1627
icculus@931
  1628
typedef struct MOJOSHADER_astVariableLowLevel
icculus@931
  1629
{
icculus@931
  1630
    MOJOSHADER_astNodeInfo ast;
icculus@931
  1631
    MOJOSHADER_astPackOffset *packoffset;
icculus@931
  1632
    const char *register_name;
icculus@931
  1633
} MOJOSHADER_astVariableLowLevel;
icculus@931
  1634
icculus@931
  1635
typedef struct MOJOSHADER_astStructMembers
icculus@931
  1636
{
icculus@931
  1637
    MOJOSHADER_astNodeInfo ast;
icculus@964
  1638
    const MOJOSHADER_astDataType *datatype;
icculus@931
  1639
    const char *semantic;
icculus@931
  1640
    MOJOSHADER_astScalarOrArray *details;
icculus@931
  1641
    MOJOSHADER_astInterpolationModifier interpolation_mod;
icculus@931
  1642
    struct MOJOSHADER_astStructMembers *next;
icculus@931
  1643
} MOJOSHADER_astStructMembers;
icculus@931
  1644
icculus@931
  1645
typedef struct MOJOSHADER_astStructDeclaration
icculus@931
  1646
{
icculus@931
  1647
    MOJOSHADER_astNodeInfo ast;
icculus@964
  1648
    const MOJOSHADER_astDataType *datatype;
icculus@931
  1649
    const char *name;
icculus@931
  1650
    MOJOSHADER_astStructMembers *members;
icculus@931
  1651
} MOJOSHADER_astStructDeclaration;
icculus@931
  1652
icculus@931
  1653
typedef struct MOJOSHADER_astVariableDeclaration
icculus@931
  1654
{
icculus@931
  1655
    MOJOSHADER_astNodeInfo ast;
icculus@931
  1656
    int attributes;
icculus@964
  1657
    const MOJOSHADER_astDataType *datatype;
icculus@931
  1658
    MOJOSHADER_astStructDeclaration *anonymous_datatype;
icculus@931
  1659
    MOJOSHADER_astScalarOrArray *details;
icculus@931
  1660
    const char *semantic;
icculus@931
  1661
    MOJOSHADER_astAnnotations *annotations;
icculus@931
  1662
    MOJOSHADER_astExpression *initializer;
icculus@931
  1663
    MOJOSHADER_astVariableLowLevel *lowlevel;
icculus@931
  1664
    struct MOJOSHADER_astVariableDeclaration *next;
icculus@931
  1665
} MOJOSHADER_astVariableDeclaration;
icculus@931
  1666
icculus@931
  1667
typedef struct MOJOSHADER_astStatement
icculus@931
  1668
{
icculus@931
  1669
    MOJOSHADER_astNodeInfo ast;
icculus@931
  1670
    struct MOJOSHADER_astStatement *next;
icculus@931
  1671
} MOJOSHADER_astStatement;
icculus@931
  1672
icculus@931
  1673
typedef MOJOSHADER_astStatement MOJOSHADER_astEmptyStatement;
icculus@931
  1674
typedef MOJOSHADER_astStatement MOJOSHADER_astBreakStatement;
icculus@931
  1675
typedef MOJOSHADER_astStatement MOJOSHADER_astContinueStatement;
icculus@931
  1676
typedef MOJOSHADER_astStatement MOJOSHADER_astDiscardStatement;
icculus@931
  1677
icculus@931
  1678
/* something enclosed in "{}" braces. */
icculus@931
  1679
typedef struct MOJOSHADER_astBlockStatement
icculus@931
  1680
{
icculus@931
  1681
    MOJOSHADER_astNodeInfo ast;
icculus@931
  1682
    MOJOSHADER_astStatement *next;
icculus@931
  1683
    MOJOSHADER_astStatement *statements;  /* list of child statements. */
icculus@931
  1684
} MOJOSHADER_astBlockStatement;
icculus@931
  1685
icculus@931
  1686
typedef struct MOJOSHADER_astReturnStatement
icculus@931
  1687
{
icculus@931
  1688
    MOJOSHADER_astNodeInfo ast;
icculus@931
  1689
    MOJOSHADER_astStatement *next;
icculus@931
  1690
    MOJOSHADER_astExpression *expr;
icculus@931
  1691
} MOJOSHADER_astReturnStatement;
icculus@931
  1692
icculus@931
  1693
typedef struct MOJOSHADER_astExpressionStatement
icculus@931
  1694
{
icculus@931
  1695
    MOJOSHADER_astNodeInfo ast;
icculus@931
  1696
    MOJOSHADER_astStatement *next;
icculus@931
  1697
    MOJOSHADER_astExpression *expr;
icculus@931
  1698
} MOJOSHADER_astExpressionStatement;
icculus@931
  1699
icculus@931
  1700
typedef struct MOJOSHADER_astIfStatement
icculus@931
  1701
{
icculus@931
  1702
    MOJOSHADER_astNodeInfo ast;
icculus@931
  1703
    MOJOSHADER_astStatement *next;
icculus@931
  1704
    int attributes;
icculus@931
  1705
    MOJOSHADER_astExpression *expr;
icculus@931
  1706
    MOJOSHADER_astStatement *statement;
icculus@931
  1707
    MOJOSHADER_astStatement *else_statement;
icculus@931
  1708
} MOJOSHADER_astIfStatement;
icculus@931
  1709
icculus@931
  1710
typedef struct MOJOSHADER_astSwitchCases
icculus@931
  1711
{
icculus@931
  1712
    MOJOSHADER_astNodeInfo ast;
icculus@931
  1713
    MOJOSHADER_astExpression *expr;
icculus@931
  1714
    MOJOSHADER_astStatement *statement;
icculus@931
  1715
    struct MOJOSHADER_astSwitchCases *next;
icculus@931
  1716
} MOJOSHADER_astSwitchCases;
icculus@931
  1717
icculus@931
  1718
typedef struct MOJOSHADER_astSwitchStatement
icculus@931
  1719
{
icculus@931
  1720
    MOJOSHADER_astNodeInfo ast;
icculus@931
  1721
    MOJOSHADER_astStatement *next;
icculus@931
  1722
    int attributes;
icculus@931
  1723
    MOJOSHADER_astExpression *expr;
icculus@931
  1724
    MOJOSHADER_astSwitchCases *cases;
icculus@931
  1725
} MOJOSHADER_astSwitchStatement;
icculus@931
  1726
icculus@931
  1727
typedef struct MOJOSHADER_astWhileStatement
icculus@931
  1728
{
icculus@931
  1729
    MOJOSHADER_astNodeInfo ast;
icculus@931
  1730
    MOJOSHADER_astStatement *next;
icculus@931
  1731
    int unroll;  /* # times to unroll, 0 to loop, < 0 == compiler's choice. */
icculus@931
  1732
    MOJOSHADER_astExpression *expr;
icculus@931
  1733
    MOJOSHADER_astStatement *statement;
icculus@931
  1734
} MOJOSHADER_astWhileStatement;
icculus@931
  1735
icculus@931
  1736
typedef MOJOSHADER_astWhileStatement MOJOSHADER_astDoStatement;
icculus@931
  1737
icculus@931
  1738
typedef struct MOJOSHADER_astForStatement
icculus@931
  1739
{
icculus@931
  1740
    MOJOSHADER_astNodeInfo ast;
icculus@931
  1741
    MOJOSHADER_astStatement *next;
icculus@931
  1742
    int unroll;  /* # times to unroll, 0 to loop, < 0 == compiler's choice. */
icculus@1006
  1743
    MOJOSHADER_astVariableDeclaration *var_decl;  /* either this ... */
icculus@1006
  1744
    MOJOSHADER_astExpression *initializer;        /*  ... or this will used. */
icculus@931
  1745
    MOJOSHADER_astExpression *looptest;
icculus@931
  1746
    MOJOSHADER_astExpression *counter;
icculus@931
  1747
    MOJOSHADER_astStatement *statement;
icculus@931
  1748
} MOJOSHADER_astForStatement;
icculus@931
  1749
icculus@931
  1750
typedef struct MOJOSHADER_astTypedef
icculus@931
  1751
{
icculus@931
  1752
    MOJOSHADER_astNodeInfo ast;
icculus@964
  1753
    const MOJOSHADER_astDataType *datatype;
icculus@931
  1754
    int isconst;  /* boolean: 1 or 0 */
icculus@931
  1755
    MOJOSHADER_astScalarOrArray *details;
icculus@931
  1756
} MOJOSHADER_astTypedef;
icculus@931
  1757
icculus@931
  1758
typedef struct MOJOSHADER_astTypedefStatement
icculus@931
  1759
{
icculus@931
  1760
    MOJOSHADER_astNodeInfo ast;
icculus@931
  1761
    MOJOSHADER_astStatement *next;
icculus@931
  1762
    MOJOSHADER_astTypedef *type_info;
icculus@931
  1763
} MOJOSHADER_astTypedefStatement;
icculus@931
  1764
icculus@931
  1765
typedef struct MOJOSHADER_astVarDeclStatement
icculus@931
  1766
{
icculus@931
  1767
    MOJOSHADER_astNodeInfo ast;
icculus@931
  1768
    MOJOSHADER_astStatement *next;
icculus@931
  1769
    MOJOSHADER_astVariableDeclaration *declaration;
icculus@931
  1770
} MOJOSHADER_astVarDeclStatement;
icculus@931
  1771
icculus@931
  1772
typedef struct MOJOSHADER_astStructStatement
icculus@931
  1773
{
icculus@931
  1774
    MOJOSHADER_astNodeInfo ast;
icculus@931
  1775
    MOJOSHADER_astStatement *next;
icculus@931
  1776
    MOJOSHADER_astStructDeclaration *struct_info;
icculus@931
  1777
} MOJOSHADER_astStructStatement;
icculus@931
  1778
icculus@931
  1779
typedef struct MOJOSHADER_astCompilationUnitFunction
icculus@931
  1780
{
icculus@931
  1781
    MOJOSHADER_astNodeInfo ast;
icculus@931
  1782
    MOJOSHADER_astCompilationUnit *next;
icculus@931
  1783
    MOJOSHADER_astFunctionSignature *declaration;
icculus@931
  1784
    MOJOSHADER_astStatement *definition;
icculus@1014
  1785
    int index;  /* unique id. Will be 0 until semantic analysis runs. */
icculus@931
  1786
} MOJOSHADER_astCompilationUnitFunction;
icculus@931
  1787
icculus@931
  1788
typedef struct MOJOSHADER_astCompilationUnitTypedef
icculus@931
  1789
{
icculus@931
  1790
    MOJOSHADER_astNodeInfo ast;
icculus@931
  1791
    MOJOSHADER_astCompilationUnit *next;
icculus@931
  1792
    MOJOSHADER_astTypedef *type_info;
icculus@931
  1793
} MOJOSHADER_astCompilationUnitTypedef;
icculus@931
  1794
icculus@931
  1795
typedef struct MOJOSHADER_astCompilationUnitStruct
icculus@931
  1796
{
icculus@931
  1797
    MOJOSHADER_astNodeInfo ast;
icculus@931
  1798
    MOJOSHADER_astCompilationUnit *next;
icculus@931
  1799
    MOJOSHADER_astStructDeclaration *struct_info;
icculus@931
  1800
} MOJOSHADER_astCompilationUnitStruct;
icculus@931
  1801
icculus@931
  1802
typedef struct MOJOSHADER_astCompilationUnitVariable
icculus@931
  1803
{
icculus@931
  1804
    MOJOSHADER_astNodeInfo ast;
icculus@931
  1805
    MOJOSHADER_astCompilationUnit *next;
icculus@931
  1806
    MOJOSHADER_astVariableDeclaration *declaration;
icculus@931
  1807
} MOJOSHADER_astCompilationUnitVariable;
icculus@931
  1808
icculus@931
  1809
icculus@931
  1810
/* this is way cleaner than all the nasty typecasting. */
icculus@931
  1811
typedef union MOJOSHADER_astNode
icculus@931
  1812
{
icculus@931
  1813
    MOJOSHADER_astNodeInfo ast;
icculus@931
  1814
    MOJOSHADER_astGeneric generic;
icculus@931
  1815
    MOJOSHADER_astExpression expression;
icculus@931
  1816
    MOJOSHADER_astArguments arguments;
icculus@931
  1817
    MOJOSHADER_astExpressionUnary unary;
icculus@931
  1818
    MOJOSHADER_astExpressionBinary binary;
icculus@931
  1819
    MOJOSHADER_astExpressionTernary ternary;
icculus@931
  1820
    MOJOSHADER_astExpressionIdentifier identifier;
icculus@931
  1821
    MOJOSHADER_astExpressionIntLiteral intliteral;
icculus@931
  1822
    MOJOSHADER_astExpressionFloatLiteral floatliteral;
icculus@931
  1823
    MOJOSHADER_astExpressionStringLiteral stringliteral;
icculus@931
  1824
    MOJOSHADER_astExpressionBooleanLiteral boolliteral;
icculus@931
  1825
    MOJOSHADER_astExpressionConstructor constructor;
icculus@931
  1826
    MOJOSHADER_astExpressionDerefStruct derefstruct;
icculus@931
  1827
    MOJOSHADER_astExpressionCallFunction callfunc;
icculus@931
  1828
    MOJOSHADER_astExpressionCast cast;
icculus@931
  1829
    MOJOSHADER_astCompilationUnit compunit;
icculus@931
  1830
    MOJOSHADER_astFunctionParameters params;
icculus@931
  1831
    MOJOSHADER_astFunctionSignature funcsig;
icculus@931
  1832
    MOJOSHADER_astScalarOrArray soa;
icculus@931
  1833
    MOJOSHADER_astAnnotations annotations;
icculus@931
  1834
    MOJOSHADER_astPackOffset packoffset;
icculus@931
  1835
    MOJOSHADER_astVariableLowLevel varlowlevel;
icculus@931
  1836
    MOJOSHADER_astStructMembers structmembers;
icculus@931
  1837
    MOJOSHADER_astStructDeclaration structdecl;
icculus@931
  1838
    MOJOSHADER_astVariableDeclaration vardecl;
icculus@931
  1839
    MOJOSHADER_astStatement stmt;
icculus@931
  1840
    MOJOSHADER_astEmptyStatement emptystmt;
icculus@931
  1841
    MOJOSHADER_astBreakStatement breakstmt;
icculus@931
  1842
    MOJOSHADER_astContinueStatement contstmt;
icculus@931
  1843
    MOJOSHADER_astDiscardStatement discardstmt;
icculus@931
  1844
    MOJOSHADER_astBlockStatement blockstmt;
icculus@931
  1845
    MOJOSHADER_astReturnStatement returnstmt;
icculus@931
  1846
    MOJOSHADER_astExpressionStatement exprstmt;
icculus@931
  1847
    MOJOSHADER_astIfStatement ifstmt;
icculus@931
  1848
    MOJOSHADER_astSwitchCases cases;
icculus@931
  1849
    MOJOSHADER_astSwitchStatement switchstmt;
icculus@931
  1850
    MOJOSHADER_astWhileStatement whilestmt;
icculus@931
  1851
    MOJOSHADER_astDoStatement dostmt;
icculus@931
  1852
    MOJOSHADER_astForStatement forstmt;
icculus@931
  1853
    MOJOSHADER_astTypedef typdef;
icculus@931
  1854
    MOJOSHADER_astTypedefStatement typedefstmt;
icculus@931
  1855
    MOJOSHADER_astVarDeclStatement vardeclstmt;
icculus@931
  1856
    MOJOSHADER_astStructStatement structstmt;
icculus@931
  1857
    MOJOSHADER_astCompilationUnitFunction funcunit;
icculus@931
  1858
    MOJOSHADER_astCompilationUnitTypedef typedefunit;
icculus@931
  1859
    MOJOSHADER_astCompilationUnitStruct structunit;
icculus@931
  1860
    MOJOSHADER_astCompilationUnitVariable varunit;
icculus@931
  1861
} MOJOSHADER_astNode;
icculus@931
  1862
icculus@931
  1863
icculus@931
  1864
/*
icculus@931
  1865
 * Structure used to return data from parsing of a shader into an AST...
icculus@931
  1866
 */
icculus@931
  1867
/* !!! FIXME: most of these ints should be unsigned. */
icculus@931
  1868
typedef struct MOJOSHADER_astData
icculus@931
  1869
{
icculus@931
  1870
    /*
icculus@931
  1871
     * The number of elements pointed to by (errors).
icculus@931
  1872
     */
icculus@931
  1873
    int error_count;
icculus@931
  1874
icculus@931
  1875
    /*
icculus@931
  1876
     * (error_count) elements of data that specify errors that were generated
icculus@931
  1877
     *  by parsing this shader.
icculus@931
  1878
     * This can be NULL if there were no errors or if (error_count) is zero.
icculus@931
  1879
     *  Note that this will only produce errors for syntax problems. Most of
icculus@931
  1880
     *  the things we expect a compiler to produce errors for--incompatible
icculus@931
  1881
     *  types, unknown identifiers, etc--are not checked at all during
icculus@931
  1882
     *  initial generation of the syntax tree...bogus programs that would
icculus@931
  1883
     *  fail to compile will pass here without error, if they are syntactically
icculus@931
  1884
     *  correct!
icculus@931
  1885
     */
icculus@931
  1886
    MOJOSHADER_error *errors;
icculus@931
  1887
icculus@931
  1888
    /*
icculus@931
  1889
     * The name of the source profile used to parse the shader. Will be NULL
icculus@931
  1890
     *  on error.
icculus@931
  1891
     */
icculus@931
  1892
    const char *source_profile;
icculus@931
  1893
icculus@931
  1894
    /*
icculus@931
  1895
     * The actual syntax tree. You are responsible for walking it yourself.
icculus@931
  1896
     *  CompilationUnits are always the top of the tree (functions, typedefs,
icculus@932
  1897
     *  global variables, etc). Will be NULL on error.
icculus@931
  1898
     */
icculus@931
  1899
    const MOJOSHADER_astNode *ast;
icculus@931
  1900
icculus@931
  1901
    /*
icculus@931
  1902
     * This is the malloc implementation you passed to MOJOSHADER_parse().
icculus@931
  1903
     */
icculus@931
  1904
    MOJOSHADER_malloc malloc;
icculus@931
  1905
icculus@931
  1906
    /*
icculus@931
  1907
     * This is the free implementation you passed to MOJOSHADER_parse().
icculus@931
  1908
     */
icculus@931
  1909
    MOJOSHADER_free free;
icculus@931
  1910
icculus@931
  1911
    /*
icculus@931
  1912
     * This is the pointer you passed as opaque data for your allocator.
icculus@931
  1913
     */
icculus@931
  1914
    void *malloc_data;
icculus@936
  1915
icculus@936
  1916
    /*
icculus@936
  1917
     * This is internal data, and not for the application to touch.
icculus@936
  1918
     */
icculus@939
  1919
    void *opaque;
icculus@931
  1920
} MOJOSHADER_astData;
icculus@931
  1921
icculus@931
  1922
icculus@931
  1923
/*
icculus@931
  1924
 * You almost certainly don't need this function, unless you absolutely know
icculus@931
  1925
 *  why you need it without hesitation. This is almost certainly only good for
icculus@931
  1926
 *  building code analysis tools on top of.
icculus@931
  1927
 *
icculus@931
  1928
 * This is intended to parse HLSL source code, turning it into an abstract
icculus@931
  1929
 *  syntax tree.
icculus@931
  1930
 *
icculus@931
  1931
 * (srcprofile) specifies the source language of the shader. You can specify
icculus@931
  1932
 *  a shader model with this, too. See MOJOSHADER_SRC_PROFILE_* constants.
icculus@931
  1933
 *
icculus@931
  1934
 * (filename) is a NULL-terminated UTF-8 filename. It can be NULL. We do not
icculus@931
  1935
 *  actually access this file, as we obtain our data from (source). This
icculus@931
  1936
 *  string is copied when we need to report errors while processing (source),
icculus@931
  1937
 *  as opposed to errors in a file referenced via the #include directive in
icculus@931
  1938
 *  (source). If this is NULL, then errors will report the filename as NULL,
icculus@931
  1939
 *  too.
icculus@931
  1940
 *
icculus@931
  1941
 * (source) is an UTF-8 string of valid high-level shader source code.
icculus@931
  1942
 *  It does not need to be NULL-terminated.
icculus@931
  1943
 *
icculus@931
  1944
 * (sourcelen) is the length of the string pointed to by (source), in bytes.
icculus@931
  1945
 *
icculus@931
  1946
 * (defines) points to (define_count) preprocessor definitions, and can be
icculus@931
  1947
 *  NULL. These are treated by the preprocessor as if the source code started
icculus@931
  1948
 *  with one #define for each entry you pass in here.
icculus@931
  1949
 *
icculus@931
  1950
 * (include_open) and (include_close) let the app control the preprocessor's
icculus@931
  1951
 *  behaviour for #include statements. Both are optional and can be NULL, but
icculus@931
  1952
 *  both must be specified if either is specified.
icculus@931
  1953
 *
icculus@931
  1954
 * This will return a MOJOSHADER_astData. The data supplied here gives the
icculus@931
  1955
 *  application a tree-like structure they can walk to see the layout of
icculus@931
  1956
 *  a given program. When you are done with this data, pass it to
icculus@931
  1957
 *  MOJOSHADER_freeCompileData() to deallocate resources.
icculus@931
  1958
 *
icculus@931
  1959
 * This function will never return NULL, even if the system is completely
icculus@931
  1960
 *  out of memory upon entry (in which case, this function returns a static
icculus@931
  1961
 *  MOJOSHADER_astData object, which is still safe to pass to
icculus@931
  1962
 *  MOJOSHADER_freeAstData()).
icculus@931
  1963
 *
icculus@931
  1964
 * As parsing requires some memory to be allocated, you may provide a
icculus@931
  1965
 *  custom allocator to this function, which will be used to allocate/free
icculus@931
  1966
 *  memory. They function just like malloc() and free(). We do not use
icculus@931
  1967
 *  realloc(). If you don't care, pass NULL in for the allocator functions.
icculus@931
  1968
 *  If your allocator needs instance-specific data, you may supply it with the
icculus@931
  1969
 *  (d) parameter. This pointer is passed as-is to your (m) and (f) functions.
icculus@931
  1970
 *
icculus@931
  1971
 * This function is thread safe, so long as the various callback functions
icculus@931
  1972
 *  are, too, and that the parameters remains intact for the duration of the
icculus@931
  1973
 *  call. This allows you to parse several shaders on separate CPU cores
icculus@931
  1974
 *  at the same time.
icculus@931
  1975
 */
flibitijibibo@1150
  1976
DECLSPEC const MOJOSHADER_astData *MOJOSHADER_parseAst(const char *srcprofile,
icculus@931
  1977
                                    const char *filename, const char *source,
icculus@931
  1978
                                    unsigned int sourcelen,
icculus@931
  1979
                                    const MOJOSHADER_preprocessorDefine *defs,
icculus@931
  1980
                                    unsigned int define_count,
icculus@931
  1981
                                    MOJOSHADER_includeOpen include_open,
icculus@931
  1982
                                    MOJOSHADER_includeClose include_close,
icculus@931
  1983
                                    MOJOSHADER_malloc m, MOJOSHADER_free f,
icculus@931
  1984
                                    void *d);
icculus@931
  1985
icculus@1001
  1986
icculus@1001
  1987
/* !!! FIXME: expose semantic analysis to the public API? */
icculus@1001
  1988
icculus@1001
  1989
icculus@931
  1990
/*
icculus@931
  1991
 * Call this to dispose of AST parsing results when you are done with them.
icculus@931
  1992
 *  This will call the MOJOSHADER_free function you provided to
icculus@931
  1993
 *  MOJOSHADER_parseAst() multiple times, if you provided one.
icculus@931
  1994
 *  Passing a NULL here is a safe no-op.
icculus@931
  1995
 *
icculus@931
  1996
 * This function is thread safe, so long as any allocator you passed into
icculus@931
  1997
 *  MOJOSHADER_parseAst() is, too.
icculus@931
  1998
 */
flibitijibibo@1150
  1999
DECLSPEC void MOJOSHADER_freeAstData(const MOJOSHADER_astData *data);
icculus@931
  2000
icculus@931
  2001
icculus@1011
  2002
/* Intermediate Representation interface... */
icculus@1011
  2003
/* !!! FIXME: there is currently no way to access the IR via the public API. */
icculus@1011
  2004
typedef enum MOJOSHADER_irNodeType
icculus@1011
  2005
{
icculus@1011
  2006
    MOJOSHADER_IR_START_RANGE_EXPR,
icculus@1011
  2007
    MOJOSHADER_IR_CONSTANT,
icculus@1011
  2008
    MOJOSHADER_IR_TEMP,
icculus@1011
  2009
    MOJOSHADER_IR_BINOP,
icculus@1011
  2010
    MOJOSHADER_IR_MEMORY,
icculus@1011
  2011
    MOJOSHADER_IR_CALL,
icculus@1011
  2012
    MOJOSHADER_IR_ESEQ,
icculus@1011
  2013
    MOJOSHADER_IR_ARRAY,
icculus@1011
  2014
    MOJOSHADER_IR_CONVERT,
icculus@1011
  2015
    MOJOSHADER_IR_SWIZZLE,
icculus@1011
  2016
    MOJOSHADER_IR_CONSTRUCT,
icculus@1011
  2017
    MOJOSHADER_IR_END_RANGE_EXPR,
icculus@1011
  2018
icculus@1011
  2019
    MOJOSHADER_IR_START_RANGE_STMT,
icculus@1011
  2020
    MOJOSHADER_IR_MOVE,
icculus@1011
  2021
    MOJOSHADER_IR_EXPR_STMT,
icculus@1011
  2022
    MOJOSHADER_IR_JUMP,
icculus@1011
  2023
    MOJOSHADER_IR_CJUMP,
icculus@1011
  2024
    MOJOSHADER_IR_SEQ,
icculus@1011
  2025
    MOJOSHADER_IR_LABEL,
icculus@1011
  2026
    MOJOSHADER_IR_DISCARD,
icculus@1011
  2027
    MOJOSHADER_IR_END_RANGE_STMT,
icculus@1011
  2028
icculus@1011
  2029
    MOJOSHADER_IR_START_RANGE_MISC,
icculus@1011
  2030
    MOJOSHADER_IR_EXPRLIST,
icculus@1011
  2031
    MOJOSHADER_IR_END_RANGE_MISC,
icculus@1011
  2032
icculus@1011
  2033
    MOJOSHADER_IR_END_RANGE
icculus@1011
  2034
} MOJOSHADER_irNodeType;
icculus@1011
  2035
icculus@1011
  2036
typedef struct MOJOSHADER_irNodeInfo
icculus@1011
  2037
{
icculus@1011
  2038
    MOJOSHADER_irNodeType type;
icculus@1011
  2039
    const char *filename;
icculus@1011
  2040
    unsigned int line;
icculus@1011
  2041
} MOJOSHADER_irNodeInfo;
icculus@1011
  2042
icculus@1011
  2043
typedef struct MOJOSHADER_irExprList MOJOSHADER_irExprList;
icculus@1011
  2044
icculus@1011
  2045
/*
icculus@1011
  2046
 * IR nodes are categorized into Expressions, Statements, and Everything Else.
icculus@1011
  2047
 *  You can cast any of them to MOJOSHADER_irGeneric, but this split is
icculus@1011
  2048
 *  useful for slightly better type-checking (you can't cleanly assign
icculus@1011
  2049
 *  something that doesn't return a value to something that wants one, etc).
icculus@1011
  2050
 * These broader categories are just unions of the simpler types, so the
icculus@1011
  2051
 *  real definitions are below all the things they contain (but these
icculus@1011
  2052
 *  predeclarations are because the simpler types refer to the broader
icculus@1011
  2053
 *  categories).
icculus@1011
  2054
 */
icculus@1011
  2055
typedef union MOJOSHADER_irExpression MOJOSHADER_irExpression;  /* returns a value. */
icculus@1011
  2056
typedef union MOJOSHADER_irStatement MOJOSHADER_irStatement;   /* no returned value. */
icculus@1011
  2057
typedef union MOJOSHADER_irMisc MOJOSHADER_irMisc;        /* Everything Else. */
icculus@1011
  2058
typedef union MOJOSHADER_irNode MOJOSHADER_irNode;        /* Generic uber-wrapper. */
icculus@1011
  2059
icculus@1011
  2060
/* You can cast any IR node pointer to this. */
icculus@1011
  2061
typedef struct MOJOSHADER_irGeneric
icculus@1011
  2062
{
icculus@1011
  2063
    MOJOSHADER_irNodeInfo ir;
icculus@1011
  2064
} MOJOSHADER_irGeneric;
icculus@1011
  2065
icculus@1011
  2066
icculus@1011
  2067
/* These are used for MOJOSHADER_irBinOp */
icculus@1011
  2068
typedef enum MOJOSHADER_irBinOpType
icculus@1011
  2069
{
icculus@1011
  2070
    MOJOSHADER_IR_BINOP_ADD,
icculus@1011
  2071
    MOJOSHADER_IR_BINOP_SUBTRACT,
icculus@1011
  2072
    MOJOSHADER_IR_BINOP_MULTIPLY,
icculus@1011
  2073
    MOJOSHADER_IR_BINOP_DIVIDE,
icculus@1011
  2074
    MOJOSHADER_IR_BINOP_MODULO,
icculus@1011
  2075
    MOJOSHADER_IR_BINOP_AND,
icculus@1011
  2076
    MOJOSHADER_IR_BINOP_OR,
icculus@1011
  2077
    MOJOSHADER_IR_BINOP_XOR,
icculus@1011
  2078
    MOJOSHADER_IR_BINOP_LSHIFT,
icculus@1011
  2079
    MOJOSHADER_IR_BINOP_RSHIFT,
icculus@1011
  2080
    MOJOSHADER_IR_BINOP_UNKNOWN
icculus@1011
  2081
} MOJOSHADER_irBinOpType;
icculus@1011
  2082
icculus@1011
  2083
typedef enum MOJOSHADER_irConditionType
icculus@1011
  2084
{
icculus@1011
  2085
    MOJOSHADER_IR_COND_EQL,
icculus@1011
  2086
    MOJOSHADER_IR_COND_NEQ,
icculus@1011
  2087
    MOJOSHADER_IR_COND_LT,
icculus@1011
  2088
    MOJOSHADER_IR_COND_GT,
icculus@1011
  2089
    MOJOSHADER_IR_COND_LEQ,
icculus@1011
  2090
    MOJOSHADER_IR_COND_GEQ,
icculus@1011
  2091
    MOJOSHADER_IR_COND_UNKNOWN
icculus@1011
  2092
} MOJOSHADER_irConditionType;
icculus@1011
  2093
icculus@1011
  2094
icculus@1011
  2095
/* MOJOSHADER_irExpression types... */
icculus@1011
  2096
icculus@1011
  2097
typedef struct MOJOSHADER_irExprInfo
icculus@1011
  2098
{
icculus@1011
  2099
    MOJOSHADER_irNodeInfo ir;
icculus@1011
  2100
    MOJOSHADER_astDataTypeType type;
icculus@1011
  2101
    int elements;
icculus@1011
  2102
} MOJOSHADER_irExprInfo;
icculus@1011
  2103
icculus@1011
  2104
typedef struct MOJOSHADER_irConstant    /* Constant value */
icculus@1011
  2105
{
icculus@1011
  2106
    MOJOSHADER_irExprInfo info;  /* Always MOJOSHADER_IR_CONSTANT */
icculus@1011
  2107
    union
icculus@1011
  2108
    {
icculus@1011
  2109
        int ival[16];
icculus@1011
  2110
        float fval[16];
icculus@1011
  2111
    } value;
icculus@1011
  2112
} MOJOSHADER_irConstant;
icculus@1011
  2113
icculus@1011
  2114
typedef struct MOJOSHADER_irTemp /* temp value (not necessarily a register). */
icculus@1011
  2115
{
icculus@1011
  2116
    MOJOSHADER_irExprInfo info;  /* Always MOJOSHADER_IR_TEMP */
icculus@1011
  2117
    int index;
icculus@1011
  2118
} MOJOSHADER_irTemp;
icculus@1011
  2119
icculus@1011
  2120
typedef struct MOJOSHADER_irBinOp  /* binary operator (+, -, etc) */
icculus@1011
  2121
{
icculus@1011
  2122
    MOJOSHADER_irExprInfo info;  /* Always MOJOSHADER_IR_BINOP */
icculus@1011
  2123
    MOJOSHADER_irBinOpType op;
icculus@1011
  2124
    MOJOSHADER_irExpression *left;
icculus@1011
  2125
    MOJOSHADER_irExpression *right;
icculus@1011
  2126
} MOJOSHADER_irBinOp;
icculus@1011
  2127
icculus@1011
  2128
typedef struct MOJOSHADER_irMemory
icculus@1011
  2129
{
icculus@1011
  2130
    MOJOSHADER_irExprInfo info;  /* Always MOJOSHADER_IR_MEMORY */
icculus@1011
  2131
    int index;  /* not final addresses, just a unique identifier. */
icculus@1011
  2132
} MOJOSHADER_irMemory;
icculus@1011
  2133
icculus@1011
  2134
typedef struct MOJOSHADER_irCall
icculus@1011
  2135
{
icculus@1011
  2136
    MOJOSHADER_irExprInfo info;  /* Always MOJOSHADER_IR_CALL */
icculus@1011
  2137
    int index;
icculus@1011
  2138
    MOJOSHADER_irExprList *args;
icculus@1011
  2139
} MOJOSHADER_irCall;
icculus@1011
  2140
icculus@1011
  2141
typedef struct MOJOSHADER_irESeq  /* statement with result */
icculus@1011
  2142
{
icculus@1011
  2143
    MOJOSHADER_irExprInfo info;  /* Always MOJOSHADER_IR_ESEQ */
icculus@1011
  2144
    MOJOSHADER_irStatement *stmt;  /* execute this for side-effects, then... */
icculus@1011
  2145
    MOJOSHADER_irExpression *expr; /* ...use this for the result. */
icculus@1011
  2146
} MOJOSHADER_irESeq;
icculus@1011
  2147
icculus@1011
  2148
typedef struct MOJOSHADER_irArray  /* Array dereference. */
icculus@1011
  2149
{
icculus@1011
  2150
    MOJOSHADER_irExprInfo info;  /* Always MOJOSHADER_IR_ARRAY */
icculus@1011
  2151
    MOJOSHADER_irExpression *array;
icculus@1011
  2152
    MOJOSHADER_irExpression *element;
icculus@1011
  2153
} MOJOSHADER_irArray;
icculus@1011
  2154
icculus@1011
  2155
typedef struct MOJOSHADER_irConvert  /* casting between datatypes */
icculus@1011
  2156
{
icculus@1011
  2157
    MOJOSHADER_irExprInfo info;  /* Always MOJOSHADER_IR_CONVERT */
icculus@1011
  2158
    MOJOSHADER_irExpression *expr;
icculus@1011
  2159
} MOJOSHADER_irConvert;
icculus@1011
  2160
icculus@1011
  2161
typedef struct MOJOSHADER_irSwizzle  /* vector swizzle */
icculus@1011
  2162
{
icculus@1011
  2163
    MOJOSHADER_irExprInfo info;  /* Always MOJOSHADER_IR_SWIZZLE */
icculus@1011
  2164
    MOJOSHADER_irExpression *expr;
icculus@1011
  2165
    char channels[4];
icculus@1011
  2166
} MOJOSHADER_irSwizzle;
icculus@1011
  2167
icculus@1011
  2168
typedef struct MOJOSHADER_irConstruct  /* vector construct from discrete items */
icculus@1011
  2169
{
icculus@1011
  2170
    MOJOSHADER_irExprInfo info;  /* Always MOJOSHADER_IR_CONTSTRUCT */
icculus@1011
  2171
    MOJOSHADER_irExprList *args;
icculus@1011
  2172
} MOJOSHADER_irConstruct;
icculus@1011
  2173
icculus@1011
  2174
/* Wrap the whole category in a union for type "safety." */
icculus@1011
  2175
union MOJOSHADER_irExpression
icculus@1011
  2176
{
icculus@1011
  2177
    MOJOSHADER_irNodeInfo ir;
icculus@1011
  2178
    MOJOSHADER_irExprInfo info;
icculus@1011
  2179
    MOJOSHADER_irConstant constant;
icculus@1011
  2180
    MOJOSHADER_irTemp temp;
icculus@1011
  2181
    MOJOSHADER_irBinOp binop;
icculus@1011
  2182
    MOJOSHADER_irMemory memory;
icculus@1011
  2183
    MOJOSHADER_irCall call;
icculus@1011
  2184
    MOJOSHADER_irESeq eseq;
icculus@1011
  2185
    MOJOSHADER_irArray array;
icculus@1011
  2186
    MOJOSHADER_irConvert convert;
icculus@1011
  2187
    MOJOSHADER_irSwizzle swizzle;
icculus@1011
  2188
    MOJOSHADER_irConstruct construct;
icculus@1011
  2189
};
icculus@1011
  2190
icculus@1011
  2191
/* MOJOSHADER_irStatement types. */
icculus@1011
  2192
icculus@1011
  2193
typedef struct MOJOSHADER_irMove  /* load/store. */
icculus@1011
  2194
{
icculus@1011
  2195
    MOJOSHADER_irNodeInfo ir;  /* Always MOJOSHADER_IR_MOVE */
icculus@1011
  2196
    MOJOSHADER_irExpression *dst; /* must result in a temp or mem! */
icculus@1011
  2197
    MOJOSHADER_irExpression *src;
icculus@1011
  2198
    int writemask;  // for write-masking vector channels.
icculus@1011
  2199
} MOJOSHADER_irMove;
icculus@1011
  2200
icculus@1011
  2201
typedef struct MOJOSHADER_irExprStmt  /* evaluate expression, throw it away. */
icculus@1011
  2202
{
icculus@1011
  2203
    MOJOSHADER_irNodeInfo ir;  /* Always MOJOSHADER_IR_EXPR_STMT */
icculus@1011
  2204
    MOJOSHADER_irExpression *expr;
icculus@1011
  2205
} MOJOSHADER_irExprStmt;
icculus@1011
  2206
icculus@1011
  2207
typedef struct MOJOSHADER_irJump  /* unconditional jump */
icculus@1011
  2208
{
icculus@1011
  2209
    MOJOSHADER_irNodeInfo ir;  /* Always MOJOSHADER_IR_JUMP */
icculus@1011
  2210
    int label;
icculus@1011
  2211
    // !!! FIXME: possible label list, for further optimization passes.
icculus@1011
  2212
} MOJOSHADER_irJump;
icculus@1011
  2213
icculus@1011
  2214
typedef struct MOJOSHADER_irCJump  /* conditional jump */
icculus@1011
  2215
{
icculus@1011
  2216
    MOJOSHADER_irNodeInfo ir;  /* Always MOJOSHADER_IR_CJUMP */
icculus@1011
  2217
    MOJOSHADER_irConditionType cond;
icculus@1011
  2218
    MOJOSHADER_irExpression *left;  /* if (left cond right) */
icculus@1011
  2219
    MOJOSHADER_irExpression *right;
icculus@1011
  2220
    int iftrue;  /* label id for true case. */
icculus@1011
  2221
    int iffalse; /* label id for false case. */
icculus@1011
  2222
} MOJOSHADER_irCJump;
icculus@1011
  2223
icculus@1011
  2224
typedef struct MOJOSHADER_irSeq  /* statement without side effects */
icculus@1011
  2225
{
icculus@1011
  2226
    MOJOSHADER_irNodeInfo ir;  /* Always MOJOSHADER_IR_SEQ */
icculus@1011
  2227
    MOJOSHADER_irStatement *first;
icculus@1011
  2228
    MOJOSHADER_irStatement *next;
icculus@1011
  2229
} MOJOSHADER_irSeq;
icculus@1011
  2230
icculus@1011
  2231
typedef struct MOJOSHADER_irLabel  /* like a label in assembly language. */
icculus@1011
  2232
{
icculus@1011
  2233
    MOJOSHADER_irNodeInfo ir;  /* Always MOJOSHADER_IR_LABEL */
icculus@1011
  2234
    int index;
icculus@1011
  2235
} MOJOSHADER_irLabel;
icculus@1011
  2236
icculus@1011
  2237
typedef MOJOSHADER_irGeneric MOJOSHADER_irDiscard;  /* discard statement. */
icculus@1011
  2238
icculus@1011
  2239
icculus@1011
  2240
/* Wrap the whole category in a union for type "safety." */
icculus@1011
  2241
union MOJOSHADER_irStatement
icculus@1011
  2242
{
icculus@1011
  2243
    MOJOSHADER_irNodeInfo ir;
icculus@1011
  2244
    MOJOSHADER_irGeneric generic;
icculus@1011
  2245
    MOJOSHADER_irMove move;
icculus@1011
  2246
    MOJOSHADER_irExprStmt expr;
icculus@1011
  2247
    MOJOSHADER_irJump jump;
icculus@1011
  2248
    MOJOSHADER_irCJump cjump;
icculus@1011
  2249
    MOJOSHADER_irSeq seq;
icculus@1011
  2250
    MOJOSHADER_irLabel label;
icculus@1011
  2251
    MOJOSHADER_irDiscard discard;
icculus@1011
  2252
};
icculus@1011
  2253
icculus@1011
  2254
/* MOJOSHADER_irMisc types. */
icculus@1011
  2255
icculus@1011
  2256
struct MOJOSHADER_irExprList
icculus@1011
  2257
{
icculus@1011
  2258
    MOJOSHADER_irNodeInfo ir;  /* Always MOJOSHADER_IR_EXPRLIST */
icculus@1011
  2259
    MOJOSHADER_irExpression *expr;
icculus@1011
  2260
    MOJOSHADER_irExprList *next;
icculus@1011
  2261
};
icculus@1011
  2262
icculus@1011
  2263
/* Wrap the whole category in a union for type "safety." */
icculus@1011
  2264
union MOJOSHADER_irMisc
icculus@1011
  2265
{
icculus@1011
  2266
    MOJOSHADER_irNodeInfo ir;
icculus@1011
  2267
    MOJOSHADER_irGeneric generic;
icculus@1011
  2268
    MOJOSHADER_irExprList exprlist;
icculus@1011
  2269
};
icculus@1011
  2270
icculus@1011
  2271
/* This is a catchall for all your needs. :) */
icculus@1011
  2272
union MOJOSHADER_irNode
icculus@1011
  2273
{
icculus@1011
  2274
    MOJOSHADER_irNodeInfo ir;
icculus@1011
  2275
    MOJOSHADER_irGeneric generic;
icculus@1011
  2276
    MOJOSHADER_irExpression expr;
icculus@1011
  2277
    MOJOSHADER_irStatement stmt;
icculus@1011
  2278
    MOJOSHADER_irMisc misc;
icculus@1011
  2279
};
icculus@1011
  2280
icculus@931
  2281
icculus@931
  2282
/* Compiler interface... */
icculus@931
  2283
icculus@931
  2284
/*
icculus@931
  2285
 * Structure used to return data from parsing of a shader...
icculus@931
  2286
 */
icculus@931
  2287
/* !!! FIXME: most of these ints should be unsigned. */
icculus@931
  2288
typedef struct MOJOSHADER_compileData
icculus@931
  2289
{
icculus@931
  2290
    /*
icculus@931
  2291
     * The number of elements pointed to by (errors).
icculus@931
  2292
     */
icculus@931
  2293
    int error_count;
icculus@931
  2294
icculus@931
  2295
    /*
icculus@931
  2296
     * (error_count) elements of data that specify errors that were generated
icculus@931
  2297
     *  by compiling this shader.
icculus@931
  2298
     * This can be NULL if there were no errors or if (error_count) is zero.
icculus@931
  2299
     */
icculus@931
  2300
    MOJOSHADER_error *errors;
icculus@931
  2301
icculus@931
  2302
    /*
icculus@931
  2303
     * The number of elements pointed to by (warnings).
icculus@931
  2304
     */
icculus@931
  2305
    int warning_count;
icculus@931
  2306
icculus@931
  2307
    /*
icculus@931
  2308
     * (warning_count) elements of data that specify errors that were
icculus@931
  2309
     *  generated by compiling this shader.
icculus@931
  2310
     * This can be NULL if there were no errors or if (warning_count) is zero.
icculus@931
  2311
     */
icculus@931
  2312
    MOJOSHADER_error *warnings;
icculus@931
  2313
icculus@931
  2314
    /*
icculus@931
  2315
     * The name of the source profile used to compile the shader. Will be NULL
icculus@931
  2316
     *  on error.
icculus@931
  2317
     */
icculus@931
  2318
    const char *source_profile;
icculus@931
  2319
icculus@931
  2320
    /*
icculus@931
  2321
     * Bytes of output from compiling. This will be a null-terminated ASCII
icculus@931
  2322
     *  string of D3D assembly source code.
icculus@931
  2323
     */
icculus@931
  2324
    const char *output;
icculus@931
  2325
icculus@931
  2326
    /*
icculus@931
  2327
     * Byte count for output, not counting any null terminator.
icculus@931
  2328
     *  Will be 0 on error.
icculus@931
  2329
     */
icculus@931
  2330
    int output_len;
icculus@931
  2331
icculus@931
  2332
    /*
icculus@931
  2333
     * The number of elements pointed to by (symbols).
icculus@931
  2334
     */
icculus@931
  2335
    int symbol_count;
icculus@931
  2336
icculus@931
  2337
    /*
icculus@931
  2338
     * (symbol_count) elements of data that specify high-level symbol data
icculus@931
  2339
     *  for the shader. This can be used by MOJOSHADER_assemble() to
icculus@931
  2340
     *  generate a CTAB section in bytecode, which is needed by
icculus@931
  2341
     *  MOJOSHADER_parseData() to handle some shaders. This can be NULL on
icculus@931
  2342
     *  error or if (symbol_count) is zero.
icculus@931
  2343
     */
icculus@931
  2344
    MOJOSHADER_symbol *symbols;
icculus@931
  2345
icculus@931
  2346
    /*
icculus@931
  2347
     * This is the malloc implementation you passed to MOJOSHADER_parse().
icculus@931
  2348
     */
icculus@931
  2349
    MOJOSHADER_malloc malloc;
icculus@931
  2350
icculus@931
  2351
    /*
icculus@931
  2352
     * This is the free implementation you passed to MOJOSHADER_parse().
icculus@931
  2353
     */
icculus@931
  2354
    MOJOSHADER_free free;
icculus@931
  2355
icculus@931
  2356
    /*
icculus@931
  2357
     * This is the pointer you passed as opaque data for your allocator.
icculus@931
  2358
     */
icculus@931
  2359
    void *malloc_data;
icculus@931
  2360
} MOJOSHADER_compileData;
icculus@931
  2361
icculus@931
  2362
icculus@931
  2363
/*
icculus@931
  2364
 * This function is optional. Use this to compile high-level shader programs.
icculus@931
  2365
 *
icculus@931
  2366
 * This is intended to turn HLSL source code into D3D assembly code, which
icculus@931
  2367
 *  can then be passed to MOJOSHADER_assemble() to convert it to D3D bytecode
icculus@931
  2368
 *  (which can then be used with MOJOSHADER_parseData() to support other
icculus@931
  2369
 *  shading targets).
icculus@931
  2370
 *
icculus@931
  2371
 * (srcprofile) specifies the source language of the shader. You can specify
icculus@931
  2372
 *  a shader model with this, too. See MOJOSHADER_SRC_PROFILE_* constants.
icculus@931
  2373
 *
icculus@931
  2374
 * (filename) is a NULL-terminated UTF-8 filename. It can be NULL. We do not
icculus@931
  2375
 *  actually access this file, as we obtain our data from (source). This
icculus@931
  2376
 *  string is copied when we need to report errors while processing (source),
icculus@931
  2377
 *  as opposed to errors in a file referenced via the #include directive in
icculus@931
  2378
 *  (source). If this is NULL, then errors will report the filename as NULL,
icculus@931
  2379
 *  too.
icculus@931
  2380
 *
icculus@931
  2381
 * (source) is an UTF-8 string of valid high-level shader source code.
icculus@931
  2382
 *  It does not need to be NULL-terminated.
icculus@931
  2383
 *
icculus@931
  2384
 * (sourcelen) is the length of the string pointed to by (source), in bytes.
icculus@931
  2385
 *
icculus@931
  2386
 * (defines) points to (define_count) preprocessor definitions, and can be
icculus@931
  2387
 *  NULL. These are treated by the preprocessor as if the source code started
icculus@931
  2388
 *  with one #define for each entry you pass in here.
icculus@931
  2389
 *
icculus@931
  2390
 * (include_open) and (include_close) let the app control the preprocessor's
icculus@931
  2391
 *  behaviour for #include statements. Both are optional and can be NULL, but
icculus@931
  2392
 *  both must be specified if either is specified.
icculus@931
  2393
 *
icculus@931
  2394
 * This will return a MOJOSHADER_compileData. The data supplied here is
icculus@931
  2395
 *  sufficient to supply to MOJOSHADER_assemble() for further processing.
icculus@931
  2396
 *  When you are done with this data, pass it to MOJOSHADER_freeCompileData()
icculus@931
  2397
 *  to deallocate resources.
icculus@931
  2398
 *
icculus@931
  2399
 * This function will never return NULL, even if the system is completely
icculus@931
  2400
 *  out of memory upon entry (in which case, this function returns a static
icculus@931
  2401
 *  MOJOSHADER_compileData object, which is still safe to pass to
icculus@931
  2402
 *  MOJOSHADER_freeCompileData()).
icculus@931
  2403
 *
icculus@931
  2404
 * As compiling requires some memory to be allocated, you may provide a
icculus@931
  2405
 *  custom allocator to this function, which will be used to allocate/free
icculus@931
  2406
 *  memory. They function just like malloc() and free(). We do not use
icculus@931
  2407
 *  realloc(). If you don't care, pass NULL in for the allocator functions.
icculus@931
  2408
 *  If your allocator needs instance-specific data, you may supply it with the
icculus@931
  2409
 *  (d) parameter. This pointer is passed as-is to your (m) and (f) functions.
icculus@931
  2410
 *
icculus@931
  2411
 * This function is thread safe, so long as the various callback functions
icculus@931
  2412
 *  are, too, and that the parameters remains intact for the duration of the
icculus@931
  2413
 *  call. This allows you to compile several shaders on separate CPU cores
icculus@931
  2414
 *  at the same time.
icculus@931
  2415
 */
flibitijibibo@1150
  2416
DECLSPEC const MOJOSHADER_compileData *MOJOSHADER_compile(const char *srcprofile,
icculus@931
  2417
                                    const char *filename, const char *source,
icculus@931
  2418
                                    unsigned int sourcelen,
icculus@931
  2419
                                    const MOJOSHADER_preprocessorDefine *defs,
icculus@931
  2420
                                    unsigned int define_count,
icculus@931
  2421
                                    MOJOSHADER_includeOpen include_open,
icculus@931
  2422
                                    MOJOSHADER_includeClose include_close,
icculus@931
  2423
                                    MOJOSHADER_malloc m, MOJOSHADER_free f,
icculus@931
  2424
                                    void *d);
icculus@931
  2425
icculus@931
  2426
icculus@935
  2427
/*
icculus@935
  2428
 * Call this to dispose of compile results when you are done with them.
icculus@935
  2429
 *  This will call the MOJOSHADER_free function you provided to
icculus@935
  2430
 *  MOJOSHADER_compile() multiple times, if you provided one.
icculus@935
  2431
 *  Passing a NULL here is a safe no-op.
icculus@935
  2432
 *
icculus@935
  2433
 * This function is thread safe, so long as any allocator you passed into
icculus@935
  2434
 *  MOJOSHADER_compile() is, too.
icculus@935
  2435
 */
flibitijibibo@1150
  2436
DECLSPEC void MOJOSHADER_freeCompileData(const MOJOSHADER_compileData *data);
icculus@935
  2437
icculus@935
  2438
icculus@218
  2439
/* OpenGL interface... */
icculus@218
  2440
icculus@196
  2441
/*
icculus@904
  2442
 * Signature for function lookup callbacks. MojoShader will call a function
icculus@904
  2443
 *  you provide to get OpenGL entry points (both standard functions and
icculus@904
  2444
 *  extensions). Through this, MojoShader never links directly to OpenGL,
icculus@904
  2445
 *  but relies on you to provide the implementation. This means you can
icculus@904
  2446
 *  swap in different drivers, or hook functions (log every GL call MojoShader
icculus@904
  2447
 *  makes, etc).
icculus@904
  2448
 *
icculus@904
  2449
 * (fnname) is the function name we want the address for ("glBegin" or
icculus@904
  2450
 *  whatever. (data) is a void pointer you provide, if this callback needs
icculus@904
  2451
 *  extra information. If you don't need it, you may specify NULL.
icculus@904
  2452
 *
icculus@904
  2453
 * Return the entry point on success, NULL if it couldn't be found.
icculus@904
  2454
 *  Note that this could ask for standard entry points like glEnable(), or
icculus@904
  2455
 *  extensions like glProgramLocalParameterI4ivNV(), so you might need
icculus@904
  2456
 *  to check two places to find the desired entry point, depending on your
icculus@904
  2457
 *  platform (Windows might need to look in OpenGL32.dll and use WGL, etc).
icculus@904
  2458
 */
flibitijibibo@1150
  2459
typedef void *(MOJOSHADERCALL *MOJOSHADER_glGetProcAddress)(const char *fnname, void *data);
icculus@904
  2460
icculus@904
  2461
icculus@904
  2462
/*
icculus@237
  2463
 * "Contexts" map to OpenGL contexts...you need one per window, or whatever,
icculus@237
  2464
 *  and need to inform MojoShader when you make a new one current.
icculus@237
  2465
 *
icculus@237
  2466
 * "Shaders" refer to individual vertex or pixel programs, and are created
icculus@237
  2467
 *  by "compiling" Direct3D shader bytecode. A vertex and pixel shader are
icculus@237
  2468
 *  "linked" into a "Program" before you can use them to render.
icculus@237
  2469
 *
icculus@237
  2470
 * To the calling application, these are all opaque handles.
icculus@237
  2471
 */
icculus@237
  2472
typedef struct MOJOSHADER_glContext MOJOSHADER_glContext;
icculus@237
  2473
typedef struct MOJOSHADER_glShader MOJOSHADER_glShader;
icculus@237
  2474
typedef struct MOJOSHADER_glProgram MOJOSHADER_glProgram;
icculus@237
  2475
icculus@262
  2476
icculus@262
  2477
/*
icculus@422
  2478
 * Get a list of available profiles. This will fill in the array (profs)
icculus@422
  2479
 *  with up to (size) pointers of profiles that the current system can handle;
icculus@422
  2480
 *  that is, the profiles are built into MojoShader and the OpenGL extensions
icculus@422
  2481
 *  required for them exist at runtime. This function returns the number of
icculus@422
  2482
 *  available profiles, which may be more, less, or equal to (size).
icculus@422
  2483
 *
icculus@422
  2484
 * If there are more than (size) profiles, the (profs) buffer will not
icculus@422
  2485
 *  overflow. You can check the return value for the total number of
icculus@422
  2486
 *  available profiles, allocate more space, and try again if necessary.
icculus@422
  2487
 *  Calling this function with (size) == 0 is legal.
icculus@422
  2488
 *
icculus@422
  2489
 * You can only call this AFTER you have successfully built your GL context
icculus@422
  2490
 *  and made it current. This function will lookup the GL functions it needs
icculus@1117
  2491
 *  through the callback you supply, via (lookup) and (lookup_d). The lookup
icculus@1117
  2492
 *  function is neither stored nor used by MojoShader after this function
icculus@1117
  2493
 *  returns, nor are the functions it might look up.
icculus@1117
  2494
 *
icculus@1117
  2495
 * As MojoShader requires some memory to be allocated, you may provide a
icculus@1117
  2496
 *  custom allocator to this function, which will be used to allocate/free
icculus@1117
  2497
 *  memory. They function just like malloc() and free(). We do not use
icculus@1117
  2498
 *  realloc(). If you don't care, pass NULL in for the allocator functions.
icculus@1117
  2499
 *  If your allocator needs instance-specific data, you may supply it with the
icculus@1117
  2500
 *  (malloc_d) parameter. This pointer is passed as-is to your (m) and (f)
icculus@1117
  2501
 *  functions.
icculus@422
  2502
 *
icculus@422
  2503
 * You should not free any strings returned from this function; they are
icculus@422
  2504
 *  pointers to internal, probably static, memory.
icculus@422
  2505
 *
icculus@422
  2506
 * This call is NOT thread safe! As most OpenGL implementations are not thread
icculus@422
  2507
 *  safe, you should probably only call this from the same thread that created
icculus@422
  2508
 *  the GL context.
icculus@422
  2509
 */
flibitijibibo@1150
  2510
DECLSPEC int MOJOSHADER_glAvailableProfiles(MOJOSHADER_glGetProcAddress lookup,
flibitijibibo@1150
  2511
                                            void *lookup_d,
flibitijibibo@1150
  2512
                                            const char **profs, const int size,
flibitijibibo@1150
  2513
                                            MOJOSHADER_malloc m, MOJOSHADER_free f,
flibitijibibo@1150
  2514
                                            void *malloc_d);
icculus@422
  2515
icculus@422
  2516
icculus@422
  2517
/*
icculus@262
  2518
 * Determine the best profile to use for the current system.
icculus@262
  2519
 *
icculus@262
  2520
 * You can only call this AFTER you have successfully built your GL context
icculus@262
  2521
 *  and made it current. This function will lookup the GL functions it needs
icculus@1117
  2522
 *  through the callback you supply via (lookup) and (lookup_d). The lookup
icculus@1117
  2523
 *  function is neither stored nor used by MojoShader after this function
icculus@1117
  2524
 *  returns, nor are the functions it might look up.
icculus@262
  2525
 *
icculus@262
  2526
 * Returns the name of the "best" profile on success, NULL if none of the
icculus@262
  2527
 *  available profiles will work on this system. "Best" is a relative term,
icculus@262
  2528
 *  but it generally means the best trade off between feature set and
icculus@262
  2529
 *  performance. The selection algorithm may be arbitrary and complex.
icculus@262
  2530
 *
icculus@1117
  2531
 * As MojoShader requires some memory to be allocated, you may provide a
icculus@1117
  2532
 *  custom allocator to this function, which will be used to allocate/free
icculus@1117
  2533
 *  memory. They function just like malloc() and free(). We do not use
icculus@1117
  2534
 *  realloc(). If you don't care, pass NULL in for the allocator functions.
icculus@1117
  2535
 *  If your allocator needs instance-specific data, you may supply it with the
icculus@1117
  2536
 *  (malloc_d) parameter. This pointer is passed as-is to your (m) and (f)
icculus@1117
  2537
 *  functions.
icculus@1117
  2538
 *
icculus@262
  2539
 * The returned value is an internal static string, and should not be free()'d
icculus@262
  2540
 *  by the caller. If you get a NULL, calling MOJOSHADER_glGetError() might
icculus@262
  2541
 *  shed some light on why.
icculus@262
  2542
 *
icculus@262
  2543
 * This call is NOT thread safe! As most OpenGL implementations are not thread
icculus@262
  2544
 *  safe, you should probably only call this from the same thread that created
icculus@262
  2545
 *  the GL context.
icculus@262
  2546
 */
flibitijibibo@1150
  2547
DECLSPEC const char *MOJOSHADER_glBestProfile(MOJOSHADER_glGetProcAddress lookup,
icculus@1117
  2548
                                   void *lookup_d,
icculus@1117
  2549
                                   MOJOSHADER_malloc m, MOJOSHADER_free f,
icculus@1117
  2550
                                   void *malloc_d);
icculus@262
  2551
icculus@237
  2552
/*
icculus@196
  2553
 * Prepare MojoShader to manage OpenGL shaders.
icculus@196
  2554
 *
icculus@196
  2555
 * You do not need to call this if all you want is MOJOSHADER_parse().
icculus@196
  2556
 *
icculus@196
  2557
 * You must call this once AFTER you have successfully built your GL context
icculus@196
  2558
 *  and made it current. This function will lookup the GL functions it needs
icculus@904
  2559
 *  through the callback you supply via (lookup) and (lookup_d), after which
icculus@904
  2560
 *  it may call them at any time up until you call
icculus@904
  2561
 *  MOJOSHADER_glDestroyContext(). The lookup function is neither stored nor
icculus@904
  2562
 *  used by MojoShader after this function returns.
icculus@196
  2563
 *
icculus@196
  2564
 * (profile) is an OpenGL-specific MojoShader profile, which decides how
icculus@196
  2565
 *  Direct3D bytecode shaders get turned into OpenGL programs, and how they
icculus@196
  2566
 *  are fed to the GL.
icculus@196
  2567
 *
icculus@196
  2568
 * (lookup) is a callback that is used to load GL entry points. This callback
icculus@904
  2569
 *  has to look up base GL functions and extension entry points. The pointer
icculus@904
  2570
 *  you supply in (lookup_d) is passed as-is to the callback.
icculus@196
  2571
 *
icculus@196
  2572
 * As MojoShader requires some memory to be allocated, you may provide a
icculus@196
  2573
 *  custom allocator to this function, which will be used to allocate/free
icculus@196
  2574
 *  memory. They function just like malloc() and free(). We do not use
icculus@196
  2575
 *  realloc(). If you don't care, pass NULL in for the allocator functions.
icculus@196
  2576
 *  If your allocator needs instance-specific data, you may supply it with the
icculus@904
  2577
 *  (malloc_d) parameter. This pointer is passed as-is to your (m) and (f)
icculus@904
  2578
 *  functions.
icculus@196
  2579
 *
icculus@237
  2580
 * Returns a new context on success, NULL on error. If you get a new context,
icculus@237
  2581
 *  you need to make it current before using it with
icculus@237
  2582
 *  MOJOSHADER_glMakeContextCurrent().
icculus@196
  2583
 *
icculus@196
  2584
 * This call is NOT thread safe! It must return success before you may call
icculus@196
  2585
 *  any other MOJOSHADER_gl* function. Also, as most OpenGL implementations
icculus@196
  2586
 *  are not thread safe, you should probably only call this from the same
icculus@196
  2587
 *  thread that created the GL context.
icculus@196
  2588
 */
flibitijibibo@1150
  2589
DECLSPEC MOJOSHADER_glContext *MOJOSHADER_glCreateContext(const char *profile,
icculus@904
  2590
                                        MOJOSHADER_glGetProcAddress lookup,
icculus@904
  2591
                                        void *lookup_d,
icculus@237
  2592
                                        MOJOSHADER_malloc m, MOJOSHADER_free f,
icculus@904
  2593
                                        void *malloc_d);
icculus@237
  2594
icculus@237
  2595
/*
icculus@237
  2596
 * You must call this before using the context that you got from
icculus@238
  2597
 *  MOJOSHADER_glCreateContext(), and must use it when you switch to a new GL
icculus@238
  2598
 *  context.
icculus@237
  2599
 *
icculus@237
  2600
 * You can only have one MOJOSHADER_glContext per actual GL context, or
icculus@237
  2601
 *  undefined behaviour will result.
icculus@237
  2602
 *
icculus@237
  2603
 * It is legal to call this with a NULL pointer to make no context current,
icculus@237
  2604
 *  but you need a valid context to be current to use most of MojoShader.
icculus@237
  2605
 */
flibitijibibo@1150
  2606
DECLSPEC void MOJOSHADER_glMakeContextCurrent(MOJOSHADER_glContext *ctx);
icculus@196
  2607
icculus@219
  2608
/*
icculus@219
  2609
 * Get any error state we might have picked up. MojoShader will NOT call
icculus@219
  2610
 *  glGetError() internally, but there are other errors we can pick up,
icculus@219
  2611
 *  such as failed shader compilation, etc.
icculus@219
  2612
 *
icculus@219
  2613
 * Returns a human-readable string. This string is for debugging purposes, and
icculus@219
  2614
 *  not guaranteed to be localized, coherent, or user-friendly in any way.
icculus@219
  2615
 *  It's for programmers!
icculus@219
  2616
 *
icculus@219
  2617
 * The latest error may remain between calls. New errors replace any existing
icculus@219
  2618
 *  error. Don't check this string for a sign that an error happened, check
icculus@219
  2619
 *  return codes instead and use this for explanation when debugging.
icculus@219
  2620
 *
icculus@219
  2621
 * Do not free the returned string: it's a pointer to a static internal
icculus@219
  2622
 *  buffer. Do not keep the pointer around, either, as it's likely to become
icculus@219
  2623
 *  invalid as soon as you call into MojoShader again.
icculus@219
  2624
 *
icculus@219
  2625
 * This call is NOT thread safe! As most OpenGL implementations are not thread
icculus@219
  2626
 *  safe, you should probably only call this from the same thread that created
icculus@219
  2627
 *  the GL context.
icculus@237
  2628
 *
icculus@237
  2629
 * This call does NOT require a valid MOJOSHADER_glContext to have been made
icculus@237
  2630
 *  current. The error buffer is shared between contexts, so you can get
icculus@238
  2631
 *  error results from a failed MOJOSHADER_glCreateContext().
icculus@219
  2632
 */
flibitijibibo@1150
  2633
DECLSPEC const char *MOJOSHADER_glGetError(void);
icculus@217
  2634
icculus@196
  2635
/*
icculus@276
  2636
 * Get the maximum uniforms a shader can support for the current GL context,
icculus@276
  2637
 *  MojoShader profile, and shader type. You can use this to make decisions
icculus@276
  2638
 *  about what shaders you want to use (for example, a less complicated
icculus@276
  2639
 *  shader may be swapped in for lower-end systems).
icculus@276
  2640
 *
icculus@276
  2641
 * Returns the number, or -1 on error.
icculus@276
  2642
 *
icculus@276
  2643
 * This call is NOT thread safe! As most OpenGL implementations are not thread
icculus@276
  2644
 *  safe, you should probably only call this from the same thread that created
icculus@276
  2645
 *  the GL context.
icculus@276
  2646
 *
icculus@276
  2647
 * This call requires a valid MOJOSHADER_glContext to have been made current,
icculus@276
  2648
 *  or it will crash your program. See MOJOSHADER_glMakeContextCurrent().
icculus@276
  2649
 */
flibitijibibo@1150
  2650
DECLSPEC int MOJOSHADER_glMaxUniforms(MOJOSHADER_shaderType shader_type);
icculus@276
  2651
icculus@276
  2652
/*
icculus@196
  2653
 * Compile a buffer of Direct3D shader bytecode into an OpenGL shader.
icculus@196
  2654
 *  You still need to link the shader before you may render with it.
icculus@196
  2655
 *
icculus@196
  2656
 *   (tokenbuf) is a buffer of Direct3D shader bytecode.
icculus@196
  2657
 *   (bufsize) is the size, in bytes, of the bytecode buffer.
icculus@1104
  2658
 *   (swiz), (swizcount), (smap), and (smapcount) are passed to
icculus@1104
  2659
 *   MOJOSHADER_parse() unmolested.
icculus@196
  2660
 *
icculus@196
  2661
 * Returns NULL on error, or a shader handle on success.
icculus@217
  2662
 *
icculus@217