improving robust buffer access
This commit is contained in:
+1
-1
@@ -104,7 +104,7 @@ pub const ImageAPI = struct {
|
|||||||
writeImageInt4: *const fn (driver_image: *anyopaque, dim: spv.SpvDim, x: i32, y: i32, z: i32, pixel: Vec4(u32)) RuntimeError!void,
|
writeImageInt4: *const fn (driver_image: *anyopaque, dim: spv.SpvDim, x: i32, y: i32, z: i32, pixel: Vec4(u32)) RuntimeError!void,
|
||||||
sampleImageFloat4: *const fn (driver_image: *anyopaque, driver_sampler: *anyopaque, dim: spv.SpvDim, x: f32, y: f32, z: f32, lod: ?f32, offset: ImageOffset) RuntimeError!Vec4(f32),
|
sampleImageFloat4: *const fn (driver_image: *anyopaque, driver_sampler: *anyopaque, dim: spv.SpvDim, x: f32, y: f32, z: f32, lod: ?f32, offset: ImageOffset) RuntimeError!Vec4(f32),
|
||||||
sampleImageInt4: *const fn (driver_image: *anyopaque, driver_sampler: *anyopaque, dim: spv.SpvDim, x: f32, y: f32, z: f32, lod: ?f32, offset: ImageOffset) RuntimeError!Vec4(u32),
|
sampleImageInt4: *const fn (driver_image: *anyopaque, driver_sampler: *anyopaque, dim: spv.SpvDim, x: f32, y: f32, z: f32, lod: ?f32, offset: ImageOffset) RuntimeError!Vec4(u32),
|
||||||
sampleImageDref: *const fn (driver_image: *anyopaque, driver_sampler: *anyopaque, dim: spv.SpvDim, x: f32, y: f32, z: f32, dref: f32, lod: ?f32, offset: ImageOffset) RuntimeError!f32,
|
sampleImageDref: *const fn (driver_image: *anyopaque, driver_sampler: *anyopaque, dim: spv.SpvDim, x: f32, y: f32, z: f32, w: f32, dref: f32, lod: ?f32, offset: ImageOffset) RuntimeError!f32,
|
||||||
queryImageSize: *const fn (driver_image: *anyopaque, dim: spv.SpvDim, arrayed: bool, lod: ?i32) RuntimeError!Vec4(u32),
|
queryImageSize: *const fn (driver_image: *anyopaque, dim: spv.SpvDim, arrayed: bool, lod: ?i32) RuntimeError!Vec4(u32),
|
||||||
queryImageLevels: *const fn (driver_image: *anyopaque) RuntimeError!u32,
|
queryImageLevels: *const fn (driver_image: *anyopaque) RuntimeError!u32,
|
||||||
queryImageSamples: *const fn (driver_image: *anyopaque) RuntimeError!u32,
|
queryImageSamples: *const fn (driver_image: *anyopaque) RuntimeError!u32,
|
||||||
|
|||||||
+80
-36
@@ -96,6 +96,30 @@ pub const Value = union(Type) {
|
|||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub inline fn createRobustValueFromIndex(self: *const @This(), allocator: std.mem.Allocator, results: []const 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, false);
|
||||||
|
errdefer value.deinit(allocator);
|
||||||
|
|
||||||
|
const bytes = allocator.alloc(u8, self.stride) catch return RuntimeError.OutOfMemory;
|
||||||
|
defer allocator.free(bytes);
|
||||||
|
@memset(bytes, 0);
|
||||||
|
|
||||||
|
if (self.getRobustOffsetOfIndex(index)) |offset| {
|
||||||
|
const available = @min(self.stride, self.data.len - offset);
|
||||||
|
@memcpy(bytes[0..available], self.data[offset .. offset + available]);
|
||||||
|
}
|
||||||
|
|
||||||
|
_ = if (self.matrix_stride) |matrix_stride|
|
||||||
|
try value.writeWithMatrixLayout(bytes, matrix_stride, self.row_major)
|
||||||
|
else
|
||||||
|
try value.write(bytes);
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
pub inline fn createLocalValueFromIndex(self: *const @This(), allocator: std.mem.Allocator, results: []const Result, index: usize) RuntimeError!Value {
|
pub inline fn createLocalValueFromIndex(self: *const @This(), allocator: std.mem.Allocator, results: []const Result, index: usize) RuntimeError!Value {
|
||||||
const offset = try self.getCheckedOffsetOfIndex(index);
|
const offset = try self.getCheckedOffsetOfIndex(index);
|
||||||
var value = try Value.init(allocator, results, self.type_word, false);
|
var value = try Value.init(allocator, results, self.type_word, false);
|
||||||
@@ -111,6 +135,12 @@ pub const Value = union(Type) {
|
|||||||
return self.stride * index;
|
return self.stride * index;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub inline fn getRobustOffsetOfIndex(self: *const @This(), index: usize) ?usize {
|
||||||
|
if (self.stride == 0) return null;
|
||||||
|
const offset = std.math.mul(usize, self.stride, index) catch return null;
|
||||||
|
return if (offset < self.data.len) offset else null;
|
||||||
|
}
|
||||||
|
|
||||||
pub inline fn getCheckedOffsetOfIndex(self: *const @This(), index: usize) RuntimeError!usize {
|
pub inline fn getCheckedOffsetOfIndex(self: *const @This(), index: usize) RuntimeError!usize {
|
||||||
const offset = self.getOffsetOfIndex(index);
|
const offset = self.getOffsetOfIndex(index);
|
||||||
if (self.stride == 0 or offset > self.data.len or self.stride > self.data.len - offset)
|
if (self.stride == 0 or offset > self.data.len or self.stride > self.data.len - offset)
|
||||||
@@ -540,18 +570,18 @@ pub const Value = union(Type) {
|
|||||||
return values[lane_index].write(input);
|
return values[lane_index].write(input);
|
||||||
},
|
},
|
||||||
.Vector2f32, .Vector3f32, .Vector4f32 => {
|
.Vector2f32, .Vector3f32, .Vector4f32 => {
|
||||||
if (input.len < @sizeOf(f32)) return RuntimeError.OutOfBounds;
|
const value: f32 = if (input.len >= @sizeOf(f32)) std.mem.bytesToValue(f32, input[0..@sizeOf(f32)]) else 0;
|
||||||
try writeLane(.Float, 32, self, lane_index, std.mem.bytesToValue(f32, input[0..@sizeOf(f32)]));
|
try writeLane(.Float, 32, self, lane_index, value);
|
||||||
return @sizeOf(f32);
|
return @sizeOf(f32);
|
||||||
},
|
},
|
||||||
.Vector2i32, .Vector3i32, .Vector4i32 => {
|
.Vector2i32, .Vector3i32, .Vector4i32 => {
|
||||||
if (input.len < @sizeOf(i32)) return RuntimeError.OutOfBounds;
|
const value: i32 = if (input.len >= @sizeOf(i32)) std.mem.bytesToValue(i32, input[0..@sizeOf(i32)]) else 0;
|
||||||
try writeLane(.SInt, 32, self, lane_index, std.mem.bytesToValue(i32, input[0..@sizeOf(i32)]));
|
try writeLane(.SInt, 32, self, lane_index, value);
|
||||||
return @sizeOf(i32);
|
return @sizeOf(i32);
|
||||||
},
|
},
|
||||||
.Vector2u32, .Vector3u32, .Vector4u32 => {
|
.Vector2u32, .Vector3u32, .Vector4u32 => {
|
||||||
if (input.len < @sizeOf(u32)) return RuntimeError.OutOfBounds;
|
const value: u32 = if (input.len >= @sizeOf(u32)) std.mem.bytesToValue(u32, input[0..@sizeOf(u32)]) else 0;
|
||||||
try writeLane(.UInt, 32, self, lane_index, std.mem.bytesToValue(u32, input[0..@sizeOf(u32)]));
|
try writeLane(.UInt, 32, self, lane_index, value);
|
||||||
return @sizeOf(u32);
|
return @sizeOf(u32);
|
||||||
},
|
},
|
||||||
else => return RuntimeError.InvalidValueType,
|
else => return RuntimeError.InvalidValueType,
|
||||||
@@ -651,17 +681,17 @@ pub const Value = union(Type) {
|
|||||||
(row_count - 1) * matrix_stride_usize + columns.len * scalar_size
|
(row_count - 1) * matrix_stride_usize + columns.len * scalar_size
|
||||||
else
|
else
|
||||||
(columns.len - 1) * matrix_stride_usize + try columns[0].getPlainMemorySize();
|
(columns.len - 1) * matrix_stride_usize + try columns[0].getPlainMemorySize();
|
||||||
if (input.len < matrix_size) return RuntimeError.OutOfBounds;
|
|
||||||
|
|
||||||
if (row_major) {
|
if (row_major) {
|
||||||
for (columns, 0..) |*column, column_index| {
|
for (columns, 0..) |*column, column_index| {
|
||||||
for (0..row_count) |row_index| {
|
for (0..row_count) |row_index| {
|
||||||
_ = try column.writeVectorLane(row_index, input[row_index * matrix_stride_usize + column_index * scalar_size ..]);
|
const offset = row_index * matrix_stride_usize + column_index * scalar_size;
|
||||||
|
_ = try column.writeVectorLane(row_index, input[@min(offset, input.len)..]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (columns, 0..) |*column, column_index| {
|
for (columns, 0..) |*column, column_index| {
|
||||||
_ = try column.write(input[column_index * matrix_stride_usize ..]);
|
const offset = column_index * matrix_stride_usize;
|
||||||
|
_ = try column.write(input[@min(offset, input.len)..]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return matrix_size;
|
return matrix_size;
|
||||||
@@ -673,7 +703,7 @@ pub const Value = union(Type) {
|
|||||||
.Array => |*arr| blk: {
|
.Array => |*arr| blk: {
|
||||||
var offset: usize = 0;
|
var offset: usize = 0;
|
||||||
for (arr.values) |*value| {
|
for (arr.values) |*value| {
|
||||||
_ = try value.writeWithMatrixLayout(input[offset..], matrix_stride, row_major);
|
_ = try value.writeWithMatrixLayout(input[@min(offset, input.len)..], matrix_stride, row_major);
|
||||||
offset += if (arr.stride != 0) arr.stride else try value.getPlainMemorySize();
|
offset += if (arr.stride != 0) arr.stride else try value.getPlainMemorySize();
|
||||||
}
|
}
|
||||||
break :blk offset;
|
break :blk offset;
|
||||||
@@ -688,10 +718,12 @@ pub const Value = union(Type) {
|
|||||||
const info = @typeInfo(T).vector;
|
const info = @typeInfo(T).vector;
|
||||||
const Lane = info.child;
|
const Lane = info.child;
|
||||||
const size = info.len * @sizeOf(Lane);
|
const size = info.len * @sizeOf(Lane);
|
||||||
if (in.len < size) return RuntimeError.OutOfBounds;
|
|
||||||
inline for (0..info.len) |i| {
|
inline for (0..info.len) |i| {
|
||||||
const offset = i * @sizeOf(Lane);
|
const offset = i * @sizeOf(Lane);
|
||||||
vec[i] = std.mem.bytesToValue(Lane, in[offset..][0..@sizeOf(Lane)]);
|
vec[i] = if (offset + @sizeOf(Lane) <= in.len)
|
||||||
|
std.mem.bytesToValue(Lane, in[offset..][0..@sizeOf(Lane)])
|
||||||
|
else
|
||||||
|
0;
|
||||||
}
|
}
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
@@ -699,27 +731,25 @@ pub const Value = union(Type) {
|
|||||||
|
|
||||||
switch (self.*) {
|
switch (self.*) {
|
||||||
.Bool => |*b| {
|
.Bool => |*b| {
|
||||||
if (input.len < 1) return RuntimeError.OutOfBounds;
|
b.* = if (input.len >= 1 and input[0] != 0) true else false;
|
||||||
b.* = if (input[0] != 0) true else false;
|
|
||||||
return 1;
|
return 1;
|
||||||
},
|
},
|
||||||
.Int => |*i| {
|
.Int => |*i| {
|
||||||
switch (i.bit_count) {
|
switch (i.bit_count) {
|
||||||
8 => {
|
8 => {
|
||||||
if (input.len < 1) return RuntimeError.OutOfBounds;
|
i.value.uint8 = if (input.len >= 1) @bitCast(input[0]) else 0;
|
||||||
i.value.uint8 = @bitCast(input[0]);
|
|
||||||
},
|
},
|
||||||
16 => {
|
16 => {
|
||||||
if (input.len < 2) return RuntimeError.OutOfBounds;
|
i.value.uint16 = 0;
|
||||||
@memcpy(std.mem.asBytes(&i.value.uint16), input[0..2]);
|
if (input.len >= 2) @memcpy(std.mem.asBytes(&i.value.uint16), input[0..2]);
|
||||||
},
|
},
|
||||||
32 => {
|
32 => {
|
||||||
if (input.len < 4) return RuntimeError.OutOfBounds;
|
i.value.uint32 = 0;
|
||||||
@memcpy(std.mem.asBytes(&i.value.uint32), input[0..4]);
|
if (input.len >= 4) @memcpy(std.mem.asBytes(&i.value.uint32), input[0..4]);
|
||||||
},
|
},
|
||||||
64 => {
|
64 => {
|
||||||
if (input.len < 8) return RuntimeError.OutOfBounds;
|
i.value.uint64 = 0;
|
||||||
@memcpy(std.mem.asBytes(&i.value.uint64), input[0..8]);
|
if (input.len >= 8) @memcpy(std.mem.asBytes(&i.value.uint64), input[0..8]);
|
||||||
},
|
},
|
||||||
else => return RuntimeError.InvalidValueType,
|
else => return RuntimeError.InvalidValueType,
|
||||||
}
|
}
|
||||||
@@ -728,16 +758,16 @@ pub const Value = union(Type) {
|
|||||||
.Float => |*f| {
|
.Float => |*f| {
|
||||||
switch (f.bit_count) {
|
switch (f.bit_count) {
|
||||||
16 => {
|
16 => {
|
||||||
if (input.len < 2) return RuntimeError.OutOfBounds;
|
f.value.float16 = 0;
|
||||||
@memcpy(std.mem.asBytes(&f.value.float16), input[0..2]);
|
if (input.len >= 2) @memcpy(std.mem.asBytes(&f.value.float16), input[0..2]);
|
||||||
},
|
},
|
||||||
32 => {
|
32 => {
|
||||||
if (input.len < 4) return RuntimeError.OutOfBounds;
|
f.value.float32 = 0;
|
||||||
@memcpy(std.mem.asBytes(&f.value.float32), input[0..4]);
|
if (input.len >= 4) @memcpy(std.mem.asBytes(&f.value.float32), input[0..4]);
|
||||||
},
|
},
|
||||||
64 => {
|
64 => {
|
||||||
if (input.len < 8) return RuntimeError.OutOfBounds;
|
f.value.float64 = 0;
|
||||||
@memcpy(std.mem.asBytes(&f.value.float64), input[0..8]);
|
if (input.len >= 8) @memcpy(std.mem.asBytes(&f.value.float64), input[0..8]);
|
||||||
},
|
},
|
||||||
else => return RuntimeError.InvalidValueType,
|
else => return RuntimeError.InvalidValueType,
|
||||||
}
|
}
|
||||||
@@ -773,7 +803,12 @@ pub const Value = union(Type) {
|
|||||||
.Array => |*arr| {
|
.Array => |*arr| {
|
||||||
var offset: usize = 0;
|
var offset: usize = 0;
|
||||||
for (arr.values) |*v| {
|
for (arr.values) |*v| {
|
||||||
_ = try v.write(input[offset..]);
|
if (v.* == .RuntimeArray) {
|
||||||
|
v.RuntimeArray.data = @constCast(input[@min(offset, input.len)..]);
|
||||||
|
offset += input.len - @min(offset, input.len);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
_ = try v.write(input[@min(offset, input.len)..]);
|
||||||
offset += if (arr.stride != 0) arr.stride else try v.getPlainMemorySize();
|
offset += if (arr.stride != 0) arr.stride else try v.getPlainMemorySize();
|
||||||
}
|
}
|
||||||
return offset;
|
return offset;
|
||||||
@@ -782,20 +817,29 @@ pub const Value = union(Type) {
|
|||||||
var end_offset: usize = 0;
|
var end_offset: usize = 0;
|
||||||
for (s.values, 0..) |*v, i| {
|
for (s.values, 0..) |*v, i| {
|
||||||
const member_offset: usize = @intCast(s.offsets[i] orelse end_offset);
|
const member_offset: usize = @intCast(s.offsets[i] orelse end_offset);
|
||||||
if (member_offset > input.len) return RuntimeError.OutOfBounds;
|
if (member_offset > input.len) {
|
||||||
|
if (v.* == .RuntimeArray) {
|
||||||
|
v.RuntimeArray.data = &.{};
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
const member_input = if (v.* == .RuntimeArray and i + 1 < s.values.len and s.offsets[i + 1] != null) blk: {
|
const member_input = if (v.* == .RuntimeArray and i + 1 < s.values.len and s.offsets[i + 1] != null) blk: {
|
||||||
const next_offset: usize = @intCast(s.offsets[i + 1].?);
|
const next_offset: usize = @intCast(s.offsets[i + 1].?);
|
||||||
if (next_offset < member_offset or next_offset > input.len) return RuntimeError.OutOfBounds;
|
if (next_offset < member_offset) return RuntimeError.OutOfBounds;
|
||||||
break :blk input[member_offset..next_offset];
|
break :blk input[member_offset..@min(next_offset, input.len)];
|
||||||
} else input[member_offset..];
|
} else input[@min(member_offset, input.len)..];
|
||||||
|
if (v.* == .RuntimeArray) {
|
||||||
|
v.RuntimeArray.data = @constCast(member_input);
|
||||||
|
end_offset = @max(end_offset, input.len);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
const write_size = if (s.matrix_strides[i]) |matrix_stride|
|
const write_size = if (s.matrix_strides[i]) |matrix_stride|
|
||||||
try v.writeWithMatrixLayout(member_input, matrix_stride, s.row_major[i])
|
try v.writeWithMatrixLayout(member_input, matrix_stride, s.row_major[i])
|
||||||
else
|
else
|
||||||
try v.write(member_input);
|
try v.write(member_input);
|
||||||
end_offset = @max(end_offset, member_offset + write_size);
|
end_offset = @max(end_offset, member_offset + write_size);
|
||||||
}
|
}
|
||||||
if (end_offset > input.len) return RuntimeError.OutOfBounds;
|
s.external_data = @constCast(input[0..@min(end_offset, input.len)]);
|
||||||
s.external_data = @constCast(input[0..end_offset]);
|
|
||||||
return end_offset;
|
return end_offset;
|
||||||
},
|
},
|
||||||
.RuntimeArray => |*arr| {
|
.RuntimeArray => |*arr| {
|
||||||
|
|||||||
+239
-141
@@ -1367,7 +1367,7 @@ fn ImageEngine(comptime Op: ImageOp) type {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn readProjectedSampleCoords(coordinate: *const Value) RuntimeError!struct { x: f32, y: f32, z: f32 } {
|
fn readProjectedSampleCoords(coordinate: *const Value) RuntimeError!struct { x: f32, y: f32, z: f32, w: f32 } {
|
||||||
const lane_count = try valueLaneCount(coordinate);
|
const lane_count = try valueLaneCount(coordinate);
|
||||||
if (lane_count < 2)
|
if (lane_count < 2)
|
||||||
return RuntimeError.InvalidSpirV;
|
return RuntimeError.InvalidSpirV;
|
||||||
@@ -1378,6 +1378,7 @@ fn ImageEngine(comptime Op: ImageOp) type {
|
|||||||
.x = try readSampleCoordLane(coordinate, 0) / q,
|
.x = try readSampleCoordLane(coordinate, 0) / q,
|
||||||
.y = if (q_lane > 1) (readSampleCoordLane(coordinate, 1) catch 0.0) / q else 0.0,
|
.y = if (q_lane > 1) (readSampleCoordLane(coordinate, 1) catch 0.0) / q else 0.0,
|
||||||
.z = if (q_lane > 2) (readSampleCoordLane(coordinate, 2) catch 0.0) / q else 0.0,
|
.z = if (q_lane > 2) (readSampleCoordLane(coordinate, 2) catch 0.0) / q else 0.0,
|
||||||
|
.w = if (q_lane > 3) (readSampleCoordLane(coordinate, 3) catch 0.0) / q else 0.0,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1856,8 +1857,8 @@ fn ImageEngine(comptime Op: ImageOp) type {
|
|||||||
return parsed.lod;
|
return parsed.lod;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn sampleImageDref(rt: *Runtime, dst: *Value, driver_image: *anyopaque, driver_sampler: *anyopaque, dim: spv.SpvDim, x: f32, y: f32, z: f32, dref: f32, lod: ?f32, offset: Runtime.ImageOffset) RuntimeError!void {
|
fn sampleImageDref(rt: *Runtime, dst: *Value, driver_image: *anyopaque, driver_sampler: *anyopaque, dim: spv.SpvDim, x: f32, y: f32, z: f32, w: f32, dref: f32, lod: ?f32, offset: Runtime.ImageOffset) RuntimeError!void {
|
||||||
try writeFloatScalar(dst, try rt.image_api.sampleImageDref(driver_image, driver_sampler, dim, x, y, z, dref, lod, offset));
|
try writeFloatScalar(dst, try rt.image_api.sampleImageDref(driver_image, driver_sampler, dim, x, y, z, w, dref, lod, offset));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn gatherCoord(index: i32, extent: u32) f32 {
|
fn gatherCoord(index: i32, extent: u32) f32 {
|
||||||
@@ -2169,6 +2170,7 @@ fn ImageEngine(comptime Op: ImageOp) type {
|
|||||||
.x = try readSampleCoordLane(coordinate, 0),
|
.x = try readSampleCoordLane(coordinate, 0),
|
||||||
.y = readSampleCoordLane(coordinate, 1) catch 0,
|
.y = readSampleCoordLane(coordinate, 1) catch 0,
|
||||||
.z = readSampleCoordLane(coordinate, 2) catch 0,
|
.z = readSampleCoordLane(coordinate, 2) catch 0,
|
||||||
|
.w = readSampleCoordLane(coordinate, 3) catch 0,
|
||||||
};
|
};
|
||||||
const image_operands = if (word_count > 4) try rt.it.next() else 0;
|
const image_operands = if (word_count > 4) try rt.it.next() else 0;
|
||||||
const parsed_operands = try parseImageOperands(rt, image_operands);
|
const parsed_operands = try parseImageOperands(rt, image_operands);
|
||||||
@@ -2230,6 +2232,7 @@ fn ImageEngine(comptime Op: ImageOp) type {
|
|||||||
.x = try readSampleCoordLane(coordinate, 0),
|
.x = try readSampleCoordLane(coordinate, 0),
|
||||||
.y = readSampleCoordLane(coordinate, 1) catch 0,
|
.y = readSampleCoordLane(coordinate, 1) catch 0,
|
||||||
.z = readSampleCoordLane(coordinate, 2) catch 0,
|
.z = readSampleCoordLane(coordinate, 2) catch 0,
|
||||||
|
.w = readSampleCoordLane(coordinate, 3) catch 0,
|
||||||
};
|
};
|
||||||
const raw_dref = try readFloatLane(try rt.results[try rt.it.next()].getValue(), 0);
|
const raw_dref = try readFloatLane(try rt.results[try rt.it.next()].getValue(), 0);
|
||||||
const dref = if (comptime Op == .SampleProjDrefImplicitLod)
|
const dref = if (comptime Op == .SampleProjDrefImplicitLod)
|
||||||
@@ -2238,6 +2241,20 @@ fn ImageEngine(comptime Op: ImageOp) type {
|
|||||||
raw_dref;
|
raw_dref;
|
||||||
const image_operands = if (word_count > 5) try rt.it.next() else 0;
|
const image_operands = if (word_count > 5) try rt.it.next() else 0;
|
||||||
const parsed_operands = try parseImageOperands(rt, image_operands);
|
const parsed_operands = try parseImageOperands(rt, image_operands);
|
||||||
|
const projected = comptime Op == .SampleProjDrefImplicitLod;
|
||||||
|
const lod = try implicitSampleLod(
|
||||||
|
rt,
|
||||||
|
coordinate_id,
|
||||||
|
coordinate,
|
||||||
|
projected,
|
||||||
|
sampled_image_operand.driver_image,
|
||||||
|
sampled_image_operand.driver_sampler,
|
||||||
|
sampled_image_operand.dim,
|
||||||
|
coords.x,
|
||||||
|
coords.y,
|
||||||
|
coords.z,
|
||||||
|
parsed_operands.bias,
|
||||||
|
);
|
||||||
|
|
||||||
try sampleImageDref(
|
try sampleImageDref(
|
||||||
rt,
|
rt,
|
||||||
@@ -2248,8 +2265,9 @@ fn ImageEngine(comptime Op: ImageOp) type {
|
|||||||
coords.x,
|
coords.x,
|
||||||
coords.y,
|
coords.y,
|
||||||
coords.z,
|
coords.z,
|
||||||
|
coords.w,
|
||||||
dref,
|
dref,
|
||||||
null,
|
lod,
|
||||||
parsed_operands.offset,
|
parsed_operands.offset,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
@@ -2265,6 +2283,7 @@ fn ImageEngine(comptime Op: ImageOp) type {
|
|||||||
.x = try readSampleCoordLane(coordinate, 0),
|
.x = try readSampleCoordLane(coordinate, 0),
|
||||||
.y = readSampleCoordLane(coordinate, 1) catch 0,
|
.y = readSampleCoordLane(coordinate, 1) catch 0,
|
||||||
.z = readSampleCoordLane(coordinate, 2) catch 0,
|
.z = readSampleCoordLane(coordinate, 2) catch 0,
|
||||||
|
.w = readSampleCoordLane(coordinate, 3) catch 0,
|
||||||
};
|
};
|
||||||
const image_operands = if (word_count > 4) try rt.it.next() else 0;
|
const image_operands = if (word_count > 4) try rt.it.next() else 0;
|
||||||
const parsed_operands = try parseImageOperands(rt, image_operands);
|
const parsed_operands = try parseImageOperands(rt, image_operands);
|
||||||
@@ -2300,6 +2319,7 @@ fn ImageEngine(comptime Op: ImageOp) type {
|
|||||||
.x = try readSampleCoordLane(coordinate, 0),
|
.x = try readSampleCoordLane(coordinate, 0),
|
||||||
.y = readSampleCoordLane(coordinate, 1) catch 0,
|
.y = readSampleCoordLane(coordinate, 1) catch 0,
|
||||||
.z = readSampleCoordLane(coordinate, 2) catch 0,
|
.z = readSampleCoordLane(coordinate, 2) catch 0,
|
||||||
|
.w = readSampleCoordLane(coordinate, 3) catch 0,
|
||||||
};
|
};
|
||||||
const raw_dref = try readFloatLane(try rt.results[try rt.it.next()].getValue(), 0);
|
const raw_dref = try readFloatLane(try rt.results[try rt.it.next()].getValue(), 0);
|
||||||
const dref = if (comptime Op == .SampleProjDrefExplicitLod)
|
const dref = if (comptime Op == .SampleProjDrefExplicitLod)
|
||||||
@@ -2318,6 +2338,7 @@ fn ImageEngine(comptime Op: ImageOp) type {
|
|||||||
coords.x,
|
coords.x,
|
||||||
coords.y,
|
coords.y,
|
||||||
coords.z,
|
coords.z,
|
||||||
|
coords.w,
|
||||||
dref,
|
dref,
|
||||||
try explicitSampleLod(
|
try explicitSampleLod(
|
||||||
rt,
|
rt,
|
||||||
@@ -3514,9 +3535,60 @@ fn opAccessChain(allocator: std.mem.Allocator, word_count: SpvWord, rt: *Runtime
|
|||||||
.indexes = indexes,
|
.indexes = indexes,
|
||||||
.value = blk: {
|
.value = blk: {
|
||||||
const helpers = struct {
|
const helpers = struct {
|
||||||
|
const F32Pointer = struct {
|
||||||
|
ptr: *f32,
|
||||||
|
backing: ?*Value,
|
||||||
|
owns_backing: bool,
|
||||||
|
};
|
||||||
|
const I32Pointer = struct {
|
||||||
|
ptr: *i32,
|
||||||
|
backing: ?*Value,
|
||||||
|
owns_backing: bool,
|
||||||
|
};
|
||||||
|
const U32Pointer = struct {
|
||||||
|
ptr: *u32,
|
||||||
|
backing: ?*Value,
|
||||||
|
owns_backing: bool,
|
||||||
|
};
|
||||||
|
|
||||||
|
fn destroyBacking(gpa: std.mem.Allocator, backing: ?*Value, owns_backing: bool) void {
|
||||||
|
if (!owns_backing) return;
|
||||||
|
if (backing) |value| {
|
||||||
|
value.deinit(gpa);
|
||||||
|
gpa.destroy(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn robustF32Pointer(gpa: std.mem.Allocator, ptr: ?*f32, window: ?[]u8, descriptor_backed: bool, backing: ?*Value, owns_backing: bool) RuntimeError!F32Pointer {
|
||||||
|
if (window != null or !descriptor_backed) return .{ .ptr = ptr orelse return RuntimeError.InvalidSpirV, .backing = backing, .owns_backing = owns_backing };
|
||||||
|
|
||||||
|
destroyBacking(gpa, backing, owns_backing);
|
||||||
|
const value = gpa.create(Value) catch return RuntimeError.OutOfMemory;
|
||||||
|
value.* = .{ .Float = .{ .bit_count = 32, .value = .{ .float32 = 0 } } };
|
||||||
|
return .{ .ptr = &value.Float.value.float32, .backing = value, .owns_backing = true };
|
||||||
|
}
|
||||||
|
|
||||||
|
fn robustI32Pointer(gpa: std.mem.Allocator, ptr: ?*i32, window: ?[]u8, descriptor_backed: bool, backing: ?*Value, owns_backing: bool) RuntimeError!I32Pointer {
|
||||||
|
if (window != null or !descriptor_backed) return .{ .ptr = ptr orelse return RuntimeError.InvalidSpirV, .backing = backing, .owns_backing = owns_backing };
|
||||||
|
|
||||||
|
destroyBacking(gpa, backing, owns_backing);
|
||||||
|
const value = gpa.create(Value) catch return RuntimeError.OutOfMemory;
|
||||||
|
value.* = .{ .Int = .{ .bit_count = 32, .is_signed = true, .value = .{ .sint32 = 0 } } };
|
||||||
|
return .{ .ptr = &value.Int.value.sint32, .backing = value, .owns_backing = true };
|
||||||
|
}
|
||||||
|
|
||||||
|
fn robustU32Pointer(gpa: std.mem.Allocator, ptr: ?*u32, window: ?[]u8, descriptor_backed: bool, backing: ?*Value, owns_backing: bool) RuntimeError!U32Pointer {
|
||||||
|
if (window != null or !descriptor_backed) return .{ .ptr = ptr orelse return RuntimeError.InvalidSpirV, .backing = backing, .owns_backing = owns_backing };
|
||||||
|
|
||||||
|
destroyBacking(gpa, backing, owns_backing);
|
||||||
|
const value = gpa.create(Value) catch return RuntimeError.OutOfMemory;
|
||||||
|
value.* = .{ .Int = .{ .bit_count = 32, .is_signed = false, .value = .{ .uint32 = 0 } } };
|
||||||
|
return .{ .ptr = &value.Int.value.uint32, .backing = value, .owns_backing = true };
|
||||||
|
}
|
||||||
|
|
||||||
fn advanceWindow(window: ?[]u8, offset: usize) RuntimeError!?[]u8 {
|
fn advanceWindow(window: ?[]u8, offset: usize) RuntimeError!?[]u8 {
|
||||||
if (window) |w| {
|
if (window) |w| {
|
||||||
if (offset > w.len) return RuntimeError.OutOfBounds;
|
if (offset > w.len) return null;
|
||||||
return w[offset..];
|
return w[offset..];
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
@@ -3524,7 +3596,7 @@ fn opAccessChain(allocator: std.mem.Allocator, word_count: SpvWord, rt: *Runtime
|
|||||||
|
|
||||||
fn advanceWindowSized(window: ?[]u8, offset: usize, size: usize) RuntimeError!?[]u8 {
|
fn advanceWindowSized(window: ?[]u8, offset: usize, size: usize) RuntimeError!?[]u8 {
|
||||||
if (window) |w| {
|
if (window) |w| {
|
||||||
if (offset > w.len or size > w.len - offset) return RuntimeError.OutOfBounds;
|
if (offset > w.len or size > w.len - offset) return null;
|
||||||
return w[offset .. offset + size];
|
return w[offset .. offset + size];
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
@@ -3545,6 +3617,7 @@ fn opAccessChain(allocator: std.mem.Allocator, word_count: SpvWord, rt: *Runtime
|
|||||||
var owns_uniform_backing_value = false;
|
var owns_uniform_backing_value = false;
|
||||||
var matrix_stride: ?SpvWord = null;
|
var matrix_stride: ?SpvWord = null;
|
||||||
var matrix_row_major = false;
|
var matrix_row_major = false;
|
||||||
|
var descriptor_backed = false;
|
||||||
|
|
||||||
if (std.meta.activeTag(value_ptr.*) == .Pointer) {
|
if (std.meta.activeTag(value_ptr.*) == .Pointer) {
|
||||||
const ptr = value_ptr.Pointer;
|
const ptr = value_ptr.Pointer;
|
||||||
@@ -3553,6 +3626,7 @@ fn opAccessChain(allocator: std.mem.Allocator, word_count: SpvWord, rt: *Runtime
|
|||||||
owns_uniform_backing_value = false;
|
owns_uniform_backing_value = false;
|
||||||
matrix_stride = ptr.matrix_stride;
|
matrix_stride = ptr.matrix_stride;
|
||||||
matrix_row_major = ptr.matrix_row_major;
|
matrix_row_major = ptr.matrix_row_major;
|
||||||
|
descriptor_backed = uniform_slice_window != null or uniform_backing_value != null;
|
||||||
switch (ptr.ptr) {
|
switch (ptr.ptr) {
|
||||||
.common => |common| value_ptr = common,
|
.common => |common| value_ptr = common,
|
||||||
else => return RuntimeError.InvalidSpirV,
|
else => return RuntimeError.InvalidSpirV,
|
||||||
@@ -3579,6 +3653,7 @@ fn opAccessChain(allocator: std.mem.Allocator, word_count: SpvWord, rt: *Runtime
|
|||||||
owns_uniform_backing_value = false;
|
owns_uniform_backing_value = false;
|
||||||
matrix_stride = ptr.matrix_stride;
|
matrix_stride = ptr.matrix_stride;
|
||||||
matrix_row_major = ptr.matrix_row_major;
|
matrix_row_major = ptr.matrix_row_major;
|
||||||
|
descriptor_backed = uniform_slice_window != null or uniform_backing_value != null;
|
||||||
switch (ptr.ptr) {
|
switch (ptr.ptr) {
|
||||||
.common => |common| value_ptr = common,
|
.common => |common| value_ptr = common,
|
||||||
else => return RuntimeError.InvalidSpirV,
|
else => return RuntimeError.InvalidSpirV,
|
||||||
@@ -3639,8 +3714,10 @@ fn opAccessChain(allocator: std.mem.Allocator, word_count: SpvWord, rt: *Runtime
|
|||||||
const member_offset: usize = @intCast(s.offsets[component_index] orelse end_offset);
|
const member_offset: usize = @intCast(s.offsets[component_index] orelse end_offset);
|
||||||
|
|
||||||
if (uniform_slice_window != null) {
|
if (uniform_slice_window != null) {
|
||||||
|
descriptor_backed = true;
|
||||||
uniform_slice_window = try helpers.advanceWindow(uniform_slice_window, member_offset);
|
uniform_slice_window = try helpers.advanceWindow(uniform_slice_window, member_offset);
|
||||||
} else if (s.external_data) |data| {
|
} else if (s.external_data) |data| {
|
||||||
|
descriptor_backed = true;
|
||||||
uniform_slice_window = try helpers.advanceWindow(data, member_offset);
|
uniform_slice_window = try helpers.advanceWindow(data, member_offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3658,13 +3735,7 @@ fn opAccessChain(allocator: std.mem.Allocator, word_count: SpvWord, rt: *Runtime
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
.RuntimeArray => |*arr| {
|
.RuntimeArray => |*arr| {
|
||||||
if (component_index >= arr.getLen()) return RuntimeError.OutOfBounds;
|
const backing = try arr.createRobustValueFromIndex(allocator, rt.results, component_index);
|
||||||
|
|
||||||
const element_offset = arr.getOffsetOfIndex(component_index);
|
|
||||||
if (element_offset > arr.data.len or arr.stride > arr.data.len - element_offset)
|
|
||||||
return RuntimeError.OutOfBounds;
|
|
||||||
|
|
||||||
const backing = try arr.createValueFromIndex(allocator, rt.results, component_index);
|
|
||||||
errdefer {
|
errdefer {
|
||||||
backing.deinit(allocator);
|
backing.deinit(allocator);
|
||||||
allocator.destroy(backing);
|
allocator.destroy(backing);
|
||||||
@@ -3678,7 +3749,11 @@ fn opAccessChain(allocator: std.mem.Allocator, word_count: SpvWord, rt: *Runtime
|
|||||||
value_ptr = backing;
|
value_ptr = backing;
|
||||||
uniform_backing_value = backing;
|
uniform_backing_value = backing;
|
||||||
owns_uniform_backing_value = true;
|
owns_uniform_backing_value = true;
|
||||||
uniform_slice_window = arr.data[element_offset .. element_offset + arr.stride];
|
descriptor_backed = true;
|
||||||
|
uniform_slice_window = if (arr.getRobustOffsetOfIndex(component_index)) |element_offset|
|
||||||
|
arr.data[element_offset..]
|
||||||
|
else
|
||||||
|
null;
|
||||||
if (arr.matrix_stride) |stride| {
|
if (arr.matrix_stride) |stride| {
|
||||||
matrix_stride = stride;
|
matrix_stride = stride;
|
||||||
matrix_row_major = arr.row_major;
|
matrix_row_major = arr.row_major;
|
||||||
@@ -3692,94 +3767,103 @@ fn opAccessChain(allocator: std.mem.Allocator, word_count: SpvWord, rt: *Runtime
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
.Vector4f32 => |*v| switch (component_index) {
|
.Vector4f32 => |*v| switch (component_index) {
|
||||||
inline 0...3 => |idx| break :blk .{ .Pointer = .{
|
inline 0...3 => |idx| {
|
||||||
.ptr = .{ .f32_ptr = &v[idx] },
|
const lane_window = try helpers.advanceWindowSized(uniform_slice_window, helpers.laneOffset(matrix_stride, matrix_row_major, idx, @sizeOf(f32)), @sizeOf(f32));
|
||||||
.uniform_slice_window = try helpers.advanceWindowSized(uniform_slice_window, helpers.laneOffset(matrix_stride, matrix_row_major, idx, @sizeOf(f32)), @sizeOf(f32)),
|
const ptr = try helpers.robustF32Pointer(allocator, &v[idx], lane_window, descriptor_backed, uniform_backing_value, owns_uniform_backing_value);
|
||||||
.uniform_backing_value = uniform_backing_value,
|
break :blk .{ .Pointer = .{ .ptr = .{ .f32_ptr = ptr.ptr }, .uniform_slice_window = lane_window, .uniform_backing_value = ptr.backing, .owns_uniform_backing_value = ptr.owns_backing, .matrix_stride = null } };
|
||||||
.owns_uniform_backing_value = owns_uniform_backing_value,
|
},
|
||||||
.matrix_stride = null,
|
else => {
|
||||||
} },
|
const ptr = try helpers.robustF32Pointer(allocator, null, null, descriptor_backed, uniform_backing_value, owns_uniform_backing_value);
|
||||||
else => return RuntimeError.InvalidSpirV,
|
break :blk .{ .Pointer = .{ .ptr = .{ .f32_ptr = ptr.ptr }, .uniform_slice_window = null, .uniform_backing_value = ptr.backing, .owns_uniform_backing_value = ptr.owns_backing, .matrix_stride = null } };
|
||||||
|
},
|
||||||
},
|
},
|
||||||
.Vector3f32 => |*v| switch (component_index) {
|
.Vector3f32 => |*v| switch (component_index) {
|
||||||
inline 0...2 => |idx| break :blk .{ .Pointer = .{
|
inline 0...2 => |idx| {
|
||||||
.ptr = .{ .f32_ptr = &v[idx] },
|
const lane_window = try helpers.advanceWindowSized(uniform_slice_window, helpers.laneOffset(matrix_stride, matrix_row_major, idx, @sizeOf(f32)), @sizeOf(f32));
|
||||||
.uniform_slice_window = try helpers.advanceWindowSized(uniform_slice_window, helpers.laneOffset(matrix_stride, matrix_row_major, idx, @sizeOf(f32)), @sizeOf(f32)),
|
const ptr = try helpers.robustF32Pointer(allocator, &v[idx], lane_window, descriptor_backed, uniform_backing_value, owns_uniform_backing_value);
|
||||||
.uniform_backing_value = uniform_backing_value,
|
break :blk .{ .Pointer = .{ .ptr = .{ .f32_ptr = ptr.ptr }, .uniform_slice_window = lane_window, .uniform_backing_value = ptr.backing, .owns_uniform_backing_value = ptr.owns_backing, .matrix_stride = null } };
|
||||||
.owns_uniform_backing_value = owns_uniform_backing_value,
|
},
|
||||||
.matrix_stride = null,
|
else => {
|
||||||
} },
|
const ptr = try helpers.robustF32Pointer(allocator, null, null, descriptor_backed, uniform_backing_value, owns_uniform_backing_value);
|
||||||
else => return RuntimeError.InvalidSpirV,
|
break :blk .{ .Pointer = .{ .ptr = .{ .f32_ptr = ptr.ptr }, .uniform_slice_window = null, .uniform_backing_value = ptr.backing, .owns_uniform_backing_value = ptr.owns_backing, .matrix_stride = null } };
|
||||||
|
},
|
||||||
},
|
},
|
||||||
.Vector2f32 => |*v| switch (component_index) {
|
.Vector2f32 => |*v| switch (component_index) {
|
||||||
inline 0...1 => |idx| break :blk .{ .Pointer = .{
|
inline 0...1 => |idx| {
|
||||||
.ptr = .{ .f32_ptr = &v[idx] },
|
const lane_window = try helpers.advanceWindowSized(uniform_slice_window, helpers.laneOffset(matrix_stride, matrix_row_major, idx, @sizeOf(f32)), @sizeOf(f32));
|
||||||
.uniform_slice_window = try helpers.advanceWindowSized(uniform_slice_window, helpers.laneOffset(matrix_stride, matrix_row_major, idx, @sizeOf(f32)), @sizeOf(f32)),
|
const ptr = try helpers.robustF32Pointer(allocator, &v[idx], lane_window, descriptor_backed, uniform_backing_value, owns_uniform_backing_value);
|
||||||
.uniform_backing_value = uniform_backing_value,
|
break :blk .{ .Pointer = .{ .ptr = .{ .f32_ptr = ptr.ptr }, .uniform_slice_window = lane_window, .uniform_backing_value = ptr.backing, .owns_uniform_backing_value = ptr.owns_backing, .matrix_stride = null } };
|
||||||
.owns_uniform_backing_value = owns_uniform_backing_value,
|
},
|
||||||
.matrix_stride = null,
|
else => {
|
||||||
} },
|
const ptr = try helpers.robustF32Pointer(allocator, null, null, descriptor_backed, uniform_backing_value, owns_uniform_backing_value);
|
||||||
else => return RuntimeError.InvalidSpirV,
|
break :blk .{ .Pointer = .{ .ptr = .{ .f32_ptr = ptr.ptr }, .uniform_slice_window = null, .uniform_backing_value = ptr.backing, .owns_uniform_backing_value = ptr.owns_backing, .matrix_stride = null } };
|
||||||
|
},
|
||||||
},
|
},
|
||||||
.Vector4i32 => |*v| switch (component_index) {
|
.Vector4i32 => |*v| switch (component_index) {
|
||||||
inline 0...3 => |idx| break :blk .{ .Pointer = .{
|
inline 0...3 => |idx| {
|
||||||
.ptr = .{ .i32_ptr = &v[idx] },
|
const lane_window = try helpers.advanceWindowSized(uniform_slice_window, helpers.laneOffset(matrix_stride, matrix_row_major, idx, @sizeOf(i32)), @sizeOf(i32));
|
||||||
.uniform_slice_window = try helpers.advanceWindowSized(uniform_slice_window, helpers.laneOffset(matrix_stride, matrix_row_major, idx, @sizeOf(i32)), @sizeOf(i32)),
|
const ptr = try helpers.robustI32Pointer(allocator, &v[idx], lane_window, descriptor_backed, uniform_backing_value, owns_uniform_backing_value);
|
||||||
.uniform_backing_value = uniform_backing_value,
|
break :blk .{ .Pointer = .{ .ptr = .{ .i32_ptr = ptr.ptr }, .uniform_slice_window = lane_window, .uniform_backing_value = ptr.backing, .owns_uniform_backing_value = ptr.owns_backing, .matrix_stride = null } };
|
||||||
.owns_uniform_backing_value = owns_uniform_backing_value,
|
},
|
||||||
.matrix_stride = null,
|
else => {
|
||||||
} },
|
const ptr = try helpers.robustI32Pointer(allocator, null, null, descriptor_backed, uniform_backing_value, owns_uniform_backing_value);
|
||||||
else => return RuntimeError.InvalidSpirV,
|
break :blk .{ .Pointer = .{ .ptr = .{ .i32_ptr = ptr.ptr }, .uniform_slice_window = null, .uniform_backing_value = ptr.backing, .owns_uniform_backing_value = ptr.owns_backing, .matrix_stride = null } };
|
||||||
|
},
|
||||||
},
|
},
|
||||||
.Vector3i32 => |*v| switch (component_index) {
|
.Vector3i32 => |*v| switch (component_index) {
|
||||||
inline 0...2 => |idx| break :blk .{ .Pointer = .{
|
inline 0...2 => |idx| {
|
||||||
.ptr = .{ .i32_ptr = &v[idx] },
|
const lane_window = try helpers.advanceWindowSized(uniform_slice_window, helpers.laneOffset(matrix_stride, matrix_row_major, idx, @sizeOf(i32)), @sizeOf(i32));
|
||||||
.uniform_slice_window = try helpers.advanceWindowSized(uniform_slice_window, helpers.laneOffset(matrix_stride, matrix_row_major, idx, @sizeOf(i32)), @sizeOf(i32)),
|
const ptr = try helpers.robustI32Pointer(allocator, &v[idx], lane_window, descriptor_backed, uniform_backing_value, owns_uniform_backing_value);
|
||||||
.uniform_backing_value = uniform_backing_value,
|
break :blk .{ .Pointer = .{ .ptr = .{ .i32_ptr = ptr.ptr }, .uniform_slice_window = lane_window, .uniform_backing_value = ptr.backing, .owns_uniform_backing_value = ptr.owns_backing, .matrix_stride = null } };
|
||||||
.owns_uniform_backing_value = owns_uniform_backing_value,
|
},
|
||||||
.matrix_stride = null,
|
else => {
|
||||||
} },
|
const ptr = try helpers.robustI32Pointer(allocator, null, null, descriptor_backed, uniform_backing_value, owns_uniform_backing_value);
|
||||||
else => return RuntimeError.InvalidSpirV,
|
break :blk .{ .Pointer = .{ .ptr = .{ .i32_ptr = ptr.ptr }, .uniform_slice_window = null, .uniform_backing_value = ptr.backing, .owns_uniform_backing_value = ptr.owns_backing, .matrix_stride = null } };
|
||||||
|
},
|
||||||
},
|
},
|
||||||
.Vector2i32 => |*v| switch (component_index) {
|
.Vector2i32 => |*v| switch (component_index) {
|
||||||
inline 0...1 => |idx| break :blk .{ .Pointer = .{
|
inline 0...1 => |idx| {
|
||||||
.ptr = .{ .i32_ptr = &v[idx] },
|
const lane_window = try helpers.advanceWindowSized(uniform_slice_window, helpers.laneOffset(matrix_stride, matrix_row_major, idx, @sizeOf(i32)), @sizeOf(i32));
|
||||||
.uniform_slice_window = try helpers.advanceWindowSized(uniform_slice_window, helpers.laneOffset(matrix_stride, matrix_row_major, idx, @sizeOf(i32)), @sizeOf(i32)),
|
const ptr = try helpers.robustI32Pointer(allocator, &v[idx], lane_window, descriptor_backed, uniform_backing_value, owns_uniform_backing_value);
|
||||||
.uniform_backing_value = uniform_backing_value,
|
break :blk .{ .Pointer = .{ .ptr = .{ .i32_ptr = ptr.ptr }, .uniform_slice_window = lane_window, .uniform_backing_value = ptr.backing, .owns_uniform_backing_value = ptr.owns_backing, .matrix_stride = null } };
|
||||||
.owns_uniform_backing_value = owns_uniform_backing_value,
|
},
|
||||||
.matrix_stride = null,
|
else => {
|
||||||
} },
|
const ptr = try helpers.robustI32Pointer(allocator, null, null, descriptor_backed, uniform_backing_value, owns_uniform_backing_value);
|
||||||
else => return RuntimeError.InvalidSpirV,
|
break :blk .{ .Pointer = .{ .ptr = .{ .i32_ptr = ptr.ptr }, .uniform_slice_window = null, .uniform_backing_value = ptr.backing, .owns_uniform_backing_value = ptr.owns_backing, .matrix_stride = null } };
|
||||||
|
},
|
||||||
},
|
},
|
||||||
.Vector4u32 => |*v| switch (component_index) {
|
.Vector4u32 => |*v| switch (component_index) {
|
||||||
inline 0...3 => |idx| break :blk .{ .Pointer = .{
|
inline 0...3 => |idx| {
|
||||||
.ptr = .{ .u32_ptr = &v[idx] },
|
const lane_window = try helpers.advanceWindowSized(uniform_slice_window, helpers.laneOffset(matrix_stride, matrix_row_major, idx, @sizeOf(u32)), @sizeOf(u32));
|
||||||
.uniform_slice_window = try helpers.advanceWindowSized(uniform_slice_window, helpers.laneOffset(matrix_stride, matrix_row_major, idx, @sizeOf(u32)), @sizeOf(u32)),
|
const ptr = try helpers.robustU32Pointer(allocator, &v[idx], lane_window, descriptor_backed, uniform_backing_value, owns_uniform_backing_value);
|
||||||
.uniform_backing_value = uniform_backing_value,
|
break :blk .{ .Pointer = .{ .ptr = .{ .u32_ptr = ptr.ptr }, .uniform_slice_window = lane_window, .uniform_backing_value = ptr.backing, .owns_uniform_backing_value = ptr.owns_backing, .matrix_stride = null } };
|
||||||
.owns_uniform_backing_value = owns_uniform_backing_value,
|
},
|
||||||
.matrix_stride = null,
|
else => {
|
||||||
} },
|
const ptr = try helpers.robustU32Pointer(allocator, null, null, descriptor_backed, uniform_backing_value, owns_uniform_backing_value);
|
||||||
else => return RuntimeError.InvalidSpirV,
|
break :blk .{ .Pointer = .{ .ptr = .{ .u32_ptr = ptr.ptr }, .uniform_slice_window = null, .uniform_backing_value = ptr.backing, .owns_uniform_backing_value = ptr.owns_backing, .matrix_stride = null } };
|
||||||
|
},
|
||||||
},
|
},
|
||||||
.Vector3u32 => |*v| switch (component_index) {
|
.Vector3u32 => |*v| switch (component_index) {
|
||||||
inline 0...2 => |idx| break :blk .{ .Pointer = .{
|
inline 0...2 => |idx| {
|
||||||
.ptr = .{ .u32_ptr = &v[idx] },
|
const lane_window = try helpers.advanceWindowSized(uniform_slice_window, helpers.laneOffset(matrix_stride, matrix_row_major, idx, @sizeOf(u32)), @sizeOf(u32));
|
||||||
.uniform_slice_window = try helpers.advanceWindowSized(uniform_slice_window, helpers.laneOffset(matrix_stride, matrix_row_major, idx, @sizeOf(u32)), @sizeOf(u32)),
|
const ptr = try helpers.robustU32Pointer(allocator, &v[idx], lane_window, descriptor_backed, uniform_backing_value, owns_uniform_backing_value);
|
||||||
.uniform_backing_value = uniform_backing_value,
|
break :blk .{ .Pointer = .{ .ptr = .{ .u32_ptr = ptr.ptr }, .uniform_slice_window = lane_window, .uniform_backing_value = ptr.backing, .owns_uniform_backing_value = ptr.owns_backing, .matrix_stride = null } };
|
||||||
.owns_uniform_backing_value = owns_uniform_backing_value,
|
},
|
||||||
.matrix_stride = null,
|
else => {
|
||||||
} },
|
const ptr = try helpers.robustU32Pointer(allocator, null, null, descriptor_backed, uniform_backing_value, owns_uniform_backing_value);
|
||||||
else => return RuntimeError.InvalidSpirV,
|
break :blk .{ .Pointer = .{ .ptr = .{ .u32_ptr = ptr.ptr }, .uniform_slice_window = null, .uniform_backing_value = ptr.backing, .owns_uniform_backing_value = ptr.owns_backing, .matrix_stride = null } };
|
||||||
|
},
|
||||||
},
|
},
|
||||||
.Vector2u32 => |*v| switch (component_index) {
|
.Vector2u32 => |*v| switch (component_index) {
|
||||||
inline 0...1 => |idx| break :blk .{ .Pointer = .{
|
inline 0...1 => |idx| {
|
||||||
.ptr = .{ .u32_ptr = &v[idx] },
|
const lane_window = try helpers.advanceWindowSized(uniform_slice_window, helpers.laneOffset(matrix_stride, matrix_row_major, idx, @sizeOf(u32)), @sizeOf(u32));
|
||||||
.uniform_slice_window = try helpers.advanceWindowSized(uniform_slice_window, helpers.laneOffset(matrix_stride, matrix_row_major, idx, @sizeOf(u32)), @sizeOf(u32)),
|
const ptr = try helpers.robustU32Pointer(allocator, &v[idx], lane_window, descriptor_backed, uniform_backing_value, owns_uniform_backing_value);
|
||||||
.uniform_backing_value = uniform_backing_value,
|
break :blk .{ .Pointer = .{ .ptr = .{ .u32_ptr = ptr.ptr }, .uniform_slice_window = lane_window, .uniform_backing_value = ptr.backing, .owns_uniform_backing_value = ptr.owns_backing, .matrix_stride = null } };
|
||||||
.owns_uniform_backing_value = owns_uniform_backing_value,
|
},
|
||||||
.matrix_stride = null,
|
else => {
|
||||||
} },
|
const ptr = try helpers.robustU32Pointer(allocator, null, null, descriptor_backed, uniform_backing_value, owns_uniform_backing_value);
|
||||||
else => return RuntimeError.InvalidSpirV,
|
break :blk .{ .Pointer = .{ .ptr = .{ .u32_ptr = ptr.ptr }, .uniform_slice_window = null, .uniform_backing_value = ptr.backing, .owns_uniform_backing_value = ptr.owns_backing, .matrix_stride = null } };
|
||||||
|
},
|
||||||
},
|
},
|
||||||
else => return RuntimeError.InvalidSpirV,
|
else => return RuntimeError.InvalidSpirV,
|
||||||
}
|
}
|
||||||
@@ -4017,17 +4101,71 @@ fn opCompositeConstruct(allocator: std.mem.Allocator, word_count: SpvWord, rt: *
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn extractCompositeValue(allocator: std.mem.Allocator, results: []Result, value: *const Value, member_ids: []const SpvWord) RuntimeError!Value {
|
||||||
|
var composite = value.*;
|
||||||
|
for (member_ids) |member_id_word| {
|
||||||
|
const member_id: usize = @intCast(member_id_word);
|
||||||
|
if (composite.getCompositeDataOrNull()) |v| {
|
||||||
|
composite = v[member_id];
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
switch (composite) {
|
||||||
|
.RuntimeArray => |arr| composite = try arr.createLocalValueFromIndex(allocator, results, member_id_word),
|
||||||
|
.Vector4f32 => |v| return .{ .Float = .{ .bit_count = 32, .value = .{ .float32 = switch (member_id) {
|
||||||
|
inline 0...3 => |idx| v[idx],
|
||||||
|
else => return RuntimeError.OutOfBounds,
|
||||||
|
} } } },
|
||||||
|
.Vector3f32 => |v| return .{ .Float = .{ .bit_count = 32, .value = .{ .float32 = switch (member_id) {
|
||||||
|
inline 0...2 => |idx| v[idx],
|
||||||
|
else => return RuntimeError.OutOfBounds,
|
||||||
|
} } } },
|
||||||
|
.Vector2f32 => |v| return .{ .Float = .{ .bit_count = 32, .value = .{ .float32 = switch (member_id) {
|
||||||
|
inline 0...1 => |idx| v[idx],
|
||||||
|
else => return RuntimeError.OutOfBounds,
|
||||||
|
} } } },
|
||||||
|
.Vector4i32 => |v| return .{ .Int = .{ .bit_count = 32, .is_signed = true, .value = .{ .sint32 = switch (member_id) {
|
||||||
|
inline 0...3 => |idx| v[idx],
|
||||||
|
else => return RuntimeError.OutOfBounds,
|
||||||
|
} } } },
|
||||||
|
.Vector3i32 => |v| return .{ .Int = .{ .bit_count = 32, .is_signed = true, .value = .{ .sint32 = switch (member_id) {
|
||||||
|
inline 0...2 => |idx| v[idx],
|
||||||
|
else => return RuntimeError.OutOfBounds,
|
||||||
|
} } } },
|
||||||
|
.Vector2i32 => |v| return .{ .Int = .{ .bit_count = 32, .is_signed = true, .value = .{ .sint32 = switch (member_id) {
|
||||||
|
inline 0...1 => |idx| v[idx],
|
||||||
|
else => return RuntimeError.OutOfBounds,
|
||||||
|
} } } },
|
||||||
|
.Vector4u32 => |v| return .{ .Int = .{ .bit_count = 32, .is_signed = false, .value = .{ .uint32 = switch (member_id) {
|
||||||
|
inline 0...3 => |idx| v[idx],
|
||||||
|
else => return RuntimeError.OutOfBounds,
|
||||||
|
} } } },
|
||||||
|
.Vector3u32 => |v| return .{ .Int = .{ .bit_count = 32, .is_signed = false, .value = .{ .uint32 = switch (member_id) {
|
||||||
|
inline 0...2 => |idx| v[idx],
|
||||||
|
else => return RuntimeError.OutOfBounds,
|
||||||
|
} } } },
|
||||||
|
.Vector2u32 => |v| return .{ .Int = .{ .bit_count = 32, .is_signed = false, .value = .{ .uint32 = switch (member_id) {
|
||||||
|
inline 0...1 => |idx| v[idx],
|
||||||
|
else => return RuntimeError.OutOfBounds,
|
||||||
|
} } } },
|
||||||
|
else => return RuntimeError.InvalidValueType,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return composite.dupe(allocator);
|
||||||
|
}
|
||||||
|
|
||||||
fn opCompositeExtract(allocator: std.mem.Allocator, word_count: SpvWord, rt: *Runtime) RuntimeError!void {
|
fn opCompositeExtract(allocator: std.mem.Allocator, word_count: SpvWord, rt: *Runtime) RuntimeError!void {
|
||||||
const res_type = try rt.it.next();
|
const res_type = try rt.it.next();
|
||||||
const id = try rt.it.next();
|
const id = try rt.it.next();
|
||||||
const composite_id = try rt.it.next();
|
const composite_id = try rt.it.next();
|
||||||
const index_count: usize = @intCast(word_count - 3);
|
const index_count: usize = @intCast(word_count - 3);
|
||||||
|
|
||||||
var arena = std.heap.ArenaAllocator.init(allocator);
|
const member_ids = allocator.alloc(SpvWord, index_count) catch return RuntimeError.OutOfMemory;
|
||||||
defer arena.deinit();
|
defer allocator.free(member_ids);
|
||||||
|
for (member_ids) |*member_id| {
|
||||||
const arena_allocator = arena.allocator();
|
member_id.* = try rt.it.next();
|
||||||
|
}
|
||||||
|
|
||||||
|
const value = try extractCompositeValue(allocator, rt.results, try rt.results[composite_id].getValue(), member_ids);
|
||||||
rt.results[id].variant = .{
|
rt.results[id].variant = .{
|
||||||
.Constant = .{
|
.Constant = .{
|
||||||
.type_word = res_type,
|
.type_word = res_type,
|
||||||
@@ -4035,59 +4173,19 @@ fn opCompositeExtract(allocator: std.mem.Allocator, word_count: SpvWord, rt: *Ru
|
|||||||
.Type => |t| @as(Result.Type, t),
|
.Type => |t| @as(Result.Type, t),
|
||||||
else => return RuntimeError.InvalidSpirV,
|
else => return RuntimeError.InvalidSpirV,
|
||||||
},
|
},
|
||||||
.value = blk: {
|
.value = value,
|
||||||
var composite = (try rt.results[composite_id].getValue()).*;
|
|
||||||
for (0..index_count) |_| {
|
|
||||||
const member_id = try rt.it.next();
|
|
||||||
if (composite.getCompositeDataOrNull()) |v| {
|
|
||||||
composite = v[member_id];
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
switch (composite) {
|
|
||||||
.RuntimeArray => |arr| composite = try arr.createLocalValueFromIndex(arena_allocator, rt.results, member_id),
|
|
||||||
.Vector4f32 => |v| break :blk .{ .Float = .{ .bit_count = 32, .value = .{ .float32 = switch (member_id) {
|
|
||||||
inline 0...3 => |idx| v[idx],
|
|
||||||
else => return RuntimeError.OutOfBounds,
|
|
||||||
} } } },
|
|
||||||
.Vector3f32 => |v| break :blk .{ .Float = .{ .bit_count = 32, .value = .{ .float32 = switch (member_id) {
|
|
||||||
inline 0...2 => |idx| v[idx],
|
|
||||||
else => return RuntimeError.OutOfBounds,
|
|
||||||
} } } },
|
|
||||||
.Vector2f32 => |v| break :blk .{ .Float = .{ .bit_count = 32, .value = .{ .float32 = switch (member_id) {
|
|
||||||
inline 0...1 => |idx| v[idx],
|
|
||||||
else => return RuntimeError.OutOfBounds,
|
|
||||||
} } } },
|
|
||||||
.Vector4i32 => |v| break :blk .{ .Int = .{ .bit_count = 32, .is_signed = true, .value = .{ .sint32 = switch (member_id) {
|
|
||||||
inline 0...3 => |idx| v[idx],
|
|
||||||
else => return RuntimeError.OutOfBounds,
|
|
||||||
} } } },
|
|
||||||
.Vector3i32 => |v| break :blk .{ .Int = .{ .bit_count = 32, .is_signed = true, .value = .{ .sint32 = switch (member_id) {
|
|
||||||
inline 0...2 => |idx| v[idx],
|
|
||||||
else => return RuntimeError.OutOfBounds,
|
|
||||||
} } } },
|
|
||||||
.Vector2i32 => |v| break :blk .{ .Int = .{ .bit_count = 32, .is_signed = true, .value = .{ .sint32 = switch (member_id) {
|
|
||||||
inline 0...1 => |idx| v[idx],
|
|
||||||
else => return RuntimeError.OutOfBounds,
|
|
||||||
} } } },
|
|
||||||
.Vector4u32 => |v| break :blk .{ .Int = .{ .bit_count = 32, .is_signed = false, .value = .{ .uint32 = switch (member_id) {
|
|
||||||
inline 0...3 => |idx| v[idx],
|
|
||||||
else => return RuntimeError.OutOfBounds,
|
|
||||||
} } } },
|
|
||||||
.Vector3u32 => |v| break :blk .{ .Int = .{ .bit_count = 32, .is_signed = false, .value = .{ .uint32 = switch (member_id) {
|
|
||||||
inline 0...2 => |idx| v[idx],
|
|
||||||
else => return RuntimeError.OutOfBounds,
|
|
||||||
} } } },
|
|
||||||
.Vector2u32 => |v| break :blk .{ .Int = .{ .bit_count = 32, .is_signed = false, .value = .{ .uint32 = switch (member_id) {
|
|
||||||
inline 0...1 => |idx| v[idx],
|
|
||||||
else => return RuntimeError.OutOfBounds,
|
|
||||||
} } } },
|
|
||||||
else => return RuntimeError.InvalidValueType,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break :blk try composite.dupe(allocator);
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (rt.derivatives.get(composite_id)) |derivative| {
|
||||||
|
var dx = try extractCompositeValue(allocator, rt.results, &derivative.dx, member_ids);
|
||||||
|
defer dx.deinit(allocator);
|
||||||
|
var dy = try extractCompositeValue(allocator, rt.results, &derivative.dy, member_ids);
|
||||||
|
defer dy.deinit(allocator);
|
||||||
|
try rt.setDerivative(allocator, id, &dx, &dy);
|
||||||
|
} else {
|
||||||
|
rt.clearDerivative(allocator, id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn opCompositeInsert(allocator: std.mem.Allocator, word_count: SpvWord, rt: *Runtime) RuntimeError!void {
|
fn opCompositeInsert(allocator: std.mem.Allocator, word_count: SpvWord, rt: *Runtime) RuntimeError!void {
|
||||||
|
|||||||
Reference in New Issue
Block a user