Shader linking i guess
This commit is contained in:
507
minispv/minispv.h
Normal file
507
minispv/minispv.h
Normal file
@@ -0,0 +1,507 @@
|
||||
#ifndef MINI_SPIRV_H
|
||||
#define MINI_SPIRV_H
|
||||
#include "stdlib.h"
|
||||
#include "stdint.h"
|
||||
#include "stdio.h"
|
||||
#include "string.h"
|
||||
#include "unistd.h"
|
||||
#define SPV_ENABLE_UTILITY_CODE
|
||||
#include "spirv/unified1/spirv.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
/* arrays */
|
||||
|
||||
static inline uint32_t _mspvalign2( uint32_t x )
|
||||
{
|
||||
if (x <= 1) return 1;
|
||||
x--;
|
||||
x |= x >> 1;
|
||||
x |= x >> 2;
|
||||
x |= x >> 4;
|
||||
x |= x >> 8;
|
||||
x |= x >> 16;
|
||||
x++;
|
||||
return x;
|
||||
}
|
||||
|
||||
#define mspv_array(T) \
|
||||
struct \
|
||||
{ \
|
||||
size_t count; \
|
||||
size_t capacity; \
|
||||
T *data; \
|
||||
}
|
||||
|
||||
#define mspv_array_zero(array) \
|
||||
array.count = 0; \
|
||||
array.capacity = 0; \
|
||||
array.data = NULL;
|
||||
|
||||
#define mspv_array_create(array, count) \
|
||||
array.count = count; \
|
||||
array.capacity = _mspvalign2(count); \
|
||||
array.data = malloc(array.capacity * sizeof(*array.data));
|
||||
|
||||
#define mspv_array_push(array, value) \
|
||||
do { \
|
||||
if (array.count >= array.capacity) { \
|
||||
if (array.capacity == 0) array.capacity = 4; \
|
||||
else array.capacity *= 2; \
|
||||
array.data = (typeof(array.data))realloc(array.data, array.capacity * sizeof(*array.data)); \
|
||||
} \
|
||||
array.data[array.count++] = value;\
|
||||
} while(0) \
|
||||
|
||||
#define mspv_array_destroy(array) \
|
||||
if (array.data) free(array.data); \
|
||||
mspv_array_zero(array)
|
||||
|
||||
/* strings views for simplicity */
|
||||
typedef struct
|
||||
{
|
||||
const char *data;
|
||||
size_t len;
|
||||
} mspv_string_view;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t *data;
|
||||
size_t len;
|
||||
} mspv_data_view;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t id;
|
||||
mspv_string_view name;
|
||||
} mspv_ext_import;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
SpvExecutionModel model;
|
||||
uint32_t id;
|
||||
mspv_string_view name;
|
||||
mspv_array(uint32_t) params;
|
||||
} mspv_entry_point;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t id;
|
||||
SpvExecutionMode mode;
|
||||
mspv_data_view dv;
|
||||
} mspv_execution_mode;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t resulttype;
|
||||
uint32_t result;
|
||||
uint32_t functionctrl;
|
||||
uint32_t functiontype;
|
||||
mspv_data_view instructions;
|
||||
} mspv_function;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t magic;
|
||||
uint32_t reserved1;
|
||||
uint32_t reserved2;
|
||||
uint32_t reserved3;
|
||||
uint32_t reserved4;
|
||||
} mspv_header;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t id;
|
||||
mspv_data_view dv;
|
||||
} mspv_type;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t resulttype;
|
||||
uint32_t result;
|
||||
uint32_t storageclass;
|
||||
uint32_t initializer;
|
||||
} mspv_variable;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t id;
|
||||
mspv_string_view name;
|
||||
} mspv_name;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
mspv_header header;
|
||||
SpvMemoryModel memory_model;
|
||||
SpvAddressingModel addressing_model;
|
||||
mspv_array(SpvCapability) capabilities;
|
||||
mspv_array(mspv_string_view) extensions;
|
||||
mspv_array(mspv_ext_import) ext_instructions;
|
||||
mspv_array(mspv_string_view) instruction_imports;
|
||||
mspv_array(mspv_entry_point) entry_points;
|
||||
mspv_array(mspv_execution_mode) execution_modes;
|
||||
mspv_array(mspv_name) names;
|
||||
mspv_array(mspv_type) types;
|
||||
mspv_array(mspv_variable) variables;
|
||||
mspv_array(mspv_function) functions;
|
||||
|
||||
uint32_t *data;
|
||||
uint32_t count;
|
||||
} mspv_module;
|
||||
|
||||
|
||||
mspv_module *mspv_read_module( uint32_t count, uint32_t *data );
|
||||
void mspv_close_module( mspv_module* module );
|
||||
|
||||
#define mspv_todo(str) printf("todo!!! " str "\n"); _exit(0)
|
||||
|
||||
#define mspv_sv_fmt "%.*s"
|
||||
#define mspv_psv(sv) sv.len, sv.data
|
||||
|
||||
//#ifdef MINI_SPIRV_IMPLEMENTATION
|
||||
static inline mspv_string_view mspv_sv_from_op( uint32_t *op )
|
||||
{
|
||||
return { (char*)op, strlen((char*)op)};
|
||||
|
||||
};
|
||||
|
||||
mspv_module *mspv_read_module( uint32_t count, uint32_t *data )
|
||||
{
|
||||
mspv_module m;
|
||||
mspv_header *h;
|
||||
int i;
|
||||
uint32_t u;
|
||||
SpvOp op;
|
||||
uint16_t instruction_size;
|
||||
uint16_t local_offset;
|
||||
mspv_string_view sv;
|
||||
mspv_data_view dv;
|
||||
mspv_entry_point ep;
|
||||
mspv_ext_import imp;
|
||||
mspv_execution_mode em;
|
||||
mspv_type type;
|
||||
mspv_variable var;
|
||||
mspv_function fn;
|
||||
mspv_name nm;
|
||||
int isfn;
|
||||
|
||||
if ( count == 0 || data == NULL)
|
||||
return 0;
|
||||
|
||||
m = {};
|
||||
m.data = data;
|
||||
m.count = count;
|
||||
|
||||
h = (mspv_header*)data;
|
||||
if ( h->magic != SpvMagicNumber )
|
||||
return 0;
|
||||
m.header = *h;
|
||||
|
||||
/* loop instrucitons */
|
||||
isfn = 0;
|
||||
|
||||
for ( u = 5; u < count; )
|
||||
{
|
||||
instruction_size = data[u] >> 16;
|
||||
op = (SpvOp)(data[u] & 0xFFFF);
|
||||
switch (op)
|
||||
{
|
||||
case SpvOpCapability:
|
||||
mspv_array_push(m.capabilities, (SpvCapability)data[u+1]);
|
||||
break;
|
||||
case SpvOpExtension:
|
||||
sv.len = strlen((char*)(data + u + 1));
|
||||
sv.data = (char*)&data[u+1];
|
||||
mspv_array_push(m.extensions, sv);
|
||||
break;
|
||||
case SpvOpExtInstImport:
|
||||
imp.id = data[u+1];
|
||||
imp.name.len = strlen((char*)(data + u + 2));
|
||||
imp.name.data = (char*)&data[u+2];
|
||||
mspv_array_push(m.ext_instructions, imp);
|
||||
break;
|
||||
case SpvOpMemoryModel:
|
||||
m.addressing_model = (SpvAddressingModel)data[u+1];
|
||||
m.memory_model = (SpvMemoryModel)data[u+2];
|
||||
break;
|
||||
case SpvOpEntryPoint:
|
||||
ep.model = (SpvExecutionModel)data[u+1];
|
||||
ep.id = (SpvExecutionModel)data[u+2];
|
||||
ep.name = mspv_sv_from_op(data+u+3);
|
||||
ep.params = {};
|
||||
for ( i = 4 + ep.name.len/4; i < instruction_size; i++ )
|
||||
{
|
||||
mspv_array_push(ep.params, data[u+i]);
|
||||
}
|
||||
mspv_array_push(m.entry_points, ep);
|
||||
break;
|
||||
case SpvOpExecutionMode:
|
||||
em.id = data[u+1];
|
||||
em.mode = (SpvExecutionMode)data[u+2];
|
||||
em.dv.data = data + u;
|
||||
em.dv.len = instruction_size - 1;
|
||||
mspv_array_push(m.execution_modes, em);
|
||||
break;
|
||||
case SpvOpString:
|
||||
case SpvOpSourceExtension:
|
||||
case SpvOpSource:
|
||||
case SpvOpSourceContinued:
|
||||
case SpvOpMemberName:
|
||||
case SpvOpModuleProcessed:
|
||||
break;
|
||||
case SpvOpName:
|
||||
nm.id = data[u+1];
|
||||
nm.name = mspv_sv_from_op(data+u+2);
|
||||
mspv_array_push(m.names, nm);
|
||||
|
||||
break;
|
||||
|
||||
case SpvOpTypeVoid:
|
||||
case SpvOpTypeBool:
|
||||
case SpvOpTypeInt:
|
||||
case SpvOpTypeFloat:
|
||||
case SpvOpTypeVector:
|
||||
case SpvOpTypeMatrix:
|
||||
case SpvOpTypeImage:
|
||||
case SpvOpTypeSampler:
|
||||
case SpvOpTypeSampledImage:
|
||||
case SpvOpTypeArray:
|
||||
case SpvOpTypeRuntimeArray:
|
||||
case SpvOpTypeStruct:
|
||||
case SpvOpTypeOpaque:
|
||||
case SpvOpTypePointer:
|
||||
case SpvOpTypeFunction:
|
||||
case SpvOpTypeEvent:
|
||||
case SpvOpTypeDeviceEvent:
|
||||
case SpvOpTypeReserveId:
|
||||
case SpvOpTypeQueue:
|
||||
case SpvOpTypePipe:
|
||||
case SpvOpTypeForwardPointer:
|
||||
type.dv.data = data+u;
|
||||
type.dv.len = instruction_size;
|
||||
type.id = data[u+1];
|
||||
mspv_array_push(m.types, type);
|
||||
break;
|
||||
|
||||
case SpvOpVariable:
|
||||
var.resulttype = data[u+1];
|
||||
var.result = data[u+2];
|
||||
var.storageclass = data[u+3];
|
||||
if (instruction_size > 4)
|
||||
var.initializer = data[u+4];
|
||||
else
|
||||
var.initializer = 0;
|
||||
if (!isfn)
|
||||
mspv_array_push(m.variables, var);
|
||||
else
|
||||
fn.instructions.len += instruction_size;
|
||||
break;
|
||||
|
||||
|
||||
case SpvOpFunction:
|
||||
fn = {};
|
||||
fn.resulttype = data[u+1];
|
||||
fn.result = data[u+2];
|
||||
fn.functionctrl = data[u+3];
|
||||
fn.functiontype = data[u+4];
|
||||
fn.instructions.data = data+u+instruction_size;
|
||||
fn.instructions.len = 0;
|
||||
isfn = 1;
|
||||
break;
|
||||
case SpvOpFunctionEnd:
|
||||
mspv_array_push(m.functions, fn);
|
||||
isfn = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
fn.instructions.len += instruction_size;
|
||||
break;
|
||||
}
|
||||
u += instruction_size;
|
||||
|
||||
};
|
||||
return (mspv_module*)memcpy(malloc(sizeof(m)),&m, sizeof(m));
|
||||
}
|
||||
|
||||
void mspv_close_module( mspv_module* m )
|
||||
{
|
||||
if (m == NULL)
|
||||
return;
|
||||
|
||||
mspv_array_destroy(m->capabilities);
|
||||
mspv_array_destroy(m->extensions);
|
||||
mspv_array_destroy(m->execution_modes);
|
||||
mspv_array_destroy(m->entry_points);
|
||||
mspv_array_destroy(m->types);
|
||||
mspv_array_destroy(m->functions);
|
||||
free(m);
|
||||
}
|
||||
|
||||
typedef struct
|
||||
{
|
||||
SpvOp op;
|
||||
uint16_t size;
|
||||
} mspv_op;
|
||||
|
||||
|
||||
typedef mspv_array(uint32_t) mspv_spv;
|
||||
static inline void mspv_write_op( mspv_spv *as, SpvOp op, uint16_t ops )
|
||||
{
|
||||
mspv_array_push((*as), op | (ops+1) << 16);
|
||||
};
|
||||
|
||||
static inline void mspv_write_string( mspv_spv *as, mspv_string_view s )
|
||||
{
|
||||
uint32_t u;
|
||||
uint32_t val;
|
||||
char cval[4];
|
||||
for ( u = 0; u < s.len/4; u++ )
|
||||
{
|
||||
mspv_array_push((*as), *(uint32_t*)(s.data+u*4));
|
||||
}
|
||||
if (!(s.len%4))
|
||||
{
|
||||
mspv_array_push((*as), 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
cval[0] = 0;
|
||||
cval[0] = 1;
|
||||
cval[0] = 2;
|
||||
cval[0] = 3;
|
||||
|
||||
for (u = 0; u < s.len%4; u++)
|
||||
{
|
||||
cval[u] = s.data[(s.len/4)*4+u];
|
||||
}
|
||||
mspv_array_push((*as), *(uint32_t*)cval);
|
||||
}
|
||||
};
|
||||
|
||||
static inline void mspv_write_dv( mspv_spv *as, mspv_data_view s )
|
||||
{
|
||||
uint32_t u;
|
||||
for ( u = 0; u < s.len; u++ )
|
||||
{
|
||||
mspv_array_push((*as), *(s.data+u));
|
||||
}
|
||||
}
|
||||
|
||||
mspv_spv mspv_write_module( mspv_module *m )
|
||||
{
|
||||
mspv_spv as;
|
||||
uint32_t u;
|
||||
uint32_t n;
|
||||
uint32_t il;
|
||||
|
||||
mspv_array_zero(as);
|
||||
|
||||
if (m == NULL)
|
||||
return as;
|
||||
|
||||
mspv_array_push(as, m->header.magic);
|
||||
mspv_array_push(as, m->header.reserved1);
|
||||
mspv_array_push(as, m->header.reserved2);
|
||||
mspv_array_push(as, m->header.reserved3);
|
||||
mspv_array_push(as, m->header.reserved4);
|
||||
|
||||
for ( u = 0; u < m->capabilities.count; u++ )
|
||||
{
|
||||
mspv_write_op(&as, SpvOpCapability, 1);
|
||||
mspv_array_push(as, m->capabilities.data[u]);
|
||||
}
|
||||
for ( u = 0; u < m->extensions.count; u++ )
|
||||
{
|
||||
il = 0;
|
||||
if (m->extensions.data[u].len%4)
|
||||
il = m->extensions.data[u].len/4+1;
|
||||
else
|
||||
il = m->extensions.data[u].len/4+2;
|
||||
mspv_write_op(&as, SpvOpExtension, il);
|
||||
mspv_write_string(&as, m->extensions.data[u]);
|
||||
}
|
||||
|
||||
for ( u = 0; u < m->ext_instructions.count; u++ )
|
||||
{
|
||||
|
||||
il = 0;
|
||||
if (m->ext_instructions.data[u].name.len%4)
|
||||
il = m->ext_instructions.data[u].name.len/4+2;
|
||||
else
|
||||
il = m->ext_instructions.data[u].name.len/4+3;
|
||||
mspv_write_op(&as, SpvOpExtInstImport, il);
|
||||
mspv_array_push(as, m->ext_instructions.data[u].id);
|
||||
mspv_write_string(&as, m->ext_instructions.data[u].name);
|
||||
}
|
||||
for ( u = 0; u < m->entry_points.count; u++ )
|
||||
{
|
||||
il = 0;
|
||||
if (m->entry_points.data[u].name.len%4)
|
||||
il = m->entry_points.data[u].name.len/4+2;
|
||||
else
|
||||
il = m->entry_points.data[u].name.len/4+3;
|
||||
il += m->entry_points.data[u].params.count;
|
||||
mspv_write_op(&as, SpvOpEntryPoint, il);
|
||||
mspv_array_push(as, m->entry_points.data[u].model);
|
||||
mspv_array_push(as, m->entry_points.data[u].id);
|
||||
mspv_write_string(&as, m->entry_points.data[u].name);
|
||||
for ( n = 0; n < m->entry_points.data[u].params.count; n++ )
|
||||
{
|
||||
mspv_array_push(as, m->entry_points.data[u].params.data[n]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
mspv_write_op(&as, SpvOpMemoryModel, 2);
|
||||
mspv_array_push(as, m->addressing_model);
|
||||
mspv_array_push(as, m->memory_model);
|
||||
|
||||
for ( u = 0; u < m->types.count; u++ )
|
||||
{
|
||||
mspv_write_op(&as, (SpvOp)m->types.data[u].dv.data[0], m->types.data[u].dv.len-1);
|
||||
mspv_array_push(as, m->types.data[u].id);
|
||||
if (m->types.data[u].dv.len-2)
|
||||
mspv_write_dv(&as, {m->types.data[u].dv.data+2, m->types.data[u].dv.len-2});
|
||||
}
|
||||
for ( u = 0; u < m->variables.count; u++ )
|
||||
{
|
||||
mspv_write_op(&as, SpvOpVariable, m->variables.data[u].initializer ? 4 : 3);
|
||||
mspv_array_push(as, m->variables.data[u].resulttype);
|
||||
mspv_array_push(as, m->variables.data[u].result);
|
||||
mspv_array_push(as, m->variables.data[u].storageclass);
|
||||
if (m->variables.data[u].initializer)
|
||||
{
|
||||
mspv_array_push(as, m->variables.data[u].initializer);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
for ( u = 0; u < m->functions.count; u++ )
|
||||
{
|
||||
mspv_write_op(&as, SpvOpFunction, 4);
|
||||
mspv_array_push(as, m->functions.data[u].resulttype);
|
||||
mspv_array_push(as, m->functions.data[u].result);
|
||||
mspv_array_push(as, m->functions.data[u].functionctrl);
|
||||
mspv_array_push(as, m->functions.data[u].functiontype);
|
||||
|
||||
mspv_write_dv(&as, m->functions.data[u].instructions);
|
||||
|
||||
mspv_write_op(&as, SpvOpFunctionEnd, 0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
return as;
|
||||
|
||||
}
|
||||
|
||||
//#endif
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user