adding array stride to runtime arrays
This commit is contained in:
@@ -116,6 +116,7 @@ pub const TypeData = union(Type) {
|
|||||||
RuntimeArray: struct {
|
RuntimeArray: struct {
|
||||||
components_type_word: SpvWord,
|
components_type_word: SpvWord,
|
||||||
components_type: Type,
|
components_type: Type,
|
||||||
|
stride: SpvWord,
|
||||||
},
|
},
|
||||||
Structure: struct {
|
Structure: struct {
|
||||||
members_type_word: []const SpvWord,
|
members_type_word: []const SpvWord,
|
||||||
@@ -142,7 +143,7 @@ pub const TypeData = union(Type) {
|
|||||||
.Vector => |v| results[v.components_type_word].variant.?.Type.getSize(results),
|
.Vector => |v| results[v.components_type_word].variant.?.Type.getSize(results),
|
||||||
.Array => |a| results[a.components_type_word].variant.?.Type.getSize(results),
|
.Array => |a| results[a.components_type_word].variant.?.Type.getSize(results),
|
||||||
.Matrix => |m| results[m.column_type_word].variant.?.Type.getSize(results),
|
.Matrix => |m| results[m.column_type_word].variant.?.Type.getSize(results),
|
||||||
.RuntimeArray => |a| results[a.components_type_word].variant.?.Type.getSize(results),
|
.RuntimeArray => |a| a.stride,
|
||||||
.Structure => |s| blk: {
|
.Structure => |s| blk: {
|
||||||
var total: usize = 0;
|
var total: usize = 0;
|
||||||
for (s.members_type_word) |type_word| {
|
for (s.members_type_word) |type_word| {
|
||||||
@@ -425,75 +426,6 @@ pub fn getMemberCounts(self: *const Self) usize {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn initValue(allocator: std.mem.Allocator, member_count: usize, results: []const Self, resolved: *const Self) RuntimeError!Value {
|
|
||||||
return switch (resolved.variant.?) {
|
|
||||||
.Type => |t| switch (t) {
|
|
||||||
.Void => .{ .Void = .{} },
|
|
||||||
.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: {
|
|
||||||
const value: Value = .{ .Vector = allocator.alloc(Value, member_count) catch return RuntimeError.OutOfMemory };
|
|
||||||
errdefer allocator.free(value.Vector);
|
|
||||||
for (value.Vector) |*val| {
|
|
||||||
val.* = try Value.init(allocator, results, v.components_type_word);
|
|
||||||
}
|
|
||||||
break :blk value;
|
|
||||||
},
|
|
||||||
.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: {
|
|
||||||
const value: Value = .{ .Matrix = allocator.alloc(Value, member_count) catch return RuntimeError.OutOfMemory };
|
|
||||||
errdefer allocator.free(value.Matrix);
|
|
||||||
for (value.Matrix) |*v| {
|
|
||||||
v.* = try Value.init(allocator, results, m.column_type_word);
|
|
||||||
}
|
|
||||||
break :blk value;
|
|
||||||
},
|
|
||||||
.Array => |a| blk: {
|
|
||||||
const value: Value = .{ .Array = allocator.alloc(Value, member_count) catch return RuntimeError.OutOfMemory };
|
|
||||||
errdefer allocator.free(value.Array);
|
|
||||||
for (value.Array) |*val| {
|
|
||||||
val.* = try Value.init(allocator, results, a.components_type_word);
|
|
||||||
}
|
|
||||||
break :blk value;
|
|
||||||
},
|
|
||||||
.RuntimeArray => |a| .{
|
|
||||||
.RuntimeArray = .{
|
|
||||||
.type_word = a.components_type_word,
|
|
||||||
.data = &.{},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
.Structure => |s| blk: {
|
|
||||||
const value: Value = .{ .Structure = allocator.alloc(Value, member_count) catch return RuntimeError.OutOfMemory };
|
|
||||||
errdefer allocator.free(value.Structure);
|
|
||||||
for (value.Structure, s.members_type_word) |*v, member_type_word| {
|
|
||||||
v.* = try Value.init(allocator, results, member_type_word);
|
|
||||||
}
|
|
||||||
break :blk value;
|
|
||||||
},
|
|
||||||
.Image => RuntimeError.ToDo,
|
|
||||||
.Sampler => RuntimeError.ToDo,
|
|
||||||
.SampledImage => RuntimeError.ToDo,
|
|
||||||
else => RuntimeError.InvalidSpirV,
|
|
||||||
},
|
|
||||||
else => RuntimeError.InvalidSpirV,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn flushPtr(self: *Self, allocator: std.mem.Allocator) RuntimeError!void {
|
pub fn flushPtr(self: *Self, allocator: std.mem.Allocator) RuntimeError!void {
|
||||||
if (self.variant) |*variant| {
|
if (self.variant) |*variant| {
|
||||||
switch (variant.*) {
|
switch (variant.*) {
|
||||||
|
|||||||
@@ -64,7 +64,22 @@ pub const Value = union(Type) {
|
|||||||
Array: []Self,
|
Array: []Self,
|
||||||
RuntimeArray: struct {
|
RuntimeArray: struct {
|
||||||
type_word: SpvWord,
|
type_word: SpvWord,
|
||||||
|
stride: SpvWord,
|
||||||
data: []u8,
|
data: []u8,
|
||||||
|
|
||||||
|
pub inline fn createValueFromIndex(self: *const @This(), allocator: std.mem.Allocator, results: []Result, index: usize) RuntimeError!*Value {
|
||||||
|
const value = allocator.create(Value) catch return RuntimeError.OutOfMemory;
|
||||||
|
errdefer allocator.destroy(value);
|
||||||
|
|
||||||
|
value.* = try Value.init(allocator, results, self.type_word);
|
||||||
|
_ = try value.writeConst(self.data[(try self.getOffsetOfIndex(index))..]);
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn getOffsetOfIndex(self: *const @This(), index: usize) RuntimeError!usize {
|
||||||
|
return self.stride * index;
|
||||||
|
}
|
||||||
},
|
},
|
||||||
Structure: []Self,
|
Structure: []Self,
|
||||||
Function: noreturn,
|
Function: noreturn,
|
||||||
@@ -94,6 +109,7 @@ pub const Value = union(Type) {
|
|||||||
|
|
||||||
return switch (resolved.variant.?) {
|
return switch (resolved.variant.?) {
|
||||||
.Type => |t| switch (t) {
|
.Type => |t| switch (t) {
|
||||||
|
.Void => .{ .Void = .{} },
|
||||||
.Bool => .{ .Bool = false },
|
.Bool => .{ .Bool = false },
|
||||||
.Int => |i| .{ .Int = .{
|
.Int => |i| .{ .Int = .{
|
||||||
.bit_count = i.bit_length,
|
.bit_count = i.bit_length,
|
||||||
@@ -151,12 +167,16 @@ pub const Value = union(Type) {
|
|||||||
.RuntimeArray => |a| .{
|
.RuntimeArray => |a| .{
|
||||||
.RuntimeArray = .{
|
.RuntimeArray = .{
|
||||||
.type_word = a.components_type_word,
|
.type_word = a.components_type_word,
|
||||||
|
.stride = a.stride,
|
||||||
.data = &.{},
|
.data = &.{},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
else => unreachable,
|
.Image => RuntimeError.ToDo,
|
||||||
|
.Sampler => RuntimeError.ToDo,
|
||||||
|
.SampledImage => RuntimeError.ToDo,
|
||||||
|
else => RuntimeError.InvalidSpirV,
|
||||||
},
|
},
|
||||||
else => unreachable,
|
else => RuntimeError.InvalidSpirV,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1206,21 +1206,14 @@ fn opAccessChain(allocator: std.mem.Allocator, word_count: SpvWord, rt: *Runtime
|
|||||||
|
|
||||||
switch (value_ptr.*) {
|
switch (value_ptr.*) {
|
||||||
.Vector, .Matrix, .Array, .Structure => |v| {
|
.Vector, .Matrix, .Array, .Structure => |v| {
|
||||||
if (i.value.uint32 >= v.len) return RuntimeError.OutOfBounds;
|
if (i.value.uint32 >= v.len)
|
||||||
|
return RuntimeError.OutOfBounds;
|
||||||
value_ptr = &v[i.value.uint32];
|
value_ptr = &v[i.value.uint32];
|
||||||
},
|
},
|
||||||
.RuntimeArray => |*arr| {
|
.RuntimeArray => |*arr| {
|
||||||
const concrete_allocator = if (is_last) allocator else arena_allocator;
|
value_ptr = try arr.createValueFromIndex(if (is_last) allocator else arena_allocator, rt.results, i.value.uint32);
|
||||||
const type_size = (try rt.results[arr.type_word].getVariant()).Type.getSize(rt.results);
|
|
||||||
|
|
||||||
value_ptr = concrete_allocator.create(Value) catch return RuntimeError.OutOfMemory;
|
|
||||||
errdefer concrete_allocator.destroy(value_ptr);
|
|
||||||
|
|
||||||
value_ptr.* = try Value.init(concrete_allocator, rt.results, arr.type_word);
|
|
||||||
_ = try value_ptr.writeConst(arr.data[(type_size * i.value.uint32)..]);
|
|
||||||
|
|
||||||
if (is_last)
|
if (is_last)
|
||||||
runtime_array_window = arr.data[(type_size * i.value.uint32)..];
|
runtime_array_window = arr.data[(try arr.getOffsetOfIndex(i.value.uint32))..];
|
||||||
},
|
},
|
||||||
.Vector4f32 => |*v| {
|
.Vector4f32 => |*v| {
|
||||||
if (i.value.uint32 > 4) return RuntimeError.OutOfBounds;
|
if (i.value.uint32 > 4) return RuntimeError.OutOfBounds;
|
||||||
@@ -1320,13 +1313,12 @@ fn opCompositeConstruct(_: std.mem.Allocator, word_count: SpvWord, rt: *Runtime)
|
|||||||
|
|
||||||
switch (value.*) {
|
switch (value.*) {
|
||||||
.RuntimeArray => |arr| {
|
.RuntimeArray => |arr| {
|
||||||
const type_size = (try rt.results[arr.type_word].getVariant()).Type.getSize(rt.results);
|
|
||||||
var offset: usize = 0;
|
var offset: usize = 0;
|
||||||
|
|
||||||
for (0..index_count) |_| {
|
for (0..index_count) |_| {
|
||||||
const elem_value = (try rt.results[try rt.it.next()].getVariant()).Constant.value;
|
const elem_value = (try rt.results[try rt.it.next()].getVariant()).Constant.value;
|
||||||
std.mem.copyForwards(u8, arr.data[offset..(offset + type_size)], std.mem.asBytes(&elem_value));
|
std.mem.copyForwards(u8, arr.data[offset..(offset + arr.stride)], std.mem.asBytes(&elem_value));
|
||||||
offset += type_size;
|
offset += arr.stride;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
.Vector4f32 => |*vec| inline for (0..4) |i| {
|
.Vector4f32 => |*vec| inline for (0..4) |i| {
|
||||||
@@ -1388,9 +1380,8 @@ 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);
|
|
||||||
composite = try 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[(try arr.getOffsetOfIndex(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] } } },
|
||||||
.Vector3f32 => |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] } } },
|
||||||
@@ -2006,14 +1997,20 @@ fn opTypePointer(_: std.mem.Allocator, _: SpvWord, rt: *Runtime) RuntimeError!vo
|
|||||||
|
|
||||||
fn opTypeRuntimeArray(_: std.mem.Allocator, _: SpvWord, rt: *Runtime) RuntimeError!void {
|
fn opTypeRuntimeArray(_: std.mem.Allocator, _: SpvWord, rt: *Runtime) RuntimeError!void {
|
||||||
const id = try rt.it.next();
|
const id = try rt.it.next();
|
||||||
|
var target = &rt.mod.results[id];
|
||||||
const components_type_word = try rt.it.next();
|
const components_type_word = try rt.it.next();
|
||||||
rt.mod.results[id].variant = .{
|
const components_type_data = &((try rt.mod.results[components_type_word].getVariant()).*).Type;
|
||||||
|
target.variant = .{
|
||||||
.Type = .{
|
.Type = .{
|
||||||
.RuntimeArray = .{
|
.RuntimeArray = .{
|
||||||
.components_type_word = components_type_word,
|
.components_type_word = components_type_word,
|
||||||
.components_type = switch ((try rt.mod.results[components_type_word].getVariant()).*) {
|
.components_type = @as(Result.Type, components_type_data.*),
|
||||||
.Type => |t| @as(Result.Type, t),
|
.stride = blk: {
|
||||||
else => return RuntimeError.InvalidSpirV,
|
for (target.decorations.items) |decoration| {
|
||||||
|
if (decoration.rtype == .ArrayStride)
|
||||||
|
break :blk decoration.literal_1;
|
||||||
|
}
|
||||||
|
break :blk @intCast(components_type_data.getSize(rt.mod.results));
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -2121,7 +2118,6 @@ fn opVariable(allocator: std.mem.Allocator, word_count: SpvWord, rt: *Runtime) R
|
|||||||
|
|
||||||
const resolved_word = if (rt.mod.results[var_type].resolveTypeWordOrNull()) |word| word else var_type;
|
const resolved_word = if (rt.mod.results[var_type].resolveTypeWordOrNull()) |word| word else var_type;
|
||||||
const resolved = &rt.mod.results[resolved_word];
|
const resolved = &rt.mod.results[resolved_word];
|
||||||
const member_count = resolved.getMemberCounts();
|
|
||||||
target.variant = .{
|
target.variant = .{
|
||||||
.Variable = .{
|
.Variable = .{
|
||||||
.storage_class = storage_class,
|
.storage_class = storage_class,
|
||||||
@@ -2130,7 +2126,7 @@ fn opVariable(allocator: std.mem.Allocator, word_count: SpvWord, rt: *Runtime) R
|
|||||||
.Type => |t| @as(Result.Type, t),
|
.Type => |t| @as(Result.Type, t),
|
||||||
else => return RuntimeError.InvalidSpirV,
|
else => return RuntimeError.InvalidSpirV,
|
||||||
},
|
},
|
||||||
.value = try Result.initValue(allocator, member_count, rt.mod.results, resolved),
|
.value = try Value.init(allocator, rt.mod.results, resolved_word),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -2171,10 +2167,9 @@ fn setupConstant(allocator: std.mem.Allocator, rt: *Runtime) RuntimeError!*Resul
|
|||||||
const target = &rt.mod.results[id];
|
const target = &rt.mod.results[id];
|
||||||
|
|
||||||
const resolved = rt.mod.results[res_type].resolveType(rt.mod.results);
|
const resolved = rt.mod.results[res_type].resolveType(rt.mod.results);
|
||||||
const member_count = resolved.getMemberCounts();
|
|
||||||
target.variant = .{
|
target.variant = .{
|
||||||
.Constant = .{
|
.Constant = .{
|
||||||
.value = try Result.initValue(allocator, member_count, rt.mod.results, resolved),
|
.value = try Value.init(allocator, rt.mod.results, res_type),
|
||||||
.type_word = res_type,
|
.type_word = res_type,
|
||||||
.type = switch ((try resolved.getConstVariant()).*) {
|
.type = switch ((try resolved.getConstVariant()).*) {
|
||||||
.Type => |t| @as(Result.Type, t),
|
.Type => |t| @as(Result.Type, t),
|
||||||
|
|||||||
Reference in New Issue
Block a user