initial commit

This commit is contained in:
2025-12-22 23:04:20 +01:00
parent 5821a7f929
commit 977d05f15d
13 changed files with 320 additions and 0 deletions

34
.github/workflows/build.yml vendored git.filemode.normal_file
View File

@@ -0,0 +1,34 @@
name: Build
on:
push:
branches: [ "master" ]
pull_request:
branches: [ "master" ]
permissions:
contents: read
deployments: write
jobs:
build:
runs-on: ubuntu-latest
if: "!contains(github.event.head_commit.message, 'ci skip')"
steps:
- uses: actions/checkout@v4
- uses: mlugg/setup-zig@v2
- name: Building
run: zig build
- name: Generating docs
run: zig build docs
- name: Publish to Cloudflare Pages
uses: cloudflare/wrangler-action@v3
with:
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
command: pages deploy zig-out/docs --project-name=spirv-interpreter-docs
gitHubToken: ${{ secrets.GITHUB_TOKEN }}

23
.github/workflows/test.yml vendored git.filemode.normal_file
View File

@@ -0,0 +1,23 @@
name: Test
on:
push:
branches: [ "master" ]
pull_request:
branches: [ "master" ]
permissions:
contents: read
deployments: write
jobs:
build:
runs-on: ubuntu-latest
if: "!contains(github.event.head_commit.message, 'ci skip')"
steps:
- uses: actions/checkout@v4
- uses: mlugg/setup-zig@v2
- name: Test
run: zig build test

85
build.zig git.filemode.normal_file
View File

@@ -0,0 +1,85 @@
const std = @import("std");
pub fn build(b: *std.Build) void {
const target = b.standardTargetOptions(.{});
const optimize = b.standardOptimizeOption(.{});
const mod = b.createModule(.{
.root_source_file = b.path("src/lib.zig"),
.target = target,
.optimize = optimize,
});
const spirv_headers = b.dependency("spirv_headers", .{});
mod.addSystemIncludePath(spirv_headers.path("include/spirv/unified1"));
const lib = b.addLibrary(.{
.name = "spirv_interpreter",
.root_module = mod,
.linkage = .dynamic,
});
const lib_install = b.addInstallArtifact(lib, .{});
// Zig example setup
const example_exe = b.addExecutable(.{
.name = "spirv_interpreter_example",
.root_module = b.createModule(.{
.root_source_file = b.path("example/main.zig"),
.target = target,
.optimize = optimize,
.imports = &.{
.{ .name = "spv", .module = mod },
},
}),
});
const spirv_target = b.resolveTargetQuery(.{
.cpu_arch = .spirv32,
.cpu_model = .{ .explicit = &std.Target.spirv.cpu.vulkan_v1_2 },
.os_tag = .vulkan,
.ofmt = .spirv,
});
const shader = b.addObject(.{
.name = "shader.zig",
.root_module = b.createModule(.{
.root_source_file = b.path("example/shader.zig"),
.target = spirv_target,
}),
.use_llvm = false,
});
example_exe.root_module.addAnonymousImport("shader", .{ .root_source_file = shader.getEmittedBin() });
const example_install = b.addInstallArtifact(example_exe, .{});
example_install.step.dependOn(&lib_install.step);
const run_example = b.addRunArtifact(example_exe);
run_example.step.dependOn(&example_install.step);
const run_example_step = b.step("example", "Run the basic example");
run_example_step.dependOn(&run_example.step);
// Zig unit tests setup
const lib_tests = b.addTest(.{ .root_module = mod });
const run_tests = b.addRunArtifact(lib_tests);
const test_step = b.step("test", "Run Zig unit tests");
test_step.dependOn(&run_tests.step);
// Docs generation
const autodoc_test = b.addObject(.{
.name = "lib",
.root_module = mod,
});
const install_docs = b.addInstallDirectory(.{
.source_dir = autodoc_test.getEmittedDocs(),
.install_dir = .prefix,
.install_subdir = "docs",
});
const docs_step = b.step("docs", "Build and install the documentation");
docs_step.dependOn(&install_docs.step);
}

18
build.zig.zon git.filemode.normal_file
View File

@@ -0,0 +1,18 @@
.{
.name = .SPIRV_Interpreter,
.version = "0.0.1",
.dependencies = .{
.spirv_headers = .{
.url = "git+https://github.com/KhronosGroup/SPIRV-Headers#0a7f626a6ae86284a413d105b47a6fb413bf6c92",
.hash = "N-V-__8AAGOhPABkbhEc-SenlpOzOI4ppi0CDXVSteii5ywV",
},
},
.minimum_zig_version = "0.15.2",
.paths = .{
"build.zig",
"build.zig.zon",
"src",
"LICENSE",
},
.fingerprint = 0xd87ec8ab9fa9396a,
}

20
example/main.zig git.filemode.normal_file
View File

@@ -0,0 +1,20 @@
const std = @import("std");
const spv = @import("spv");
const shader_source = @embedFile("shader");
pub fn main() !void {
{
var gpa: std.heap.DebugAllocator(.{}) = .init;
defer _ = gpa.deinit();
const allocator = gpa.allocator();
const ctx = try spv.Interpreter.init();
defer ctx.deinit();
const module = try spv.Module.init(allocator, &ctx, @ptrCast(@alignCast(shader_source)));
defer module.deinit(allocator);
}
std.log.info("Successfully executed", .{});
}

10
example/shader.zig git.filemode.normal_file
View File

@@ -0,0 +1,10 @@
const std = @import("std");
const gpu = std.gpu;
extern var frag_color: @Vector(4, f32) addrspace(.output);
export fn main() callconv(.spirv_fragment) void {
gpu.location(&frag_color, 0);
frag_color = .{ 1.0, 1.0, 1.0, 1.0 };
}

0
src/Image.zig git.filemode.normal_file
View File

9
src/Interpreter.zig git.filemode.normal_file
View File

@@ -0,0 +1,9 @@
const Self = @This();
pub fn init() !Self {
return .{};
}
pub fn deinit(self: *const Self) void {
_ = self;
}

58
src/Module.zig git.filemode.normal_file
View File

@@ -0,0 +1,58 @@
const std = @import("std");
const lib = @import("lib.zig");
const SpvVoid = lib.SpvVoid;
const SpvByte = lib.SpvByte;
const SpvWord = lib.SpvWord;
const SpvBool = lib.SpvBool;
const spv = lib.spv;
const Interpreter = @import("Interpreter.zig");
const WordIterator = @import("WordIterator.zig");
const Self = @This();
const SpvEntryPoint = struct {
exec_model: spv.SpvExecutionModel,
id: SpvWord,
name: []const u8,
globals_count: SpvWord,
globals: []const SpvWord,
};
ctx: *const Interpreter,
it: WordIterator,
version_major: SpvByte,
version_minor: SpvByte,
generator_magic: SpvWord,
bound: SpvWord,
code: []const SpvWord,
addressing: spv.SpvAddressingModel,
memory_model: spv.SpvMemoryModel,
entry_point_count: SpvWord,
entry_points: []const SpvEntryPoint,
local_size_x: SpvWord,
local_size_y: SpvWord,
local_size_z: SpvWord,
pub fn init(allocator: std.mem.Allocator, ctx: *const Interpreter, source: []const SpvWord) !Self {
var self: Self = std.mem.zeroInit(Self, .{
.ctx = ctx,
.code = try allocator.dupe(SpvWord, source),
});
self.it = WordIterator.init(self.code);
return self;
}
pub fn deinit(self: *const Self, allocator: std.mem.Allocator) void {
allocator.free(self.code);
}

9
src/State.zig git.filemode.normal_file
View File

@@ -0,0 +1,9 @@
const std = @import("std");
const Interpreter = @import("Interpreter.zig");
const Module = @import("Module.zig");
const Self = @This();
ctx: *Interpreter,
owner: *Module,

33
src/WordIterator.zig git.filemode.normal_file
View File

@@ -0,0 +1,33 @@
const lib = @import("lib.zig");
const SpvWord = lib.SpvWord;
const Self = @This();
buffer: []const SpvWord,
index: usize,
pub fn init(buffer: []const SpvWord) Self {
return .{
.buffer = buffer,
.index = 0,
};
}
pub fn next(self: *Self) ?SpvWord {
const word = self.peek() orelse return null;
self.index += 1;
return word;
}
pub fn peek(self: *const Self) ?SpvWord {
return if (self.index >= self.buffer.len) null else self.buffer[self.index];
}
pub fn skip(self: *Self) bool {
if (self.index >= self.buffer.len) {
return false;
}
self.index += 1;
return true;
}

21
src/lib.zig git.filemode.normal_file
View File

@@ -0,0 +1,21 @@
const std = @import("std");
pub const spv = @cImport(@cInclude("spirv.h"));
pub const Image = @import("Image.zig");
pub const Interpreter = @import("Interpreter.zig");
pub const Module = @import("Module.zig");
pub const State = @import("State.zig");
const opcode = @import("opcode.zig");
pub const SpvVoid = void;
pub const SpvByte = u8;
pub const SpvWord = u32;
pub const SpvBool = bool;
test {
std.testing.refAllDecls(Image);
std.testing.refAllDecls(Interpreter);
std.testing.refAllDecls(Module);
std.testing.refAllDecls(State);
std.testing.refAllDecls(opcode);
}

0
src/opcode.zig git.filemode.normal_file
View File