Compare commits
2 Commits
046b1c8f9e
...
ce17209004
| Author | SHA1 | Date | |
|---|---|---|---|
| ce17209004 | |||
| 11a59d8d7f |
+171
-76
@@ -120,8 +120,16 @@ pub const Value = union(Type) {
|
|||||||
i32_ptr: *i32, //< For vector specializations
|
i32_ptr: *i32, //< For vector specializations
|
||||||
u32_ptr: *u32,
|
u32_ptr: *u32,
|
||||||
},
|
},
|
||||||
is_owner_of_uniform_slice: bool = false,
|
|
||||||
|
/// Exact byte window in externally visible descriptor storage that
|
||||||
|
/// corresponds to this pointer. For a pointer to struct member N this
|
||||||
|
/// starts at the member offset, not at the containing struct.
|
||||||
uniform_slice_window: ?[]u8 = null,
|
uniform_slice_window: ?[]u8 = null,
|
||||||
|
|
||||||
|
/// Heap-owned value that backs a pointer into a materialized runtime
|
||||||
|
/// array element. This may differ from ptr.common when the pointer is
|
||||||
|
/// to a child/member of that materialized value.
|
||||||
|
uniform_backing_value: ?*Self = null,
|
||||||
},
|
},
|
||||||
|
|
||||||
pub inline fn getCompositeDataOrNull(self: *const Self) ?[]Self {
|
pub inline fn getCompositeDataOrNull(self: *const Self) ?[]Self {
|
||||||
@@ -291,73 +299,100 @@ pub const Value = union(Type) {
|
|||||||
.Int => |i| {
|
.Int => |i| {
|
||||||
switch (i.bit_count) {
|
switch (i.bit_count) {
|
||||||
8 => output[0] = @bitCast(i.value.uint8),
|
8 => output[0] = @bitCast(i.value.uint8),
|
||||||
16 => std.mem.copyForwards(u8, output[0..], std.mem.asBytes(&i.value.uint16)),
|
16 => @memcpy(output[0..2], std.mem.asBytes(&i.value.uint16)),
|
||||||
32 => std.mem.copyForwards(u8, output[0..], std.mem.asBytes(&i.value.uint32)),
|
32 => @memcpy(output[0..4], std.mem.asBytes(&i.value.uint32)),
|
||||||
64 => std.mem.copyForwards(u8, output[0..], std.mem.asBytes(&i.value.uint64)),
|
64 => @memcpy(output[0..8], std.mem.asBytes(&i.value.uint64)),
|
||||||
else => return RuntimeError.InvalidValueType,
|
else => return RuntimeError.InvalidValueType,
|
||||||
}
|
}
|
||||||
return @divExact(i.bit_count, 8);
|
return @divExact(i.bit_count, 8);
|
||||||
},
|
},
|
||||||
.Float => |f| {
|
.Float => |f| {
|
||||||
switch (f.bit_count) {
|
switch (f.bit_count) {
|
||||||
16 => std.mem.copyForwards(u8, output[0..], std.mem.asBytes(&f.value.float16)),
|
16 => @memcpy(output[0..2], std.mem.asBytes(&f.value.float16)),
|
||||||
32 => std.mem.copyForwards(u8, output[0..], std.mem.asBytes(&f.value.float32)),
|
32 => @memcpy(output[0..4], std.mem.asBytes(&f.value.float32)),
|
||||||
64 => std.mem.copyForwards(u8, output[0..], std.mem.asBytes(&f.value.float64)),
|
64 => @memcpy(output[0..8], std.mem.asBytes(&f.value.float64)),
|
||||||
else => return RuntimeError.InvalidValueType,
|
else => return RuntimeError.InvalidValueType,
|
||||||
}
|
}
|
||||||
return @divExact(f.bit_count, 8);
|
return @divExact(f.bit_count, 8);
|
||||||
},
|
},
|
||||||
.Vector4f32 => |vec| {
|
.Vector4f32 => |vec| {
|
||||||
inline for (0..4) |i| {
|
inline for (0..4) |i| {
|
||||||
std.mem.copyForwards(u8, output[(i * 4)..], std.mem.asBytes(&vec[i]));
|
const start = i * 4;
|
||||||
|
const end = (i + 1) * 4;
|
||||||
|
if (start >= output.len or end > output.len) return RuntimeError.OutOfBounds;
|
||||||
|
@memcpy(output[start..end], std.mem.asBytes(&vec[i]));
|
||||||
}
|
}
|
||||||
return 4 * 4;
|
return 4 * 4;
|
||||||
},
|
},
|
||||||
.Vector3f32 => |vec| {
|
.Vector3f32 => |vec| {
|
||||||
inline for (0..3) |i| {
|
inline for (0..3) |i| {
|
||||||
std.mem.copyForwards(u8, output[(i * 4)..], std.mem.asBytes(&vec[i]));
|
const start = i * 4;
|
||||||
|
const end = (i + 1) * 4;
|
||||||
|
if (start >= output.len or end > output.len) return RuntimeError.OutOfBounds;
|
||||||
|
@memcpy(output[start..end], std.mem.asBytes(&vec[i]));
|
||||||
}
|
}
|
||||||
return 3 * 4;
|
return 3 * 4;
|
||||||
},
|
},
|
||||||
.Vector2f32 => |vec| {
|
.Vector2f32 => |vec| {
|
||||||
inline for (0..2) |i| {
|
inline for (0..2) |i| {
|
||||||
std.mem.copyForwards(u8, output[(i * 4)..], std.mem.asBytes(&vec[i]));
|
const start = i * 4;
|
||||||
|
const end = (i + 1) * 4;
|
||||||
|
if (start >= output.len or end > output.len) return RuntimeError.OutOfBounds;
|
||||||
|
@memcpy(output[start..end], std.mem.asBytes(&vec[i]));
|
||||||
}
|
}
|
||||||
return 2 * 4;
|
return 2 * 4;
|
||||||
},
|
},
|
||||||
.Vector4i32 => |vec| {
|
.Vector4i32 => |vec| {
|
||||||
inline for (0..4) |i| {
|
inline for (0..4) |i| {
|
||||||
std.mem.copyForwards(u8, output[(i * 4)..], std.mem.asBytes(&vec[i]));
|
const start = i * 4;
|
||||||
|
const end = (i + 1) * 4;
|
||||||
|
if (start >= output.len or end > output.len) return RuntimeError.OutOfBounds;
|
||||||
|
@memcpy(output[start..end], std.mem.asBytes(&vec[i]));
|
||||||
}
|
}
|
||||||
return 4 * 4;
|
return 4 * 4;
|
||||||
},
|
},
|
||||||
.Vector3i32 => |vec| {
|
.Vector3i32 => |vec| {
|
||||||
inline for (0..3) |i| {
|
inline for (0..3) |i| {
|
||||||
std.mem.copyForwards(u8, output[(i * 4)..], std.mem.asBytes(&vec[i]));
|
const start = i * 4;
|
||||||
|
const end = (i + 1) * 4;
|
||||||
|
if (start >= output.len or end > output.len) return RuntimeError.OutOfBounds;
|
||||||
|
@memcpy(output[start..end], std.mem.asBytes(&vec[i]));
|
||||||
}
|
}
|
||||||
return 3 * 4;
|
return 3 * 4;
|
||||||
},
|
},
|
||||||
.Vector2i32 => |vec| {
|
.Vector2i32 => |vec| {
|
||||||
inline for (0..2) |i| {
|
inline for (0..2) |i| {
|
||||||
std.mem.copyForwards(u8, output[(i * 4)..], std.mem.asBytes(&vec[i]));
|
const start = i * 4;
|
||||||
|
const end = (i + 1) * 4;
|
||||||
|
if (start >= output.len or end > output.len) return RuntimeError.OutOfBounds;
|
||||||
|
@memcpy(output[start..end], std.mem.asBytes(&vec[i]));
|
||||||
}
|
}
|
||||||
return 2 * 4;
|
return 2 * 4;
|
||||||
},
|
},
|
||||||
.Vector4u32 => |vec| {
|
.Vector4u32 => |vec| {
|
||||||
inline for (0..4) |i| {
|
inline for (0..4) |i| {
|
||||||
std.mem.copyForwards(u8, output[(i * 4)..], std.mem.asBytes(&vec[i]));
|
const start = i * 4;
|
||||||
|
const end = (i + 1) * 4;
|
||||||
|
if (start >= output.len or end > output.len) return RuntimeError.OutOfBounds;
|
||||||
|
@memcpy(output[start..end], std.mem.asBytes(&vec[i]));
|
||||||
}
|
}
|
||||||
return 4 * 4;
|
return 4 * 4;
|
||||||
},
|
},
|
||||||
.Vector3u32 => |vec| {
|
.Vector3u32 => |vec| {
|
||||||
inline for (0..3) |i| {
|
inline for (0..3) |i| {
|
||||||
std.mem.copyForwards(u8, output[(i * 4)..], std.mem.asBytes(&vec[i]));
|
const start = i * 4;
|
||||||
|
const end = (i + 1) * 4;
|
||||||
|
if (start >= output.len or end > output.len) return RuntimeError.OutOfBounds;
|
||||||
|
@memcpy(output[start..end], std.mem.asBytes(&vec[i]));
|
||||||
}
|
}
|
||||||
return 3 * 4;
|
return 3 * 4;
|
||||||
},
|
},
|
||||||
.Vector2u32 => |vec| {
|
.Vector2u32 => |vec| {
|
||||||
inline for (0..2) |i| {
|
inline for (0..2) |i| {
|
||||||
std.mem.copyForwards(u8, output[(i * 4)..], std.mem.asBytes(&vec[i]));
|
const start = i * 4;
|
||||||
|
const end = (i + 1) * 4;
|
||||||
|
if (start >= output.len or end > output.len) return RuntimeError.OutOfBounds;
|
||||||
|
@memcpy(output[start..end], std.mem.asBytes(&vec[i]));
|
||||||
}
|
}
|
||||||
return 2 * 4;
|
return 2 * 4;
|
||||||
},
|
},
|
||||||
@@ -377,18 +412,13 @@ pub const Value = union(Type) {
|
|||||||
return offset;
|
return offset;
|
||||||
},
|
},
|
||||||
.Structure => |s| {
|
.Structure => |s| {
|
||||||
var offset: usize = 0;
|
var end_offset: usize = 0;
|
||||||
for (s.values, 0..) |v, i| {
|
for (s.values, 0..) |v, i| {
|
||||||
const read_size = try v.read(output[offset..]);
|
const member_offset: usize = @intCast(s.offsets[i] orelse end_offset);
|
||||||
if (i + 1 < s.offsets.len) {
|
const read_size = try v.read(output[member_offset..]);
|
||||||
if (s.offsets[i + 1]) |o| {
|
end_offset = @max(end_offset, member_offset + read_size);
|
||||||
offset = o;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
offset += read_size;
|
|
||||||
}
|
}
|
||||||
return offset;
|
return end_offset;
|
||||||
},
|
},
|
||||||
else => return RuntimeError.InvalidValueType,
|
else => return RuntimeError.InvalidValueType,
|
||||||
}
|
}
|
||||||
@@ -408,18 +438,18 @@ pub const Value = union(Type) {
|
|||||||
.Int => |*i| {
|
.Int => |*i| {
|
||||||
switch (i.bit_count) {
|
switch (i.bit_count) {
|
||||||
8 => i.value.uint8 = @bitCast(input[0]),
|
8 => i.value.uint8 = @bitCast(input[0]),
|
||||||
16 => std.mem.copyForwards(u8, std.mem.asBytes(&i.value.uint16), input[0..2]),
|
16 => @memcpy(std.mem.asBytes(&i.value.uint16), input[0..2]),
|
||||||
32 => std.mem.copyForwards(u8, std.mem.asBytes(&i.value.uint32), input[0..4]),
|
32 => @memcpy(std.mem.asBytes(&i.value.uint32), input[0..4]),
|
||||||
64 => std.mem.copyForwards(u8, std.mem.asBytes(&i.value.uint64), input[0..8]),
|
64 => @memcpy(std.mem.asBytes(&i.value.uint64), input[0..8]),
|
||||||
else => return RuntimeError.InvalidValueType,
|
else => return RuntimeError.InvalidValueType,
|
||||||
}
|
}
|
||||||
return @divExact(i.bit_count, 8);
|
return @divExact(i.bit_count, 8);
|
||||||
},
|
},
|
||||||
.Float => |*f| {
|
.Float => |*f| {
|
||||||
switch (f.bit_count) {
|
switch (f.bit_count) {
|
||||||
16 => std.mem.copyForwards(u8, std.mem.asBytes(&f.value.float16), input[0..2]),
|
16 => @memcpy(std.mem.asBytes(&f.value.float16), input[0..2]),
|
||||||
32 => std.mem.copyForwards(u8, std.mem.asBytes(&f.value.float32), input[0..4]),
|
32 => @memcpy(std.mem.asBytes(&f.value.float32), input[0..4]),
|
||||||
64 => std.mem.copyForwards(u8, std.mem.asBytes(&f.value.float64), input[0..8]),
|
64 => @memcpy(std.mem.asBytes(&f.value.float64), input[0..8]),
|
||||||
else => return RuntimeError.InvalidValueType,
|
else => return RuntimeError.InvalidValueType,
|
||||||
}
|
}
|
||||||
return @divExact(f.bit_count, 8);
|
return @divExact(f.bit_count, 8);
|
||||||
@@ -429,7 +459,7 @@ pub const Value = union(Type) {
|
|||||||
const start = i * 4;
|
const start = i * 4;
|
||||||
const end = (i + 1) * 4;
|
const end = (i + 1) * 4;
|
||||||
if (start >= input.len or end > input.len) return RuntimeError.OutOfBounds;
|
if (start >= input.len or end > input.len) return RuntimeError.OutOfBounds;
|
||||||
std.mem.copyForwards(u8, std.mem.asBytes(&vec[i]), input[start..end]);
|
@memcpy(std.mem.asBytes(&vec[i]), input[start..end]);
|
||||||
}
|
}
|
||||||
return 4 * 4;
|
return 4 * 4;
|
||||||
},
|
},
|
||||||
@@ -438,7 +468,7 @@ pub const Value = union(Type) {
|
|||||||
const start = i * 4;
|
const start = i * 4;
|
||||||
const end = (i + 1) * 4;
|
const end = (i + 1) * 4;
|
||||||
if (start >= input.len or end > input.len) return RuntimeError.OutOfBounds;
|
if (start >= input.len or end > input.len) return RuntimeError.OutOfBounds;
|
||||||
std.mem.copyForwards(u8, std.mem.asBytes(&vec[i]), input[start..end]);
|
@memcpy(std.mem.asBytes(&vec[i]), input[start..end]);
|
||||||
}
|
}
|
||||||
return 3 * 4;
|
return 3 * 4;
|
||||||
},
|
},
|
||||||
@@ -447,7 +477,7 @@ pub const Value = union(Type) {
|
|||||||
const start = i * 4;
|
const start = i * 4;
|
||||||
const end = (i + 1) * 4;
|
const end = (i + 1) * 4;
|
||||||
if (start >= input.len or end > input.len) return RuntimeError.OutOfBounds;
|
if (start >= input.len or end > input.len) return RuntimeError.OutOfBounds;
|
||||||
std.mem.copyForwards(u8, std.mem.asBytes(&vec[i]), input[start..end]);
|
@memcpy(std.mem.asBytes(&vec[i]), input[start..end]);
|
||||||
}
|
}
|
||||||
return 2 * 4;
|
return 2 * 4;
|
||||||
},
|
},
|
||||||
@@ -456,7 +486,7 @@ pub const Value = union(Type) {
|
|||||||
const start = i * 4;
|
const start = i * 4;
|
||||||
const end = (i + 1) * 4;
|
const end = (i + 1) * 4;
|
||||||
if (start >= input.len or end > input.len) return RuntimeError.OutOfBounds;
|
if (start >= input.len or end > input.len) return RuntimeError.OutOfBounds;
|
||||||
std.mem.copyForwards(u8, std.mem.asBytes(&vec[i]), input[start..end]);
|
@memcpy(std.mem.asBytes(&vec[i]), input[start..end]);
|
||||||
}
|
}
|
||||||
return 4 * 4;
|
return 4 * 4;
|
||||||
},
|
},
|
||||||
@@ -465,7 +495,7 @@ pub const Value = union(Type) {
|
|||||||
const start = i * 4;
|
const start = i * 4;
|
||||||
const end = (i + 1) * 4;
|
const end = (i + 1) * 4;
|
||||||
if (start >= input.len or end > input.len) return RuntimeError.OutOfBounds;
|
if (start >= input.len or end > input.len) return RuntimeError.OutOfBounds;
|
||||||
std.mem.copyForwards(u8, std.mem.asBytes(&vec[i]), input[start..end]);
|
@memcpy(std.mem.asBytes(&vec[i]), input[start..end]);
|
||||||
}
|
}
|
||||||
return 3 * 4;
|
return 3 * 4;
|
||||||
},
|
},
|
||||||
@@ -474,7 +504,7 @@ pub const Value = union(Type) {
|
|||||||
const start = i * 4;
|
const start = i * 4;
|
||||||
const end = (i + 1) * 4;
|
const end = (i + 1) * 4;
|
||||||
if (start >= input.len or end > input.len) return RuntimeError.OutOfBounds;
|
if (start >= input.len or end > input.len) return RuntimeError.OutOfBounds;
|
||||||
std.mem.copyForwards(u8, std.mem.asBytes(&vec[i]), input[start..end]);
|
@memcpy(std.mem.asBytes(&vec[i]), input[start..end]);
|
||||||
}
|
}
|
||||||
return 2 * 4;
|
return 2 * 4;
|
||||||
},
|
},
|
||||||
@@ -483,7 +513,7 @@ pub const Value = union(Type) {
|
|||||||
const start = i * 4;
|
const start = i * 4;
|
||||||
const end = (i + 1) * 4;
|
const end = (i + 1) * 4;
|
||||||
if (start >= input.len or end > input.len) return RuntimeError.OutOfBounds;
|
if (start >= input.len or end > input.len) return RuntimeError.OutOfBounds;
|
||||||
std.mem.copyForwards(u8, std.mem.asBytes(&vec[i]), input[start..end]);
|
@memcpy(std.mem.asBytes(&vec[i]), input[start..end]);
|
||||||
}
|
}
|
||||||
return 4 * 4;
|
return 4 * 4;
|
||||||
},
|
},
|
||||||
@@ -492,7 +522,7 @@ pub const Value = union(Type) {
|
|||||||
const start = i * 4;
|
const start = i * 4;
|
||||||
const end = (i + 1) * 4;
|
const end = (i + 1) * 4;
|
||||||
if (start >= input.len or end > input.len) return RuntimeError.OutOfBounds;
|
if (start >= input.len or end > input.len) return RuntimeError.OutOfBounds;
|
||||||
std.mem.copyForwards(u8, std.mem.asBytes(&vec[i]), input[start..end]);
|
@memcpy(std.mem.asBytes(&vec[i]), input[start..end]);
|
||||||
}
|
}
|
||||||
return 3 * 4;
|
return 3 * 4;
|
||||||
},
|
},
|
||||||
@@ -501,7 +531,7 @@ pub const Value = union(Type) {
|
|||||||
const start = i * 4;
|
const start = i * 4;
|
||||||
const end = (i + 1) * 4;
|
const end = (i + 1) * 4;
|
||||||
if (start >= input.len or end > input.len) return RuntimeError.OutOfBounds;
|
if (start >= input.len or end > input.len) return RuntimeError.OutOfBounds;
|
||||||
std.mem.copyForwards(u8, std.mem.asBytes(&vec[i]), input[start..end]);
|
@memcpy(std.mem.asBytes(&vec[i]), input[start..end]);
|
||||||
}
|
}
|
||||||
return 2 * 4;
|
return 2 * 4;
|
||||||
},
|
},
|
||||||
@@ -521,18 +551,13 @@ pub const Value = union(Type) {
|
|||||||
return offset;
|
return offset;
|
||||||
},
|
},
|
||||||
.Structure => |s| {
|
.Structure => |s| {
|
||||||
var offset: usize = 0;
|
var end_offset: usize = 0;
|
||||||
for (s.values, 0..) |*v, i| {
|
for (s.values, 0..) |*v, i| {
|
||||||
const write_size = try v.write(input[offset..]);
|
const member_offset: usize = @intCast(s.offsets[i] orelse end_offset);
|
||||||
if (i + 1 < s.offsets.len) {
|
const write_size = try v.write(input[member_offset..]);
|
||||||
if (s.offsets[i + 1]) |o| {
|
end_offset = @max(end_offset, member_offset + write_size);
|
||||||
offset = o;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
offset += write_size;
|
|
||||||
}
|
}
|
||||||
return offset;
|
return end_offset;
|
||||||
},
|
},
|
||||||
.RuntimeArray => |*arr| arr.data = input[0..],
|
.RuntimeArray => |*arr| arr.data = input[0..],
|
||||||
.Image => |*img| img.driver_image = @ptrFromInt(std.mem.bytesToValue(usize, input[0..])),
|
.Image => |*img| img.driver_image = @ptrFromInt(std.mem.bytesToValue(usize, input[0..])),
|
||||||
@@ -560,13 +585,8 @@ pub const Value = union(Type) {
|
|||||||
.Structure => |s| blk: {
|
.Structure => |s| blk: {
|
||||||
var size: usize = 0;
|
var size: usize = 0;
|
||||||
for (s.values, 0..) |v, i| {
|
for (s.values, 0..) |v, i| {
|
||||||
if (i + 1 < s.offsets.len) {
|
const member_offset: usize = @intCast(s.offsets[i] orelse size);
|
||||||
if (s.offsets[i + 1]) |o| {
|
size = @max(size, member_offset + try v.getPlainMemorySize());
|
||||||
size = o;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
size += try v.getPlainMemorySize();
|
|
||||||
}
|
}
|
||||||
break :blk size;
|
break :blk size;
|
||||||
},
|
},
|
||||||
@@ -617,12 +637,27 @@ pub const Value = union(Type) {
|
|||||||
switch (p.ptr) {
|
switch (p.ptr) {
|
||||||
.common => |ptr| {
|
.common => |ptr| {
|
||||||
_ = try ptr.read(window);
|
_ = try ptr.read(window);
|
||||||
ptr.deinit(allocator);
|
|
||||||
if (p.is_owner_of_uniform_slice)
|
|
||||||
allocator.destroy(ptr);
|
|
||||||
},
|
},
|
||||||
else => {},
|
.f32_ptr => |ptr| {
|
||||||
|
if (window.len < @sizeOf(f32)) return RuntimeError.OutOfBounds;
|
||||||
|
std.mem.copyForwards(u8, window[0..@sizeOf(f32)], std.mem.asBytes(ptr));
|
||||||
|
},
|
||||||
|
.i32_ptr => |ptr| {
|
||||||
|
if (window.len < @sizeOf(i32)) return RuntimeError.OutOfBounds;
|
||||||
|
std.mem.copyForwards(u8, window[0..@sizeOf(i32)], std.mem.asBytes(ptr));
|
||||||
|
},
|
||||||
|
.u32_ptr => |ptr| {
|
||||||
|
if (window.len < @sizeOf(u32)) return RuntimeError.OutOfBounds;
|
||||||
|
std.mem.copyForwards(u8, window[0..@sizeOf(u32)], std.mem.asBytes(ptr));
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (p.uniform_backing_value) |backing| {
|
||||||
|
backing.deinit(allocator);
|
||||||
|
allocator.destroy(backing);
|
||||||
|
p.uniform_backing_value = null;
|
||||||
|
}
|
||||||
|
|
||||||
p.uniform_slice_window = null;
|
p.uniform_slice_window = null;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -658,28 +693,64 @@ pub const Value = union(Type) {
|
|||||||
.Vector => |lanes| (try getPrimitiveField(T, bits, &lanes[lane_index])).*,
|
.Vector => |lanes| (try getPrimitiveField(T, bits, &lanes[lane_index])).*,
|
||||||
|
|
||||||
.Vector2i32 => |*vec| switch (lane_index) {
|
.Vector2i32 => |*vec| switch (lane_index) {
|
||||||
inline 0...1 => |i| if (bits == 32) @as(TT, @bitCast(vec[i])) else return RuntimeError.InvalidSpirV,
|
inline 0...1 => |i| blk: {
|
||||||
|
if (bits == 32) {
|
||||||
|
break :blk @as(TT, @bitCast(vec[i]));
|
||||||
|
} else {
|
||||||
|
return RuntimeError.InvalidSpirV;
|
||||||
|
}
|
||||||
|
},
|
||||||
else => return RuntimeError.InvalidSpirV,
|
else => return RuntimeError.InvalidSpirV,
|
||||||
},
|
},
|
||||||
.Vector3i32 => |*vec| switch (lane_index) {
|
.Vector3i32 => |*vec| switch (lane_index) {
|
||||||
inline 0...2 => |i| if (bits == 32) @as(TT, @bitCast(vec[i])) else return RuntimeError.InvalidSpirV,
|
inline 0...2 => |i| blk: {
|
||||||
|
if (bits == 32) {
|
||||||
|
break :blk @as(TT, @bitCast(vec[i]));
|
||||||
|
} else {
|
||||||
|
return RuntimeError.InvalidSpirV;
|
||||||
|
}
|
||||||
|
},
|
||||||
else => return RuntimeError.InvalidSpirV,
|
else => return RuntimeError.InvalidSpirV,
|
||||||
},
|
},
|
||||||
.Vector4i32 => |*vec| switch (lane_index) {
|
.Vector4i32 => |*vec| switch (lane_index) {
|
||||||
inline 0...3 => |i| if (bits == 32) @as(TT, @bitCast(vec[i])) else return RuntimeError.InvalidSpirV,
|
inline 0...3 => |i| blk: {
|
||||||
|
if (bits == 32) {
|
||||||
|
break :blk @as(TT, @bitCast(vec[i]));
|
||||||
|
} else {
|
||||||
|
return RuntimeError.InvalidSpirV;
|
||||||
|
}
|
||||||
|
},
|
||||||
else => return RuntimeError.InvalidSpirV,
|
else => return RuntimeError.InvalidSpirV,
|
||||||
},
|
},
|
||||||
|
|
||||||
.Vector2u32 => |*vec| switch (lane_index) {
|
.Vector2u32 => |*vec| switch (lane_index) {
|
||||||
inline 0...1 => |i| if (bits == 32) @as(TT, @bitCast(vec[i])) else return RuntimeError.InvalidSpirV,
|
inline 0...1 => |i| blk: {
|
||||||
|
if (bits == 32) {
|
||||||
|
break :blk @as(TT, @bitCast(vec[i]));
|
||||||
|
} else {
|
||||||
|
return RuntimeError.InvalidSpirV;
|
||||||
|
}
|
||||||
|
},
|
||||||
else => return RuntimeError.InvalidSpirV,
|
else => return RuntimeError.InvalidSpirV,
|
||||||
},
|
},
|
||||||
.Vector3u32 => |*vec| switch (lane_index) {
|
.Vector3u32 => |*vec| switch (lane_index) {
|
||||||
inline 0...2 => |i| if (bits == 32) @as(TT, @bitCast(vec[i])) else return RuntimeError.InvalidSpirV,
|
inline 0...2 => |i| blk: {
|
||||||
|
if (bits == 32) {
|
||||||
|
break :blk @as(TT, @bitCast(vec[i]));
|
||||||
|
} else {
|
||||||
|
return RuntimeError.InvalidSpirV;
|
||||||
|
}
|
||||||
|
},
|
||||||
else => return RuntimeError.InvalidSpirV,
|
else => return RuntimeError.InvalidSpirV,
|
||||||
},
|
},
|
||||||
.Vector4u32 => |*vec| switch (lane_index) {
|
.Vector4u32 => |*vec| switch (lane_index) {
|
||||||
inline 0...3 => |i| if (bits == 32) @as(TT, @bitCast(vec[i])) else return RuntimeError.InvalidSpirV,
|
inline 0...3 => |i| blk: {
|
||||||
|
if (bits == 32) {
|
||||||
|
break :blk @as(TT, @bitCast(vec[i]));
|
||||||
|
} else {
|
||||||
|
return RuntimeError.InvalidSpirV;
|
||||||
|
}
|
||||||
|
},
|
||||||
else => return RuntimeError.InvalidSpirV,
|
else => return RuntimeError.InvalidSpirV,
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -694,28 +765,52 @@ pub const Value = union(Type) {
|
|||||||
.Vector => |lanes| try setScalarLaneValue(T, bits, &lanes[lane_index], value),
|
.Vector => |lanes| try setScalarLaneValue(T, bits, &lanes[lane_index], value),
|
||||||
|
|
||||||
.Vector2i32 => |*vec| switch (lane_index) {
|
.Vector2i32 => |*vec| switch (lane_index) {
|
||||||
inline 0...1 => |i| vec[i] = if (bits == 32) @bitCast(value) else return RuntimeError.InvalidSpirV,
|
inline 0...1 => |i| if (bits == 32) {
|
||||||
|
vec[i] = @bitCast(value);
|
||||||
|
} else {
|
||||||
|
return RuntimeError.InvalidSpirV;
|
||||||
|
},
|
||||||
else => return RuntimeError.InvalidSpirV,
|
else => return RuntimeError.InvalidSpirV,
|
||||||
},
|
},
|
||||||
.Vector3i32 => |*vec| switch (lane_index) {
|
.Vector3i32 => |*vec| switch (lane_index) {
|
||||||
inline 0...2 => |i| vec[i] = if (bits == 32) @bitCast(value) else return RuntimeError.InvalidSpirV,
|
inline 0...2 => |i| if (bits == 32) {
|
||||||
|
vec[i] = @bitCast(value);
|
||||||
|
} else {
|
||||||
|
return RuntimeError.InvalidSpirV;
|
||||||
|
},
|
||||||
else => return RuntimeError.InvalidSpirV,
|
else => return RuntimeError.InvalidSpirV,
|
||||||
},
|
},
|
||||||
.Vector4i32 => |*vec| switch (lane_index) {
|
.Vector4i32 => |*vec| switch (lane_index) {
|
||||||
inline 0...3 => |i| vec[i] = if (bits == 32) @bitCast(value) else return RuntimeError.InvalidSpirV,
|
inline 0...3 => |i| if (bits == 32) {
|
||||||
|
vec[i] = @bitCast(value);
|
||||||
|
} else {
|
||||||
|
return RuntimeError.InvalidSpirV;
|
||||||
|
},
|
||||||
else => return RuntimeError.InvalidSpirV,
|
else => return RuntimeError.InvalidSpirV,
|
||||||
},
|
},
|
||||||
|
|
||||||
.Vector2u32 => |*vec| switch (lane_index) {
|
.Vector2u32 => |*vec| switch (lane_index) {
|
||||||
inline 0...1 => |i| vec[i] = if (bits == 32) @bitCast(value) else return RuntimeError.InvalidSpirV,
|
inline 0...1 => |i| if (bits == 32) {
|
||||||
|
vec[i] = @bitCast(value);
|
||||||
|
} else {
|
||||||
|
return RuntimeError.InvalidSpirV;
|
||||||
|
},
|
||||||
else => return RuntimeError.InvalidSpirV,
|
else => return RuntimeError.InvalidSpirV,
|
||||||
},
|
},
|
||||||
.Vector3u32 => |*vec| switch (lane_index) {
|
.Vector3u32 => |*vec| switch (lane_index) {
|
||||||
inline 0...2 => |i| vec[i] = if (bits == 32) @bitCast(value) else return RuntimeError.InvalidSpirV,
|
inline 0...2 => |i| if (bits == 32) {
|
||||||
|
vec[i] = @bitCast(value);
|
||||||
|
} else {
|
||||||
|
return RuntimeError.InvalidSpirV;
|
||||||
|
},
|
||||||
else => return RuntimeError.InvalidSpirV,
|
else => return RuntimeError.InvalidSpirV,
|
||||||
},
|
},
|
||||||
.Vector4u32 => |*vec| switch (lane_index) {
|
.Vector4u32 => |*vec| switch (lane_index) {
|
||||||
inline 0...3 => |i| vec[i] = if (bits == 32) @bitCast(value) else return RuntimeError.InvalidSpirV,
|
inline 0...3 => |i| if (bits == 32) {
|
||||||
|
vec[i] = @bitCast(value);
|
||||||
|
} else {
|
||||||
|
return RuntimeError.InvalidSpirV;
|
||||||
|
},
|
||||||
else => return RuntimeError.InvalidSpirV,
|
else => return RuntimeError.InvalidSpirV,
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -790,8 +885,8 @@ pub const Value = union(Type) {
|
|||||||
pub fn resolveLaneBitWidth(self: *const Self) RuntimeError!SpvWord {
|
pub fn resolveLaneBitWidth(self: *const Self) RuntimeError!SpvWord {
|
||||||
return switch (self.*) {
|
return switch (self.*) {
|
||||||
.Bool => 8,
|
.Bool => 8,
|
||||||
.Float => |f| f.bit_length,
|
.Float => |f| @intCast(f.bit_count),
|
||||||
.Int => |i| i.bit_length,
|
.Int => |i| @intCast(i.bit_count),
|
||||||
.Vector => |v| v[0].resolveLaneBitWidth(),
|
.Vector => |v| v[0].resolveLaneBitWidth(),
|
||||||
.Vector4f32,
|
.Vector4f32,
|
||||||
.Vector3f32,
|
.Vector3f32,
|
||||||
|
|||||||
+261
-68
@@ -324,6 +324,7 @@ pub fn initRuntimeDispatcher() void {
|
|||||||
runtime_dispatcher[@intFromEnum(spv.SpvOp.VectorTimesMatrix)] = MathEngine(.Float, .VectorTimesMatrix, false).op; // TODO
|
runtime_dispatcher[@intFromEnum(spv.SpvOp.VectorTimesMatrix)] = MathEngine(.Float, .VectorTimesMatrix, false).op; // TODO
|
||||||
runtime_dispatcher[@intFromEnum(spv.SpvOp.VectorTimesScalar)] = MathEngine(.Float, .VectorTimesScalar, false).op;
|
runtime_dispatcher[@intFromEnum(spv.SpvOp.VectorTimesScalar)] = MathEngine(.Float, .VectorTimesScalar, false).op;
|
||||||
runtime_dispatcher[@intFromEnum(spv.SpvOp.SMulExtended)] = opSMulExtended;
|
runtime_dispatcher[@intFromEnum(spv.SpvOp.SMulExtended)] = opSMulExtended;
|
||||||
|
runtime_dispatcher[@intFromEnum(spv.SpvOp.UMulExtended)] = opUMulExtended;
|
||||||
runtime_dispatcher[@intFromEnum(spv.SpvOp.ImageRead)] = opImageRead;
|
runtime_dispatcher[@intFromEnum(spv.SpvOp.ImageRead)] = opImageRead;
|
||||||
runtime_dispatcher[@intFromEnum(spv.SpvOp.ImageWrite)] = opImageWrite;
|
runtime_dispatcher[@intFromEnum(spv.SpvOp.ImageWrite)] = opImageWrite;
|
||||||
// zig fmt: on
|
// zig fmt: on
|
||||||
@@ -1303,9 +1304,6 @@ fn opAccessChain(allocator: std.mem.Allocator, word_count: SpvWord, rt: *Runtime
|
|||||||
const base = &rt.results[base_id];
|
const base = &rt.results[base_id];
|
||||||
var value_ptr = try base.getValue();
|
var value_ptr = try base.getValue();
|
||||||
|
|
||||||
var arena = std.heap.ArenaAllocator.init(allocator);
|
|
||||||
defer arena.deinit();
|
|
||||||
|
|
||||||
const index_count: usize = @intCast(word_count - 3);
|
const index_count: usize = @intCast(word_count - 3);
|
||||||
|
|
||||||
const indexes, const free_responsability = blk: {
|
const indexes, const free_responsability = blk: {
|
||||||
@@ -1331,11 +1329,38 @@ fn opAccessChain(allocator: std.mem.Allocator, word_count: SpvWord, rt: *Runtime
|
|||||||
.base = base_id,
|
.base = base_id,
|
||||||
.indexes = indexes,
|
.indexes = indexes,
|
||||||
.value = blk: {
|
.value = blk: {
|
||||||
var is_owner_of_uniform_slice = false;
|
const helpers = struct {
|
||||||
|
fn advanceWindow(window: ?[]u8, offset: usize) RuntimeError!?[]u8 {
|
||||||
|
if (window) |w| {
|
||||||
|
if (offset > w.len) return RuntimeError.OutOfBounds;
|
||||||
|
return w[offset..];
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn advanceWindowSized(window: ?[]u8, offset: usize, size: usize) RuntimeError!?[]u8 {
|
||||||
|
if (window) |w| {
|
||||||
|
if (offset > w.len or size > w.len - offset) return RuntimeError.OutOfBounds;
|
||||||
|
return w[offset .. offset + size];
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
var uniform_slice_window: ?[]u8 = null;
|
var uniform_slice_window: ?[]u8 = null;
|
||||||
|
var uniform_backing_value: ?*Value = null;
|
||||||
|
|
||||||
|
if (std.meta.activeTag(value_ptr.*) == .Pointer) {
|
||||||
|
const ptr = value_ptr.Pointer;
|
||||||
|
uniform_slice_window = ptr.uniform_slice_window;
|
||||||
|
uniform_backing_value = ptr.uniform_backing_value;
|
||||||
|
switch (ptr.ptr) {
|
||||||
|
.common => |common| value_ptr = common,
|
||||||
|
else => return RuntimeError.InvalidSpirV,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (0..index_count) |index| {
|
for (0..index_count) |index| {
|
||||||
const is_last = (index == index_count - 1);
|
|
||||||
const index_id = try rt.it.next();
|
const index_id = try rt.it.next();
|
||||||
indexes[index] = index_id;
|
indexes[index] = index_id;
|
||||||
const member = &rt.results[index_id];
|
const member = &rt.results[index_id];
|
||||||
@@ -1348,63 +1373,135 @@ fn opAccessChain(allocator: std.mem.Allocator, word_count: SpvWord, rt: *Runtime
|
|||||||
switch (member_value.*) {
|
switch (member_value.*) {
|
||||||
.Int => |i| {
|
.Int => |i| {
|
||||||
if (std.meta.activeTag(value_ptr.*) == .Pointer) {
|
if (std.meta.activeTag(value_ptr.*) == .Pointer) {
|
||||||
value_ptr = value_ptr.Pointer.ptr.common; // Don't know if I should check for specialized pointers
|
const ptr = value_ptr.Pointer;
|
||||||
|
uniform_slice_window = ptr.uniform_slice_window;
|
||||||
|
uniform_backing_value = ptr.uniform_backing_value;
|
||||||
|
switch (ptr.ptr) {
|
||||||
|
.common => |common| value_ptr = common,
|
||||||
|
else => return RuntimeError.InvalidSpirV,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const component_index: usize = @intCast(i.value.uint32);
|
||||||
|
|
||||||
switch (value_ptr.*) {
|
switch (value_ptr.*) {
|
||||||
.Vector, .Matrix => |v| {
|
.Vector, .Matrix => |v| {
|
||||||
if (i.value.uint32 >= v.len) return RuntimeError.OutOfBounds;
|
if (component_index >= v.len) return RuntimeError.OutOfBounds;
|
||||||
value_ptr = &v[i.value.uint32];
|
var offset: usize = 0;
|
||||||
|
for (v[0..component_index]) |*element| {
|
||||||
|
offset += try element.getPlainMemorySize();
|
||||||
|
}
|
||||||
|
uniform_slice_window = try helpers.advanceWindow(uniform_slice_window, offset);
|
||||||
|
value_ptr = &v[component_index];
|
||||||
},
|
},
|
||||||
.Array => |a| {
|
.Array => |a| {
|
||||||
if (i.value.uint32 >= a.values.len) return RuntimeError.OutOfBounds;
|
if (component_index >= a.values.len) return RuntimeError.OutOfBounds;
|
||||||
value_ptr = &a.values[i.value.uint32];
|
uniform_slice_window = try helpers.advanceWindow(uniform_slice_window, component_index * a.stride);
|
||||||
|
value_ptr = &a.values[component_index];
|
||||||
},
|
},
|
||||||
.Structure => |s| {
|
.Structure => |s| {
|
||||||
if (i.value.uint32 >= s.values.len) return RuntimeError.OutOfBounds;
|
if (component_index >= s.values.len) return RuntimeError.OutOfBounds;
|
||||||
value_ptr = &s.values[i.value.uint32];
|
var end_offset: usize = 0;
|
||||||
|
for (s.values[0..component_index], 0..) |*field, field_index| {
|
||||||
|
const field_offset: usize = @intCast(s.offsets[field_index] orelse end_offset);
|
||||||
|
end_offset = @max(end_offset, field_offset + try field.getPlainMemorySize());
|
||||||
|
}
|
||||||
|
const member_offset: usize = @intCast(s.offsets[component_index] orelse end_offset);
|
||||||
|
uniform_slice_window = try helpers.advanceWindow(uniform_slice_window, member_offset);
|
||||||
|
value_ptr = &s.values[component_index];
|
||||||
},
|
},
|
||||||
.RuntimeArray => |*arr| {
|
.RuntimeArray => |*arr| {
|
||||||
if (i.value.uint32 >= arr.getLen()) return RuntimeError.OutOfBounds;
|
if (component_index >= arr.getLen()) return RuntimeError.OutOfBounds;
|
||||||
value_ptr = try arr.createValueFromIndex(if (is_last) allocator else arena.allocator(), rt.results, i.value.uint32);
|
|
||||||
if (is_last)
|
const element_offset = arr.getOffsetOfIndex(component_index);
|
||||||
is_owner_of_uniform_slice = true;
|
if (element_offset > arr.data.len or arr.stride > arr.data.len - element_offset)
|
||||||
uniform_slice_window = arr.data[arr.getOffsetOfIndex(i.value.uint32)..];
|
return RuntimeError.OutOfBounds;
|
||||||
|
|
||||||
|
const backing = try arr.createValueFromIndex(allocator, rt.results, component_index);
|
||||||
|
errdefer {
|
||||||
|
backing.deinit(allocator);
|
||||||
|
allocator.destroy(backing);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (uniform_backing_value) |old_backing| {
|
||||||
|
old_backing.deinit(allocator);
|
||||||
|
allocator.destroy(old_backing);
|
||||||
|
}
|
||||||
|
|
||||||
|
value_ptr = backing;
|
||||||
|
uniform_backing_value = backing;
|
||||||
|
uniform_slice_window = arr.data[element_offset .. element_offset + arr.stride];
|
||||||
},
|
},
|
||||||
.Vector4f32 => |*v| switch (i.value.uint32) {
|
.Vector4f32 => |*v| switch (component_index) {
|
||||||
inline 0...3 => |idx| break :blk .{ .Pointer = .{ .ptr = .{ .f32_ptr = &v[idx] } } },
|
inline 0...3 => |idx| break :blk .{ .Pointer = .{
|
||||||
|
.ptr = .{ .f32_ptr = &v[idx] },
|
||||||
|
.uniform_slice_window = try helpers.advanceWindowSized(uniform_slice_window, idx * @sizeOf(f32), @sizeOf(f32)),
|
||||||
|
.uniform_backing_value = uniform_backing_value,
|
||||||
|
} },
|
||||||
else => return RuntimeError.InvalidSpirV,
|
else => return RuntimeError.InvalidSpirV,
|
||||||
},
|
},
|
||||||
.Vector3f32 => |*v| switch (i.value.uint32) {
|
.Vector3f32 => |*v| switch (component_index) {
|
||||||
inline 0...2 => |idx| break :blk .{ .Pointer = .{ .ptr = .{ .f32_ptr = &v[idx] } } },
|
inline 0...2 => |idx| break :blk .{ .Pointer = .{
|
||||||
|
.ptr = .{ .f32_ptr = &v[idx] },
|
||||||
|
.uniform_slice_window = try helpers.advanceWindowSized(uniform_slice_window, idx * @sizeOf(f32), @sizeOf(f32)),
|
||||||
|
.uniform_backing_value = uniform_backing_value,
|
||||||
|
} },
|
||||||
else => return RuntimeError.InvalidSpirV,
|
else => return RuntimeError.InvalidSpirV,
|
||||||
},
|
},
|
||||||
.Vector2f32 => |*v| switch (i.value.uint32) {
|
.Vector2f32 => |*v| switch (component_index) {
|
||||||
inline 0...1 => |idx| break :blk .{ .Pointer = .{ .ptr = .{ .f32_ptr = &v[idx] } } },
|
inline 0...1 => |idx| break :blk .{ .Pointer = .{
|
||||||
|
.ptr = .{ .f32_ptr = &v[idx] },
|
||||||
|
.uniform_slice_window = try helpers.advanceWindowSized(uniform_slice_window, idx * @sizeOf(f32), @sizeOf(f32)),
|
||||||
|
.uniform_backing_value = uniform_backing_value,
|
||||||
|
} },
|
||||||
else => return RuntimeError.InvalidSpirV,
|
else => return RuntimeError.InvalidSpirV,
|
||||||
},
|
},
|
||||||
.Vector4i32 => |*v| switch (i.value.uint32) {
|
.Vector4i32 => |*v| switch (component_index) {
|
||||||
inline 0...3 => |idx| break :blk .{ .Pointer = .{ .ptr = .{ .i32_ptr = &v[idx] } } },
|
inline 0...3 => |idx| break :blk .{ .Pointer = .{
|
||||||
|
.ptr = .{ .i32_ptr = &v[idx] },
|
||||||
|
.uniform_slice_window = try helpers.advanceWindowSized(uniform_slice_window, idx * @sizeOf(i32), @sizeOf(i32)),
|
||||||
|
.uniform_backing_value = uniform_backing_value,
|
||||||
|
} },
|
||||||
else => return RuntimeError.InvalidSpirV,
|
else => return RuntimeError.InvalidSpirV,
|
||||||
},
|
},
|
||||||
.Vector3i32 => |*v| switch (i.value.uint32) {
|
.Vector3i32 => |*v| switch (component_index) {
|
||||||
inline 0...2 => |idx| break :blk .{ .Pointer = .{ .ptr = .{ .i32_ptr = &v[idx] } } },
|
inline 0...2 => |idx| break :blk .{ .Pointer = .{
|
||||||
|
.ptr = .{ .i32_ptr = &v[idx] },
|
||||||
|
.uniform_slice_window = try helpers.advanceWindowSized(uniform_slice_window, idx * @sizeOf(i32), @sizeOf(i32)),
|
||||||
|
.uniform_backing_value = uniform_backing_value,
|
||||||
|
} },
|
||||||
else => return RuntimeError.InvalidSpirV,
|
else => return RuntimeError.InvalidSpirV,
|
||||||
},
|
},
|
||||||
.Vector2i32 => |*v| switch (i.value.uint32) {
|
.Vector2i32 => |*v| switch (component_index) {
|
||||||
inline 0...1 => |idx| break :blk .{ .Pointer = .{ .ptr = .{ .i32_ptr = &v[idx] } } },
|
inline 0...1 => |idx| break :blk .{ .Pointer = .{
|
||||||
|
.ptr = .{ .i32_ptr = &v[idx] },
|
||||||
|
.uniform_slice_window = try helpers.advanceWindowSized(uniform_slice_window, idx * @sizeOf(i32), @sizeOf(i32)),
|
||||||
|
.uniform_backing_value = uniform_backing_value,
|
||||||
|
} },
|
||||||
else => return RuntimeError.InvalidSpirV,
|
else => return RuntimeError.InvalidSpirV,
|
||||||
},
|
},
|
||||||
.Vector4u32 => |*v| switch (i.value.uint32) {
|
.Vector4u32 => |*v| switch (component_index) {
|
||||||
inline 0...3 => |idx| break :blk .{ .Pointer = .{ .ptr = .{ .u32_ptr = &v[idx] } } },
|
inline 0...3 => |idx| break :blk .{ .Pointer = .{
|
||||||
|
.ptr = .{ .u32_ptr = &v[idx] },
|
||||||
|
.uniform_slice_window = try helpers.advanceWindowSized(uniform_slice_window, idx * @sizeOf(u32), @sizeOf(u32)),
|
||||||
|
.uniform_backing_value = uniform_backing_value,
|
||||||
|
} },
|
||||||
else => return RuntimeError.InvalidSpirV,
|
else => return RuntimeError.InvalidSpirV,
|
||||||
},
|
},
|
||||||
.Vector3u32 => |*v| switch (i.value.uint32) {
|
.Vector3u32 => |*v| switch (component_index) {
|
||||||
inline 0...2 => |idx| break :blk .{ .Pointer = .{ .ptr = .{ .u32_ptr = &v[idx] } } },
|
inline 0...2 => |idx| break :blk .{ .Pointer = .{
|
||||||
|
.ptr = .{ .u32_ptr = &v[idx] },
|
||||||
|
.uniform_slice_window = try helpers.advanceWindowSized(uniform_slice_window, idx * @sizeOf(u32), @sizeOf(u32)),
|
||||||
|
.uniform_backing_value = uniform_backing_value,
|
||||||
|
} },
|
||||||
else => return RuntimeError.InvalidSpirV,
|
else => return RuntimeError.InvalidSpirV,
|
||||||
},
|
},
|
||||||
.Vector2u32 => |*v| switch (i.value.uint32) {
|
.Vector2u32 => |*v| switch (component_index) {
|
||||||
inline 0...1 => |idx| break :blk .{ .Pointer = .{ .ptr = .{ .u32_ptr = &v[idx] } } },
|
inline 0...1 => |idx| break :blk .{ .Pointer = .{
|
||||||
|
.ptr = .{ .u32_ptr = &v[idx] },
|
||||||
|
.uniform_slice_window = try helpers.advanceWindowSized(uniform_slice_window, idx * @sizeOf(u32), @sizeOf(u32)),
|
||||||
|
.uniform_backing_value = uniform_backing_value,
|
||||||
|
} },
|
||||||
else => return RuntimeError.InvalidSpirV,
|
else => return RuntimeError.InvalidSpirV,
|
||||||
},
|
},
|
||||||
else => return RuntimeError.InvalidSpirV,
|
else => return RuntimeError.InvalidSpirV,
|
||||||
@@ -1416,15 +1513,14 @@ fn opAccessChain(allocator: std.mem.Allocator, word_count: SpvWord, rt: *Runtime
|
|||||||
break :blk .{
|
break :blk .{
|
||||||
.Pointer = .{
|
.Pointer = .{
|
||||||
.ptr = .{ .common = value_ptr },
|
.ptr = .{ .common = value_ptr },
|
||||||
.is_owner_of_uniform_slice = is_owner_of_uniform_slice,
|
|
||||||
.uniform_slice_window = uniform_slice_window,
|
.uniform_slice_window = uniform_slice_window,
|
||||||
|
.uniform_backing_value = uniform_backing_value,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn opAtomicStore(_: std.mem.Allocator, _: SpvWord, rt: *Runtime) RuntimeError!void {
|
fn opAtomicStore(_: std.mem.Allocator, _: SpvWord, rt: *Runtime) RuntimeError!void {
|
||||||
const ptr_id = try rt.it.next();
|
const ptr_id = try rt.it.next();
|
||||||
_ = rt.it.skip(); // scope
|
_ = rt.it.skip(); // scope
|
||||||
@@ -1781,58 +1877,145 @@ fn opConstantComposite(allocator: std.mem.Allocator, _: SpvWord, rt: *Runtime) R
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn opSMulExtended(_: std.mem.Allocator, _: SpvWord, rt: *Runtime) RuntimeError!void {
|
fn writeMulExtendedBits(comptime bits: u32, dst: *Value, lane_index: usize, value: Value.getPrimitiveFieldType(.UInt, bits)) RuntimeError!void {
|
||||||
const result_type_id = try rt.it.next();
|
switch (dst.*) {
|
||||||
const id = try rt.it.next();
|
.Int => |*i| {
|
||||||
|
if (i.bit_count != bits) return RuntimeError.InvalidSpirV;
|
||||||
|
if (i.is_signed) {
|
||||||
|
switch (bits) {
|
||||||
|
8 => i.value.sint8 = @bitCast(value),
|
||||||
|
16 => i.value.sint16 = @bitCast(value),
|
||||||
|
32 => i.value.sint32 = @bitCast(value),
|
||||||
|
64 => i.value.sint64 = @bitCast(value),
|
||||||
|
else => unreachable,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
switch (bits) {
|
||||||
|
8 => i.value.uint8 = value,
|
||||||
|
16 => i.value.uint16 = value,
|
||||||
|
32 => i.value.uint32 = value,
|
||||||
|
64 => i.value.uint64 = value,
|
||||||
|
else => unreachable,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
.Vector => |lanes| try writeMulExtendedBits(bits, &lanes[lane_index], 0, value),
|
||||||
|
.Vector2i32 => |*v| switch (lane_index) {
|
||||||
|
inline 0...1 => |i| if (bits == 32) {
|
||||||
|
v[i] = @bitCast(value);
|
||||||
|
} else {
|
||||||
|
return RuntimeError.InvalidSpirV;
|
||||||
|
},
|
||||||
|
else => return RuntimeError.InvalidSpirV,
|
||||||
|
},
|
||||||
|
.Vector3i32 => |*v| switch (lane_index) {
|
||||||
|
inline 0...2 => |i| if (bits == 32) {
|
||||||
|
v[i] = @bitCast(value);
|
||||||
|
} else {
|
||||||
|
return RuntimeError.InvalidSpirV;
|
||||||
|
},
|
||||||
|
else => return RuntimeError.InvalidSpirV,
|
||||||
|
},
|
||||||
|
.Vector4i32 => |*v| switch (lane_index) {
|
||||||
|
inline 0...3 => |i| if (bits == 32) {
|
||||||
|
v[i] = @bitCast(value);
|
||||||
|
} else {
|
||||||
|
return RuntimeError.InvalidSpirV;
|
||||||
|
},
|
||||||
|
else => return RuntimeError.InvalidSpirV,
|
||||||
|
},
|
||||||
|
.Vector2u32 => |*v| switch (lane_index) {
|
||||||
|
inline 0...1 => |i| if (bits == 32) {
|
||||||
|
v[i] = @bitCast(value);
|
||||||
|
} else {
|
||||||
|
return RuntimeError.InvalidSpirV;
|
||||||
|
},
|
||||||
|
else => return RuntimeError.InvalidSpirV,
|
||||||
|
},
|
||||||
|
.Vector3u32 => |*v| switch (lane_index) {
|
||||||
|
inline 0...2 => |i| if (bits == 32) {
|
||||||
|
v[i] = @bitCast(value);
|
||||||
|
} else {
|
||||||
|
return RuntimeError.InvalidSpirV;
|
||||||
|
},
|
||||||
|
else => return RuntimeError.InvalidSpirV,
|
||||||
|
},
|
||||||
|
.Vector4u32 => |*v| switch (lane_index) {
|
||||||
|
inline 0...3 => |i| if (bits == 32) {
|
||||||
|
v[i] = @bitCast(value);
|
||||||
|
} else {
|
||||||
|
return RuntimeError.InvalidSpirV;
|
||||||
|
},
|
||||||
|
else => return RuntimeError.InvalidSpirV,
|
||||||
|
},
|
||||||
|
else => return RuntimeError.InvalidSpirV,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn opMulExtended(comptime is_signed: bool, rt: *Runtime) RuntimeError!void {
|
||||||
|
_ = try rt.it.next(); // Result Type
|
||||||
|
const result_id = try rt.it.next();
|
||||||
const lhs = try rt.results[try rt.it.next()].getValue();
|
const lhs = try rt.results[try rt.it.next()].getValue();
|
||||||
const rhs = try rt.results[try rt.it.next()].getValue();
|
const rhs = try rt.results[try rt.it.next()].getValue();
|
||||||
const dst = try rt.results[id].getValue();
|
|
||||||
|
|
||||||
const result_members = switch (dst.*) {
|
const result = try rt.results[result_id].getValue();
|
||||||
.Structure => |s| s.values,
|
const result_members = switch (result.*) {
|
||||||
|
.Structure => |*s| s.values,
|
||||||
else => return RuntimeError.InvalidSpirV,
|
else => return RuntimeError.InvalidSpirV,
|
||||||
};
|
};
|
||||||
if (result_members.len != 2) return RuntimeError.InvalidSpirV;
|
if (result_members.len != 2) return RuntimeError.InvalidSpirV;
|
||||||
|
|
||||||
const lsb_dst = &result_members[0];
|
const low_dst = &result_members[0];
|
||||||
const msb_dst = &result_members[1];
|
const high_dst = &result_members[1];
|
||||||
|
|
||||||
const result_type = (try rt.results[result_type_id].getVariant()).Type;
|
const lane_count = try lhs.resolveLaneCount();
|
||||||
const member_types = switch (result_type) {
|
if (try rhs.resolveLaneCount() != lane_count) return RuntimeError.InvalidSpirV;
|
||||||
.Structure => |s| s.members_type_word,
|
if (try low_dst.resolveLaneCount() != lane_count) return RuntimeError.InvalidSpirV;
|
||||||
else => return RuntimeError.InvalidSpirV,
|
if (try high_dst.resolveLaneCount() != lane_count) return RuntimeError.InvalidSpirV;
|
||||||
};
|
|
||||||
if (member_types.len != 2) return RuntimeError.InvalidSpirV;
|
|
||||||
|
|
||||||
const value_type = (try rt.results[member_types[0]].getVariant()).Type;
|
const lane_bits = try lhs.resolveLaneBitWidth();
|
||||||
const lane_count = try Result.resolveLaneCount(value_type);
|
if (try rhs.resolveLaneBitWidth() != lane_bits) return RuntimeError.InvalidSpirV;
|
||||||
const lane_bits = try Result.resolveLaneBitWidth(value_type, rt);
|
if (try low_dst.resolveLaneBitWidth() != lane_bits) return RuntimeError.InvalidSpirV;
|
||||||
|
if (try high_dst.resolveLaneBitWidth() != lane_bits) return RuntimeError.InvalidSpirV;
|
||||||
|
|
||||||
switch (lane_bits) {
|
switch (lane_bits) {
|
||||||
inline 8, 16, 32, 64 => |bits| {
|
inline 8, 16, 32, 64 => |bits| {
|
||||||
//const SIntT = Value.getPrimitiveFieldType(.SInt, bits);
|
|
||||||
const UIntT = Value.getPrimitiveFieldType(.UInt, bits);
|
const UIntT = Value.getPrimitiveFieldType(.UInt, bits);
|
||||||
const WideSIntT = std.meta.Int(.signed, bits * 2);
|
|
||||||
const WideUIntT = std.meta.Int(.unsigned, bits * 2);
|
const WideUIntT = std.meta.Int(.unsigned, bits * 2);
|
||||||
|
|
||||||
for (0..lane_count) |lane_index| {
|
for (0..lane_count) |lane_index| {
|
||||||
const l = try Value.readLane(.SInt, bits, lhs, lane_index);
|
const product_bits: WideUIntT = if (is_signed) blk: {
|
||||||
const r = try Value.readLane(.SInt, bits, rhs, lane_index);
|
const SIntT = Value.getPrimitiveFieldType(.SInt, bits);
|
||||||
|
const WideSIntT = std.meta.Int(.signed, bits * 2);
|
||||||
|
const l: SIntT = try Value.readLane(.SInt, bits, lhs, lane_index);
|
||||||
|
const r: SIntT = try Value.readLane(.SInt, bits, rhs, lane_index);
|
||||||
|
const product: WideSIntT = @as(WideSIntT, l) * @as(WideSIntT, r);
|
||||||
|
break :blk @bitCast(product);
|
||||||
|
} else blk: {
|
||||||
|
const l: UIntT = try Value.readLane(.UInt, bits, lhs, lane_index);
|
||||||
|
const r: UIntT = try Value.readLane(.UInt, bits, rhs, lane_index);
|
||||||
|
break :blk @as(WideUIntT, l) * @as(WideUIntT, r);
|
||||||
|
};
|
||||||
|
|
||||||
const product: WideSIntT = @as(WideSIntT, l) * @as(WideSIntT, r);
|
const low: UIntT = @truncate(product_bits);
|
||||||
const product_bits: WideUIntT = @bitCast(product);
|
const high: UIntT = @truncate(product_bits >> bits);
|
||||||
|
|
||||||
const lsb_bits: UIntT = @truncate(product_bits);
|
try writeMulExtendedBits(bits, low_dst, lane_index, low);
|
||||||
const msb_bits: UIntT = @truncate(product_bits >> bits);
|
try writeMulExtendedBits(bits, high_dst, lane_index, high);
|
||||||
|
|
||||||
try Value.writeLane(.SInt, bits, lsb_dst, lane_index, @bitCast(lsb_bits));
|
|
||||||
try Value.writeLane(.SInt, bits, msb_dst, lane_index, @bitCast(msb_bits));
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
else => return RuntimeError.InvalidSpirV,
|
else => return RuntimeError.InvalidSpirV,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn opUMulExtended(_: std.mem.Allocator, _: SpvWord, rt: *Runtime) RuntimeError!void {
|
||||||
|
try opMulExtended(false, rt);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn opSMulExtended(_: std.mem.Allocator, _: SpvWord, rt: *Runtime) RuntimeError!void {
|
||||||
|
try opMulExtended(true, rt);
|
||||||
|
}
|
||||||
|
|
||||||
fn opSpecConstant(allocator: std.mem.Allocator, word_count: SpvWord, rt: *Runtime) RuntimeError!void {
|
fn opSpecConstant(allocator: std.mem.Allocator, word_count: SpvWord, rt: *Runtime) RuntimeError!void {
|
||||||
const location = rt.it.emitSourceLocation();
|
const location = rt.it.emitSourceLocation();
|
||||||
_ = rt.it.skip();
|
_ = rt.it.skip();
|
||||||
@@ -2258,7 +2441,6 @@ fn opImageRead(_: std.mem.Allocator, _: SpvWord, rt: *Runtime) RuntimeError!void
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fn opImageWrite(_: std.mem.Allocator, _: SpvWord, rt: *Runtime) RuntimeError!void {
|
fn opImageWrite(_: std.mem.Allocator, _: SpvWord, rt: *Runtime) RuntimeError!void {
|
||||||
const image = &rt.results[try rt.it.next()];
|
const image = &rt.results[try rt.it.next()];
|
||||||
const coordinate = try rt.results[try rt.it.next()].getValue();
|
const coordinate = try rt.results[try rt.it.next()].getValue();
|
||||||
@@ -2396,8 +2578,19 @@ fn opImageWrite(_: std.mem.Allocator, _: SpvWord, rt: *Runtime) RuntimeError!voi
|
|||||||
const z = helpers.readCoordLane(coordinate, 2) catch 0;
|
const z = helpers.readCoordLane(coordinate, 2) catch 0;
|
||||||
|
|
||||||
switch (texel.*) {
|
switch (texel.*) {
|
||||||
.Float, .Vector4f32, .Vector3f32, .Vector2f32 => try rt.image_api.writeImageFloat4(driver_image, x, y, z, try helpers.readFloatTexel(texel)),
|
.Float,
|
||||||
.Int, .Vector4i32, .Vector3i32, .Vector2i32, .Vector4u32, .Vector3u32, .Vector2u32 => try rt.image_api.writeImageInt4(driver_image, x, y, z, try helpers.readIntTexel(texel)),
|
.Vector4f32,
|
||||||
|
.Vector3f32,
|
||||||
|
.Vector2f32,
|
||||||
|
=> try rt.image_api.writeImageFloat4(driver_image, x, y, z, try helpers.readFloatTexel(texel)),
|
||||||
|
.Int,
|
||||||
|
.Vector4i32,
|
||||||
|
.Vector3i32,
|
||||||
|
.Vector2i32,
|
||||||
|
.Vector4u32,
|
||||||
|
.Vector3u32,
|
||||||
|
.Vector2u32,
|
||||||
|
=> try rt.image_api.writeImageInt4(driver_image, x, y, z, try helpers.readIntTexel(texel)),
|
||||||
.Vector => |lanes| {
|
.Vector => |lanes| {
|
||||||
if (lanes.len == 0) return RuntimeError.InvalidSpirV;
|
if (lanes.len == 0) return RuntimeError.InvalidSpirV;
|
||||||
switch (lanes[0]) {
|
switch (lanes[0]) {
|
||||||
|
|||||||
Reference in New Issue
Block a user