adding C bindings
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
MIT License
|
MIT License
|
||||||
|
|
||||||
Copyright (c) 2025 kbz_8
|
Copyright (c) 2026 kbz_8
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# SPIR-V Interpreter <a href="https://git.kbz8.me/kbz_8/SPIRV-Interpreter/actions?workflows=build.yml"><img src="https://git.kbz8.me/kbz_8/SPIRV-Interpreter/actions/workflows/build.yml/badge.svg"></a> <a href="https://git.kbz8.me/kbz_8/SPIRV-Interpreter/actions?workflows=test.yml"><img src="https://git.kbz8.me/kbz_8/SPIRV-Interpreter/actions/workflows/test.yml/badge.svg"></a>
|
# SPIR-V Interpreter <a href="https://git.kbz8.me/kbz_8/SPIRV-Interpreter/actions?workflows=build.yml"><img src="https://git.kbz8.me/kbz_8/SPIRV-Interpreter/actions/workflows/build.yml/badge.svg"></a> <a href="https://git.kbz8.me/kbz_8/SPIRV-Interpreter/actions?workflows=test.yml"><img src="https://git.kbz8.me/kbz_8/SPIRV-Interpreter/actions/workflows/test.yml/badge.svg"></a>
|
||||||
|
|
||||||
A small footprint SPIR-V interpreter to execute SPIR-V shaders on the CPU. It is designed to be used with multiple runtimes concurrently.
|
A small footprint SPIR-V interpreter to execute SPIR-V shaders on the CPU. It is designed to be used with multiple runtimes concurrently and can be SIMD accelerated.
|
||||||
|
|
||||||
```zig
|
```zig
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
@@ -29,3 +29,58 @@ pub fn main() !void {
|
|||||||
std.log.info("Successfully executed", .{});
|
std.log.info("Successfully executed", .{});
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## C bindings
|
||||||
|
|
||||||
|
### Build
|
||||||
|
To build the FFI bindings just
|
||||||
|
```
|
||||||
|
zig build ffi-c --release=[fast, small, safe]
|
||||||
|
```
|
||||||
|
|
||||||
|
You can also build a shared lib using
|
||||||
|
```
|
||||||
|
zig build ffi-c --release=[fast, small, sage] -Dffi-build-static=false
|
||||||
|
```
|
||||||
|
|
||||||
|
You'll find the library in `./zig-out/lib/` and the header file in `./zig-out/include/` or in `./ffi/`.
|
||||||
|
|
||||||
|
### Example
|
||||||
|
|
||||||
|
```c
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <SpirvInterpreter.h>
|
||||||
|
|
||||||
|
static const unsigned char shader_source[] = {
|
||||||
|
/* Shader bytecode */
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
SpvRuntime runtime;
|
||||||
|
if(SpvInitRuntime(&runtime, module) != SPV_RESULT_SUCCESS)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
SpvWord main_entry_index;
|
||||||
|
SpvGetEntryPointByName(runtime, "main", &main_entry_index);
|
||||||
|
SpvCallEntryPoint(runtime, main_entry_index);
|
||||||
|
|
||||||
|
float output[4];
|
||||||
|
SpvWord output_result;
|
||||||
|
SpvGetResultByName(runtime, "color", &output_result);
|
||||||
|
SpvReadOutput(runtime, (SpvByte*)output, sizeof(output), output_result);
|
||||||
|
|
||||||
|
printf("Output: Vec4[%f, %f, %f, %f]\n", output[0], output[1], output[2], output[3]);
|
||||||
|
|
||||||
|
SpvDeinitRuntime(runtime);
|
||||||
|
SpvDeinitModule(module);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|||||||
@@ -3,129 +3,256 @@ const std = @import("std");
|
|||||||
pub fn build(b: *std.Build) void {
|
pub fn build(b: *std.Build) void {
|
||||||
const target = b.standardTargetOptions(.{});
|
const target = b.standardTargetOptions(.{});
|
||||||
const optimize = b.standardOptimizeOption(.{});
|
const optimize = b.standardOptimizeOption(.{});
|
||||||
|
const use_llvm = b.option(bool, "use-llvm", "Use LLVM backend") orelse (b.release_mode != .off);
|
||||||
|
|
||||||
const use_llvm = b.option(bool, "use-llvm", "use llvm") orelse (b.release_mode != .off);
|
const spv_mod = b.addModule("spv", .{
|
||||||
|
|
||||||
const mod = b.addModule("spv", .{
|
|
||||||
.root_source_file = b.path("src/lib.zig"),
|
.root_source_file = b.path("src/lib.zig"),
|
||||||
.target = target,
|
.target = target,
|
||||||
.optimize = optimize,
|
.optimize = optimize,
|
||||||
});
|
});
|
||||||
|
|
||||||
const zmath = b.dependency("zmath", .{});
|
const zmath = b.dependency("zmath", .{});
|
||||||
mod.addImport("zmath", zmath.module("root"));
|
spv_mod.addImport("zmath", zmath.module("root"));
|
||||||
|
|
||||||
const pretty = b.dependency("pretty", .{ .target = target, .optimize = optimize });
|
const pretty = b.dependency("pretty", .{
|
||||||
mod.addImport("pretty", pretty.module("pretty"));
|
.target = target,
|
||||||
|
.optimize = optimize,
|
||||||
|
});
|
||||||
|
spv_mod.addImport("pretty", pretty.module("pretty"));
|
||||||
|
|
||||||
const lib = b.addLibrary(.{
|
const spv_lib = b.addLibrary(.{
|
||||||
.name = "spirv_interpreter",
|
.name = "spirv_interpreter",
|
||||||
.root_module = mod,
|
.root_module = spv_mod,
|
||||||
.linkage = .dynamic,
|
.linkage = .dynamic,
|
||||||
.use_llvm = use_llvm,
|
.use_llvm = use_llvm,
|
||||||
});
|
});
|
||||||
const lib_install = b.addInstallArtifact(lib, .{});
|
|
||||||
|
|
||||||
// Zig example setup
|
const install_spv_lib = b.addInstallArtifact(spv_lib, .{});
|
||||||
|
|
||||||
const no_example = b.option(bool, "no-example", "skips example dependencies fetch") orelse false;
|
addSandbox(b, target, optimize, use_llvm, spv_mod, &install_spv_lib.step);
|
||||||
|
addExample(b, target, optimize, use_llvm, spv_mod, &install_spv_lib.step);
|
||||||
|
addZigTests(b, target, optimize, spv_mod, zmath);
|
||||||
|
addCffi(b, target, optimize, use_llvm, spv_mod);
|
||||||
|
addDocs(b, spv_mod);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn addExample(
|
||||||
|
b: *std.Build,
|
||||||
|
target: std.Build.ResolvedTarget,
|
||||||
|
optimize: std.builtin.OptimizeMode,
|
||||||
|
use_llvm: bool,
|
||||||
|
spv_mod: *std.Build.Module,
|
||||||
|
install_spv_lib_step: *std.Build.Step,
|
||||||
|
) void {
|
||||||
|
const no_example = b.option(bool, "no-example", "Skip example build") orelse false;
|
||||||
if (!no_example and false) {
|
if (!no_example and false) {
|
||||||
const sdl3 = b.lazyDependency("sdl3", .{ .target = target, .optimize = optimize }) orelse return;
|
const sdl3 = b.lazyDependency("sdl3", .{
|
||||||
const example_exe = b.addExecutable(.{
|
.target = target,
|
||||||
|
.optimize = optimize,
|
||||||
|
}) orelse return;
|
||||||
|
|
||||||
|
const exe = b.addExecutable(.{
|
||||||
.name = "spirv_interpreter_example",
|
.name = "spirv_interpreter_example",
|
||||||
.root_module = b.createModule(.{
|
.root_module = b.createModule(.{
|
||||||
.root_source_file = b.path("example/main.zig"),
|
.root_source_file = b.path("example/main.zig"),
|
||||||
.target = target,
|
.target = target,
|
||||||
.optimize = optimize,
|
.optimize = optimize,
|
||||||
.imports = &.{
|
.imports = &.{
|
||||||
.{ .name = "spv", .module = mod },
|
.{ .name = "spv", .module = spv_mod },
|
||||||
.{ .name = "sdl3", .module = sdl3.module("sdl3") },
|
.{ .name = "sdl3", .module = sdl3.module("sdl3") },
|
||||||
//.{ .name = "pretty", .module = pretty.module("pretty") },
|
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
.use_llvm = use_llvm,
|
.use_llvm = use_llvm,
|
||||||
});
|
});
|
||||||
|
|
||||||
const example_install = b.addInstallArtifact(example_exe, .{});
|
const install_exe = b.addInstallArtifact(exe, .{});
|
||||||
example_install.step.dependOn(&lib_install.step);
|
install_exe.step.dependOn(install_spv_lib_step);
|
||||||
|
|
||||||
const run_example = b.addRunArtifact(example_exe);
|
const run_exe = b.addRunArtifact(exe);
|
||||||
run_example.step.dependOn(&example_install.step);
|
run_exe.step.dependOn(&install_exe.step);
|
||||||
|
|
||||||
const run_example_step = b.step("example", "Run the example");
|
const run_step = b.step("example", "Run the example");
|
||||||
run_example_step.dependOn(&run_example.step);
|
run_step.dependOn(&run_exe.step);
|
||||||
|
|
||||||
const compile_shader_cmd = b.addSystemCommand(&[_][]const u8{ "nzslc", "example/shader.nzsl", "--compile=spv,spv-dis", "-o", "example" });
|
addShaderCompileStep(
|
||||||
const compile_shader_step = b.step("example-shader", "Compiles example's shader (needs nzslc installed)");
|
b,
|
||||||
compile_shader_step.dependOn(&compile_shader_cmd.step);
|
"example-shader",
|
||||||
|
"Compile example shader using nzslc",
|
||||||
|
"example/shader.nzsl",
|
||||||
|
"example",
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Zig sandbox setup
|
fn addSandbox(
|
||||||
|
b: *std.Build,
|
||||||
const sandbox_exe = b.addExecutable(.{
|
target: std.Build.ResolvedTarget,
|
||||||
|
optimize: std.builtin.OptimizeMode,
|
||||||
|
use_llvm: bool,
|
||||||
|
spv_mod: *std.Build.Module,
|
||||||
|
install_spv_lib_step: *std.Build.Step,
|
||||||
|
) void {
|
||||||
|
const exe = b.addExecutable(.{
|
||||||
.name = "spirv_interpreter_sandbox",
|
.name = "spirv_interpreter_sandbox",
|
||||||
.root_module = b.createModule(.{
|
.root_module = b.createModule(.{
|
||||||
.root_source_file = b.path("sandbox/main.zig"),
|
.root_source_file = b.path("sandbox/main.zig"),
|
||||||
.target = target,
|
.target = target,
|
||||||
.optimize = optimize,
|
.optimize = optimize,
|
||||||
.imports = &.{
|
.imports = &.{
|
||||||
.{ .name = "spv", .module = mod },
|
.{ .name = "spv", .module = spv_mod },
|
||||||
//.{ .name = "pretty", .module = pretty.module("pretty") },
|
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
.use_llvm = use_llvm,
|
.use_llvm = use_llvm,
|
||||||
});
|
});
|
||||||
|
|
||||||
const sandbox_install = b.addInstallArtifact(sandbox_exe, .{});
|
const install_exe = b.addInstallArtifact(exe, .{});
|
||||||
sandbox_install.step.dependOn(&lib_install.step);
|
install_exe.step.dependOn(install_spv_lib_step);
|
||||||
|
|
||||||
const run_sandbox = b.addRunArtifact(sandbox_exe);
|
const run_exe = b.addRunArtifact(exe);
|
||||||
run_sandbox.step.dependOn(&sandbox_install.step);
|
run_exe.step.dependOn(&install_exe.step);
|
||||||
|
|
||||||
const run_sandbox_step = b.step("sandbox", "Run the sandbox");
|
const run_step = b.step("sandbox", "Run the sandbox");
|
||||||
run_sandbox_step.dependOn(&run_sandbox.step);
|
run_step.dependOn(&run_exe.step);
|
||||||
|
|
||||||
const compile_shader_cmd = b.addSystemCommand(&[_][]const u8{ "nzslc", "sandbox/shader.nzsl", "--compile=spv,spv-dis", "-o", "sandbox" });
|
addShaderCompileStep(
|
||||||
const compile_shader_step = b.step("sandbox-shader", "Compiles sandbox's shader (needs nzslc installed)");
|
b,
|
||||||
compile_shader_step.dependOn(&compile_shader_cmd.step);
|
"sandbox-shader",
|
||||||
|
"Compile sandbox shader using nzslc",
|
||||||
|
"sandbox/shader.nzsl",
|
||||||
|
"sandbox",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
// Zig unit tests setup
|
fn addShaderCompileStep(
|
||||||
|
b: *std.Build,
|
||||||
|
step_name: []const u8,
|
||||||
|
description: []const u8,
|
||||||
|
shader_path: []const u8,
|
||||||
|
output_dir: []const u8,
|
||||||
|
) void {
|
||||||
|
const cmd = b.addSystemCommand(&.{
|
||||||
|
"nzslc",
|
||||||
|
shader_path,
|
||||||
|
"--compile=spv,spv-dis",
|
||||||
|
"-o",
|
||||||
|
output_dir,
|
||||||
|
});
|
||||||
|
|
||||||
const no_test = b.option(bool, "no-test", "skips unit test dependencies fetch") orelse false;
|
const step = b.step(step_name, description);
|
||||||
|
step.dependOn(&cmd.step);
|
||||||
|
}
|
||||||
|
|
||||||
if (!no_test) {
|
fn addZigTests(
|
||||||
const nzsl = b.lazyDependency("NZSL", .{ .target = target, .optimize = optimize }) orelse return;
|
b: *std.Build,
|
||||||
const lib_tests = b.addTest(.{
|
target: std.Build.ResolvedTarget,
|
||||||
|
optimize: std.builtin.OptimizeMode,
|
||||||
|
spv_mod: *std.Build.Module,
|
||||||
|
zmath: *std.Build.Dependency,
|
||||||
|
) void {
|
||||||
|
const no_test = b.option(bool, "no-test", "Skip unit test dependencies fetch") orelse false;
|
||||||
|
if (no_test) return;
|
||||||
|
|
||||||
|
const nzsl = b.lazyDependency("NZSL", .{
|
||||||
|
.target = target,
|
||||||
|
.optimize = optimize,
|
||||||
|
}) orelse return;
|
||||||
|
|
||||||
|
const tests = b.addTest(.{
|
||||||
.root_module = b.createModule(.{
|
.root_module = b.createModule(.{
|
||||||
.root_source_file = b.path("test/root.zig"),
|
.root_source_file = b.path("test/root.zig"),
|
||||||
.target = target,
|
.target = target,
|
||||||
.optimize = optimize,
|
.optimize = optimize,
|
||||||
.imports = &.{
|
.imports = &.{
|
||||||
.{ .name = "spv", .module = mod },
|
.{ .name = "spv", .module = spv_mod },
|
||||||
.{ .name = "nzsl", .module = nzsl.module("nzigsl") },
|
.{ .name = "nzsl", .module = nzsl.module("nzigsl") },
|
||||||
.{ .name = "zmath", .module = zmath.module("root") },
|
.{ .name = "zmath", .module = zmath.module("root") },
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
.test_runner = .{ .path = b.path("test/test_runner.zig"), .mode = .simple },
|
.test_runner = .{
|
||||||
|
.path = b.path("test/test_runner.zig"),
|
||||||
|
.mode = .simple,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
const run_tests = b.addRunArtifact(lib_tests);
|
|
||||||
|
const run_tests = b.addRunArtifact(tests);
|
||||||
|
|
||||||
const test_step = b.step("test", "Run Zig unit tests");
|
const test_step = b.step("test", "Run Zig unit tests");
|
||||||
test_step.dependOn(&run_tests.step);
|
test_step.dependOn(&run_tests.step);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Docs generation
|
fn addCffi(
|
||||||
|
b: *std.Build,
|
||||||
|
target: std.Build.ResolvedTarget,
|
||||||
|
optimize: std.builtin.OptimizeMode,
|
||||||
|
use_llvm: bool,
|
||||||
|
spv_mod: *std.Build.Module,
|
||||||
|
) void {
|
||||||
|
const static_c_ffi = b.option(bool, "ffi-build-static", "Build C FFI statically") orelse true;
|
||||||
|
|
||||||
const autodoc_test = b.addObject(.{
|
const c_ffi_mod = b.addModule("c_ffi_spv", .{
|
||||||
.name = "lib",
|
.root_source_file = b.path("ffi/ffi.zig"),
|
||||||
.root_module = mod,
|
.target = target,
|
||||||
|
.optimize = optimize,
|
||||||
|
.link_libc = true,
|
||||||
|
.imports = &.{
|
||||||
|
.{ .name = "spv", .module = spv_mod },
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const install_header = b.addInstallHeaderFile(
|
||||||
|
b.path("ffi/SpirvInterpreter.h"),
|
||||||
|
"SpirvInterpreter.h",
|
||||||
|
);
|
||||||
|
|
||||||
|
const c_ffi_lib = b.addLibrary(.{
|
||||||
|
.name = "spirv_interpreter_c_ffi",
|
||||||
|
.root_module = c_ffi_mod,
|
||||||
|
.linkage = if (static_c_ffi) .static else .dynamic,
|
||||||
|
.use_llvm = use_llvm,
|
||||||
|
});
|
||||||
|
|
||||||
|
const install_lib = b.addInstallArtifact(c_ffi_lib, .{});
|
||||||
|
|
||||||
|
const ffi_step = b.step("ffi-c", "Build C FFI");
|
||||||
|
ffi_step.dependOn(&install_lib.step);
|
||||||
|
ffi_step.dependOn(&install_header.step);
|
||||||
|
|
||||||
|
const c_test = b.addExecutable(.{
|
||||||
|
.name = "c_test",
|
||||||
|
.root_module = b.createModule(.{
|
||||||
|
.target = target,
|
||||||
|
.optimize = optimize,
|
||||||
|
.link_libc = true,
|
||||||
|
}),
|
||||||
|
.use_llvm = use_llvm,
|
||||||
|
});
|
||||||
|
|
||||||
|
c_test.root_module.addCSourceFile(.{ .file = b.path("test_c/main.c") });
|
||||||
|
c_test.root_module.linkLibrary(c_ffi_lib);
|
||||||
|
c_test.root_module.addSystemIncludePath(b.path("ffi"));
|
||||||
|
|
||||||
|
const install_c_test = b.addInstallArtifact(c_test, .{});
|
||||||
|
install_c_test.step.dependOn(&install_lib.step);
|
||||||
|
|
||||||
|
const run_c_test = b.addRunArtifact(c_test);
|
||||||
|
run_c_test.step.dependOn(&install_c_test.step);
|
||||||
|
|
||||||
|
const test_c_step = b.step("test-c", "Run C test");
|
||||||
|
test_c_step.dependOn(&run_c_test.step);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn addDocs(b: *std.Build, spv_mod: *std.Build.Module) void {
|
||||||
|
const autodoc_obj = b.addObject(.{
|
||||||
|
.name = "lib",
|
||||||
|
.root_module = spv_mod,
|
||||||
|
});
|
||||||
|
|
||||||
const install_docs = b.addInstallDirectory(.{
|
const install_docs = b.addInstallDirectory(.{
|
||||||
.source_dir = autodoc_test.getEmittedDocs(),
|
.source_dir = autodoc_obj.getEmittedDocs(),
|
||||||
.install_dir = .prefix,
|
.install_dir = .prefix,
|
||||||
.install_subdir = "docs",
|
.install_subdir = "docs",
|
||||||
});
|
});
|
||||||
|
|
||||||
const docs_step = b.step("docs", "Build and install the documentation");
|
const docs_step = b.step("docs", "Build and install documentation");
|
||||||
docs_step.dependOn(&install_docs.step);
|
docs_step.dependOn(&install_docs.step);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,265 @@
|
|||||||
|
/*
|
||||||
|
Copyright (C) 2026 kbz_8 (contact@kbz8.me)
|
||||||
|
This file is part of the "SPIR-V Interpreter - FFI C Bindings" project
|
||||||
|
|
||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2026 kbz_8
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SPIRV_INTERPRETER_H
|
||||||
|
#define SPIRV_INTERPRETER_H
|
||||||
|
|
||||||
|
#ifndef SPV_API
|
||||||
|
#define SPV_API extern
|
||||||
|
#endif /* SPV_API */
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef spirv_H
|
||||||
|
typedef enum SpvBuiltIn_ SpvBuiltIn;
|
||||||
|
#endif /* spirv_H */
|
||||||
|
|
||||||
|
typedef int SpvBool;
|
||||||
|
typedef unsigned char SpvByte;
|
||||||
|
typedef unsigned long SpvWord;
|
||||||
|
typedef unsigned long SpvSize;
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
SPV_RESULT_SUCCESS = 0,
|
||||||
|
SPV_RESULT_DIVISION_BY_ZERO = -1,
|
||||||
|
SPV_RESULT_INVALID_ENTRY_POINT = -2,
|
||||||
|
SPV_RESULT_INVALID_SPIRV = -3,
|
||||||
|
SPV_RESULT_INVALID_VALUE_TYPE = -4,
|
||||||
|
SPV_RESULT_KILLED = -5,
|
||||||
|
SPV_RESULT_NOT_FOUND = -6,
|
||||||
|
SPV_RESULT_OUT_OF_MEMORY = -7,
|
||||||
|
SPV_RESULT_OUT_OF_BOUNDS = -8,
|
||||||
|
SPV_RESULT_TODO = -9,
|
||||||
|
SPV_RESULT_UNREACHABLE = -10,
|
||||||
|
SPV_RESULT_UNSUPPORTED_SPIRV = -11,
|
||||||
|
SPV_RESULT_UNSUPPORTED_EXTENSION = -12,
|
||||||
|
SPV_RESULT_UNSUPPORTED_ENDIANNESS = -13,
|
||||||
|
SPV_RESULT_INVALID_MAGIC = -14,
|
||||||
|
SPV_RESULT_UNKNOWN = -15,
|
||||||
|
} SpvResult;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
SpvBool use_simd_vectors_specializations;
|
||||||
|
} SpvModuleOptions;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
SpvWord id;
|
||||||
|
SpvSize offset;
|
||||||
|
SpvSize size;
|
||||||
|
} SpvRuntimeSpecializationEntry;
|
||||||
|
|
||||||
|
typedef void* SpvModule;
|
||||||
|
typedef void* SpvRuntime;
|
||||||
|
|
||||||
|
SPV_API SpvResult SpvInitModule(SpvModule* module, const SpvWord* source, SpvSize source_len, SpvModuleOptions options);
|
||||||
|
SPV_API void SpvDeinitModule(SpvModule module);
|
||||||
|
|
||||||
|
SPV_API SpvResult SpvInitRuntime(SpvRuntime* runtime, SpvModule module);
|
||||||
|
SPV_API void SpvDeinitRuntime(SpvRuntime runtime);
|
||||||
|
|
||||||
|
SPV_API SpvResult SpvFlushDescriptorSets(SpvRuntime runtime);
|
||||||
|
|
||||||
|
SPV_API SpvResult SpvAddSpecializationInfo(SpvRuntime runtime, SpvRuntimeSpecializationEntry entry, const SpvByte* data, SpvSize data_size);
|
||||||
|
|
||||||
|
SPV_API SpvResult SpvGetResultByName(SpvRuntime runtime, const char* name, SpvWord* result);
|
||||||
|
SPV_API SpvResult SpvGetEntryPointByName(SpvRuntime runtime, const char* name, SpvWord* result);
|
||||||
|
SPV_API SpvResult SpvCallEntryPoint(SpvRuntime runtime, SpvWord entry_point_index);
|
||||||
|
|
||||||
|
SPV_API SpvResult SpvReadOutput(SpvRuntime runtime, SpvByte* output, SpvSize output_size, SpvWord result);
|
||||||
|
|
||||||
|
SPV_API SpvResult SpvWriteInput(SpvRuntime runtime, const SpvByte* input, SpvSize input_size, SpvWord result);
|
||||||
|
SPV_API SpvResult SpvWriteBuiltIn(SpvRuntime runtime, const SpvByte* input, SpvSize input_size, SpvBuiltIn builtin);
|
||||||
|
SPV_API SpvResult SpvWriteDescriptorSet(SpvRuntime runtime, const SpvByte* input, SpvSize input_size, SpvWord set, SpvWord binding, SpvWord descriptor_index);
|
||||||
|
|
||||||
|
#ifndef spirv_H
|
||||||
|
enum SpvBuiltIn_
|
||||||
|
{
|
||||||
|
SpvBuiltInPosition = 0,
|
||||||
|
SpvBuiltInPointSize = 1,
|
||||||
|
SpvBuiltInClipDistance = 3,
|
||||||
|
SpvBuiltInCullDistance = 4,
|
||||||
|
SpvBuiltInVertexId = 5,
|
||||||
|
SpvBuiltInInstanceId = 6,
|
||||||
|
SpvBuiltInPrimitiveId = 7,
|
||||||
|
SpvBuiltInInvocationId = 8,
|
||||||
|
SpvBuiltInLayer = 9,
|
||||||
|
SpvBuiltInViewportIndex = 10,
|
||||||
|
SpvBuiltInTessLevelOuter = 11,
|
||||||
|
SpvBuiltInTessLevelInner = 12,
|
||||||
|
SpvBuiltInTessCoord = 13,
|
||||||
|
SpvBuiltInPatchVertices = 14,
|
||||||
|
SpvBuiltInFragCoord = 15,
|
||||||
|
SpvBuiltInPointCoord = 16,
|
||||||
|
SpvBuiltInFrontFacing = 17,
|
||||||
|
SpvBuiltInSampleId = 18,
|
||||||
|
SpvBuiltInSamplePosition = 19,
|
||||||
|
SpvBuiltInSampleMask = 20,
|
||||||
|
SpvBuiltInFragDepth = 22,
|
||||||
|
SpvBuiltInHelperInvocation = 23,
|
||||||
|
SpvBuiltInNumWorkgroups = 24,
|
||||||
|
SpvBuiltInWorkgroupSize = 25,
|
||||||
|
SpvBuiltInWorkgroupId = 26,
|
||||||
|
SpvBuiltInLocalInvocationId = 27,
|
||||||
|
SpvBuiltInGlobalInvocationId = 28,
|
||||||
|
SpvBuiltInLocalInvocationIndex = 29,
|
||||||
|
SpvBuiltInWorkDim = 30,
|
||||||
|
SpvBuiltInGlobalSize = 31,
|
||||||
|
SpvBuiltInEnqueuedWorkgroupSize = 32,
|
||||||
|
SpvBuiltInGlobalOffset = 33,
|
||||||
|
SpvBuiltInGlobalLinearId = 34,
|
||||||
|
SpvBuiltInSubgroupSize = 36,
|
||||||
|
SpvBuiltInSubgroupMaxSize = 37,
|
||||||
|
SpvBuiltInNumSubgroups = 38,
|
||||||
|
SpvBuiltInNumEnqueuedSubgroups = 39,
|
||||||
|
SpvBuiltInSubgroupId = 40,
|
||||||
|
SpvBuiltInSubgroupLocalInvocationId = 41,
|
||||||
|
SpvBuiltInVertexIndex = 42,
|
||||||
|
SpvBuiltInInstanceIndex = 43,
|
||||||
|
SpvBuiltInCoreIDARM = 4160,
|
||||||
|
SpvBuiltInCoreCountARM = 4161,
|
||||||
|
SpvBuiltInCoreMaxIDARM = 4162,
|
||||||
|
SpvBuiltInWarpIDARM = 4163,
|
||||||
|
SpvBuiltInWarpMaxIDARM = 4164,
|
||||||
|
SpvBuiltInSubgroupEqMask = 4416,
|
||||||
|
SpvBuiltInSubgroupEqMaskKHR = 4416,
|
||||||
|
SpvBuiltInSubgroupGeMask = 4417,
|
||||||
|
SpvBuiltInSubgroupGeMaskKHR = 4417,
|
||||||
|
SpvBuiltInSubgroupGtMask = 4418,
|
||||||
|
SpvBuiltInSubgroupGtMaskKHR = 4418,
|
||||||
|
SpvBuiltInSubgroupLeMask = 4419,
|
||||||
|
SpvBuiltInSubgroupLeMaskKHR = 4419,
|
||||||
|
SpvBuiltInSubgroupLtMask = 4420,
|
||||||
|
SpvBuiltInSubgroupLtMaskKHR = 4420,
|
||||||
|
SpvBuiltInBaseVertex = 4424,
|
||||||
|
SpvBuiltInBaseInstance = 4425,
|
||||||
|
SpvBuiltInDrawIndex = 4426,
|
||||||
|
SpvBuiltInPrimitiveShadingRateKHR = 4432,
|
||||||
|
SpvBuiltInDeviceIndex = 4438,
|
||||||
|
SpvBuiltInViewIndex = 4440,
|
||||||
|
SpvBuiltInShadingRateKHR = 4444,
|
||||||
|
SpvBuiltInTileOffsetQCOM = 4492,
|
||||||
|
SpvBuiltInTileDimensionQCOM = 4493,
|
||||||
|
SpvBuiltInTileApronSizeQCOM = 4494,
|
||||||
|
SpvBuiltInBaryCoordNoPerspAMD = 4992,
|
||||||
|
SpvBuiltInBaryCoordNoPerspCentroidAMD = 4993,
|
||||||
|
SpvBuiltInBaryCoordNoPerspSampleAMD = 4994,
|
||||||
|
SpvBuiltInBaryCoordSmoothAMD = 4995,
|
||||||
|
SpvBuiltInBaryCoordSmoothCentroidAMD = 4996,
|
||||||
|
SpvBuiltInBaryCoordSmoothSampleAMD = 4997,
|
||||||
|
SpvBuiltInBaryCoordPullModelAMD = 4998,
|
||||||
|
SpvBuiltInFragStencilRefEXT = 5014,
|
||||||
|
SpvBuiltInRemainingRecursionLevelsAMDX = 5021,
|
||||||
|
SpvBuiltInShaderIndexAMDX = 5073,
|
||||||
|
SpvBuiltInSamplerHeapEXT = 5122,
|
||||||
|
SpvBuiltInResourceHeapEXT = 5123,
|
||||||
|
SpvBuiltInViewportMaskNV = 5253,
|
||||||
|
SpvBuiltInSecondaryPositionNV = 5257,
|
||||||
|
SpvBuiltInSecondaryViewportMaskNV = 5258,
|
||||||
|
SpvBuiltInPositionPerViewNV = 5261,
|
||||||
|
SpvBuiltInViewportMaskPerViewNV = 5262,
|
||||||
|
SpvBuiltInFullyCoveredEXT = 5264,
|
||||||
|
SpvBuiltInTaskCountNV = 5274,
|
||||||
|
SpvBuiltInPrimitiveCountNV = 5275,
|
||||||
|
SpvBuiltInPrimitiveIndicesNV = 5276,
|
||||||
|
SpvBuiltInClipDistancePerViewNV = 5277,
|
||||||
|
SpvBuiltInCullDistancePerViewNV = 5278,
|
||||||
|
SpvBuiltInLayerPerViewNV = 5279,
|
||||||
|
SpvBuiltInMeshViewCountNV = 5280,
|
||||||
|
SpvBuiltInMeshViewIndicesNV = 5281,
|
||||||
|
SpvBuiltInBaryCoordKHR = 5286,
|
||||||
|
SpvBuiltInBaryCoordNV = 5286,
|
||||||
|
SpvBuiltInBaryCoordNoPerspKHR = 5287,
|
||||||
|
SpvBuiltInBaryCoordNoPerspNV = 5287,
|
||||||
|
SpvBuiltInFragSizeEXT = 5292,
|
||||||
|
SpvBuiltInFragmentSizeNV = 5292,
|
||||||
|
SpvBuiltInFragInvocationCountEXT = 5293,
|
||||||
|
SpvBuiltInInvocationsPerPixelNV = 5293,
|
||||||
|
SpvBuiltInPrimitivePointIndicesEXT = 5294,
|
||||||
|
SpvBuiltInPrimitiveLineIndicesEXT = 5295,
|
||||||
|
SpvBuiltInPrimitiveTriangleIndicesEXT = 5296,
|
||||||
|
SpvBuiltInCullPrimitiveEXT = 5299,
|
||||||
|
SpvBuiltInLaunchIdKHR = 5319,
|
||||||
|
SpvBuiltInLaunchIdNV = 5319,
|
||||||
|
SpvBuiltInLaunchSizeKHR = 5320,
|
||||||
|
SpvBuiltInLaunchSizeNV = 5320,
|
||||||
|
SpvBuiltInWorldRayOriginKHR = 5321,
|
||||||
|
SpvBuiltInWorldRayOriginNV = 5321,
|
||||||
|
SpvBuiltInWorldRayDirectionKHR = 5322,
|
||||||
|
SpvBuiltInWorldRayDirectionNV = 5322,
|
||||||
|
SpvBuiltInObjectRayOriginKHR = 5323,
|
||||||
|
SpvBuiltInObjectRayOriginNV = 5323,
|
||||||
|
SpvBuiltInObjectRayDirectionKHR = 5324,
|
||||||
|
SpvBuiltInObjectRayDirectionNV = 5324,
|
||||||
|
SpvBuiltInRayTminKHR = 5325,
|
||||||
|
SpvBuiltInRayTminNV = 5325,
|
||||||
|
SpvBuiltInRayTmaxKHR = 5326,
|
||||||
|
SpvBuiltInRayTmaxNV = 5326,
|
||||||
|
SpvBuiltInInstanceCustomIndexKHR = 5327,
|
||||||
|
SpvBuiltInInstanceCustomIndexNV = 5327,
|
||||||
|
SpvBuiltInObjectToWorldKHR = 5330,
|
||||||
|
SpvBuiltInObjectToWorldNV = 5330,
|
||||||
|
SpvBuiltInWorldToObjectKHR = 5331,
|
||||||
|
SpvBuiltInWorldToObjectNV = 5331,
|
||||||
|
SpvBuiltInHitTNV = 5332,
|
||||||
|
SpvBuiltInHitKindKHR = 5333,
|
||||||
|
SpvBuiltInHitKindNV = 5333,
|
||||||
|
SpvBuiltInCurrentRayTimeNV = 5334,
|
||||||
|
SpvBuiltInHitTriangleVertexPositionsKHR = 5335,
|
||||||
|
SpvBuiltInHitMicroTriangleVertexPositionsNV = 5337,
|
||||||
|
SpvBuiltInHitMicroTriangleVertexBarycentricsNV = 5344,
|
||||||
|
SpvBuiltInIncomingRayFlagsKHR = 5351,
|
||||||
|
SpvBuiltInIncomingRayFlagsNV = 5351,
|
||||||
|
SpvBuiltInRayGeometryIndexKHR = 5352,
|
||||||
|
SpvBuiltInHitIsSphereNV = 5359,
|
||||||
|
SpvBuiltInHitIsLSSNV = 5360,
|
||||||
|
SpvBuiltInHitSpherePositionNV = 5361,
|
||||||
|
SpvBuiltInWarpsPerSMNV = 5374,
|
||||||
|
SpvBuiltInSMCountNV = 5375,
|
||||||
|
SpvBuiltInWarpIDNV = 5376,
|
||||||
|
SpvBuiltInSMIDNV = 5377,
|
||||||
|
SpvBuiltInHitLSSPositionsNV = 5396,
|
||||||
|
SpvBuiltInHitKindFrontFacingMicroTriangleNV = 5405,
|
||||||
|
SpvBuiltInHitKindBackFacingMicroTriangleNV = 5406,
|
||||||
|
SpvBuiltInHitSphereRadiusNV = 5420,
|
||||||
|
SpvBuiltInHitLSSRadiiNV = 5421,
|
||||||
|
SpvBuiltInClusterIDNV = 5436,
|
||||||
|
SpvBuiltInCullMaskKHR = 6021,
|
||||||
|
SpvBuiltInMax = 0x7fffffff,
|
||||||
|
};
|
||||||
|
#endif /* spirv_H */
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* SPIRV_INTERPRETER_H */
|
||||||
+29
@@ -0,0 +1,29 @@
|
|||||||
|
pub const spv = @import("spv");
|
||||||
|
|
||||||
|
pub const SpvCBool = c_int;
|
||||||
|
pub const SpvCWord = c_ulong;
|
||||||
|
pub const SpvCSize = c_ulong;
|
||||||
|
|
||||||
|
pub const Result = enum(c_int) {
|
||||||
|
Success = 0,
|
||||||
|
DivisionByZero = -1,
|
||||||
|
InvalidEntryPoint = -2,
|
||||||
|
InvalidSpirV = -3,
|
||||||
|
InvalidValueType = -4,
|
||||||
|
Killed = -5,
|
||||||
|
NotFound = -6,
|
||||||
|
OutOfMemory = -7,
|
||||||
|
OutOfBounds = -8,
|
||||||
|
ToDo = -9,
|
||||||
|
Unreachable = -10,
|
||||||
|
UnsupportedSpirV = -11,
|
||||||
|
UnsupportedExtension = -12,
|
||||||
|
UnsupportedEndianness = -13,
|
||||||
|
InvalidMagic = -14,
|
||||||
|
Unknown = -15,
|
||||||
|
};
|
||||||
|
|
||||||
|
comptime {
|
||||||
|
_ = @import("module.zig");
|
||||||
|
_ = @import("runtime.zig");
|
||||||
|
}
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
const std = @import("std");
|
||||||
|
const ffi = @import("ffi.zig");
|
||||||
|
const spv = ffi.spv;
|
||||||
|
|
||||||
|
const Options = extern struct {
|
||||||
|
use_simd_vectors_specializations: ffi.SpvCBool,
|
||||||
|
};
|
||||||
|
|
||||||
|
fn toCResult(err: spv.Module.ModuleError) ffi.Result {
|
||||||
|
return switch (err) {
|
||||||
|
spv.Module.ModuleError.InvalidSpirV => ffi.Result.InvalidSpirV,
|
||||||
|
spv.Module.ModuleError.InvalidMagic => ffi.Result.InvalidMagic,
|
||||||
|
spv.Module.ModuleError.UnsupportedEndianness => ffi.Result.UnsupportedEndianness,
|
||||||
|
spv.Module.ModuleError.UnsupportedExtension => ffi.Result.UnsupportedExtension,
|
||||||
|
spv.Module.ModuleError.OutOfMemory => ffi.Result.OutOfMemory,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export fn SpvInitModule(module: **spv.Module, source: [*]const ffi.SpvCWord, source_len: ffi.SpvCSize, options: Options) callconv(.c) ffi.Result {
|
||||||
|
const allocator = std.heap.c_allocator;
|
||||||
|
|
||||||
|
module.* = allocator.create(spv.Module) catch return .OutOfMemory;
|
||||||
|
|
||||||
|
const cast_source: []const u32 = @as([*]const u32, @ptrCast(source[0..source_len]))[0..source_len];
|
||||||
|
module.*.* = spv.Module.init(
|
||||||
|
allocator,
|
||||||
|
cast_source[0..source_len],
|
||||||
|
.{
|
||||||
|
.use_simd_vectors_specializations = if (options.use_simd_vectors_specializations == 0) false else true,
|
||||||
|
},
|
||||||
|
) catch |err| {
|
||||||
|
allocator.destroy(module.*);
|
||||||
|
return toCResult(err);
|
||||||
|
};
|
||||||
|
return .Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
export fn SpvDeinitModule(module: *spv.Module) callconv(.c) void {
|
||||||
|
const allocator = std.heap.c_allocator;
|
||||||
|
module.deinit(allocator);
|
||||||
|
allocator.destroy(module);
|
||||||
|
}
|
||||||
@@ -0,0 +1,95 @@
|
|||||||
|
const std = @import("std");
|
||||||
|
const ffi = @import("ffi.zig");
|
||||||
|
const spv = ffi.spv;
|
||||||
|
|
||||||
|
const CSpecializationEntry = extern struct {
|
||||||
|
id: spv.SpvWord,
|
||||||
|
offset: u32,
|
||||||
|
size: u32,
|
||||||
|
};
|
||||||
|
|
||||||
|
fn toCResult(err: spv.Runtime.RuntimeError) ffi.Result {
|
||||||
|
return switch (err) {
|
||||||
|
spv.Runtime.RuntimeError.DivisionByZero => ffi.Result.DivisionByZero,
|
||||||
|
spv.Runtime.RuntimeError.InvalidEntryPoint => ffi.Result.InvalidEntryPoint,
|
||||||
|
spv.Runtime.RuntimeError.InvalidSpirV => ffi.Result.InvalidSpirV,
|
||||||
|
spv.Runtime.RuntimeError.InvalidValueType => ffi.Result.InvalidValueType,
|
||||||
|
spv.Runtime.RuntimeError.Killed => ffi.Result.Killed,
|
||||||
|
spv.Runtime.RuntimeError.NotFound => ffi.Result.NotFound,
|
||||||
|
spv.Runtime.RuntimeError.OutOfMemory => ffi.Result.OutOfMemory,
|
||||||
|
spv.Runtime.RuntimeError.OutOfBounds => ffi.Result.OutOfBounds,
|
||||||
|
spv.Runtime.RuntimeError.ToDo => ffi.Result.ToDo,
|
||||||
|
spv.Runtime.RuntimeError.Unreachable => ffi.Result.Unreachable,
|
||||||
|
spv.Runtime.RuntimeError.UnsupportedSpirV => ffi.Result.UnsupportedSpirV,
|
||||||
|
spv.Runtime.RuntimeError.UnsupportedExtension => ffi.Result.UnsupportedExtension,
|
||||||
|
spv.Runtime.RuntimeError.Unknown => ffi.Result.Unknown,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export fn SpvInitRuntime(rt: **spv.Runtime, module: *spv.Module) callconv(.c) ffi.Result {
|
||||||
|
const allocator = std.heap.c_allocator;
|
||||||
|
|
||||||
|
rt.* = allocator.create(spv.Runtime) catch return .OutOfMemory;
|
||||||
|
|
||||||
|
rt.*.* = spv.Runtime.init(allocator, module) catch |err| {
|
||||||
|
allocator.destroy(rt.*);
|
||||||
|
return toCResult(err);
|
||||||
|
};
|
||||||
|
return .Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
export fn SpvDeinitRuntime(rt: *spv.Runtime) callconv(.c) void {
|
||||||
|
const allocator = std.heap.c_allocator;
|
||||||
|
rt.deinit(allocator);
|
||||||
|
allocator.destroy(rt);
|
||||||
|
}
|
||||||
|
|
||||||
|
export fn SpvAddSpecializationInfo(rt: *spv.Runtime, entry: CSpecializationEntry, data: [*]const u8, data_size: u32) callconv(.c) ffi.Result {
|
||||||
|
const allocator = std.heap.c_allocator;
|
||||||
|
rt.addSpecializationInfo(
|
||||||
|
allocator,
|
||||||
|
.{
|
||||||
|
.id = entry.id,
|
||||||
|
.offset = @intCast(entry.offset),
|
||||||
|
.size = @intCast(entry.size),
|
||||||
|
},
|
||||||
|
data[0..data_size],
|
||||||
|
) catch |err| return toCResult(err);
|
||||||
|
return .Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
export fn SpvGetEntryPointByName(rt: *spv.Runtime, name: [*:0]const u8, result: *spv.SpvWord) callconv(.c) ffi.Result {
|
||||||
|
result.* = rt.getEntryPointByName(std.mem.span(name)) catch |err| return toCResult(err);
|
||||||
|
return .Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
export fn SpvGetResultByName(rt: *spv.Runtime, name: [*:0]const u8, result: *spv.SpvWord) callconv(.c) ffi.Result {
|
||||||
|
result.* = rt.getResultByName(std.mem.span(name)) catch |err| return toCResult(err);
|
||||||
|
return .Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
export fn SpvCallEntryPoint(rt: *spv.Runtime, entry_point: spv.SpvWord) callconv(.c) ffi.Result {
|
||||||
|
const allocator = std.heap.c_allocator;
|
||||||
|
rt.callEntryPoint(allocator, entry_point) catch |err| return toCResult(err);
|
||||||
|
return .Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
export fn SpvReadOutput(rt: *spv.Runtime, output: [*]u8, output_size: u32, result: spv.SpvWord) callconv(.c) ffi.Result {
|
||||||
|
rt.readOutput(output[0..output_size], result) catch |err| return toCResult(err);
|
||||||
|
return .Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
export fn SpvWriteInput(rt: *spv.Runtime, input: [*]const u8, input_size: u32, result: spv.SpvWord) callconv(.c) ffi.Result {
|
||||||
|
rt.writeInput(input[0..input_size], result) catch |err| return toCResult(err);
|
||||||
|
return .Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
export fn SpvWriteBuiltIn(rt: *spv.Runtime, input: [*]const u8, input_size: u32, builtin: spv.spv.SpvBuiltIn) callconv(.c) ffi.Result {
|
||||||
|
rt.writeBuiltIn(input[0..input_size], builtin) catch |err| return toCResult(err);
|
||||||
|
return .Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
export fn SpvWriteDescriptorSet(rt: *spv.Runtime, input: [*]const u8, input_size: u32, set: spv.SpvWord, binding: spv.SpvWord, descriptor_index: spv.SpvWord) callconv(.c) ffi.Result {
|
||||||
|
rt.writeDescriptorSet(input[0..input_size], set, binding, descriptor_index) catch |err| return toCResult(err);
|
||||||
|
return .Success;
|
||||||
|
}
|
||||||
+3
-3
@@ -210,19 +210,19 @@ fn pass(self: *Self, allocator: std.mem.Allocator, op_set: ?std.EnumSet(spv.SpvO
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn writeDescriptorSet(self: *const Self, input: []u8, set: SpvWord, binding: SpvWord, descriptor_index: SpvWord) RuntimeError!void {
|
pub fn writeDescriptorSet(self: *const Self, input: []const u8, set: SpvWord, binding: SpvWord, descriptor_index: SpvWord) RuntimeError!void {
|
||||||
if (set < lib.SPIRV_MAX_SET and binding < lib.SPIRV_MAX_SET_BINDINGS) {
|
if (set < lib.SPIRV_MAX_SET and binding < lib.SPIRV_MAX_SET_BINDINGS) {
|
||||||
const value = &self.results[self.mod.bindings[set][binding]].variant.?.Variable.value;
|
const value = &self.results[self.mod.bindings[set][binding]].variant.?.Variable.value;
|
||||||
switch (value.*) {
|
switch (value.*) {
|
||||||
.Array => |arr| {
|
.Array => |arr| {
|
||||||
if (descriptor_index >= arr.values.len)
|
if (descriptor_index >= arr.values.len)
|
||||||
return RuntimeError.NotFound;
|
return RuntimeError.NotFound;
|
||||||
_ = try arr.values[descriptor_index].write(input);
|
_ = try arr.values[descriptor_index].writeConst(input);
|
||||||
},
|
},
|
||||||
else => {
|
else => {
|
||||||
if (descriptor_index != 0)
|
if (descriptor_index != 0)
|
||||||
return RuntimeError.NotFound;
|
return RuntimeError.NotFound;
|
||||||
_ = try value.write(input);
|
_ = try value.writeConst(input);
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
+1
-1
@@ -35,7 +35,7 @@ pub const Module = @import("Module.zig");
|
|||||||
pub const Runtime = @import("Runtime.zig");
|
pub const Runtime = @import("Runtime.zig");
|
||||||
|
|
||||||
const opcodes = @import("opcodes.zig");
|
const opcodes = @import("opcodes.zig");
|
||||||
const spv = @import("spv.zig");
|
pub const spv = @import("spv.zig");
|
||||||
|
|
||||||
pub const SpvVoid = spv.SpvVoid;
|
pub const SpvVoid = spv.SpvVoid;
|
||||||
pub const SpvByte = spv.SpvByte;
|
pub const SpvByte = spv.SpvByte;
|
||||||
|
|||||||
@@ -0,0 +1,77 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <SpirvInterpreter.h>
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
SpvRuntime runtime;
|
||||||
|
if(SpvInitRuntime(&runtime, module) != SPV_RESULT_SUCCESS)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Runtime init failed\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
SpvWord main_entry_index;
|
||||||
|
SpvGetEntryPointByName(runtime, "main", &main_entry_index);
|
||||||
|
SpvCallEntryPoint(runtime, main_entry_index);
|
||||||
|
|
||||||
|
float output[4];
|
||||||
|
SpvWord output_result;
|
||||||
|
SpvGetResultByName(runtime, "color", &output_result);
|
||||||
|
SpvReadOutput(runtime, (SpvByte*)output, sizeof(output), output_result);
|
||||||
|
|
||||||
|
printf("Output: Vec4[%f, %f, %f, %f]\n", output[0], output[1], output[2], output[3]);
|
||||||
|
|
||||||
|
SpvDeinitRuntime(runtime);
|
||||||
|
SpvDeinitModule(module);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user