small refactor of values
This commit is contained in:
@@ -8,6 +8,7 @@ const Module = @import("../Module.zig");
|
|||||||
const Runtime = @import("../Runtime.zig");
|
const Runtime = @import("../Runtime.zig");
|
||||||
const Result = @import("../Result.zig");
|
const Result = @import("../Result.zig");
|
||||||
const WordIterator = @import("../WordIterator.zig");
|
const WordIterator = @import("../WordIterator.zig");
|
||||||
|
const Value = @import("../Value.zig").Value;
|
||||||
|
|
||||||
const RuntimeError = Runtime.RuntimeError;
|
const RuntimeError = Runtime.RuntimeError;
|
||||||
const ValueType = opc.ValueType;
|
const ValueType = opc.ValueType;
|
||||||
@@ -123,7 +124,7 @@ fn MathEngine(comptime T: ValueType, comptime Op: MathOp) type {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn applyScalar(bit_count: SpvWord, d: *Result.Value, s: *const Result.Value) RuntimeError!void {
|
fn applyScalar(bit_count: SpvWord, d: *Value, s: *const Value) RuntimeError!void {
|
||||||
switch (bit_count) {
|
switch (bit_count) {
|
||||||
inline 8, 16, 32, 64 => |bits| {
|
inline 8, 16, 32, 64 => |bits| {
|
||||||
if (bits == 8 and T == .Float) return RuntimeError.InvalidSpirV;
|
if (bits == 8 and T == .Float) return RuntimeError.InvalidSpirV;
|
||||||
@@ -177,7 +178,7 @@ fn MathEngine(comptime T: ValueType, comptime Op: MathOp) type {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn applyScalar(bit_count: SpvWord, d: *Result.Value, l: *const Result.Value, r: *const Result.Value) RuntimeError!void {
|
fn applyScalar(bit_count: SpvWord, d: *Value, l: *const Value, r: *const Value) RuntimeError!void {
|
||||||
switch (bit_count) {
|
switch (bit_count) {
|
||||||
inline 8, 16, 32, 64 => |bits| {
|
inline 8, 16, 32, 64 => |bits| {
|
||||||
if (bits == 8 and T == .Float) return RuntimeError.InvalidSpirV;
|
if (bits == 8 and T == .Float) return RuntimeError.InvalidSpirV;
|
||||||
|
|||||||
@@ -13,10 +13,9 @@ const SpvBinding = spv.SpvBinding;
|
|||||||
|
|
||||||
const Result = @import("Result.zig");
|
const Result = @import("Result.zig");
|
||||||
const Runtime = @import("Runtime.zig");
|
const Runtime = @import("Runtime.zig");
|
||||||
|
const Value = @import("Value.zig").Value;
|
||||||
const WordIterator = @import("WordIterator.zig");
|
const WordIterator = @import("WordIterator.zig");
|
||||||
|
|
||||||
const Value = Result.Value;
|
|
||||||
|
|
||||||
const Self = @This();
|
const Self = @This();
|
||||||
|
|
||||||
pub const ModuleOptions = struct {
|
pub const ModuleOptions = struct {
|
||||||
|
|||||||
441
src/Result.zig
441
src/Result.zig
@@ -1,6 +1,8 @@
|
|||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const spv = @import("spv.zig");
|
const spv = @import("spv.zig");
|
||||||
const op = @import("opcodes.zig");
|
const op = @import("opcodes.zig");
|
||||||
|
const lib = @import("lib.zig");
|
||||||
|
const Value = @import("Value.zig").Value;
|
||||||
|
|
||||||
const Runtime = @import("Runtime.zig");
|
const Runtime = @import("Runtime.zig");
|
||||||
const RuntimeError = Runtime.RuntimeError;
|
const RuntimeError = Runtime.RuntimeError;
|
||||||
@@ -10,17 +12,17 @@ const SpvByte = spv.SpvByte;
|
|||||||
const SpvWord = spv.SpvWord;
|
const SpvWord = spv.SpvWord;
|
||||||
const SpvBool = spv.SpvBool;
|
const SpvBool = spv.SpvBool;
|
||||||
|
|
||||||
pub const Vec4f32 = @Vector(4, f32);
|
const Vec4f32 = lib.Vec4f32;
|
||||||
pub const Vec3f32 = @Vector(3, f32);
|
const Vec3f32 = lib.Vec3f32;
|
||||||
pub const Vec2f32 = @Vector(2, f32);
|
const Vec2f32 = lib.Vec2f32;
|
||||||
|
|
||||||
pub const Vec4i32 = @Vector(4, i32);
|
const Vec4i32 = lib.Vec4i32;
|
||||||
pub const Vec3i32 = @Vector(3, i32);
|
const Vec3i32 = lib.Vec3i32;
|
||||||
pub const Vec2i32 = @Vector(2, i32);
|
const Vec2i32 = lib.Vec2i32;
|
||||||
|
|
||||||
pub const Vec4u32 = @Vector(4, u32);
|
const Vec4u32 = lib.Vec4u32;
|
||||||
pub const Vec3u32 = @Vector(3, u32);
|
const Vec3u32 = lib.Vec3u32;
|
||||||
pub const Vec2u32 = @Vector(2, u32);
|
const Vec2u32 = lib.Vec2u32;
|
||||||
|
|
||||||
pub const Variant = enum {
|
pub const Variant = enum {
|
||||||
String,
|
String,
|
||||||
@@ -77,427 +79,6 @@ const Decoration = struct {
|
|||||||
index: SpvWord,
|
index: SpvWord,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const Value = union(Type) {
|
|
||||||
Void: struct {},
|
|
||||||
Bool: bool,
|
|
||||||
Int: struct {
|
|
||||||
bit_count: usize,
|
|
||||||
value: extern union {
|
|
||||||
sint8: i8,
|
|
||||||
sint16: i16,
|
|
||||||
sint32: i32,
|
|
||||||
sint64: i64,
|
|
||||||
uint8: u8,
|
|
||||||
uint16: u16,
|
|
||||||
uint32: u32,
|
|
||||||
uint64: u64,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Float: struct {
|
|
||||||
bit_count: usize,
|
|
||||||
value: extern union {
|
|
||||||
float16: f16,
|
|
||||||
float32: f32,
|
|
||||||
float64: f64,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Vector: []Value,
|
|
||||||
Vector4f32: Vec4f32,
|
|
||||||
Vector3f32: Vec3f32,
|
|
||||||
Vector2f32: Vec2f32,
|
|
||||||
Vector4i32: Vec4i32,
|
|
||||||
Vector3i32: Vec3i32,
|
|
||||||
Vector2i32: Vec2i32,
|
|
||||||
Vector4u32: Vec4u32,
|
|
||||||
Vector3u32: Vec3u32,
|
|
||||||
Vector2u32: Vec2u32,
|
|
||||||
Matrix: []Value,
|
|
||||||
Array: []Value,
|
|
||||||
RuntimeArray: struct {
|
|
||||||
type_word: SpvWord,
|
|
||||||
data: []u8,
|
|
||||||
},
|
|
||||||
Structure: []Value,
|
|
||||||
Function: noreturn,
|
|
||||||
Image: struct {},
|
|
||||||
Sampler: struct {},
|
|
||||||
SampledImage: struct {},
|
|
||||||
Pointer: struct {
|
|
||||||
ptr: union(enum) {
|
|
||||||
common: *Value,
|
|
||||||
f32_ptr: *f32,
|
|
||||||
i32_ptr: *i32, //< For vector specializations
|
|
||||||
u32_ptr: *u32,
|
|
||||||
},
|
|
||||||
runtime_array_window: ?[]u8 = null,
|
|
||||||
},
|
|
||||||
|
|
||||||
pub inline fn getCompositeDataOrNull(self: *const Value) ?[]Value {
|
|
||||||
return switch (self.*) {
|
|
||||||
.Vector, .Matrix, .Array, .Structure => |v| v,
|
|
||||||
else => null,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn init(allocator: std.mem.Allocator, results: []const Self, target: SpvWord) RuntimeError!Value {
|
|
||||||
const resolved = results[target].resolveType(results);
|
|
||||||
const member_count = resolved.getMemberCounts();
|
|
||||||
|
|
||||||
return switch (resolved.variant.?) {
|
|
||||||
.Type => |t| switch (t) {
|
|
||||||
.Bool => .{ .Bool = false },
|
|
||||||
.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);
|
|
||||||
|
|
||||||
for (self.Vector) |*value| {
|
|
||||||
value.* = try Value.init(allocator, results, v.components_type_word);
|
|
||||||
}
|
|
||||||
break :blk self;
|
|
||||||
},
|
|
||||||
.Vector4f32 => .{ .Vector4f32 = Vec4f32{ 0.0, 0.0, 0.0, 0.0 } },
|
|
||||||
.Vector3f32 => .{ .Vector3f32 = Vec3f32{ 0.0, 0.0, 0.0 } },
|
|
||||||
.Vector2f32 => .{ .Vector2f32 = Vec2f32{ 0.0, 0.0 } },
|
|
||||||
.Vector4i32 => .{ .Vector4i32 = Vec4i32{ 0, 0, 0, 0 } },
|
|
||||||
.Vector3i32 => .{ .Vector3i32 = Vec3i32{ 0, 0, 0 } },
|
|
||||||
.Vector2i32 => .{ .Vector2i32 = Vec2i32{ 0, 0 } },
|
|
||||||
.Vector4u32 => .{ .Vector4u32 = Vec4u32{ 0, 0, 0, 0 } },
|
|
||||||
.Vector3u32 => .{ .Vector3u32 = Vec3u32{ 0, 0, 0 } },
|
|
||||||
.Vector2u32 => .{ .Vector2u32 = Vec2u32{ 0, 0 } },
|
|
||||||
.Matrix => |m| blk: {
|
|
||||||
var self: Value = .{ .Matrix = allocator.alloc(Value, member_count) catch return RuntimeError.OutOfMemory };
|
|
||||||
errdefer self.deinit(allocator);
|
|
||||||
|
|
||||||
for (self.Matrix) |*value| {
|
|
||||||
value.* = try Value.init(allocator, results, m.column_type_word);
|
|
||||||
}
|
|
||||||
break :blk self;
|
|
||||||
},
|
|
||||||
.Array => |a| blk: {
|
|
||||||
var self: Value = .{ .Array = allocator.alloc(Value, member_count) catch return RuntimeError.OutOfMemory };
|
|
||||||
errdefer self.deinit(allocator);
|
|
||||||
|
|
||||||
for (self.Array) |*value| {
|
|
||||||
value.* = try Value.init(allocator, results, a.components_type_word);
|
|
||||||
}
|
|
||||||
break :blk self;
|
|
||||||
},
|
|
||||||
.Structure => |s| blk: {
|
|
||||||
var self: Value = .{ .Structure = allocator.alloc(Value, member_count) catch return RuntimeError.OutOfMemory };
|
|
||||||
errdefer self.deinit(allocator);
|
|
||||||
|
|
||||||
for (self.Structure, s.members_type_word) |*value, member_type_word| {
|
|
||||||
value.* = try Value.init(allocator, results, member_type_word);
|
|
||||||
}
|
|
||||||
break :blk self;
|
|
||||||
},
|
|
||||||
.RuntimeArray => |a| .{
|
|
||||||
.RuntimeArray = .{
|
|
||||||
.type_word = a.components_type_word,
|
|
||||||
.data = &.{},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
else => unreachable,
|
|
||||||
},
|
|
||||||
else => unreachable,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Performs a deep copy
|
|
||||||
pub fn dupe(self: *const Value, allocator: std.mem.Allocator) RuntimeError!Value {
|
|
||||||
return switch (self.*) {
|
|
||||||
.Vector => |v| .{
|
|
||||||
.Vector = blk: {
|
|
||||||
const values = allocator.dupe(Value, v) catch return RuntimeError.OutOfMemory;
|
|
||||||
for (values, v) |*new_value, value| new_value.* = try value.dupe(allocator);
|
|
||||||
break :blk values;
|
|
||||||
},
|
|
||||||
},
|
|
||||||
.Matrix => |m| .{
|
|
||||||
.Matrix = blk: {
|
|
||||||
const values = allocator.dupe(Value, m) catch return RuntimeError.OutOfMemory;
|
|
||||||
for (values, m) |*new_value, value| new_value.* = try value.dupe(allocator);
|
|
||||||
break :blk values;
|
|
||||||
},
|
|
||||||
},
|
|
||||||
.Array => |a| .{
|
|
||||||
.Array = blk: {
|
|
||||||
const values = allocator.dupe(Value, a) catch return RuntimeError.OutOfMemory;
|
|
||||||
for (values, a) |*new_value, value| new_value.* = try value.dupe(allocator);
|
|
||||||
break :blk values;
|
|
||||||
},
|
|
||||||
},
|
|
||||||
.Structure => |s| .{
|
|
||||||
.Structure = blk: {
|
|
||||||
const values = allocator.dupe(Value, s) catch return RuntimeError.OutOfMemory;
|
|
||||||
for (values, s) |*new_value, value| new_value.* = try value.dupe(allocator);
|
|
||||||
break :blk values;
|
|
||||||
},
|
|
||||||
},
|
|
||||||
else => self.*,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn read(self: *const Value, output: []u8) RuntimeError!usize {
|
|
||||||
switch (self.*) {
|
|
||||||
.Bool => |b| {
|
|
||||||
output[0] = if (b == true) 1 else 0;
|
|
||||||
return 1;
|
|
||||||
},
|
|
||||||
.Int => |i| {
|
|
||||||
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 (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 v.read(output[offset..]);
|
|
||||||
}
|
|
||||||
return offset;
|
|
||||||
},
|
|
||||||
else => return RuntimeError.InvalidValueType,
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn writeConst(self: *Value, input: []const u8) RuntimeError!usize {
|
|
||||||
return self.write(@constCast(input));
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn write(self: *Value, input: []u8) RuntimeError!usize {
|
|
||||||
switch (self.*) {
|
|
||||||
.Bool => |*b| {
|
|
||||||
b.* = if (input[0] != 0) true else false;
|
|
||||||
return 1;
|
|
||||||
},
|
|
||||||
.Int => |*i| {
|
|
||||||
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;
|
|
||||||
if (start >= input.len or end > input.len) return RuntimeError.OutOfBounds;
|
|
||||||
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;
|
|
||||||
if (start >= input.len or end > input.len) return RuntimeError.OutOfBounds;
|
|
||||||
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;
|
|
||||||
if (start >= input.len or end > input.len) return RuntimeError.OutOfBounds;
|
|
||||||
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;
|
|
||||||
if (start >= input.len or end > input.len) return RuntimeError.OutOfBounds;
|
|
||||||
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;
|
|
||||||
if (start >= input.len or end > input.len) return RuntimeError.OutOfBounds;
|
|
||||||
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;
|
|
||||||
if (start >= input.len or end > input.len) return RuntimeError.OutOfBounds;
|
|
||||||
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;
|
|
||||||
if (start >= input.len or end > input.len) return RuntimeError.OutOfBounds;
|
|
||||||
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;
|
|
||||||
if (start >= input.len or end > input.len) return RuntimeError.OutOfBounds;
|
|
||||||
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;
|
|
||||||
if (start >= input.len or end > input.len) return RuntimeError.OutOfBounds;
|
|
||||||
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 v.write(input[offset..]);
|
|
||||||
}
|
|
||||||
return offset;
|
|
||||||
},
|
|
||||||
.RuntimeArray => |*arr| arr.data = input[0..],
|
|
||||||
else => return RuntimeError.InvalidValueType,
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn flushPtr(self: *Value, allocator: std.mem.Allocator) RuntimeError!void {
|
|
||||||
switch (self.*) {
|
|
||||||
.Pointer => |*p| {
|
|
||||||
if (p.runtime_array_window) |window| {
|
|
||||||
switch (p.ptr) {
|
|
||||||
.common => |ptr| {
|
|
||||||
_ = try ptr.read(window);
|
|
||||||
ptr.deinit(allocator);
|
|
||||||
allocator.destroy(ptr);
|
|
||||||
},
|
|
||||||
else => {},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
p.runtime_array_window = null;
|
|
||||||
},
|
|
||||||
else => {},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn deinit(self: *Value, allocator: std.mem.Allocator) void {
|
|
||||||
switch (self.*) {
|
|
||||||
.Vector, .Matrix, .Array, .Structure => |values| {
|
|
||||||
for (values) |*value| value.deinit(allocator);
|
|
||||||
allocator.free(values);
|
|
||||||
},
|
|
||||||
else => {},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
pub const TypeData = union(Type) {
|
pub const TypeData = union(Type) {
|
||||||
Void: struct {},
|
Void: struct {},
|
||||||
Bool: struct {},
|
Bool: struct {},
|
||||||
|
|||||||
448
src/Value.zig
git.filemode.normal_file
448
src/Value.zig
git.filemode.normal_file
@@ -0,0 +1,448 @@
|
|||||||
|
const std = @import("std");
|
||||||
|
const lib = @import("lib.zig");
|
||||||
|
|
||||||
|
const Result = @import("Result.zig");
|
||||||
|
const Runtime = @import("Runtime.zig");
|
||||||
|
const RuntimeError = Runtime.RuntimeError;
|
||||||
|
|
||||||
|
const SpvVoid = lib.SpvVoid;
|
||||||
|
const SpvByte = lib.SpvByte;
|
||||||
|
const SpvWord = lib.SpvWord;
|
||||||
|
const SpvBool = lib.SpvBool;
|
||||||
|
|
||||||
|
const Vec4f32 = lib.Vec4f32;
|
||||||
|
const Vec3f32 = lib.Vec3f32;
|
||||||
|
const Vec2f32 = lib.Vec2f32;
|
||||||
|
|
||||||
|
const Vec4i32 = lib.Vec4i32;
|
||||||
|
const Vec3i32 = lib.Vec3i32;
|
||||||
|
const Vec2i32 = lib.Vec2i32;
|
||||||
|
|
||||||
|
const Vec4u32 = lib.Vec4u32;
|
||||||
|
const Vec3u32 = lib.Vec3u32;
|
||||||
|
const Vec2u32 = lib.Vec2u32;
|
||||||
|
|
||||||
|
const Type = Result.Type;
|
||||||
|
|
||||||
|
pub const Value = union(Type) {
|
||||||
|
const Self = @This();
|
||||||
|
|
||||||
|
Void: struct {},
|
||||||
|
Bool: bool,
|
||||||
|
Int: struct {
|
||||||
|
bit_count: usize,
|
||||||
|
value: extern union {
|
||||||
|
sint8: i8,
|
||||||
|
sint16: i16,
|
||||||
|
sint32: i32,
|
||||||
|
sint64: i64,
|
||||||
|
uint8: u8,
|
||||||
|
uint16: u16,
|
||||||
|
uint32: u32,
|
||||||
|
uint64: u64,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Float: struct {
|
||||||
|
bit_count: usize,
|
||||||
|
value: extern union {
|
||||||
|
float16: f16,
|
||||||
|
float32: f32,
|
||||||
|
float64: f64,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Vector: []Self,
|
||||||
|
Vector4f32: Vec4f32,
|
||||||
|
Vector3f32: Vec3f32,
|
||||||
|
Vector2f32: Vec2f32,
|
||||||
|
Vector4i32: Vec4i32,
|
||||||
|
Vector3i32: Vec3i32,
|
||||||
|
Vector2i32: Vec2i32,
|
||||||
|
Vector4u32: Vec4u32,
|
||||||
|
Vector3u32: Vec3u32,
|
||||||
|
Vector2u32: Vec2u32,
|
||||||
|
Matrix: []Self,
|
||||||
|
Array: []Self,
|
||||||
|
RuntimeArray: struct {
|
||||||
|
type_word: SpvWord,
|
||||||
|
data: []u8,
|
||||||
|
},
|
||||||
|
Structure: []Self,
|
||||||
|
Function: noreturn,
|
||||||
|
Image: struct {},
|
||||||
|
Sampler: struct {},
|
||||||
|
SampledImage: struct {},
|
||||||
|
Pointer: struct {
|
||||||
|
ptr: union(enum) {
|
||||||
|
common: *Self,
|
||||||
|
f32_ptr: *f32,
|
||||||
|
i32_ptr: *i32, //< For vector specializations
|
||||||
|
u32_ptr: *u32,
|
||||||
|
},
|
||||||
|
runtime_array_window: ?[]u8 = null,
|
||||||
|
},
|
||||||
|
|
||||||
|
pub inline fn getCompositeDataOrNull(self: *const Self) ?[]Self {
|
||||||
|
return switch (self.*) {
|
||||||
|
.Vector, .Matrix, .Array, .Structure => |v| v,
|
||||||
|
else => null,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn init(allocator: std.mem.Allocator, results: []const Result, target: SpvWord) RuntimeError!Self {
|
||||||
|
const resolved = results[target].resolveType(results);
|
||||||
|
const member_count = resolved.getMemberCounts();
|
||||||
|
|
||||||
|
return switch (resolved.variant.?) {
|
||||||
|
.Type => |t| switch (t) {
|
||||||
|
.Bool => .{ .Bool = false },
|
||||||
|
.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: Self = .{ .Vector = allocator.alloc(Self, member_count) catch return RuntimeError.OutOfMemory };
|
||||||
|
errdefer self.deinit(allocator);
|
||||||
|
|
||||||
|
for (self.Vector) |*value| {
|
||||||
|
value.* = try Self.init(allocator, results, v.components_type_word);
|
||||||
|
}
|
||||||
|
break :blk self;
|
||||||
|
},
|
||||||
|
.Vector4f32 => .{ .Vector4f32 = Vec4f32{ 0.0, 0.0, 0.0, 0.0 } },
|
||||||
|
.Vector3f32 => .{ .Vector3f32 = Vec3f32{ 0.0, 0.0, 0.0 } },
|
||||||
|
.Vector2f32 => .{ .Vector2f32 = Vec2f32{ 0.0, 0.0 } },
|
||||||
|
.Vector4i32 => .{ .Vector4i32 = Vec4i32{ 0, 0, 0, 0 } },
|
||||||
|
.Vector3i32 => .{ .Vector3i32 = Vec3i32{ 0, 0, 0 } },
|
||||||
|
.Vector2i32 => .{ .Vector2i32 = Vec2i32{ 0, 0 } },
|
||||||
|
.Vector4u32 => .{ .Vector4u32 = Vec4u32{ 0, 0, 0, 0 } },
|
||||||
|
.Vector3u32 => .{ .Vector3u32 = Vec3u32{ 0, 0, 0 } },
|
||||||
|
.Vector2u32 => .{ .Vector2u32 = Vec2u32{ 0, 0 } },
|
||||||
|
.Matrix => |m| blk: {
|
||||||
|
var self: Self = .{ .Matrix = allocator.alloc(Self, member_count) catch return RuntimeError.OutOfMemory };
|
||||||
|
errdefer self.deinit(allocator);
|
||||||
|
|
||||||
|
for (self.Matrix) |*value| {
|
||||||
|
value.* = try Self.init(allocator, results, m.column_type_word);
|
||||||
|
}
|
||||||
|
break :blk self;
|
||||||
|
},
|
||||||
|
.Array => |a| blk: {
|
||||||
|
var self: Self = .{ .Array = allocator.alloc(Self, member_count) catch return RuntimeError.OutOfMemory };
|
||||||
|
errdefer self.deinit(allocator);
|
||||||
|
|
||||||
|
for (self.Array) |*value| {
|
||||||
|
value.* = try Self.init(allocator, results, a.components_type_word);
|
||||||
|
}
|
||||||
|
break :blk self;
|
||||||
|
},
|
||||||
|
.Structure => |s| blk: {
|
||||||
|
var self: Self = .{ .Structure = allocator.alloc(Self, member_count) catch return RuntimeError.OutOfMemory };
|
||||||
|
errdefer self.deinit(allocator);
|
||||||
|
|
||||||
|
for (self.Structure, s.members_type_word) |*value, member_type_word| {
|
||||||
|
value.* = try Self.init(allocator, results, member_type_word);
|
||||||
|
}
|
||||||
|
break :blk self;
|
||||||
|
},
|
||||||
|
.RuntimeArray => |a| .{
|
||||||
|
.RuntimeArray = .{
|
||||||
|
.type_word = a.components_type_word,
|
||||||
|
.data = &.{},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
else => unreachable,
|
||||||
|
},
|
||||||
|
else => unreachable,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Performs a deep copy
|
||||||
|
pub fn dupe(self: *const Self, allocator: std.mem.Allocator) RuntimeError!Self {
|
||||||
|
return switch (self.*) {
|
||||||
|
.Vector => |v| .{
|
||||||
|
.Vector = blk: {
|
||||||
|
const values = allocator.dupe(Self, v) catch return RuntimeError.OutOfMemory;
|
||||||
|
for (values, v) |*new_value, value| new_value.* = try value.dupe(allocator);
|
||||||
|
break :blk values;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
.Matrix => |m| .{
|
||||||
|
.Matrix = blk: {
|
||||||
|
const values = allocator.dupe(Self, m) catch return RuntimeError.OutOfMemory;
|
||||||
|
for (values, m) |*new_value, value| new_value.* = try value.dupe(allocator);
|
||||||
|
break :blk values;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
.Array => |a| .{
|
||||||
|
.Array = blk: {
|
||||||
|
const values = allocator.dupe(Self, a) catch return RuntimeError.OutOfMemory;
|
||||||
|
for (values, a) |*new_value, value| new_value.* = try value.dupe(allocator);
|
||||||
|
break :blk values;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
.Structure => |s| .{
|
||||||
|
.Structure = blk: {
|
||||||
|
const values = allocator.dupe(Self, s) catch return RuntimeError.OutOfMemory;
|
||||||
|
for (values, s) |*new_value, value| new_value.* = try value.dupe(allocator);
|
||||||
|
break :blk values;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
else => self.*,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn read(self: *const Self, output: []u8) RuntimeError!usize {
|
||||||
|
switch (self.*) {
|
||||||
|
.Bool => |b| {
|
||||||
|
output[0] = if (b == true) 1 else 0;
|
||||||
|
return 1;
|
||||||
|
},
|
||||||
|
.Int => |i| {
|
||||||
|
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 (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 v.read(output[offset..]);
|
||||||
|
}
|
||||||
|
return offset;
|
||||||
|
},
|
||||||
|
else => return RuntimeError.InvalidValueType,
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn writeConst(self: *Self, input: []const u8) RuntimeError!usize {
|
||||||
|
return self.write(@constCast(input));
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn write(self: *Self, input: []u8) RuntimeError!usize {
|
||||||
|
switch (self.*) {
|
||||||
|
.Bool => |*b| {
|
||||||
|
b.* = if (input[0] != 0) true else false;
|
||||||
|
return 1;
|
||||||
|
},
|
||||||
|
.Int => |*i| {
|
||||||
|
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;
|
||||||
|
if (start >= input.len or end > input.len) return RuntimeError.OutOfBounds;
|
||||||
|
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;
|
||||||
|
if (start >= input.len or end > input.len) return RuntimeError.OutOfBounds;
|
||||||
|
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;
|
||||||
|
if (start >= input.len or end > input.len) return RuntimeError.OutOfBounds;
|
||||||
|
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;
|
||||||
|
if (start >= input.len or end > input.len) return RuntimeError.OutOfBounds;
|
||||||
|
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;
|
||||||
|
if (start >= input.len or end > input.len) return RuntimeError.OutOfBounds;
|
||||||
|
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;
|
||||||
|
if (start >= input.len or end > input.len) return RuntimeError.OutOfBounds;
|
||||||
|
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;
|
||||||
|
if (start >= input.len or end > input.len) return RuntimeError.OutOfBounds;
|
||||||
|
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;
|
||||||
|
if (start >= input.len or end > input.len) return RuntimeError.OutOfBounds;
|
||||||
|
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;
|
||||||
|
if (start >= input.len or end > input.len) return RuntimeError.OutOfBounds;
|
||||||
|
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 v.write(input[offset..]);
|
||||||
|
}
|
||||||
|
return offset;
|
||||||
|
},
|
||||||
|
.RuntimeArray => |*arr| arr.data = input[0..],
|
||||||
|
else => return RuntimeError.InvalidValueType,
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn flushPtr(self: *Self, allocator: std.mem.Allocator) RuntimeError!void {
|
||||||
|
switch (self.*) {
|
||||||
|
.Pointer => |*p| {
|
||||||
|
if (p.runtime_array_window) |window| {
|
||||||
|
switch (p.ptr) {
|
||||||
|
.common => |ptr| {
|
||||||
|
_ = try ptr.read(window);
|
||||||
|
ptr.deinit(allocator);
|
||||||
|
allocator.destroy(ptr);
|
||||||
|
},
|
||||||
|
else => {},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
p.runtime_array_window = null;
|
||||||
|
},
|
||||||
|
else => {},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn deinit(self: *Self, allocator: std.mem.Allocator) void {
|
||||||
|
switch (self.*) {
|
||||||
|
.Vector, .Matrix, .Array, .Structure => |values| {
|
||||||
|
for (values) |*value| value.deinit(allocator);
|
||||||
|
allocator.free(values);
|
||||||
|
},
|
||||||
|
else => {},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
12
src/lib.zig
12
src/lib.zig
@@ -42,6 +42,18 @@ pub const SpvByte = spv.SpvByte;
|
|||||||
pub const SpvWord = spv.SpvWord;
|
pub const SpvWord = spv.SpvWord;
|
||||||
pub const SpvBool = spv.SpvBool;
|
pub const SpvBool = spv.SpvBool;
|
||||||
|
|
||||||
|
pub const Vec4f32 = @Vector(4, f32);
|
||||||
|
pub const Vec3f32 = @Vector(3, f32);
|
||||||
|
pub const Vec2f32 = @Vector(2, f32);
|
||||||
|
|
||||||
|
pub const Vec4i32 = @Vector(4, i32);
|
||||||
|
pub const Vec3i32 = @Vector(3, i32);
|
||||||
|
pub const Vec2i32 = @Vector(2, i32);
|
||||||
|
|
||||||
|
pub const Vec4u32 = @Vector(4, u32);
|
||||||
|
pub const Vec3u32 = @Vector(3, u32);
|
||||||
|
pub const Vec2u32 = @Vector(2, u32);
|
||||||
|
|
||||||
pub const GLSL_std_450 = @import("GLSL_std_450/opcodes.zig");
|
pub const GLSL_std_450 = @import("GLSL_std_450/opcodes.zig");
|
||||||
|
|
||||||
/// Maximum number of input locations per module
|
/// Maximum number of input locations per module
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ const GLSL_std_450 = @import("GLSL_std_450/opcodes.zig");
|
|||||||
const Module = @import("Module.zig");
|
const Module = @import("Module.zig");
|
||||||
const Runtime = @import("Runtime.zig");
|
const Runtime = @import("Runtime.zig");
|
||||||
const Result = @import("Result.zig");
|
const Result = @import("Result.zig");
|
||||||
|
const Value = @import("Value.zig").Value;
|
||||||
const WordIterator = @import("WordIterator.zig");
|
const WordIterator = @import("WordIterator.zig");
|
||||||
|
|
||||||
const RuntimeError = Runtime.RuntimeError;
|
const RuntimeError = Runtime.RuntimeError;
|
||||||
@@ -359,7 +360,7 @@ fn BitOperator(comptime T: ValueType, comptime Op: BitOp) type {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn applyScalarBits(rt: *Runtime, bit_count: SpvWord, dst: *Result.Value, op1_v: *const Result.Value, op2_v: ?*const Result.Value) RuntimeError!void {
|
fn applyScalarBits(rt: *Runtime, bit_count: SpvWord, dst: *Value, op1_v: *const Value, op2_v: ?*const Value) RuntimeError!void {
|
||||||
switch (bit_count) {
|
switch (bit_count) {
|
||||||
inline 8, 16, 32, 64 => |bits| {
|
inline 8, 16, 32, 64 => |bits| {
|
||||||
const TT = getValuePrimitiveFieldType(T, bits);
|
const TT = getValuePrimitiveFieldType(T, bits);
|
||||||
@@ -379,13 +380,13 @@ fn BitOperator(comptime T: ValueType, comptime Op: BitOp) type {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn laneRhsPtr(op2_value: ?*Result.Value, index: usize) ?*const Result.Value {
|
fn laneRhsPtr(op2_value: ?*Value, index: usize) ?*const Value {
|
||||||
if (comptime isUnaryOp()) return null;
|
if (comptime isUnaryOp()) return null;
|
||||||
const v = op2_value orelse return null;
|
const v = op2_value orelse return null;
|
||||||
return &v.Vector[index];
|
return &v.Vector[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
fn applyFixedVector(comptime ElemT: type, comptime N: usize, dst: *[N]ElemT, op1: *[N]ElemT, op2_value: ?*Result.Value) RuntimeError!void {
|
fn applyFixedVector(comptime ElemT: type, comptime N: usize, dst: *[N]ElemT, op1: *[N]ElemT, op2_value: ?*Value) RuntimeError!void {
|
||||||
if (comptime isUnaryOp()) {
|
if (comptime isUnaryOp()) {
|
||||||
inline for (0..N) |i| dst[i] = try operationUnary(ElemT, op1[i]);
|
inline for (0..N) |i| dst[i] = try operationUnary(ElemT, op1[i]);
|
||||||
} else {
|
} else {
|
||||||
@@ -432,7 +433,7 @@ fn BitEngine(comptime T: ValueType, comptime Op: BitOp) type {
|
|||||||
|
|
||||||
const operator = BitOperator(T, Op);
|
const operator = BitOperator(T, Op);
|
||||||
|
|
||||||
const op2_value: ?*Result.Value = if (comptime operator.isUnaryOp()) null else try rt.results[try rt.it.next()].getValue();
|
const op2_value: ?*Value = if (comptime operator.isUnaryOp()) null else try rt.results[try rt.it.next()].getValue();
|
||||||
|
|
||||||
const lane_bits = try Result.resolveLaneBitWidth(target_type, rt);
|
const lane_bits = try Result.resolveLaneBitWidth(target_type, rt);
|
||||||
|
|
||||||
@@ -529,7 +530,7 @@ fn CondOperator(comptime T: ValueType, comptime Op: CondOp) type {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn applyLane(bit_count: SpvWord, dst_bool: *Result.Value, a_v: *const Result.Value, b_v: ?*const Result.Value) RuntimeError!void {
|
fn applyLane(bit_count: SpvWord, dst_bool: *Value, a_v: *const Value, b_v: ?*const Value) RuntimeError!void {
|
||||||
switch (bit_count) {
|
switch (bit_count) {
|
||||||
inline 8, 16, 32, 64 => |bits| {
|
inline 8, 16, 32, 64 => |bits| {
|
||||||
if (bits == 8 and T == .Float) return RuntimeError.InvalidSpirV;
|
if (bits == 8 and T == .Float) return RuntimeError.InvalidSpirV;
|
||||||
@@ -549,7 +550,7 @@ fn CondOperator(comptime T: ValueType, comptime Op: CondOp) type {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn laneRhsPtr(op2_value: ?*Result.Value, index: usize) ?*const Result.Value {
|
fn laneRhsPtr(op2_value: ?*Value, index: usize) ?*const Value {
|
||||||
if (comptime Op == .LogicalNot) return null;
|
if (comptime Op == .LogicalNot) return null;
|
||||||
const v = op2_value orelse return null;
|
const v = op2_value orelse return null;
|
||||||
return &v.Vector[index];
|
return &v.Vector[index];
|
||||||
@@ -572,7 +573,7 @@ fn CondEngine(comptime T: ValueType, comptime Op: CondOp) type {
|
|||||||
const op1_type = try op1_result.getValueTypeWord();
|
const op1_type = try op1_result.getValueTypeWord();
|
||||||
const op1_value = try op1_result.getValue();
|
const op1_value = try op1_result.getValue();
|
||||||
|
|
||||||
const op2_value: ?*Result.Value = if (unary_condition_set.contains(Op)) null else try rt.results[try rt.it.next()].getValue();
|
const op2_value: ?*Value = if (unary_condition_set.contains(Op)) null else try rt.results[try rt.it.next()].getValue();
|
||||||
|
|
||||||
const lane_bits = try Result.resolveLaneBitWidth((try rt.results[op1_type].getVariant()).Type, rt);
|
const lane_bits = try Result.resolveLaneBitWidth((try rt.results[op1_type].getVariant()).Type, rt);
|
||||||
|
|
||||||
@@ -606,7 +607,7 @@ fn ConversionEngine(comptime from_kind: ValueType, comptime to_kind: ValueType)
|
|||||||
const to_bits = try Result.resolveLaneBitWidth(target_type, rt);
|
const to_bits = try Result.resolveLaneBitWidth(target_type, rt);
|
||||||
|
|
||||||
const caster = struct {
|
const caster = struct {
|
||||||
fn castLane(comptime ToT: type, from_bit_count: SpvWord, from: *Result.Value) RuntimeError!ToT {
|
fn castLane(comptime ToT: type, from_bit_count: SpvWord, from: *Value) RuntimeError!ToT {
|
||||||
return switch (from_bit_count) {
|
return switch (from_bit_count) {
|
||||||
inline 8, 16, 32, 64 => |bits| blk: {
|
inline 8, 16, 32, 64 => |bits| blk: {
|
||||||
if (bits == 8 and from_kind == .Float) return RuntimeError.InvalidSpirV; // No f8
|
if (bits == 8 and from_kind == .Float) return RuntimeError.InvalidSpirV; // No f8
|
||||||
@@ -617,7 +618,7 @@ fn ConversionEngine(comptime from_kind: ValueType, comptime to_kind: ValueType)
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn applyScalar(from_bit_count: SpvWord, to_bit_count: SpvWord, dst: *Result.Value, from: *Result.Value) RuntimeError!void {
|
fn applyScalar(from_bit_count: SpvWord, to_bit_count: SpvWord, dst: *Value, from: *Value) RuntimeError!void {
|
||||||
switch (to_bit_count) {
|
switch (to_bit_count) {
|
||||||
inline 8, 16, 32, 64 => |bits| {
|
inline 8, 16, 32, 64 => |bits| {
|
||||||
if (bits == 8 and to_kind == .Float) return RuntimeError.InvalidSpirV; // No f8
|
if (bits == 8 and to_kind == .Float) return RuntimeError.InvalidSpirV; // No f8
|
||||||
@@ -743,7 +744,7 @@ fn MathEngine(comptime T: ValueType, comptime Op: MathOp) type {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn applyScalar(bit_count: SpvWord, d: *Result.Value, l: *Result.Value, r: *Result.Value) RuntimeError!void {
|
fn applyScalar(bit_count: SpvWord, d: *Value, l: *Value, r: *Value) RuntimeError!void {
|
||||||
switch (bit_count) {
|
switch (bit_count) {
|
||||||
inline 8, 16, 32, 64 => |bits| {
|
inline 8, 16, 32, 64 => |bits| {
|
||||||
if (bits == 8 and T == .Float) return RuntimeError.InvalidSpirV;
|
if (bits == 8 and T == .Float) return RuntimeError.InvalidSpirV;
|
||||||
@@ -758,7 +759,7 @@ fn MathEngine(comptime T: ValueType, comptime Op: MathOp) type {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline fn applyVectorTimesScalarF32(d: []Result.Value, l: []const Result.Value, r: f32) void {
|
inline fn applyVectorTimesScalarF32(d: []Value, l: []const Value, r: f32) void {
|
||||||
for (d, l) |*d_v, l_v| {
|
for (d, l) |*d_v, l_v| {
|
||||||
d_v.Float.value.float32 = l_v.Float.value.float32 * r;
|
d_v.Float.value.float32 = l_v.Float.value.float32 * r;
|
||||||
}
|
}
|
||||||
@@ -776,7 +777,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 {
|
inline fn applySIMDVectorf32(comptime N: usize, d: *@Vector(N, f32), l: *const @Vector(N, f32), r: *const Value) RuntimeError!void {
|
||||||
switch (Op) {
|
switch (Op) {
|
||||||
.VectorTimesScalar => applyVectorSIMDTimesScalarF32(N, d, l, r.Float.value.float32),
|
.VectorTimesScalar => applyVectorSIMDTimesScalarF32(N, d, l, r.Float.value.float32),
|
||||||
else => {
|
else => {
|
||||||
@@ -833,7 +834,7 @@ fn MathEngine(comptime T: ValueType, comptime Op: MathOp) type {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn applyScalar(bit_count: SpvWord, d: *Result.Value, v: *Result.Value) RuntimeError!void {
|
fn applyScalar(bit_count: SpvWord, d: *Value, v: *Value) RuntimeError!void {
|
||||||
switch (bit_count) {
|
switch (bit_count) {
|
||||||
inline 8, 16, 32, 64 => |bits| {
|
inline 8, 16, 32, 64 => |bits| {
|
||||||
if (bits == 8 and T == .Float) return RuntimeError.InvalidSpirV;
|
if (bits == 8 and T == .Float) return RuntimeError.InvalidSpirV;
|
||||||
@@ -938,7 +939,7 @@ fn opBitcast(_: std.mem.Allocator, _: SpvWord, rt: *Runtime) RuntimeError!void {
|
|||||||
|
|
||||||
const caster = struct {
|
const caster = struct {
|
||||||
/// Asumes that values passed are primitives ints or floats
|
/// Asumes that values passed are primitives ints or floats
|
||||||
fn cast(to: *Result.Value, from: *const Result.Value) RuntimeError!void {
|
fn cast(to: *Value, from: *const Value) RuntimeError!void {
|
||||||
const from_bytes: u64 = switch (from.*) {
|
const from_bytes: u64 = switch (from.*) {
|
||||||
.Float => |f| @bitCast(f.value.float64),
|
.Float => |f| @bitCast(f.value.float64),
|
||||||
.Int => |i| i.value.uint64,
|
.Int => |i| i.value.uint64,
|
||||||
@@ -961,22 +962,22 @@ fn opBitcast(_: std.mem.Allocator, _: SpvWord, rt: *Runtime) RuntimeError!void {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn copyValue(dst: *Result.Value, src: *const Result.Value) void {
|
fn copyValue(dst: *Value, src: *const Value) void {
|
||||||
const helpers = struct {
|
const helpers = struct {
|
||||||
inline fn copySlice(dst_slice: []Result.Value, src_slice: []const Result.Value) void {
|
inline fn copySlice(dst_slice: []Value, src_slice: []const Value) void {
|
||||||
for (0..@min(dst_slice.len, src_slice.len)) |i| {
|
for (0..@min(dst_slice.len, src_slice.len)) |i| {
|
||||||
copyValue(&dst_slice[i], &src_slice[i]);
|
copyValue(&dst_slice[i], &src_slice[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline fn getDstSlice(v: *Result.Value) ?[]Result.Value {
|
inline fn getDstSlice(v: *Value) ?[]Value {
|
||||||
return switch (v.*) {
|
return switch (v.*) {
|
||||||
.Vector, .Matrix, .Array, .Structure => |s| s,
|
.Vector, .Matrix, .Array, .Structure => |s| s,
|
||||||
else => null,
|
else => null,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
inline fn writeF32(dst_f32_ptr: *f32, src_v: *const Result.Value) void {
|
inline fn writeF32(dst_f32_ptr: *f32, src_v: *const Value) void {
|
||||||
switch (src_v.*) {
|
switch (src_v.*) {
|
||||||
.Pointer => |src_ptr| switch (src_ptr.ptr) {
|
.Pointer => |src_ptr| switch (src_ptr.ptr) {
|
||||||
.f32_ptr => |src_f32_ptr| dst_f32_ptr.* = src_f32_ptr.*,
|
.f32_ptr => |src_f32_ptr| dst_f32_ptr.* = src_f32_ptr.*,
|
||||||
@@ -988,7 +989,7 @@ fn copyValue(dst: *Result.Value, src: *const Result.Value) void {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline fn writeI32(dst_i32_ptr: *i32, src_v: *const Result.Value) void {
|
inline fn writeI32(dst_i32_ptr: *i32, src_v: *const Value) void {
|
||||||
switch (src_v.*) {
|
switch (src_v.*) {
|
||||||
.Pointer => |src_ptr| switch (src_ptr.ptr) {
|
.Pointer => |src_ptr| switch (src_ptr.ptr) {
|
||||||
.i32_ptr => |src_i32_ptr| dst_i32_ptr.* = src_i32_ptr.*,
|
.i32_ptr => |src_i32_ptr| dst_i32_ptr.* = src_i32_ptr.*,
|
||||||
@@ -1000,7 +1001,7 @@ fn copyValue(dst: *Result.Value, src: *const Result.Value) void {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline fn writeU32(dst_u32_ptr: *u32, src_v: *const Result.Value) void {
|
inline fn writeU32(dst_u32_ptr: *u32, src_v: *const Value) void {
|
||||||
switch (src_v.*) {
|
switch (src_v.*) {
|
||||||
.Pointer => |src_ptr| switch (src_ptr.ptr) {
|
.Pointer => |src_ptr| switch (src_ptr.ptr) {
|
||||||
.u32_ptr => |src_u32_ptr| dst_u32_ptr.* = src_u32_ptr.*,
|
.u32_ptr => |src_u32_ptr| dst_u32_ptr.* = src_u32_ptr.*,
|
||||||
@@ -1050,7 +1051,7 @@ fn copyValue(dst: *Result.Value, src: *const Result.Value) void {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn getValuePrimitiveField(comptime T: ValueType, comptime BitCount: SpvWord, v: *Result.Value) RuntimeError!*getValuePrimitiveFieldType(T, BitCount) {
|
pub fn getValuePrimitiveField(comptime T: ValueType, comptime BitCount: SpvWord, v: *Value) RuntimeError!*getValuePrimitiveFieldType(T, BitCount) {
|
||||||
if (std.meta.activeTag(v.*) == .Pointer) {
|
if (std.meta.activeTag(v.*) == .Pointer) {
|
||||||
return switch (v.Pointer.ptr) {
|
return switch (v.Pointer.ptr) {
|
||||||
.common => |value| getValuePrimitiveField(T, BitCount, value),
|
.common => |value| getValuePrimitiveField(T, BitCount, value),
|
||||||
@@ -1138,10 +1139,10 @@ fn opAccessChain(allocator: std.mem.Allocator, word_count: SpvWord, rt: *Runtime
|
|||||||
const concrete_allocator = if (is_last) allocator else arena_allocator;
|
const concrete_allocator = if (is_last) allocator else arena_allocator;
|
||||||
const type_size = (try rt.results[arr.type_word].getVariant()).Type.getSize(rt.results);
|
const type_size = (try rt.results[arr.type_word].getVariant()).Type.getSize(rt.results);
|
||||||
|
|
||||||
value_ptr = concrete_allocator.create(Result.Value) catch return RuntimeError.OutOfMemory;
|
value_ptr = concrete_allocator.create(Value) catch return RuntimeError.OutOfMemory;
|
||||||
errdefer concrete_allocator.destroy(value_ptr);
|
errdefer concrete_allocator.destroy(value_ptr);
|
||||||
|
|
||||||
value_ptr.* = try Result.Value.init(concrete_allocator, rt.results, arr.type_word);
|
value_ptr.* = try Value.init(concrete_allocator, rt.results, arr.type_word);
|
||||||
_ = try value_ptr.writeConst(arr.data[(type_size * i.value.uint32)..]);
|
_ = try value_ptr.writeConst(arr.data[(type_size * i.value.uint32)..]);
|
||||||
|
|
||||||
if (is_last)
|
if (is_last)
|
||||||
@@ -1314,7 +1315,7 @@ fn opCompositeExtract(allocator: std.mem.Allocator, word_count: SpvWord, rt: *Ru
|
|||||||
switch (composite) {
|
switch (composite) {
|
||||||
.RuntimeArray => |arr| {
|
.RuntimeArray => |arr| {
|
||||||
const type_size = (try rt.results[arr.type_word].getVariant()).Type.getSize(rt.results);
|
const type_size = (try rt.results[arr.type_word].getVariant()).Type.getSize(rt.results);
|
||||||
composite = try Result.Value.init(arena_allocator, rt.results, arr.type_word);
|
composite = try Value.init(arena_allocator, rt.results, arr.type_word);
|
||||||
_ = try composite.writeConst(arr.data[(type_size * member_id)..]);
|
_ = try composite.writeConst(arr.data[(type_size * member_id)..]);
|
||||||
},
|
},
|
||||||
.Vector4f32 => |v| break :blk .{ .Float = .{ .bit_count = 32, .value = .{ .float32 = v[member_id] } } },
|
.Vector4f32 => |v| break :blk .{ .Float = .{ .bit_count = 32, .value = .{ .float32 = v[member_id] } } },
|
||||||
@@ -1368,6 +1369,38 @@ fn opConstantComposite(allocator: std.mem.Allocator, _: SpvWord, rt: *Runtime) R
|
|||||||
for (values.*) |*element| {
|
for (values.*) |*element| {
|
||||||
copyValue(element, try rt.mod.results[try rt.it.next()].getValue());
|
copyValue(element, try rt.mod.results[try rt.it.next()].getValue());
|
||||||
}
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (target_value.*) {
|
||||||
|
.Vector4f32 => |*v| inline for (0..4) |i| {
|
||||||
|
v[i] = (try rt.mod.results[try rt.it.next()].getValue()).Float.value.float32;
|
||||||
|
},
|
||||||
|
.Vector3f32 => |*v| inline for (0..3) |i| {
|
||||||
|
v[i] = (try rt.mod.results[try rt.it.next()].getValue()).Float.value.float32;
|
||||||
|
},
|
||||||
|
.Vector2f32 => |*v| inline for (0..2) |i| {
|
||||||
|
v[i] = (try rt.mod.results[try rt.it.next()].getValue()).Float.value.float32;
|
||||||
|
},
|
||||||
|
.Vector4i32 => |*v| inline for (0..4) |i| {
|
||||||
|
v[i] = (try rt.mod.results[try rt.it.next()].getValue()).Int.value.sint32;
|
||||||
|
},
|
||||||
|
.Vector3i32 => |*v| inline for (0..3) |i| {
|
||||||
|
v[i] = (try rt.mod.results[try rt.it.next()].getValue()).Int.value.sint32;
|
||||||
|
},
|
||||||
|
.Vector2i32 => |*v| inline for (0..2) |i| {
|
||||||
|
v[i] = (try rt.mod.results[try rt.it.next()].getValue()).Int.value.sint32;
|
||||||
|
},
|
||||||
|
.Vector4u32 => |*v| inline for (0..4) |i| {
|
||||||
|
v[i] = (try rt.mod.results[try rt.it.next()].getValue()).Int.value.uint32;
|
||||||
|
},
|
||||||
|
.Vector3u32 => |*v| inline for (0..3) |i| {
|
||||||
|
v[i] = (try rt.mod.results[try rt.it.next()].getValue()).Int.value.uint32;
|
||||||
|
},
|
||||||
|
.Vector2u32 => |*v| inline for (0..2) |i| {
|
||||||
|
v[i] = (try rt.mod.results[try rt.it.next()].getValue()).Int.value.uint32;
|
||||||
|
},
|
||||||
|
else => return RuntimeError.InvalidSpirV,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user