adding bitsize to primitive values
All checks were successful
Build / build (push) Successful in 1m43s
Test / build (push) Successful in 4m37s

This commit is contained in:
2026-02-15 02:06:15 +01:00
parent ac4f41ddd4
commit 2ea707ea57
5 changed files with 320 additions and 208 deletions

View File

@@ -31,12 +31,12 @@ pub fn main() !void {
var input: Input = .{};
var output: Output = .{};
try rt.writeDescriptorSet(Input, allocator, &input, 0, 0);
try rt.writeDescriptorSet(Output, allocator, &output, 0, 1);
try rt.writeDescriptorSet(allocator, std.mem.asBytes(&input), 0, 0);
try rt.writeDescriptorSet(allocator, std.mem.asBytes(&output), 0, 1);
try rt.callEntryPoint(allocator, entry);
try rt.readDescriptorSet(Output, allocator, &output, 0, 1);
try rt.readDescriptorSet(std.mem.asBytes(&output), 0, 1);
std.log.info("Output: {any}", .{output});

View File

@@ -80,7 +80,9 @@ const Decoration = struct {
pub const Value = union(Type) {
Void: struct {},
Bool: bool,
Int: extern union {
Int: struct {
bit_count: usize,
value: extern union {
sint8: i8,
sint16: i16,
sint32: i32,
@@ -90,11 +92,15 @@ pub const Value = union(Type) {
uint32: u32,
uint64: u64,
},
Float: extern union {
},
Float: struct {
bit_count: usize,
value: extern union {
float16: f16,
float32: f32,
float64: f64,
},
},
Vector: []Value,
Vector4f32: Vec4f32,
Vector3f32: Vec3f32,
@@ -116,7 +122,7 @@ pub const Value = union(Type) {
Pointer: union(enum) {
common: *Value,
f32_ptr: *f32,
i32_ptr: *i32, //< For vectors specializations
i32_ptr: *i32, //< For vector specializations
u32_ptr: *u32,
},
@@ -135,8 +141,14 @@ pub const Value = union(Type) {
return switch (resolved.variant.?) {
.Type => |t| switch (t) {
.Bool => .{ .Bool = false },
.Int => .{ .Int = .{ .uint64 = 0 } },
.Float => .{ .Float = .{ .float64 = 0.0 } },
.Int => |i| .{ .Int = .{
.bit_count = i.bit_length,
.value = .{ .uint64 = 0 },
} },
.Float => |f| .{ .Float = .{
.bit_count = f.bit_length,
.value = .{ .float64 = 0 },
} },
.Vector => |v| blk: {
var self: Value = .{ .Vector = allocator.alloc(Value, member_count) catch return RuntimeError.OutOfMemory };
errdefer self.deinit(allocator);
@@ -529,7 +541,7 @@ pub fn resolveSign(target_type: TypeData, rt: *const Runtime) RuntimeError!enum
.Vector4u32 => .unsigned,
.Vector3u32 => .unsigned,
.Vector2u32 => .unsigned,
else => .unsinged,
else => .unsigned,
};
}
@@ -573,8 +585,14 @@ pub fn initValue(allocator: std.mem.Allocator, member_count: usize, results: []c
.Type => |t| switch (t) {
.Void => .{ .Void = .{} },
.Bool => .{ .Bool = false },
.Int => .{ .Int = .{ .uint64 = 0 } },
.Float => .{ .Float = .{ .float64 = 0.0 } },
.Int => |i| .{ .Int = .{
.bit_count = i.bit_length,
.value = .{ .uint64 = 0 },
} },
.Float => |f| .{ .Float = .{
.bit_count = f.bit_length,
.value = .{ .float64 = 0 },
} },
.Vector => |v| blk: {
const value: Value = .{ .Vector = allocator.alloc(Value, member_count) catch return RuntimeError.OutOfMemory };
errdefer allocator.free(value.Vector);
@@ -609,7 +627,6 @@ pub fn initValue(allocator: std.mem.Allocator, member_count: usize, results: []c
break :blk value;
},
.RuntimeArray => |a| blk: {
std.debug.print("test {d}\n", .{member_count});
if (member_count == 0) {
break :blk Value{ .RuntimeArray = null };
}

View File

@@ -150,43 +150,58 @@ pub fn callEntryPoint(self: *Self, allocator: std.mem.Allocator, entry_point_ind
//}) catch return RuntimeError.OutOfMemory;
}
pub fn readDescriptorSet(self: *const Self, comptime T: type, output: *T, set: SpvWord, binding: SpvWord) RuntimeError!void {
pub fn readDescriptorSet(self: *const Self, output: []u8, set: SpvWord, binding: SpvWord) RuntimeError!void {
if (set < lib.SPIRV_MAX_SET and binding < lib.SPIRV_MAX_SET_BINDINGS) {
try self.readValue(T, output, &self.results[self.mod.bindings[set][binding]].variant.?.Variable.value);
_ = try self.readValue(output, &self.results[self.mod.bindings[set][binding]].variant.?.Variable.value);
} else {
return RuntimeError.NotFound;
}
}
pub fn writeDescriptorSet(self: *const Self, comptime T: type, allocator: std.mem.Allocator, input: *const T, set: SpvWord, binding: SpvWord) RuntimeError!void {
pub fn writeDescriptorSet(self: *const Self, allocator: std.mem.Allocator, input: []const u8, set: SpvWord, binding: SpvWord) RuntimeError!void {
if (set < lib.SPIRV_MAX_SET and binding < lib.SPIRV_MAX_SET_BINDINGS) {
const variable = &self.results[self.mod.bindings[set][binding]].variant.?.Variable;
switch (variable.value) {
const helper = struct {
fn init(allocator2: std.mem.Allocator, len: usize, value: *Result.Value, type_word: SpvWord, results: []Result) RuntimeError!void {
const resolved = results[type_word].resolveType(results);
switch (value.*) {
.RuntimeArray => {
const resolved = self.results[variable.type_word].resolveType(self.results);
variable.value = try Result.initValue(allocator, input.len, self.results, resolved);
value.* = try Result.initValue(allocator2, len, results, resolved);
},
.Vector, .Matrix, .Array, .Structure => |v| {
_ = v;
.Structure => |*s| for (s.*, 0..) |*elem, i| {
try @This().init(allocator2, len, elem, resolved.variant.?.Type.Structure.members_type_word[i], results);
},
else => {},
}
try self.writeValue(T, input, &variable.value);
}
};
try helper.init(allocator, input.len, &variable.value, variable.type_word, self.results);
@import("pretty").print(allocator, variable, .{
.tab_size = 4,
.max_depth = 0,
.struct_max_len = 0,
.array_max_len = 0,
}) catch return RuntimeError.OutOfMemory;
_ = try self.writeValue(input, &variable.value);
} else {
return RuntimeError.NotFound;
}
}
pub fn readOutput(self: *const Self, comptime T: type, output: []T, result: SpvWord) RuntimeError!void {
pub fn readOutput(self: *const Self, output: []u8, result: SpvWord) RuntimeError!void {
if (std.mem.indexOf(SpvWord, &self.mod.output_locations, &.{result})) |_| {
try self.readValue(T, output, &self.results[result].variant.?.Variable.value);
_ = try self.readValue(output, &self.results[result].variant.?.Variable.value);
} else {
return RuntimeError.NotFound;
}
}
pub fn writeInput(self: *const Self, comptime T: type, input: []const T, result: SpvWord) RuntimeError!void {
pub fn writeInput(self: *const Self, input: []const u8, result: SpvWord) RuntimeError!void {
if (std.mem.indexOf(SpvWord, &self.mod.input_locations, &.{result})) |_| {
try self.writeValue(T, input, &self.results[result].variant.?.Variable.value);
_ = try self.writeValue(input, &self.results[result].variant.?.Variable.value);
} else {
return RuntimeError.NotFound;
}
@@ -197,144 +212,224 @@ fn reset(self: *Self) void {
self.current_function = null;
}
fn readValue(self: *const Self, comptime T: type, output: []T, value: *const Result.Value) RuntimeError!void {
fn readValue(self: *const Self, output: []u8, value: *const Result.Value) RuntimeError!usize {
switch (value.*) {
.Bool => |b| {
if (T == bool) {
output[0] = b;
} else {
return RuntimeError.InvalidValueType;
}
output[0] = if (b == true) 1 else 0;
return 1;
},
.Int => |i| {
switch (T) {
i8 => output[0] = i.sint8,
i16 => output[0] = i.sint16,
i32 => output[0] = i.sint32,
i64 => output[0] = i.sint64,
u8 => output[0] = i.uint8,
u16 => output[0] = i.uint16,
u32 => output[0] = i.uint32,
u64 => output[0] = i.uint64,
inline else => return RuntimeError.InvalidValueType,
switch (i.bit_count) {
8 => output[0] = @bitCast(i.value.uint8),
16 => std.mem.copyForwards(u8, output[0..], std.mem.asBytes(&i.value.uint16)),
32 => std.mem.copyForwards(u8, output[0..], std.mem.asBytes(&i.value.uint32)),
64 => std.mem.copyForwards(u8, output[0..], std.mem.asBytes(&i.value.uint64)),
else => return RuntimeError.InvalidValueType,
}
return @divExact(i.bit_count, 8);
},
.Float => |f| {
switch (T) {
f16 => output[0] = f.float16,
f32 => output[0] = f.float32,
f64 => output[0] = f.float64,
inline else => return RuntimeError.InvalidValueType,
}
},
.Vector4f32 => |vec| inline for (0..4) |i| switch (T) {
f32 => output[i] = vec[i],
inline else => return RuntimeError.InvalidValueType,
},
.Vector3f32 => |vec| inline for (0..3) |i| switch (T) {
f32 => output[i] = vec[i],
inline else => return RuntimeError.InvalidValueType,
},
.Vector2f32 => |vec| inline for (0..2) |i| switch (T) {
f32 => output[i] = vec[i],
inline else => return RuntimeError.InvalidValueType,
},
.Vector4i32 => |vec| inline for (0..4) |i| switch (T) {
i32 => output[i] = vec[i],
inline else => return RuntimeError.InvalidValueType,
},
.Vector3i32 => |vec| inline for (0..3) |i| switch (T) {
i32 => output[i] = vec[i],
inline else => return RuntimeError.InvalidValueType,
},
.Vector2i32 => |vec| inline for (0..2) |i| switch (T) {
i32 => output[i] = vec[i],
inline else => return RuntimeError.InvalidValueType,
},
.Vector4u32 => |vec| inline for (0..4) |i| switch (T) {
u32 => output[i] = vec[i],
inline else => return RuntimeError.InvalidValueType,
},
.Vector3u32 => |vec| inline for (0..3) |i| switch (T) {
u32 => output[i] = vec[i],
inline else => return RuntimeError.InvalidValueType,
},
.Vector2u32 => |vec| inline for (0..2) |i| switch (T) {
u32 => output[i] = vec[i],
inline else => return RuntimeError.InvalidValueType,
},
.Vector, .Matrix, .Array, .Structure => |values| for (values, 0..) |v, i| try self.readValue(T, output[i..], &v),
switch (f.bit_count) {
16 => std.mem.copyForwards(u8, output[0..], std.mem.asBytes(&f.value.float16)),
32 => std.mem.copyForwards(u8, output[0..], std.mem.asBytes(&f.value.float32)),
64 => std.mem.copyForwards(u8, output[0..], std.mem.asBytes(&f.value.float64)),
else => return RuntimeError.InvalidValueType,
}
return @divExact(f.bit_count, 8);
},
.Vector4f32 => |vec| {
inline for (0..4) |i| {
std.mem.copyForwards(u8, output[(i * 4)..], std.mem.asBytes(&vec[i]));
}
return 4 * 4;
},
.Vector3f32 => |vec| {
inline for (0..3) |i| {
std.mem.copyForwards(u8, output[(i * 4)..], std.mem.asBytes(&vec[i]));
}
return 3 * 4;
},
.Vector2f32 => |vec| {
inline for (0..2) |i| {
std.mem.copyForwards(u8, output[(i * 4)..], std.mem.asBytes(&vec[i]));
}
return 2 * 4;
},
.Vector4i32 => |vec| {
inline for (0..4) |i| {
std.mem.copyForwards(u8, output[(i * 4)..], std.mem.asBytes(&vec[i]));
}
return 4 * 4;
},
.Vector3i32 => |vec| {
inline for (0..3) |i| {
std.mem.copyForwards(u8, output[(i * 4)..], std.mem.asBytes(&vec[i]));
}
return 3 * 4;
},
.Vector2i32 => |vec| {
inline for (0..2) |i| {
std.mem.copyForwards(u8, output[(i * 4)..], std.mem.asBytes(&vec[i]));
}
return 2 * 4;
},
.Vector4u32 => |vec| {
inline for (0..4) |i| {
std.mem.copyForwards(u8, output[(i * 4)..], std.mem.asBytes(&vec[i]));
}
return 4 * 4;
},
.Vector3u32 => |vec| {
inline for (0..3) |i| {
std.mem.copyForwards(u8, output[(i * 4)..], std.mem.asBytes(&vec[i]));
}
return 3 * 4;
},
.Vector2u32 => |vec| {
inline for (0..2) |i| {
std.mem.copyForwards(u8, output[(i * 4)..], std.mem.asBytes(&vec[i]));
}
return 2 * 4;
},
.Vector,
.Matrix,
.Array,
.Structure,
=> |values| {
var offset: usize = 0;
for (values) |v| {
offset += try self.readValue(output[offset..], &v);
}
return offset;
},
.RuntimeArray => |opt_values| if (opt_values) |values| {
var offset: usize = 0;
for (values) |v| {
offset += try self.readValue(output[offset..], &v);
}
return offset;
},
else => return RuntimeError.InvalidValueType,
}
return 0;
}
fn writeValue(self: *const Self, comptime T: type, input: []const T, value: *Result.Value) RuntimeError!void {
fn writeValue(self: *const Self, input: []const u8, value: *Result.Value) RuntimeError!usize {
switch (value.*) {
.Bool => |*b| {
if (T == bool) {
b.* = input[0];
} else {
return RuntimeError.InvalidValueType;
}
b.* = if (input[0] != 0) true else false;
return 1;
},
.Int => |*i| {
switch (T) {
i8 => i.sint8 = input[0],
i16 => i.sint16 = input[0],
i32 => i.sint32 = input[0],
i64 => i.sint64 = input[0],
u8 => i.uint8 = input[0],
u16 => i.uint16 = input[0],
u32 => i.uint32 = input[0],
u64 => i.uint64 = input[0],
inline else => return RuntimeError.InvalidValueType,
}
},
.Float => |*f| {
switch (T) {
f16 => f.float16 = input[0],
f32 => f.float32 = input[0],
f64 => f.float64 = input[0],
inline else => return RuntimeError.InvalidValueType,
}
},
.Vector4f32 => |*vec| inline for (0..4) |i| switch (T) {
f32 => vec[i] = input[i],
inline else => return RuntimeError.InvalidValueType,
},
.Vector3f32 => |*vec| inline for (0..3) |i| switch (T) {
f32 => vec[i] = input[i],
inline else => return RuntimeError.InvalidValueType,
},
.Vector2f32 => |*vec| inline for (0..2) |i| switch (T) {
f32 => vec[i] = input[i],
inline else => return RuntimeError.InvalidValueType,
},
.Vector4i32 => |*vec| inline for (0..4) |i| switch (T) {
i32 => vec[i] = input[i],
inline else => return RuntimeError.InvalidValueType,
},
.Vector3i32 => |*vec| inline for (0..3) |i| switch (T) {
i32 => vec[i] = input[i],
inline else => return RuntimeError.InvalidValueType,
},
.Vector2i32 => |*vec| inline for (0..2) |i| switch (T) {
i32 => vec[i] = input[i],
inline else => return RuntimeError.InvalidValueType,
},
.Vector4u32 => |*vec| inline for (0..4) |i| switch (T) {
u32 => vec[i] = input[i],
inline else => return RuntimeError.InvalidValueType,
},
.Vector3u32 => |*vec| inline for (0..3) |i| switch (T) {
u32 => vec[i] = input[i],
inline else => return RuntimeError.InvalidValueType,
},
.Vector2u32 => |*vec| inline for (0..2) |i| switch (T) {
u32 => vec[i] = input[i],
inline else => return RuntimeError.InvalidValueType,
},
.Vector, .Matrix, .Array, .Structure => |*values| for (values.*, 0..) |*v, i| try self.writeValue(T, input[i..], v),
switch (i.bit_count) {
8 => i.value.uint8 = @bitCast(input[0]),
16 => std.mem.copyForwards(u8, std.mem.asBytes(&i.value.uint16), input[0..2]),
32 => std.mem.copyForwards(u8, std.mem.asBytes(&i.value.uint32), input[0..4]),
64 => std.mem.copyForwards(u8, std.mem.asBytes(&i.value.uint64), input[0..8]),
else => return RuntimeError.InvalidValueType,
}
return @divExact(i.bit_count, 8);
},
.Float => |*f| {
switch (f.bit_count) {
16 => std.mem.copyForwards(u8, std.mem.asBytes(&f.value.float16), input[0..2]),
32 => std.mem.copyForwards(u8, std.mem.asBytes(&f.value.float32), input[0..4]),
64 => std.mem.copyForwards(u8, std.mem.asBytes(&f.value.float64), input[0..8]),
else => return RuntimeError.InvalidValueType,
}
return @divExact(f.bit_count, 8);
},
.Vector4f32 => |*vec| {
inline for (0..4) |i| {
const start = i * 4;
const end = (i + 1) * 4;
std.mem.copyForwards(u8, std.mem.asBytes(&vec[i]), input[start..end]);
}
return 4 * 4;
},
.Vector3f32 => |*vec| {
inline for (0..3) |i| {
const start = i * 4;
const end = (i + 1) * 4;
std.mem.copyForwards(u8, std.mem.asBytes(&vec[i]), input[start..end]);
}
return 3 * 4;
},
.Vector2f32 => |*vec| {
inline for (0..2) |i| {
const start = i * 4;
const end = (i + 1) * 4;
std.mem.copyForwards(u8, std.mem.asBytes(&vec[i]), input[start..end]);
}
return 2 * 4;
},
.Vector4i32 => |*vec| {
inline for (0..4) |i| {
const start = i * 4;
const end = (i + 1) * 4;
std.mem.copyForwards(u8, std.mem.asBytes(&vec[i]), input[start..end]);
}
return 4 * 4;
},
.Vector3i32 => |*vec| {
inline for (0..3) |i| {
const start = i * 4;
const end = (i + 1) * 4;
std.mem.copyForwards(u8, std.mem.asBytes(&vec[i]), input[start..end]);
}
return 3 * 4;
},
.Vector2i32 => |*vec| {
inline for (0..2) |i| {
const start = i * 4;
const end = (i + 1) * 4;
std.mem.copyForwards(u8, std.mem.asBytes(&vec[i]), input[start..end]);
}
return 2 * 4;
},
.Vector4u32 => |*vec| {
inline for (0..4) |i| {
const start = i * 4;
const end = (i + 1) * 4;
std.mem.copyForwards(u8, std.mem.asBytes(&vec[i]), input[start..end]);
}
return 4 * 4;
},
.Vector3u32 => |*vec| {
inline for (0..3) |i| {
const start = i * 4;
const end = (i + 1) * 4;
std.mem.copyForwards(u8, std.mem.asBytes(&vec[i]), input[start..end]);
}
return 3 * 4;
},
.Vector2u32 => |*vec| {
inline for (0..2) |i| {
const start = i * 4;
const end = (i + 1) * 4;
std.mem.copyForwards(u8, std.mem.asBytes(&vec[i]), input[start..end]);
}
return 2 * 4;
},
.Vector,
.Matrix,
.Array,
.Structure,
=> |*values| {
var offset: usize = 0;
for (values.*) |*v| {
offset += try self.writeValue(input[offset..], v);
}
return offset;
},
.RuntimeArray => |opt_values| if (opt_values) |*values| {
var offset: usize = 0;
for (values.*) |*v| {
offset += try self.writeValue(input[offset..], v);
}
return offset;
},
else => return RuntimeError.InvalidValueType,
}
return 0;
}

View File

@@ -316,17 +316,17 @@ fn BitOperator(comptime T: ValueType, comptime Op: BitOp) type {
.BitFieldInsert => blk: {
const offset = try rt.results[try rt.it.next()].getValue();
const count = try rt.results[try rt.it.next()].getValue();
break :blk bitInsert(TT, op1, op2, offset.Int.uint64, count.Int.uint64);
break :blk bitInsert(TT, op1, op2, offset.Int.value.uint64, count.Int.value.uint64);
},
.BitFieldSExtract => blk: {
if (T == .UInt) return RuntimeError.InvalidSpirV;
const count = try rt.results[try rt.it.next()].getValue();
break :blk bitExtract(TT, op1, op2, count.Int.uint64);
break :blk bitExtract(TT, op1, op2, count.Int.value.uint64);
},
.BitFieldUExtract => blk: {
if (T == .SInt) return RuntimeError.InvalidSpirV;
const count = try rt.results[try rt.it.next()].getValue();
break :blk bitExtract(TT, op1, op2, count.Int.uint64);
break :blk bitExtract(TT, op1, op2, count.Int.value.uint64);
},
.BitwiseAnd => op1 & op2,
@@ -728,7 +728,7 @@ fn MathEngine(comptime T: ValueType, comptime Op: MathOp) type {
inline fn applyVectorTimesScalarF32(d: []Result.Value, l: []const Result.Value, r: f32) void {
for (d, l) |*d_v, l_v| {
d_v.Float.float32 = l_v.Float.float32 * r;
d_v.Float.value.float32 = l_v.Float.value.float32 * r;
}
}
@@ -746,7 +746,7 @@ fn MathEngine(comptime T: ValueType, comptime Op: MathOp) type {
inline fn applySIMDVectorf32(comptime N: usize, d: *@Vector(N, f32), l: *const @Vector(N, f32), r: *const Result.Value) RuntimeError!void {
switch (Op) {
.VectorTimesScalar => applyVectorSIMDTimesScalarF32(N, d, l, r.Float.float32),
.VectorTimesScalar => applyVectorSIMDTimesScalarF32(N, d, l, r.Float.value.float32),
else => {
const rh: *const @Vector(N, f32) = switch (N) {
2 => &r.Vector2f32,
@@ -764,7 +764,7 @@ fn MathEngine(comptime T: ValueType, comptime Op: MathOp) type {
.Int, .Float => try operator.applyScalar(lane_bits, dst, lhs, rhs),
.Vector => |dst_vec| switch (Op) {
.VectorTimesScalar => operator.applyVectorTimesScalarF32(dst_vec, lhs.Vector, rhs.Float.float32),
.VectorTimesScalar => operator.applyVectorTimesScalarF32(dst_vec, lhs.Vector, rhs.Float.value.float32),
else => for (dst_vec, lhs.Vector, rhs.Vector) |*d_lane, *l_lane, *r_lane| {
try operator.applyScalar(lane_bits, d_lane, l_lane, r_lane);
},
@@ -845,14 +845,14 @@ fn opBitcast(_: std.mem.Allocator, _: SpvWord, rt: *Runtime) RuntimeError!void {
/// Asumes that values passed are primitives ints or floats
fn cast(to: *Result.Value, from: *const Result.Value) RuntimeError!void {
const from_bytes: u64 = switch (from.*) {
.Float => |f| @bitCast(f.float64),
.Int => |i| i.uint64,
.Float => |f| @bitCast(f.value.float64),
.Int => |i| i.value.uint64,
else => return RuntimeError.InvalidSpirV,
};
switch (to.*) {
.Float => |*f| f.float64 = @bitCast(from_bytes),
.Int => |*i| i.uint64 = from_bytes,
.Float => |*f| f.value.float64 = @bitCast(from_bytes),
.Int => |*i| i.value.uint64 = from_bytes,
else => return RuntimeError.InvalidSpirV,
}
}
@@ -887,12 +887,12 @@ fn copyValue(dst: *Result.Value, src: *const Result.Value) void {
.Pointer => |src_ptr| switch (src_ptr) {
.f32_ptr => |src_f32_ptr| dst_f32_ptr.* = src_f32_ptr.*,
.common => |src_val_ptr| switch (src_val_ptr.*) {
.Float => |f| dst_f32_ptr.* = f.float32,
.Float => |f| dst_f32_ptr.* = f.value.float32,
else => unreachable,
},
else => unreachable,
},
.Float => |f| dst_f32_ptr.* = f.float32,
.Float => |f| dst_f32_ptr.* = f.value.float32,
else => unreachable,
}
}
@@ -902,12 +902,12 @@ fn copyValue(dst: *Result.Value, src: *const Result.Value) void {
.Pointer => |src_ptr| switch (src_ptr) {
.i32_ptr => |src_i32_ptr| dst_i32_ptr.* = src_i32_ptr.*,
.common => |src_val_ptr| switch (src_val_ptr.*) {
.Int => |i| dst_i32_ptr.* = i.sint32,
.Int => |i| dst_i32_ptr.* = i.value.sint32,
else => unreachable,
},
else => unreachable,
},
.Int => |i| dst_i32_ptr.* = i.sint32,
.Int => |i| dst_i32_ptr.* = i.value.sint32,
else => unreachable,
}
}
@@ -917,12 +917,12 @@ fn copyValue(dst: *Result.Value, src: *const Result.Value) void {
.Pointer => |src_ptr| switch (src_ptr) {
.u32_ptr => |src_u32_ptr| dst_u32_ptr.* = src_u32_ptr.*,
.common => |src_val_ptr| switch (src_val_ptr.*) {
.Int => |i| dst_u32_ptr.* = i.uint32,
.Int => |i| dst_u32_ptr.* = i.value.uint32,
else => unreachable,
},
else => unreachable,
},
.Int => |i| dst_u32_ptr.* = i.uint32,
.Int => |i| dst_u32_ptr.* = i.value.uint32,
else => unreachable,
}
}
@@ -987,15 +987,15 @@ pub fn getValuePrimitiveField(comptime T: ValueType, comptime BitCount: SpvWord,
return switch (T) {
.Bool => &v.Bool,
.Float => switch (BitCount) {
inline 16, 32, 64 => |i| &@field(v.Float, std.fmt.comptimePrint("float{}", .{i})),
inline 16, 32, 64 => |i| &@field(v.Float.value, std.fmt.comptimePrint("float{}", .{i})),
else => return RuntimeError.InvalidSpirV,
},
.SInt => switch (BitCount) {
inline 8, 16, 32, 64 => |i| &@field(v.Int, std.fmt.comptimePrint("sint{}", .{i})),
inline 8, 16, 32, 64 => |i| &@field(v.Int.value, std.fmt.comptimePrint("sint{}", .{i})),
else => return RuntimeError.InvalidSpirV,
},
.UInt => switch (BitCount) {
inline 8, 16, 32, 64 => |i| &@field(v.Int, std.fmt.comptimePrint("uint{}", .{i})),
inline 8, 16, 32, 64 => |i| &@field(v.Int.value, std.fmt.comptimePrint("uint{}", .{i})),
else => return RuntimeError.InvalidSpirV,
},
};
@@ -1034,48 +1034,48 @@ fn opAccessChain(_: std.mem.Allocator, word_count: SpvWord, rt: *Runtime) Runtim
.Int => |i| {
switch (value_ptr.*) {
.Vector, .Matrix, .Array, .Structure => |v| {
if (i.uint32 > v.len) return RuntimeError.InvalidSpirV;
value_ptr = &v[i.uint32];
if (i.value.uint32 > v.len) return RuntimeError.InvalidSpirV;
value_ptr = &v[i.value.uint32];
},
.RuntimeArray => |opt_v| if (opt_v) |v| {
if (i.uint32 > v.len) return RuntimeError.InvalidSpirV;
value_ptr = &v[i.uint32];
if (i.value.uint32 > v.len) return RuntimeError.InvalidSpirV;
value_ptr = &v[i.value.uint32];
} else return RuntimeError.InvalidSpirV,
.Vector4f32 => |*v| {
if (i.uint32 > 4) return RuntimeError.InvalidSpirV;
break :blk .{ .Pointer = .{ .f32_ptr = &v[i.uint32] } };
if (i.value.uint32 > 4) return RuntimeError.InvalidSpirV;
break :blk .{ .Pointer = .{ .f32_ptr = &v[i.value.uint32] } };
},
.Vector3f32 => |*v| {
if (i.uint32 > 3) return RuntimeError.InvalidSpirV;
break :blk .{ .Pointer = .{ .f32_ptr = &v[i.uint32] } };
if (i.value.uint32 > 3) return RuntimeError.InvalidSpirV;
break :blk .{ .Pointer = .{ .f32_ptr = &v[i.value.uint32] } };
},
.Vector2f32 => |*v| {
if (i.uint32 > 2) return RuntimeError.InvalidSpirV;
break :blk .{ .Pointer = .{ .f32_ptr = &v[i.uint32] } };
if (i.value.uint32 > 2) return RuntimeError.InvalidSpirV;
break :blk .{ .Pointer = .{ .f32_ptr = &v[i.value.uint32] } };
},
.Vector4i32 => |*v| {
if (i.uint32 > 4) return RuntimeError.InvalidSpirV;
break :blk .{ .Pointer = .{ .i32_ptr = &v[i.uint32] } };
if (i.value.uint32 > 4) return RuntimeError.InvalidSpirV;
break :blk .{ .Pointer = .{ .i32_ptr = &v[i.value.uint32] } };
},
.Vector3i32 => |*v| {
if (i.uint32 > 3) return RuntimeError.InvalidSpirV;
break :blk .{ .Pointer = .{ .i32_ptr = &v[i.uint32] } };
if (i.value.uint32 > 3) return RuntimeError.InvalidSpirV;
break :blk .{ .Pointer = .{ .i32_ptr = &v[i.value.uint32] } };
},
.Vector2i32 => |*v| {
if (i.uint32 > 2) return RuntimeError.InvalidSpirV;
break :blk .{ .Pointer = .{ .i32_ptr = &v[i.uint32] } };
if (i.value.uint32 > 2) return RuntimeError.InvalidSpirV;
break :blk .{ .Pointer = .{ .i32_ptr = &v[i.value.uint32] } };
},
.Vector4u32 => |*v| {
if (i.uint32 > 4) return RuntimeError.InvalidSpirV;
break :blk .{ .Pointer = .{ .u32_ptr = &v[i.uint32] } };
if (i.value.uint32 > 4) return RuntimeError.InvalidSpirV;
break :blk .{ .Pointer = .{ .u32_ptr = &v[i.value.uint32] } };
},
.Vector3u32 => |*v| {
if (i.uint32 > 3) return RuntimeError.InvalidSpirV;
break :blk .{ .Pointer = .{ .u32_ptr = &v[i.uint32] } };
if (i.value.uint32 > 3) return RuntimeError.InvalidSpirV;
break :blk .{ .Pointer = .{ .u32_ptr = &v[i.value.uint32] } };
},
.Vector2u32 => |*v| {
if (i.uint32 > 2) return RuntimeError.InvalidSpirV;
break :blk .{ .Pointer = .{ .u32_ptr = &v[i.uint32] } };
if (i.value.uint32 > 2) return RuntimeError.InvalidSpirV;
break :blk .{ .Pointer = .{ .u32_ptr = &v[i.value.uint32] } };
},
else => return RuntimeError.InvalidSpirV,
}
@@ -1134,31 +1134,31 @@ fn opCompositeConstruct(_: std.mem.Allocator, word_count: SpvWord, rt: *Runtime)
switch (value.*) {
.Vector4f32 => |*vec| inline for (0..4) |i| {
vec[i] = (try rt.results[try rt.it.next()].getVariant()).Constant.value.Float.float32;
vec[i] = (try rt.results[try rt.it.next()].getVariant()).Constant.value.Float.value.float32;
},
.Vector3f32 => |*vec| inline for (0..3) |i| {
vec[i] = (try rt.results[try rt.it.next()].getVariant()).Constant.value.Float.float32;
vec[i] = (try rt.results[try rt.it.next()].getVariant()).Constant.value.Float.value.float32;
},
.Vector2f32 => |*vec| inline for (0..2) |i| {
vec[i] = (try rt.results[try rt.it.next()].getVariant()).Constant.value.Float.float32;
vec[i] = (try rt.results[try rt.it.next()].getVariant()).Constant.value.Float.value.float32;
},
.Vector4i32 => |*vec| inline for (0..4) |i| {
vec[i] = (try rt.results[try rt.it.next()].getVariant()).Constant.value.Int.sint32;
vec[i] = (try rt.results[try rt.it.next()].getVariant()).Constant.value.Int.value.sint32;
},
.Vector3i32 => |*vec| inline for (0..3) |i| {
vec[i] = (try rt.results[try rt.it.next()].getVariant()).Constant.value.Int.sint32;
vec[i] = (try rt.results[try rt.it.next()].getVariant()).Constant.value.Int.value.sint32;
},
.Vector2i32 => |*vec| inline for (0..2) |i| {
vec[i] = (try rt.results[try rt.it.next()].getVariant()).Constant.value.Int.sint32;
vec[i] = (try rt.results[try rt.it.next()].getVariant()).Constant.value.Int.value.sint32;
},
.Vector4u32 => |*vec| inline for (0..4) |i| {
vec[i] = (try rt.results[try rt.it.next()].getVariant()).Constant.value.Int.uint32;
vec[i] = (try rt.results[try rt.it.next()].getVariant()).Constant.value.Int.value.uint32;
},
.Vector3u32 => |*vec| inline for (0..3) |i| {
vec[i] = (try rt.results[try rt.it.next()].getVariant()).Constant.value.Int.uint32;
vec[i] = (try rt.results[try rt.it.next()].getVariant()).Constant.value.Int.value.uint32;
},
.Vector2u32 => |*vec| inline for (0..2) |i| {
vec[i] = (try rt.results[try rt.it.next()].getVariant()).Constant.value.Int.uint32;
vec[i] = (try rt.results[try rt.it.next()].getVariant()).Constant.value.Int.value.uint32;
},
else => return RuntimeError.InvalidSpirV,
}
@@ -1186,15 +1186,15 @@ fn opCompositeExtract(allocator: std.mem.Allocator, word_count: SpvWord, rt: *Ru
continue;
}
switch (composite) {
.Vector4f32 => |v| break :blk .{ .Float = .{ .float32 = v[member_id] } },
.Vector3f32 => |v| break :blk .{ .Float = .{ .float32 = v[member_id] } },
.Vector2f32 => |v| break :blk .{ .Float = .{ .float32 = v[member_id] } },
.Vector4i32 => |v| break :blk .{ .Int = .{ .sint32 = v[member_id] } },
.Vector3i32 => |v| break :blk .{ .Int = .{ .sint32 = v[member_id] } },
.Vector2i32 => |v| break :blk .{ .Int = .{ .sint32 = v[member_id] } },
.Vector4u32 => |v| break :blk .{ .Int = .{ .uint32 = v[member_id] } },
.Vector3u32 => |v| break :blk .{ .Int = .{ .uint32 = v[member_id] } },
.Vector2u32 => |v| break :blk .{ .Int = .{ .uint32 = v[member_id] } },
.Vector4f32 => |v| break :blk .{ .Float = .{ .bit_count = 32, .value = .{ .float32 = v[member_id] } } },
.Vector3f32 => |v| break :blk .{ .Float = .{ .bit_count = 32, .value = .{ .float32 = v[member_id] } } },
.Vector2f32 => |v| break :blk .{ .Float = .{ .bit_count = 32, .value = .{ .float32 = v[member_id] } } },
.Vector4i32 => |v| break :blk .{ .Int = .{ .bit_count = 32, .value = .{ .sint32 = v[member_id] } } },
.Vector3i32 => |v| break :blk .{ .Int = .{ .bit_count = 32, .value = .{ .sint32 = v[member_id] } } },
.Vector2i32 => |v| break :blk .{ .Int = .{ .bit_count = 32, .value = .{ .sint32 = v[member_id] } } },
.Vector4u32 => |v| break :blk .{ .Int = .{ .bit_count = 32, .value = .{ .uint32 = v[member_id] } } },
.Vector3u32 => |v| break :blk .{ .Int = .{ .bit_count = 32, .value = .{ .uint32 = v[member_id] } } },
.Vector2u32 => |v| break :blk .{ .Int = .{ .bit_count = 32, .value = .{ .uint32 = v[member_id] } } },
else => return RuntimeError.InvalidSpirV,
}
}
@@ -1212,18 +1212,18 @@ fn opConstant(allocator: std.mem.Allocator, word_count: SpvWord, rt: *Runtime) R
if (word_count - 2 != 1) {
const low = @as(u64, try rt.it.next());
const high = @as(u64, try rt.it.next());
i.uint64 = (high << 32) | low;
i.value.uint64 = (high << 32) | low;
} else {
i.uint32 = try rt.it.next();
i.value.uint32 = try rt.it.next();
}
},
.Float => |*f| {
if (word_count - 2 != 1) {
const low = @as(u64, try rt.it.next());
const high = @as(u64, try rt.it.next());
f.float64 = @bitCast((high << 32) | low);
f.value.float64 = @bitCast((high << 32) | low);
} else {
f.float32 = @bitCast(try rt.it.next());
f.value.float32 = @bitCast(try rt.it.next());
}
},
else => return RuntimeError.InvalidSpirV,
@@ -1260,7 +1260,7 @@ fn opDot(_: std.mem.Allocator, _: SpvWord, rt: *Runtime) RuntimeError!void {
else => return RuntimeError.InvalidSpirV,
};
value.Float.float64 = 0.0;
value.Float.value.float64 = 0.0;
switch (op1_value.*) {
.Vector => |vec| for (vec, op2_value.Vector) |*op1_v, *op2_v| {
@@ -1271,14 +1271,14 @@ fn opDot(_: std.mem.Allocator, _: SpvWord, rt: *Runtime) RuntimeError!void {
else => return RuntimeError.InvalidSpirV,
}
},
.Vector4f32 => |vec| value.Float.float32 = zm.dot4(vec, op2_value.Vector4f32)[0],
.Vector4f32 => |vec| value.Float.value.float32 = zm.dot4(vec, op2_value.Vector4f32)[0],
.Vector3f32 => |vec| {
const op2_vec = op2_value.Vector3f32;
value.Float.float32 = zm.dot3(zm.f32x4(vec[0], vec[1], vec[2], 0.0), zm.f32x4(op2_vec[0], op2_vec[1], op2_vec[2], 0.0))[0];
value.Float.value.float32 = zm.dot3(zm.f32x4(vec[0], vec[1], vec[2], 0.0), zm.f32x4(op2_vec[0], op2_vec[1], op2_vec[2], 0.0))[0];
},
.Vector2f32 => |vec| {
const op2_vec = op2_value.Vector2f32;
value.Float.float32 = zm.dot2(zm.f32x4(vec[0], vec[1], 0.0, 0.0), zm.f32x4(op2_vec[0], op2_vec[1], 0.0, 0.0))[0];
value.Float.value.float32 = zm.dot2(zm.f32x4(vec[0], vec[1], 0.0, 0.0), zm.f32x4(op2_vec[0], op2_vec[1], 0.0, 0.0))[0];
},
else => return RuntimeError.InvalidSpirV,
}

View File

@@ -41,7 +41,7 @@ pub const case = struct {
try rt.callEntryPoint(allocator, try rt.getEntryPointByName("main"));
var output: [len]T = undefined;
try rt.readOutput(T, output[0..len], try rt.getResultByName(output_name));
try rt.readOutput(std.mem.sliceAsBytes(output[0..]), try rt.getResultByName(output_name));
try std.testing.expectEqualSlices(T, expected, &output);
}
@@ -67,11 +67,11 @@ pub const case = struct {
var rt = try spv.Runtime.init(allocator, &module);
defer rt.deinit(allocator);
try rt.writeInput(T, input[0..len], try rt.getResultByName(input_name));
try rt.writeInput(std.mem.sliceAsBytes(input[0..len]), try rt.getResultByName(input_name));
try rt.callEntryPoint(allocator, try rt.getEntryPointByName("main"));
var output: [len]T = undefined;
try rt.readOutput(T, output[0..len], try rt.getResultByName(output_name));
try rt.readOutput(std.mem.sliceAsBytes(output[0..]), try rt.getResultByName(output_name));
try std.testing.expectEqualSlices(T, expected, &output);
}