yes
Test / build (push) Successful in 58s
Build / build (push) Successful in 58s

This commit is contained in:
2026-06-01 20:36:24 +02:00
parent 0eefbe63e3
commit 9c355fe126
3 changed files with 70 additions and 9 deletions
+23 -6
View File
@@ -180,7 +180,7 @@ fn resolveConstantWord(self: *const Self, id: SpvWord) ?SpvWord {
}
fn findAccessChainToMember(self: *const Self, base_id: SpvWord, member_index: SpvWord) ?SpvWord {
for (self.results, 0..) |result, id| {
for (self.results, 0..) |*result, id| {
const variant = result.variant orelse continue;
switch (variant) {
@@ -265,7 +265,7 @@ fn applyDecorations(self: *Self) ModuleError!void {
var binding: ?usize = null;
for (result.decorations.items) |decoration| {
switch (result.variant.?) {
if (result.variant) |*variant| switch (variant.*) {
.Variable => |v| {
try self.applyInterfaceDecoration(v.storage_class, decoration, @intCast(id));
@@ -294,13 +294,30 @@ fn applyDecorations(self: *Self) ModuleError!void {
}
},
else => {},
}
};
}
switch (result.variant.?) {
.Variable => |v| try self.applyStructMemberInterfaceDecorations(v.storage_class, v.type_word, @intCast(id)),
if (result.variant) |*variant| switch (variant.*) {
.Variable => |*v| {
try self.applyStructMemberInterfaceDecorations(v.storage_class, v.type_word, @intCast(id));
switch (v.storage_class) {
.StorageBuffer,
.Uniform,
.PushConstant,
=> if (v.value == .Structure) {
if (self.results[v.type_word].variant) |type_variant| switch (type_variant) {
.Type => |type_data| switch (type_data) {
.Structure => |s| @memcpy(@constCast(v.value.Structure.offsets), s.members_offsets),
else => {},
},
else => {},
};
},
else => {},
}
},
else => {},
}
};
if (set != null and binding != null) {
self.bindings[set.?][binding.?] = @intCast(id);
+30 -2
View File
@@ -18,6 +18,7 @@ const WordIterator = @import("WordIterator.zig");
const Self = @This();
pub const RuntimeError = error{
Barrier,
DivisionByZero,
InvalidEntryPoint,
InvalidSpirV,
@@ -33,6 +34,11 @@ pub const RuntimeError = error{
Unknown,
};
pub const EntryPointStatus = enum {
completed,
barrier,
};
pub const SpecializationEntry = struct {
id: SpvWord,
offset: usize,
@@ -119,6 +125,17 @@ pub fn addSpecializationInfo(self: *Self, allocator: std.mem.Allocator, entry: S
self.specialization_constants.put(allocator, entry.id, slice) catch return RuntimeError.OutOfMemory;
}
pub fn copySpecializationConstantsFrom(self: *Self, allocator: std.mem.Allocator, other: *const Self) RuntimeError!void {
var it = other.specialization_constants.iterator();
while (it.next()) |entry| {
const slice = allocator.dupe(u8, entry.value_ptr.*) catch return RuntimeError.OutOfMemory;
self.specialization_constants.put(allocator, entry.key_ptr.*, slice) catch {
allocator.free(slice);
return RuntimeError.OutOfMemory;
};
}
}
pub fn getEntryPointByName(self: *const Self, name: []const u8) RuntimeError!SpvWord {
for (self.mod.entry_points.items, 0..) |entry_point, i| {
if (blk: {
@@ -176,8 +193,11 @@ pub fn dumpResultsTable(self: *Self, allocator: std.mem.Allocator, writer: *std.
/// Calls an entry point, `entry_point_index` being the index of the entry point ordered by declaration in the bytecode
pub fn callEntryPoint(self: *Self, allocator: std.mem.Allocator, entry_point_index: SpvWord) RuntimeError!void {
self.reset();
_ = try self.beginEntryPoint(allocator, entry_point_index);
}
pub fn beginEntryPoint(self: *Self, allocator: std.mem.Allocator, entry_point_index: SpvWord) RuntimeError!EntryPointStatus {
self.reset();
if (entry_point_index > self.mod.entry_points.items.len)
return RuntimeError.InvalidEntryPoint;
@@ -212,7 +232,15 @@ pub fn callEntryPoint(self: *Self, allocator: std.mem.Allocator, entry_point_ind
}
// Execution pass
try self.pass(allocator, null);
return self.continueEntryPoint(allocator);
}
pub fn continueEntryPoint(self: *Self, allocator: std.mem.Allocator) RuntimeError!EntryPointStatus {
self.pass(allocator, null) catch |err| switch (err) {
RuntimeError.Barrier => return .barrier,
else => return err,
};
return .completed;
}
fn pass(self: *Self, allocator: std.mem.Allocator, op_set: ?std.EnumSet(spv.SpvOp)) RuntimeError!void {
+17 -1
View File
@@ -290,6 +290,7 @@ pub fn initRuntimeDispatcher() void {
runtime_dispatcher[@intFromEnum(spv.SpvOp.CompositeConstruct)] = opCompositeConstruct;
runtime_dispatcher[@intFromEnum(spv.SpvOp.CompositeExtract)] = opCompositeExtract;
runtime_dispatcher[@intFromEnum(spv.SpvOp.CompositeInsert)] = opCompositeInsert;
runtime_dispatcher[@intFromEnum(spv.SpvOp.ControlBarrier)] = opControlBarrier;
runtime_dispatcher[@intFromEnum(spv.SpvOp.ConvertFToS)] = ConversionEngine(.Float, .SInt).op;
runtime_dispatcher[@intFromEnum(spv.SpvOp.ConvertFToU)] = ConversionEngine(.Float, .UInt).op;
runtime_dispatcher[@intFromEnum(spv.SpvOp.ConvertSToF)] = ConversionEngine(.SInt, .Float).op;
@@ -349,6 +350,7 @@ pub fn initRuntimeDispatcher() void {
runtime_dispatcher[@intFromEnum(spv.SpvOp.MatrixTimesMatrix)] = MathEngine(.Float, .MatrixTimesMatrix, false).op;
runtime_dispatcher[@intFromEnum(spv.SpvOp.MatrixTimesScalar)] = MathEngine(.Float, .MatrixTimesScalar, false).op; // TODO
runtime_dispatcher[@intFromEnum(spv.SpvOp.MatrixTimesVector)] = MathEngine(.Float, .MatrixTimesVector, false).op;
runtime_dispatcher[@intFromEnum(spv.SpvOp.MemoryBarrier)] = opMemoryBarrier;
runtime_dispatcher[@intFromEnum(spv.SpvOp.Not)] = BitEngine(.UInt, .Not).op;
runtime_dispatcher[@intFromEnum(spv.SpvOp.Phi)] = opPhi;
runtime_dispatcher[@intFromEnum(spv.SpvOp.Return)] = opReturn;
@@ -1966,6 +1968,8 @@ fn MathEngine(comptime T: PrimitiveType, comptime Op: MathOp, comptime IsAtomic:
fn addDecoration(allocator: std.mem.Allocator, rt: *Runtime, target: SpvWord, decoration_type: spv.SpvDecoration, member: ?SpvWord) RuntimeError!void {
var decoration = rt.results[target].decorations.addOne(allocator) catch return RuntimeError.OutOfMemory;
decoration.rtype = decoration_type;
decoration.literal_1 = 0;
decoration.literal_2 = null;
decoration.index = if (member) |memb| memb else 0;
switch (decoration_type) {
@@ -2332,7 +2336,7 @@ fn opAccessChain(allocator: std.mem.Allocator, word_count: SpvWord, rt: *Runtime
if (uniform_slice_window != null) {
uniform_slice_window = try helpers.advanceWindow(uniform_slice_window, member_offset);
} else if (s.external_data) |data| {
uniform_slice_window = data[0..];
uniform_slice_window = try helpers.advanceWindow(data, member_offset);
}
value_ptr = &s.values[component_index];
@@ -2502,6 +2506,13 @@ fn opCapability(_: std.mem.Allocator, _: SpvWord, rt: *Runtime) RuntimeError!voi
rt.mod.capabilities.insert(try rt.it.nextAs(spv.SpvCapability));
}
fn opControlBarrier(_: std.mem.Allocator, _: SpvWord, rt: *Runtime) RuntimeError!void {
_ = rt.it.skip(); // execution scope
_ = rt.it.skip(); // memory scope
_ = rt.it.skip(); // memory semantics
return RuntimeError.Barrier;
}
fn opCompositeConstruct(_: std.mem.Allocator, word_count: SpvWord, rt: *Runtime) RuntimeError!void {
_ = rt.it.skip();
const id = try rt.it.next();
@@ -3498,6 +3509,11 @@ fn opMemoryModel(_: std.mem.Allocator, _: SpvWord, rt: *Runtime) RuntimeError!vo
rt.mod.memory_model = try rt.it.nextAs(spv.SpvMemoryModel);
}
fn opMemoryBarrier(_: std.mem.Allocator, _: SpvWord, rt: *Runtime) RuntimeError!void {
_ = rt.it.skip(); // memory scope
_ = rt.it.skip(); // memory semantics
}
fn opName(allocator: std.mem.Allocator, word_count: SpvWord, rt: *Runtime) RuntimeError!void {
const id = try rt.it.next();
var result = &rt.results[id];