{"id":23695289,"url":"https://github.com/dfranx/SPIRV-VM","last_synced_at":"2025-09-02T23:31:16.590Z","repository":{"id":38687979,"uuid":"244465198","full_name":"dfranx/SPIRV-VM","owner":"dfranx","description":"Virtual machine for executing SPIR-V","archived":false,"fork":false,"pushed_at":"2024-11-01T14:20:22.000Z","size":197,"stargazers_count":294,"open_issues_count":6,"forks_count":27,"subscribers_count":15,"default_branch":"master","last_synced_at":"2024-12-25T00:05:06.429Z","etag":null,"topics":["debugging","glsl","hlsl","shader","shaders","spir-v","spirv"],"latest_commit_sha":null,"homepage":"","language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/dfranx.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.txt","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2020-03-02T20:11:22.000Z","updated_at":"2024-11-01T14:20:27.000Z","dependencies_parsed_at":"2023-02-12T00:30:22.348Z","dependency_job_id":null,"html_url":"https://github.com/dfranx/SPIRV-VM","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dfranx%2FSPIRV-VM","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dfranx%2FSPIRV-VM/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dfranx%2FSPIRV-VM/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dfranx%2FSPIRV-VM/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dfranx","download_url":"https://codeload.github.com/dfranx/SPIRV-VM/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":231814904,"owners_count":18430593,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["debugging","glsl","hlsl","shader","shaders","spir-v","spirv"],"created_at":"2024-12-30T05:00:56.891Z","updated_at":"2024-12-30T05:01:26.354Z","avatar_url":"https://github.com/dfranx.png","language":"C","funding_links":[],"categories":["C"],"sub_categories":[],"readme":"# SPIRV-VM\n**SPIRV-VM** is a virtual machine for executing SPIR-V shaders. It is written in C, has no dependencies \u0026 is licensed under MIT license.\nBoth **HLSL \u0026 GLSL shaders** can be compiled to SPIR-V using tools such as [glslangValidator](https://github.com/KhronosGroup/glslang) and [shaderc](https://github.com/google/shaderc) which means\nthat you can use this library to debug shaders.\n\n## Example\nFirst, create a SPIRV-VM context:\n```c\nspvm_context_t ctx = spvm_context_initialize();\n```\n\nLoad your SPIR-V binary file:\n```c\nsize_t spv_length = 0;\nspvm_source spv = load_source(\"shader.spv\", \u0026spv_length);\n```\n\nNow you can create a SPIR-V program and a state. The program holds general information about \nthe SPIR-V file (like generator version, used capabilities, etc...) while the `spvm_state` holds information\nabout state of program while executing it. The idea behind states is to make it possible, for example,\nto create four states for one program and run the same shader simultaneously in 4 different threads (this is not tested though):\n```c\nspvm_program_t prog = spvm_program_create(ctx, spv, spv_length);\nspvm_state_t state = spvm_state_create(prog);\n```\n\nYou have to add extensions manually (if your program uses it):\n```c\nspvm_ext_opcode_func* glsl_ext_data = spvm_build_glsl450_ext();\nspvm_result_t glsl_std_450 = spvm_state_get_result(state, \"GLSL.std.450\");\nif (glsl_std_450)\n\tglsl_std_450-\u003eextension = glsl_ext_data;\n```\n\n\nBefore debugging your shader, you have to initialize global and uniform variables.\n\nTo set a single uniform:\n```c\nfloat someUniformData[2] = { 0.5f, 0.6f };\nspvm_result_t someUniform = spvm_state_get_result(state, \"someUniform\");\nspvm_member_set_value_f(someUniform-\u003emembers, someUniform-\u003emember_count, someUniformData); // vec2\n```\n\nBut if you are using newer GLSL version, you probably have to deal with interface blocks:\n```c\n// first get the block\nspvm_result_t uBlock = spvm_state_get_result(state, \"uBlock\");\n\n// then set its members\nfloat timeData = 0.5f;\nspvm_member_t uBlock_time = spvm_state_get_object_member(state, uBlock, \"time\"); // uBlock.time\nspvm_member_set_value_f(uBlock_time-\u003emembers, uBlock_time-\u003emember_count, \u0026timeData);\n```\n\nTo bind textures:\n```c\nspvm_image noise2D_data;\nspvm_image_create(\u0026noise2D_data, image_data, image_width, image_height, 1);\nspvm_result_t noise2D = spvm_state_get_result(state, \"noise2D\");\nnoise2D-\u003emembers[0].image_data = \u0026noise2D_data;\n```\n\nYou can run your shader in two different ways. You can step line by line through the code.\nThis can be done with the `spvm_state_step_into` function (which executes only one line).\nOr you can execute whole shader with a single function call:\n```c\nspvm_word fnMain = spvm_state_get_result_location(state, \"main\");\nspvm_state_prepare(state, fnMain);\nspvm_state_call_function(state);\n```\n\nYou can then retrieve results:\n```c\nspvm_result_t outColor = spvm_state_get_result(state, \"outColor\");\nfor (int i = 0; i \u003c outColor-\u003emember_count; i++)\n\tprintf(\"%.2f \", outColor-\u003emembers[i].value.f);\nprintf(\"\\n\");\n```\n\nUse `spvm_state_get_local_result()` function if you are stepping through code line by line and want to get local variable's value.\nExample:\n```c\nspvm_result_t a = spvm_state_get_local_result(state, fnMain, \"a\");\nprintf(\"a = %.2f\\n\", a-\u003emembers[0].value.f);\n```\n\nDon't forget to free the memory:\n```c\nspvm_state_delete(state);\nspvm_program_delete(prog);\nfree(glsl_ext_data);\nfree(spv);\n\nspvm_context_deinitialize(ctx);\n```\n\n## How to link\nIf you are using CMake add these lines to your `CMakeLists.txt` file:\n```\nadd_subdirectory(./path/to/your/SPIRV-VM)\ntarget_include_directories(example PRIVATE ./path/to/your/SPIRV-VM/inc)\n```\n\nIf you just want to build this project, run these two commands:\n```\ncmake .\nmake\n```\n\n## Contributors\n- nyorain ([Twitter](https://twitter.com/nyorain), [GitHub](https://github.com/nyorain))\n- dfranx ([Twitter](https://twitter.com/dfranx_), [GitHub](https://github.com/dfranx))\n\nContact me on this e-mail address: **dfranx at shadered dot org**\n\n## LICENSE\nSPIRV-VM is licensed under MIT license. See [LICENSE](./LICENSE) for more details.","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdfranx%2FSPIRV-VM","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdfranx%2FSPIRV-VM","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdfranx%2FSPIRV-VM/lists"}