Spvm
Tiny C++ SPIR-V virtual machine (interpreter), can be used for shader debugging. Spvm-ShaderToy simulated the runtime environment of shadertoy, and execute shader code using SPVM.
Install / Use
/learn @keith2018/SpvmREADME
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
<p float="left"> <img src="images/fstyD4.png" width="600" /> <img src="images/ftdfWn.png" width="600" /> </p> <p float="left"> <img src="images/Nt3BzM.png" width="600" /> <img src="images/XdlSDs.png" width="600" /> </p>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).
Related Skills
node-connect
344.1kDiagnose OpenClaw node connection and pairing failures for Android, iOS, and macOS companion apps
frontend-design
96.8kCreate distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, or applications. Generates creative, polished code that avoids generic AI aesthetics.
openai-whisper-api
344.1kTranscribe audio via OpenAI Audio Transcriptions API (Whisper).
qqbot-media
344.1kQQBot 富媒体收发能力。使用 <qqmedia> 标签,系统根据文件扩展名自动识别类型(图片/语音/视频/文件)。
