This commit is contained in:
+22
-5
@@ -180,7 +180,7 @@ fn resolveConstantWord(self: *const Self, id: SpvWord) ?SpvWord {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn findAccessChainToMember(self: *const Self, base_id: SpvWord, member_index: 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;
|
const variant = result.variant orelse continue;
|
||||||
|
|
||||||
switch (variant) {
|
switch (variant) {
|
||||||
@@ -265,7 +265,7 @@ fn applyDecorations(self: *Self) ModuleError!void {
|
|||||||
var binding: ?usize = null;
|
var binding: ?usize = null;
|
||||||
|
|
||||||
for (result.decorations.items) |decoration| {
|
for (result.decorations.items) |decoration| {
|
||||||
switch (result.variant.?) {
|
if (result.variant) |*variant| switch (variant.*) {
|
||||||
.Variable => |v| {
|
.Variable => |v| {
|
||||||
try self.applyInterfaceDecoration(v.storage_class, decoration, @intCast(id));
|
try self.applyInterfaceDecoration(v.storage_class, decoration, @intCast(id));
|
||||||
|
|
||||||
@@ -294,13 +294,30 @@ fn applyDecorations(self: *Self) ModuleError!void {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
else => {},
|
else => {},
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (result.variant.?) {
|
if (result.variant) |*variant| switch (variant.*) {
|
||||||
.Variable => |v| try self.applyStructMemberInterfaceDecorations(v.storage_class, v.type_word, @intCast(id)),
|
.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 => {},
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
else => {},
|
||||||
|
};
|
||||||
|
|
||||||
if (set != null and binding != null) {
|
if (set != null and binding != null) {
|
||||||
self.bindings[set.?][binding.?] = @intCast(id);
|
self.bindings[set.?][binding.?] = @intCast(id);
|
||||||
|
|||||||
+30
-2
@@ -18,6 +18,7 @@ const WordIterator = @import("WordIterator.zig");
|
|||||||
const Self = @This();
|
const Self = @This();
|
||||||
|
|
||||||
pub const RuntimeError = error{
|
pub const RuntimeError = error{
|
||||||
|
Barrier,
|
||||||
DivisionByZero,
|
DivisionByZero,
|
||||||
InvalidEntryPoint,
|
InvalidEntryPoint,
|
||||||
InvalidSpirV,
|
InvalidSpirV,
|
||||||
@@ -33,6 +34,11 @@ pub const RuntimeError = error{
|
|||||||
Unknown,
|
Unknown,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
pub const EntryPointStatus = enum {
|
||||||
|
completed,
|
||||||
|
barrier,
|
||||||
|
};
|
||||||
|
|
||||||
pub const SpecializationEntry = struct {
|
pub const SpecializationEntry = struct {
|
||||||
id: SpvWord,
|
id: SpvWord,
|
||||||
offset: usize,
|
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;
|
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 {
|
pub fn getEntryPointByName(self: *const Self, name: []const u8) RuntimeError!SpvWord {
|
||||||
for (self.mod.entry_points.items, 0..) |entry_point, i| {
|
for (self.mod.entry_points.items, 0..) |entry_point, i| {
|
||||||
if (blk: {
|
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
|
/// 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 {
|
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)
|
if (entry_point_index > self.mod.entry_points.items.len)
|
||||||
return RuntimeError.InvalidEntryPoint;
|
return RuntimeError.InvalidEntryPoint;
|
||||||
|
|
||||||
@@ -212,7 +232,15 @@ pub fn callEntryPoint(self: *Self, allocator: std.mem.Allocator, entry_point_ind
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Execution pass
|
// 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 {
|
fn pass(self: *Self, allocator: std.mem.Allocator, op_set: ?std.EnumSet(spv.SpvOp)) RuntimeError!void {
|
||||||
|
|||||||
+17
-1
@@ -290,6 +290,7 @@ pub fn initRuntimeDispatcher() void {
|
|||||||
runtime_dispatcher[@intFromEnum(spv.SpvOp.CompositeConstruct)] = opCompositeConstruct;
|
runtime_dispatcher[@intFromEnum(spv.SpvOp.CompositeConstruct)] = opCompositeConstruct;
|
||||||
runtime_dispatcher[@intFromEnum(spv.SpvOp.CompositeExtract)] = opCompositeExtract;
|
runtime_dispatcher[@intFromEnum(spv.SpvOp.CompositeExtract)] = opCompositeExtract;
|
||||||
runtime_dispatcher[@intFromEnum(spv.SpvOp.CompositeInsert)] = opCompositeInsert;
|
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.ConvertFToS)] = ConversionEngine(.Float, .SInt).op;
|
||||||
runtime_dispatcher[@intFromEnum(spv.SpvOp.ConvertFToU)] = ConversionEngine(.Float, .UInt).op;
|
runtime_dispatcher[@intFromEnum(spv.SpvOp.ConvertFToU)] = ConversionEngine(.Float, .UInt).op;
|
||||||
runtime_dispatcher[@intFromEnum(spv.SpvOp.ConvertSToF)] = ConversionEngine(.SInt, .Float).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.MatrixTimesMatrix)] = MathEngine(.Float, .MatrixTimesMatrix, false).op;
|
||||||
runtime_dispatcher[@intFromEnum(spv.SpvOp.MatrixTimesScalar)] = MathEngine(.Float, .MatrixTimesScalar, false).op; // TODO
|
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.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.Not)] = BitEngine(.UInt, .Not).op;
|
||||||
runtime_dispatcher[@intFromEnum(spv.SpvOp.Phi)] = opPhi;
|
runtime_dispatcher[@intFromEnum(spv.SpvOp.Phi)] = opPhi;
|
||||||
runtime_dispatcher[@intFromEnum(spv.SpvOp.Return)] = opReturn;
|
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 {
|
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;
|
var decoration = rt.results[target].decorations.addOne(allocator) catch return RuntimeError.OutOfMemory;
|
||||||
decoration.rtype = decoration_type;
|
decoration.rtype = decoration_type;
|
||||||
|
decoration.literal_1 = 0;
|
||||||
|
decoration.literal_2 = null;
|
||||||
decoration.index = if (member) |memb| memb else 0;
|
decoration.index = if (member) |memb| memb else 0;
|
||||||
|
|
||||||
switch (decoration_type) {
|
switch (decoration_type) {
|
||||||
@@ -2332,7 +2336,7 @@ fn opAccessChain(allocator: std.mem.Allocator, word_count: SpvWord, rt: *Runtime
|
|||||||
if (uniform_slice_window != null) {
|
if (uniform_slice_window != null) {
|
||||||
uniform_slice_window = try helpers.advanceWindow(uniform_slice_window, member_offset);
|
uniform_slice_window = try helpers.advanceWindow(uniform_slice_window, member_offset);
|
||||||
} else if (s.external_data) |data| {
|
} 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];
|
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));
|
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 {
|
fn opCompositeConstruct(_: std.mem.Allocator, word_count: SpvWord, rt: *Runtime) RuntimeError!void {
|
||||||
_ = rt.it.skip();
|
_ = rt.it.skip();
|
||||||
const id = try rt.it.next();
|
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);
|
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 {
|
fn opName(allocator: std.mem.Allocator, word_count: SpvWord, rt: *Runtime) RuntimeError!void {
|
||||||
const id = try rt.it.next();
|
const id = try rt.it.next();
|
||||||
var result = &rt.results[id];
|
var result = &rt.results[id];
|
||||||
|
|||||||
Reference in New Issue
Block a user