Files
funnygame/minispv/minispv.h
2026-04-12 14:52:33 +03:00

508 lines
11 KiB
C

#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