SPVM
Tiny C++ SPIR-V virtual machine (interpreter), you can use it to debug shaders: first compile your shader code(GLSL/HLSL) to SPIR-V binary file (using tools such as glslangValidator), then decode and execute entry point function main
with SPVM, and check the output.
Specifications that the project follows is:
Limits
- Only part of SPIR-V 1.0 instructions has been implemented right now, see the opcodes support status:
- Only support 32-bits width Numerical type (float, integer)
- Only support Addressing Model
Logical
- Not support derivative opcodes (dFdx\dFdy...)
- Not support OpenCL related instructions
TODO
- 64-bit float/integer support
- Performance optimizations
- SIMD
- JIT/AOT
The project is still working in progress ...
Spvm-ShaderToy
Spvm-ShaderToy simulated the runtime environment of shadertoy, and execute shader code using SPVM (may very slow
Gallery
Example
GLSL fragment shader (see example/shaders/simple.frag)
#version 450
layout (location = 0) in vec3 inColor;
layout (location = 0) out vec4 outFragColor;
void main()
{
outFragColor = vec4(inColor.yxz, 1.0f);
}
run with spvm (see example/main.cpp)
#define HEAP_SIZE 128 * 1024
const char *SPV_PATH = "shaders/simple.frag.spv";
SPVM::SpvmModule module;
SPVM::Runtime runtime;
// decode spir-v file
bool success = SPVM::Decoder::decodeFile(SPV_PATH, &module);
if (!success) {
std::cout << "error decode spir-v file";
return -1;
}
// init runtime
success = runtime.initWithModule(&module, HEAP_SIZE);
if (!success) {
std::cout << "error init module";
return -1;
}
// get uniform locations
SPVM::SpvmWord inColorLoc = runtime.getLocationByName("inColor");
SPVM::SpvmWord outFragColorLoc = runtime.getLocationByName("outFragColor");
// write input
float inColor[3]{0.2f, 0.3f, 0.4f};
runtime.writeInput(inColor, inColorLoc);
// execute shader entry function 'main'
success = runtime.execEntryPoint();
if (!success) {
std::cout << "error exec entrypoint function";
return -1;
}
// read output
float outFragColor[4];
runtime.readOutput(outFragColor, outFragColorLoc);
std::cout << "outFragColor[0]: " << outFragColor[0] << std::endl;
std::cout << "outFragColor[1]: " << outFragColor[1] << std::endl;
std::cout << "outFragColor[2]: " << outFragColor[2] << std::endl;
std::cout << "outFragColor[3]: " << outFragColor[3] << std::endl;
Clone
git clone --recursive https://github.com/keith2018/spvm
cd spvm
Build
mkdir build
cmake -B ./build -DCMAKE_BUILD_TYPE=Release
cmake --build ./build --config Release
Test
cd build
ctest
License
This code is licensed under the MIT License (see LICENSE).