diff --git a/src/Runtime.zig b/src/Runtime.zig index c42e521..fb2aa16 100644 --- a/src/Runtime.zig +++ b/src/Runtime.zig @@ -172,9 +172,9 @@ pub fn writeDescriptorSet(self: *const Self, input: []u8, set: SpvWord, binding: const value = &self.results[self.mod.bindings[set][binding]].variant.?.Variable.value; switch (value.*) { .Array => |arr| { - if (descriptor_index >= arr.len) + if (descriptor_index >= arr.values.len) return RuntimeError.NotFound; - _ = try arr[descriptor_index].write(input); + _ = try arr.values[descriptor_index].write(input); }, else => { if (descriptor_index != 0) diff --git a/src/Value.zig b/src/Value.zig index 35caa57..0b06fa8 100644 --- a/src/Value.zig +++ b/src/Value.zig @@ -61,7 +61,10 @@ pub const Value = union(Type) { Vector3u32: Vec3u32, Vector2u32: Vec2u32, Matrix: []Self, - Array: []Self, + Array: struct { + stride: SpvWord, + values: []Self, + }, RuntimeArray: struct { type_word: SpvWord, stride: SpvWord, @@ -107,13 +110,14 @@ pub const Value = union(Type) { pub inline fn getCompositeDataOrNull(self: *const Self) ?[]Self { return switch (self.*) { .Structure => |*s| s.values, - .Vector, .Matrix, .Array => |v| v, + .Array => |*a| a.values, + .Vector, .Matrix => |v| v, else => null, }; } - pub fn init(allocator: std.mem.Allocator, results: []const Result, target: SpvWord) RuntimeError!Self { - const resolved = results[target].resolveType(results); + pub fn init(allocator: std.mem.Allocator, results: []const Result, target_type: SpvWord) RuntimeError!Self { + const resolved = results[target_type].resolveType(results); const member_count = resolved.getMemberCounts(); return switch (resolved.variant.?) { @@ -156,10 +160,15 @@ pub const Value = union(Type) { break :blk self; }, .Array => |a| blk: { - var self: Self = .{ .Array = allocator.alloc(Self, member_count) catch return RuntimeError.OutOfMemory }; + var self: Self = .{ + .Array = .{ + .stride = a.stride, + .values = allocator.alloc(Self, member_count) catch return RuntimeError.OutOfMemory, + }, + }; errdefer self.deinit(allocator); - for (self.Array) |*value| { + for (self.Array.values) |*value| { value.* = try Self.init(allocator, results, a.components_type_word); } break :blk self; @@ -213,9 +222,12 @@ pub const Value = union(Type) { }, .Array => |a| .{ .Array = blk: { - const values = allocator.dupe(Self, a) catch return RuntimeError.OutOfMemory; - for (values, a) |*new_value, value| new_value.* = try value.dupe(allocator); - break :blk values; + const values = allocator.dupe(Self, a.values) catch return RuntimeError.OutOfMemory; + for (values, a.values) |*new_value, value| new_value.* = try value.dupe(allocator); + break :blk .{ + .stride = a.stride, + .values = values, + }; }, }, .Structure => |s| .{ @@ -311,16 +323,21 @@ pub const Value = union(Type) { } return 2 * 4; }, - .Vector, - .Matrix, - .Array, - => |values| { + .Vector, .Matrix => |values| { var offset: usize = 0; for (values) |v| { offset += try v.read(output[offset..]); } return offset; }, + .Array => |arr| { + var offset: usize = 0; + for (arr.values) |v| { + _ = try v.read(output[offset..]); + offset += arr.stride; + } + return offset; + }, .Structure => |s| { var offset: usize = 0; for (s.values, 0..) |v, i| { @@ -450,16 +467,21 @@ pub const Value = union(Type) { } return 2 * 4; }, - .Vector, - .Matrix, - .Array, - => |*values| { + .Vector, .Matrix => |*values| { var offset: usize = 0; for (values.*) |*v| { offset += try v.write(input[offset..]); } return offset; }, + .Array => |*arr| { + var offset: usize = 0; + for (arr.values) |*v| { + _ = try v.write(input[offset..]); + offset += arr.stride; + } + return offset; + }, .Structure => |s| { var offset: usize = 0; for (s.values, 0..) |*v, i| { @@ -488,13 +510,14 @@ pub const Value = union(Type) { .Vector4f32, .Vector4i32, .Vector4u32 => 4 * 4, .Vector3f32, .Vector3i32, .Vector3u32 => 3 * 4, .Vector2f32, .Vector2i32, .Vector2u32 => 2 * 4, - .Vector, .Matrix, .Array => |values| blk: { + .Vector, .Matrix => |values| blk: { var size: usize = 0; for (values) |v| { size += try v.getPlainMemorySize(); } break :blk size; }, + .Array => |arr| arr.stride * arr.values.len, .Structure => |s| blk: { var size: usize = 0; for (s.values, 0..) |v, i| { @@ -570,10 +593,14 @@ pub const Value = union(Type) { pub fn deinit(self: *Self, allocator: std.mem.Allocator) void { switch (self.*) { - .Vector, .Matrix, .Array => |values| { + .Vector, .Matrix => |values| { for (values) |*value| value.deinit(allocator); allocator.free(values); }, + .Array => |arr| { + for (arr.values) |*value| value.deinit(allocator); + allocator.free(arr.values); + }, .Structure => |s| { for (s.values) |*value| value.deinit(allocator); allocator.free(s.values); diff --git a/src/opcodes.zig b/src/opcodes.zig index 0c34f19..56d8086 100644 --- a/src/opcodes.zig +++ b/src/opcodes.zig @@ -1160,7 +1160,8 @@ fn copyValue(dst: *Value, src: *const Value) void { inline fn getDstSlice(v: *Value) ?[]Value { return switch (v.*) { - .Vector, .Matrix, .Array => |s| s, + .Vector, .Matrix => |s| s, + .Array => |a| a.values, .Structure => |s| s.values, else => null, }; @@ -1255,10 +1256,14 @@ fn copyValue(dst: *Value, src: *const Value) void { } switch (src.*) { - .Vector, .Matrix, .Array => |src_slice| { + .Vector, .Matrix => |src_slice| { const dst_slice = helpers.getDstSlice(dst); helpers.copySlice(dst_slice.?, src_slice); }, + .Array => |a| { + const dst_slice = helpers.getDstSlice(dst); + helpers.copySlice(dst_slice.?, a.values); + }, .Structure => |s| { const dst_slice = helpers.getDstSlice(dst); helpers.copySlice(dst_slice.?, s.values); @@ -1351,10 +1356,14 @@ fn opAccessChain(allocator: std.mem.Allocator, word_count: SpvWord, rt: *Runtime } switch (value_ptr.*) { - .Vector, .Matrix, .Array => |v| { + .Vector, .Matrix => |v| { if (i.value.uint32 >= v.len) return RuntimeError.OutOfBounds; value_ptr = &v[i.value.uint32]; }, + .Array => |a| { + if (i.value.uint32 >= a.values.len) return RuntimeError.OutOfBounds; + value_ptr = &a.values[i.value.uint32]; + }, .Structure => |s| { if (i.value.uint32 >= s.values.len) return RuntimeError.OutOfBounds; value_ptr = &s.values[i.value.uint32];