Files
SPIRV-Interpreter/test_c/main.c
T
kbz_8 589d30168f
Build / build (push) Successful in 42s
Test / build (push) Successful in 1m17s
implementing missing functions in FFI
2026-07-04 20:59:03 +02:00

266 lines
9.9 KiB
C

#include <stdio.h>
#include <SpirvInterpreter.h>
#define CHECK_RESULT(expr) do { \
SpvResult check_result = (expr); \
if (check_result != SPV_RESULT_SUCCESS) \
{ \
fprintf(stderr, "%s failed with %d\n", #expr, check_result); \
return -1; \
} \
} while (0)
static SpvResult ReadImageFloat4(SpvReadImageInfo info, SpvVec4f* dst)
{
(void)info;
(void)dst;
return SPV_RESULT_UNSUPPORTED_SPIRV;
}
static SpvResult ReadImageInt4(SpvReadImageInfo info, SpvVec4u* dst)
{
(void)info;
(void)dst;
return SPV_RESULT_UNSUPPORTED_SPIRV;
}
static SpvResult WriteImageFloat4(SpvWriteImageInfo info, SpvVec4f src)
{
(void)info;
(void)src;
return SPV_RESULT_UNSUPPORTED_SPIRV;
}
static SpvResult WriteImageInt4(SpvWriteImageInfo info, SpvVec4u src)
{
(void)info;
(void)src;
return SPV_RESULT_UNSUPPORTED_SPIRV;
}
static SpvResult SampleImageFloat4(SpvSampleImageInfo info, SpvVec4f* dst)
{
(void)info;
(void)dst;
return SPV_RESULT_UNSUPPORTED_SPIRV;
}
static SpvResult SampleImageInt4(SpvSampleImageInfo info, SpvVec4u* dst)
{
(void)info;
(void)dst;
return SPV_RESULT_UNSUPPORTED_SPIRV;
}
static SpvResult SampleImageDref(SpvSampleImageInfo info, float dref, float* dst)
{
(void)info;
(void)dref;
(void)dst;
return SPV_RESULT_UNSUPPORTED_SPIRV;
}
static SpvResult QueryImageSize(SpvQueryImageInfo info, SpvVec4u* dst)
{
(void)info;
(void)dst;
return SPV_RESULT_UNSUPPORTED_SPIRV;
}
static SpvResult QueryImageLevels(void* driver_image, unsigned long* dst)
{
(void)driver_image;
(void)dst;
return SPV_RESULT_UNSUPPORTED_SPIRV;
}
static SpvResult QueryImageSamples(void* driver_image, unsigned long* dst)
{
(void)driver_image;
(void)dst;
return SPV_RESULT_UNSUPPORTED_SPIRV;
}
static SpvResult QueryImageLod(SpvQueryImageLodInfo info, SpvVec4f* dst)
{
(void)info;
(void)dst;
return SPV_RESULT_UNSUPPORTED_SPIRV;
}
static const unsigned char shader_source[] = {
0x03, 0x02, 0x23, 0x07, 0x00, 0x00, 0x01, 0x00, 0x82, 0x10, 0x27, 0x00, 0x17, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x03, 0x00,
0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x06, 0x00, 0x04, 0x00, 0x00, 0x00,
0x0f, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
0x10, 0x00, 0x03, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x00,
0x09, 0x00, 0x00, 0x00, 0x00, 0x10, 0x40, 0x00, 0x04, 0x00, 0x05, 0x00, 0x56, 0x65, 0x72, 0x73,
0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x31, 0x2e, 0x31, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x04, 0x00,
0x07, 0x00, 0x00, 0x00, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x00, 0x00, 0x06, 0x00, 0x05, 0x00,
0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x00, 0x00, 0x00,
0x05, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x00, 0x00, 0x00,
0x05, 0x00, 0x04, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00,
0x47, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x48, 0x00, 0x05, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x21, 0x00, 0x03, 0x00,
0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x16, 0x00, 0x03, 0x00, 0x03, 0x00, 0x00, 0x00,
0x20, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
0x04, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x05, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
0x04, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x03, 0x00, 0x07, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
0x20, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
0x15, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
0x2b, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x2b, 0x00, 0x04, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f,
0x2b, 0x00, 0x04, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
0x2b, 0x00, 0x04, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x40,
0x2b, 0x00, 0x04, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40,
0x20, 0x00, 0x04, 0x00, 0x14, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
0x3b, 0x00, 0x04, 0x00, 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
0x36, 0x00, 0x05, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x02, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x10, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00,
0x08, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x50, 0x00, 0x07, 0x00,
0x04, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
0x0d, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x14, 0x00, 0x00, 0x00,
0x13, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00,
0x13, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00,
0x15, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x04, 0x00, 0x00, 0x00,
0x16, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00,
0x06, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0xfd, 0x00, 0x01, 0x00, 0x38, 0x00, 0x01, 0x00
};
int main(void)
{
SpvModule module;
SpvModuleOptions options;
options.use_simd_vectors_specializations = 1;
if(SpvInitModule(&module, (SpvWord*)shader_source, sizeof(shader_source) / 4, options) != SPV_RESULT_SUCCESS)
{
fprintf(stderr, "Module init failed\n");
return -1;
}
SpvWord binding_result = 0;
if (SpvModuleGetBindingResult(module, 0, 0, &binding_result) != SPV_RESULT_NOT_FOUND)
{
fprintf(stderr, "Unexpected binding lookup result\n");
return -1;
}
SpvModuleReflectionInfos reflection_infos = SpvModuleGetReflectionInfos(module);
if (reflection_infos.has_atomics || reflection_infos.early_fragment_tests)
{
fprintf(stderr, "Unexpected reflection flags\n");
return -1;
}
SpvImageAPI image_api = {
.SpvReadImageFloat4 = ReadImageFloat4,
.SpvReadImageInt4 = ReadImageInt4,
.SpvWriteImageFloat4 = WriteImageFloat4,
.SpvWriteImageInt4 = WriteImageInt4,
.SpvSampleImageFloat4 = SampleImageFloat4,
.SpvSampleImageInt4 = SampleImageInt4,
.SpvSampleImageDref = SampleImageDref,
.SpvQueryImageSize = QueryImageSize,
.SpvQueryImageLevels = QueryImageLevels,
.SpvQueryImageSamples = QueryImageSamples,
.SpvQueryImageLod = QueryImageLod
};
SpvRuntime runtime;
if(SpvInitRuntime(&runtime, module, image_api) != SPV_RESULT_SUCCESS)
{
fprintf(stderr, "Runtime init failed\n");
return -1;
}
SpvRuntime second_runtime;
if(SpvInitRuntime(&second_runtime, module, image_api) != SPV_RESULT_SUCCESS)
{
fprintf(stderr, "Second runtime init failed\n");
SpvDeinitRuntime(runtime);
return -1;
}
unsigned int spec_value = 64;
SpvRuntimeSpecializationEntry spec_entry = {
.id = 0,
.offset = 0,
.size = sizeof(spec_value)
};
CHECK_RESULT(SpvAddSpecializationInfo(runtime, spec_entry, (const SpvByte*)&spec_value, sizeof(spec_value)));
CHECK_RESULT(SpvCopySpecializationConstantsFrom(second_runtime, runtime));
SpvWord main_entry_index;
CHECK_RESULT(SpvGetEntryPointByName(runtime, "main", &main_entry_index));
SpvWord fragment_entry_index;
CHECK_RESULT(SpvGetEntryPointByNameAndExecutionModel(runtime, "main", SpvExecutionModelFragment, &fragment_entry_index));
if (fragment_entry_index != main_entry_index)
{
fprintf(stderr, "Unexpected execution-model entry point lookup\n");
return -1;
}
CHECK_RESULT(SpvSelectEntryPoint(runtime, main_entry_index));
CHECK_RESULT(SpvApplySpecializationLayout(runtime));
CHECK_RESULT(SpvApplySpecializationInvocationLayout(second_runtime));
SpvWorkgroupSize workgroup_size;
CHECK_RESULT(SpvGetWorkgroupSize(runtime, &workgroup_size));
if (workgroup_size.has_size)
{
fprintf(stderr, "Unexpected workgroup size\n");
return -1;
}
SpvWorkgroupMemory workgroup_memory;
CHECK_RESULT(SpvCreateWorkgroupMemory(runtime, &workgroup_memory));
if (SpvGetWorkgroupMemoryCount(workgroup_memory) != 0)
{
fprintf(stderr, "Unexpected workgroup memory count\n");
return -1;
}
SpvWorkgroupMemoryItem workgroup_memory_item;
if (SpvGetWorkgroupMemoryItem(workgroup_memory, 0, &workgroup_memory_item) != SPV_RESULT_OUT_OF_BOUNDS)
{
fprintf(stderr, "Unexpected workgroup memory lookup result\n");
return -1;
}
CHECK_RESULT(SpvBindWorkgroupMemory(runtime, workgroup_memory));
SpvDestroyWorkgroupMemory(runtime, workgroup_memory);
CHECK_RESULT(SpvCallEntryPoint(runtime, main_entry_index));
float output[4];
SpvWord output_result;
CHECK_RESULT(SpvGetResultByName(runtime, "color", &output_result));
CHECK_RESULT(SpvRefreshResultValueLayout(runtime, output_result));
CHECK_RESULT(SpvReadOutput(runtime, (SpvByte*)output, sizeof(output), output_result));
SpvWord builtin_result;
if (SpvGetBuiltinResult(runtime, SpvBuiltInWorkgroupId, &builtin_result) != SPV_RESULT_NOT_FOUND)
{
fprintf(stderr, "Unexpected builtin lookup result\n");
return -1;
}
SpvSize output_size = 0;
CHECK_RESULT(SpvGetResultMemorySize(runtime, output_result, &output_size));
if (output_size != sizeof(output))
{
fprintf(stderr, "Unexpected output metadata\n");
SpvDeinitRuntime(second_runtime);
SpvDeinitRuntime(runtime);
SpvDeinitModule(module);
return -1;
}
float dx[4] = { 1.0f, 2.0f, 3.0f, 4.0f };
float dy[4] = { 5.0f, 6.0f, 7.0f, 8.0f };
CHECK_RESULT(SpvSetDerivativeFromMemory(runtime, output_result, (const SpvByte*)dx, sizeof(dx), (const SpvByte*)dy, sizeof(dy)));
CHECK_RESULT(SpvCopyDerivative(runtime, output_result, output_result));
SpvClearDerivative(runtime, output_result);
printf("Output: Vec4[%f, %f, %f, %f]\n", output[0], output[1], output[2], output[3]);
SpvDeinitRuntime(second_runtime);
SpvDeinitRuntime(runtime);
SpvDeinitModule(module);
return 0;
}