fixes
This commit is contained in:
@@ -461,6 +461,41 @@ pub const Value = union(Type) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub inline fn getLaneCount(self: *const Self) RuntimeError!usize {
|
||||||
|
return switch (self.*) {
|
||||||
|
.Vector => |lanes| lanes.len,
|
||||||
|
.Vector2i32, .Vector2u32, .Vector2f32 => 2,
|
||||||
|
.Vector3i32, .Vector3u32, .Vector3f32 => 3,
|
||||||
|
.Vector4i32, .Vector4u32, .Vector4f32 => 4,
|
||||||
|
.Int, .Float, .Bool => 1,
|
||||||
|
else => RuntimeError.InvalidSpirV,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn isScalar(self: *const Self) bool {
|
||||||
|
return switch (self.*) {
|
||||||
|
.Bool, .Int, .Float => true,
|
||||||
|
else => false,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn isVector(self: *const Self) bool {
|
||||||
|
return switch (self.*) {
|
||||||
|
.Vector,
|
||||||
|
.Vector2i32,
|
||||||
|
.Vector2u32,
|
||||||
|
.Vector2f32,
|
||||||
|
.Vector3i32,
|
||||||
|
.Vector3u32,
|
||||||
|
.Vector3f32,
|
||||||
|
.Vector4i32,
|
||||||
|
.Vector4u32,
|
||||||
|
.Vector4f32,
|
||||||
|
=> true,
|
||||||
|
else => false,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
pub fn flushPtr(self: *Self, allocator: std.mem.Allocator) RuntimeError!void {
|
pub fn flushPtr(self: *Self, allocator: std.mem.Allocator) RuntimeError!void {
|
||||||
switch (self.*) {
|
switch (self.*) {
|
||||||
.Pointer => |*p| {
|
.Pointer => |*p| {
|
||||||
|
|||||||
212
src/opcodes.zig
212
src/opcodes.zig
@@ -320,12 +320,17 @@ fn BitOperator(comptime T: ValueType, comptime Op: BitOp) type {
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline fn bitExtract(comptime TT: type, v: TT, offset: TT, count: u64) TT {
|
inline fn bitExtract(comptime TT: type, v: TT, offset: TT, count: u64) TT {
|
||||||
return (v >> @intCast(offset)) & @as(TT, @intCast(bitMask(count)));
|
return (v >> @intCast(offset)) & @as(TT, @bitCast(@as(std.meta.Int(.unsigned, @bitSizeOf(TT)), @truncate(bitMask(count)))));
|
||||||
}
|
}
|
||||||
|
|
||||||
inline fn operationUnary(comptime TT: type, op1: TT) RuntimeError!TT {
|
inline fn operationUnary(comptime TT: type, op1: TT) RuntimeError!TT {
|
||||||
return switch (Op) {
|
return switch (Op) {
|
||||||
.BitCount => @as(TT, @intCast(@bitSizeOf(TT))), // keep return type TT
|
.BitCount => blk: {
|
||||||
|
const bit_set: std.bit_set.IntegerBitSet(@bitSizeOf(TT)) = .{
|
||||||
|
.mask = @bitCast(op1),
|
||||||
|
};
|
||||||
|
break :blk @as(TT, @intCast(bit_set.count()));
|
||||||
|
},
|
||||||
.BitReverse => @bitReverse(op1),
|
.BitReverse => @bitReverse(op1),
|
||||||
.Not => ~op1,
|
.Not => ~op1,
|
||||||
else => RuntimeError.InvalidSpirV,
|
else => RuntimeError.InvalidSpirV,
|
||||||
@@ -340,12 +345,12 @@ fn BitOperator(comptime T: ValueType, comptime Op: BitOp) type {
|
|||||||
break :blk bitInsert(TT, op1, op2, offset.Int.value.uint64, count.Int.value.uint64);
|
break :blk bitInsert(TT, op1, op2, offset.Int.value.uint64, count.Int.value.uint64);
|
||||||
},
|
},
|
||||||
.BitFieldSExtract => blk: {
|
.BitFieldSExtract => blk: {
|
||||||
if (T == .UInt) return RuntimeError.InvalidSpirV;
|
if (T != .SInt) return RuntimeError.InvalidSpirV;
|
||||||
const count = try rt.results[try rt.it.next()].getValue();
|
const count = try rt.results[try rt.it.next()].getValue();
|
||||||
break :blk bitExtract(TT, op1, op2, count.Int.value.uint64);
|
break :blk bitExtract(TT, op1, op2, count.Int.value.uint64);
|
||||||
},
|
},
|
||||||
.BitFieldUExtract => blk: {
|
.BitFieldUExtract => blk: {
|
||||||
if (T == .SInt) return RuntimeError.InvalidSpirV;
|
if (T != .UInt) return RuntimeError.InvalidSpirV;
|
||||||
const count = try rt.results[try rt.it.next()].getValue();
|
const count = try rt.results[try rt.it.next()].getValue();
|
||||||
break :blk bitExtract(TT, op1, op2, count.Int.value.uint64);
|
break :blk bitExtract(TT, op1, op2, count.Int.value.uint64);
|
||||||
},
|
},
|
||||||
@@ -360,50 +365,123 @@ fn BitOperator(comptime T: ValueType, comptime Op: BitOp) type {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn applyScalarBits(rt: *Runtime, bit_count: SpvWord, dst: *Value, op1_v: *const Value, op2_v: ?*const Value) RuntimeError!void {
|
inline fn readLane(comptime bits: u32, v: *const Value, lane_index: usize) RuntimeError!getValuePrimitiveFieldType(T, bits) {
|
||||||
switch (bit_count) {
|
const TT = getValuePrimitiveFieldType(T, bits);
|
||||||
inline 8, 16, 32, 64 => |bits| {
|
|
||||||
const TT = getValuePrimitiveFieldType(T, bits);
|
|
||||||
const a = (try getValuePrimitiveField(T, bits, @constCast(op1_v))).*;
|
|
||||||
|
|
||||||
const out = if (comptime isUnaryOp()) blk: {
|
return switch (v.*) {
|
||||||
break :blk try operationUnary(TT, a);
|
.Int => (try getValuePrimitiveField(T, bits, @constCast(v))).*,
|
||||||
} else blk: {
|
|
||||||
const b_ptr = op2_v orelse return RuntimeError.InvalidSpirV;
|
|
||||||
const b = (try getValuePrimitiveField(T, bits, @constCast(b_ptr))).*;
|
|
||||||
break :blk try operationBinary(TT, rt, a, b);
|
|
||||||
};
|
|
||||||
|
|
||||||
(try getValuePrimitiveField(T, bits, dst)).* = out;
|
.Vector => |lanes| (try getValuePrimitiveField(T, bits, &lanes[lane_index])).*,
|
||||||
|
|
||||||
|
.Vector4i32 => |vec| if (bits == 32) @as(TT, @bitCast(vec[lane_index])) else return RuntimeError.InvalidSpirV,
|
||||||
|
.Vector3i32 => |vec| if (bits == 32) @as(TT, @bitCast(vec[lane_index])) else return RuntimeError.InvalidSpirV,
|
||||||
|
.Vector2i32 => |vec| if (bits == 32) @as(TT, @bitCast(vec[lane_index])) else return RuntimeError.InvalidSpirV,
|
||||||
|
|
||||||
|
.Vector4u32 => |vec| if (bits == 32) @as(TT, @bitCast(vec[lane_index])) else return RuntimeError.InvalidSpirV,
|
||||||
|
.Vector3u32 => |vec| if (bits == 32) @as(TT, @bitCast(vec[lane_index])) else return RuntimeError.InvalidSpirV,
|
||||||
|
.Vector2u32 => |vec| if (bits == 32) @as(TT, @bitCast(vec[lane_index])) else return RuntimeError.InvalidSpirV,
|
||||||
|
|
||||||
|
else => RuntimeError.InvalidSpirV,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
inline fn writeLane(comptime bits: u32, dst: *Value, lane_index: usize, value: getValuePrimitiveFieldType(T, bits)) RuntimeError!void {
|
||||||
|
switch (dst.*) {
|
||||||
|
.Int => (try getValuePrimitiveField(T, bits, dst)).* = value,
|
||||||
|
|
||||||
|
.Vector => |lanes| try setScalarLaneValue(T, bits, &lanes[lane_index], value),
|
||||||
|
|
||||||
|
.Vector2i32 => |*vec| vec[lane_index] = if (bits == 32) @bitCast(value) else return RuntimeError.InvalidSpirV,
|
||||||
|
.Vector3i32 => |*vec| vec[lane_index] = if (bits == 32) @bitCast(value) else return RuntimeError.InvalidSpirV,
|
||||||
|
.Vector4i32 => |*vec| vec[lane_index] = if (bits == 32) @bitCast(value) else return RuntimeError.InvalidSpirV,
|
||||||
|
|
||||||
|
.Vector2u32 => |*vec| vec[lane_index] = if (bits == 32) @bitCast(value) else return RuntimeError.InvalidSpirV,
|
||||||
|
.Vector3u32 => |*vec| vec[lane_index] = if (bits == 32) @bitCast(value) else return RuntimeError.InvalidSpirV,
|
||||||
|
.Vector4u32 => |*vec| vec[lane_index] = if (bits == 32) @bitCast(value) else return RuntimeError.InvalidSpirV,
|
||||||
|
|
||||||
|
else => return RuntimeError.InvalidSpirV,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn setScalarLaneValue(comptime value_type: ValueType, comptime bits: u32, dst: *Value, v: getValuePrimitiveFieldType(value_type, bits)) RuntimeError!void {
|
||||||
|
switch (bits) {
|
||||||
|
inline 8, 16, 32, 64 => {
|
||||||
|
dst.* = .{ .Int = .{
|
||||||
|
.bit_count = bits,
|
||||||
|
.value = switch (value_type) {
|
||||||
|
.SInt => switch (bits) {
|
||||||
|
8 => .{ .sint8 = v },
|
||||||
|
16 => .{ .sint16 = v },
|
||||||
|
32 => .{ .sint32 = v },
|
||||||
|
64 => .{ .sint64 = v },
|
||||||
|
else => unreachable,
|
||||||
|
},
|
||||||
|
.UInt => switch (bits) {
|
||||||
|
8 => .{ .uint8 = v },
|
||||||
|
16 => .{ .uint16 = v },
|
||||||
|
32 => .{ .uint32 = v },
|
||||||
|
64 => .{ .uint64 = v },
|
||||||
|
else => unreachable,
|
||||||
|
},
|
||||||
|
else => return RuntimeError.InvalidSpirV,
|
||||||
|
},
|
||||||
|
} };
|
||||||
},
|
},
|
||||||
else => return RuntimeError.InvalidSpirV,
|
else => return RuntimeError.InvalidSpirV,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline fn laneRhsPtr(op2_value: ?*Value, index: usize) ?*const Value {
|
fn applyScalarBits(rt: *Runtime, bit_count: SpvWord, dst: *Value, op1_v: *const Value, op2_v: ?*const Value) RuntimeError!void {
|
||||||
if (comptime isUnaryOp()) return null;
|
switch (bit_count) {
|
||||||
const v = op2_value orelse return null;
|
inline 8, 16, 32, 64 => |bits| {
|
||||||
return &v.Vector[index];
|
const TT = getValuePrimitiveFieldType(T, bits);
|
||||||
|
const a = try readLane(bits, op1_v, 0);
|
||||||
|
|
||||||
|
const out: TT = if (comptime isUnaryOp())
|
||||||
|
try operationUnary(TT, a)
|
||||||
|
else blk: {
|
||||||
|
const rhs = op2_v orelse return RuntimeError.InvalidSpirV;
|
||||||
|
const b = try readLane(bits, rhs, 0);
|
||||||
|
break :blk try operationBinary(TT, rt, a, b);
|
||||||
|
};
|
||||||
|
|
||||||
|
try writeLane(bits, dst, 0, out);
|
||||||
|
},
|
||||||
|
else => return RuntimeError.InvalidSpirV,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline fn applyFixedVectorBinary(
|
fn applyVectorBits(rt: *Runtime, lane_bits: SpvWord, dst: *Value, op1_v: *const Value, op2_v: ?*const Value) RuntimeError!void {
|
||||||
comptime ElemT: type,
|
const dst_len = try dst.getLaneCount();
|
||||||
comptime N: usize,
|
const op1_len = try op1_v.getLaneCount();
|
||||||
rt: *Runtime,
|
if (op1_v.isVector() and dst_len != op1_len) return RuntimeError.InvalidSpirV;
|
||||||
dst: *[N]ElemT,
|
|
||||||
op1: *[N]ElemT,
|
|
||||||
op2: *[N]ElemT,
|
|
||||||
) RuntimeError!void {
|
|
||||||
inline for (0..N) |i| dst[i] = try operationBinary(ElemT, rt, op1[i], op2[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline fn applyFixedVectorUnary(
|
if (!comptime isUnaryOp()) {
|
||||||
comptime ElemT: type,
|
const rhs = op2_v orelse return RuntimeError.InvalidSpirV;
|
||||||
comptime N: usize,
|
const op2_len = try rhs.getLaneCount();
|
||||||
dst: *[N]ElemT,
|
if (op2_v.?.isVector() and dst_len != op2_len) return RuntimeError.InvalidSpirV;
|
||||||
op1: *[N]ElemT,
|
}
|
||||||
) RuntimeError!void {
|
|
||||||
inline for (0..N) |i| dst[i] = try operationUnary(ElemT, op1[i]);
|
switch (lane_bits) {
|
||||||
|
inline 8, 16, 32, 64 => |bits| {
|
||||||
|
const TT = getValuePrimitiveFieldType(T, bits);
|
||||||
|
|
||||||
|
for (0..dst_len) |i| {
|
||||||
|
const a = try readLane(bits, op1_v, if (op1_v.isVector()) i else 0);
|
||||||
|
|
||||||
|
const out: TT = if (comptime isUnaryOp())
|
||||||
|
try operationUnary(TT, a)
|
||||||
|
else blk: {
|
||||||
|
const rhs = op2_v orelse return RuntimeError.InvalidSpirV;
|
||||||
|
const b = try readLane(bits, rhs, if (op2_v.?.isVector()) i else 0);
|
||||||
|
break :blk try operationBinary(TT, rt, a, b);
|
||||||
|
};
|
||||||
|
|
||||||
|
try writeLane(bits, dst, i, out);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
else => return RuntimeError.InvalidSpirV,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -422,56 +500,16 @@ fn BitEngine(comptime T: ValueType, comptime Op: BitOp) type {
|
|||||||
const lane_bits = try Result.resolveLaneBitWidth(target_type, rt);
|
const lane_bits = try Result.resolveLaneBitWidth(target_type, rt);
|
||||||
|
|
||||||
switch (dst.*) {
|
switch (dst.*) {
|
||||||
.Int => try operator.applyScalarBits(rt, lane_bits, dst, op1, if (comptime operator.isUnaryOp()) null else op2_value),
|
.Int => try operator.applyScalarBits(rt, lane_bits, dst, op1, op2_value),
|
||||||
|
|
||||||
.Vector => |dst_vec| {
|
.Vector,
|
||||||
const op1_vec = op1.Vector;
|
.Vector2i32,
|
||||||
if (dst_vec.len != op1_vec.len) return RuntimeError.InvalidSpirV;
|
.Vector3i32,
|
||||||
|
.Vector4i32,
|
||||||
for (dst_vec, op1_vec, 0..) |*d_lane, a_lane, i| {
|
.Vector2u32,
|
||||||
var tmp_a = a_lane;
|
.Vector3u32,
|
||||||
const b_ptr = operator.laneRhsPtr(op2_value, i);
|
.Vector4u32,
|
||||||
try operator.applyScalarBits(rt, lane_bits, d_lane, &tmp_a, b_ptr);
|
=> try operator.applyVectorBits(rt, lane_bits, dst, op1, op2_value),
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
.Vector4i32 => |*d| {
|
|
||||||
if (comptime operator.isUnaryOp())
|
|
||||||
try operator.applyFixedVectorUnary(i32, 4, d, &op1.Vector4i32)
|
|
||||||
else
|
|
||||||
try operator.applyFixedVectorBinary(i32, 4, rt, d, &op1.Vector4i32, &op2_value.?.Vector4i32);
|
|
||||||
},
|
|
||||||
.Vector3i32 => |*d| {
|
|
||||||
if (comptime operator.isUnaryOp())
|
|
||||||
try operator.applyFixedVectorUnary(i32, 3, d, &op1.Vector3i32)
|
|
||||||
else
|
|
||||||
try operator.applyFixedVectorBinary(i32, 3, rt, d, &op1.Vector3i32, &op2_value.?.Vector3i32);
|
|
||||||
},
|
|
||||||
.Vector2i32 => |*d| {
|
|
||||||
if (comptime operator.isUnaryOp())
|
|
||||||
try operator.applyFixedVectorUnary(i32, 2, d, &op1.Vector2i32)
|
|
||||||
else
|
|
||||||
try operator.applyFixedVectorBinary(i32, 2, rt, d, &op1.Vector2i32, &op2_value.?.Vector2i32);
|
|
||||||
},
|
|
||||||
|
|
||||||
.Vector4u32 => |*d| {
|
|
||||||
if (comptime operator.isUnaryOp())
|
|
||||||
try operator.applyFixedVectorUnary(u32, 4, d, &op1.Vector4u32)
|
|
||||||
else
|
|
||||||
try operator.applyFixedVectorBinary(u32, 4, rt, d, &op1.Vector4u32, &op2_value.?.Vector4u32);
|
|
||||||
},
|
|
||||||
.Vector3u32 => |*d| {
|
|
||||||
if (comptime operator.isUnaryOp())
|
|
||||||
try operator.applyFixedVectorUnary(u32, 3, d, &op1.Vector3u32)
|
|
||||||
else
|
|
||||||
try operator.applyFixedVectorBinary(u32, 3, rt, d, &op1.Vector3u32, &op2_value.?.Vector3u32);
|
|
||||||
},
|
|
||||||
.Vector2u32 => |*d| {
|
|
||||||
if (comptime operator.isUnaryOp())
|
|
||||||
try operator.applyFixedVectorUnary(u32, 2, d, &op1.Vector2u32)
|
|
||||||
else
|
|
||||||
try operator.applyFixedVectorBinary(u32, 2, rt, d, &op1.Vector2u32, &op2_value.?.Vector2u32);
|
|
||||||
},
|
|
||||||
|
|
||||||
else => return RuntimeError.InvalidSpirV,
|
else => return RuntimeError.InvalidSpirV,
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user