fixing FFI, removing division by zero error, fixing fmod/rem
This commit is contained in:
+14
-14
@@ -418,20 +418,19 @@ typedef enum
|
|||||||
SPV_RESULT_SUCCESS = 0,
|
SPV_RESULT_SUCCESS = 0,
|
||||||
SPV_RESULT_BARRIER = 1,
|
SPV_RESULT_BARRIER = 1,
|
||||||
SPV_RESULT_KILLED = 2,
|
SPV_RESULT_KILLED = 2,
|
||||||
SPV_RESULT_DIVISION_BY_ZERO = -1,
|
SPV_RESULT_INVALID_ENTRY_POINT = -1,
|
||||||
SPV_RESULT_INVALID_ENTRY_POINT = -2,
|
SPV_RESULT_INVALID_SPIRV = -2,
|
||||||
SPV_RESULT_INVALID_SPIRV = -3,
|
SPV_RESULT_INVALID_VALUE_TYPE = -3,
|
||||||
SPV_RESULT_INVALID_VALUE_TYPE = -4,
|
SPV_RESULT_NOT_FOUND = -4,
|
||||||
SPV_RESULT_NOT_FOUND = -5,
|
SPV_RESULT_OUT_OF_MEMORY = -5,
|
||||||
SPV_RESULT_OUT_OF_MEMORY = -6,
|
SPV_RESULT_OUT_OF_BOUNDS = -6,
|
||||||
SPV_RESULT_OUT_OF_BOUNDS = -7,
|
SPV_RESULT_TODO = -7,
|
||||||
SPV_RESULT_TODO = -8,
|
SPV_RESULT_UNREACHABLE = -8,
|
||||||
SPV_RESULT_UNREACHABLE = -9,
|
SPV_RESULT_UNSUPPORTED_SPIRV = -9,
|
||||||
SPV_RESULT_UNSUPPORTED_SPIRV = -10,
|
SPV_RESULT_UNSUPPORTED_EXTENSION = -10,
|
||||||
SPV_RESULT_UNSUPPORTED_EXTENSION = -11,
|
SPV_RESULT_UNSUPPORTED_ENDIANNESS = -11,
|
||||||
SPV_RESULT_UNSUPPORTED_ENDIANNESS = -12,
|
SPV_RESULT_INVALID_MAGIC = -12,
|
||||||
SPV_RESULT_INVALID_MAGIC = -13,
|
SPV_RESULT_UNKNOWN = -13
|
||||||
SPV_RESULT_UNKNOWN = -14
|
|
||||||
} SpvResult;
|
} SpvResult;
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
@@ -538,6 +537,7 @@ typedef struct
|
|||||||
int x;
|
int x;
|
||||||
int y;
|
int y;
|
||||||
int z;
|
int z;
|
||||||
|
float w;
|
||||||
float lod;
|
float lod;
|
||||||
SpvBool has_lod;
|
SpvBool has_lod;
|
||||||
SpvImageOffset offset;
|
SpvImageOffset offset;
|
||||||
|
|||||||
+13
-14
@@ -8,20 +8,19 @@ pub const Result = enum(c_int) {
|
|||||||
Success = 0,
|
Success = 0,
|
||||||
Barrier = 1,
|
Barrier = 1,
|
||||||
Killed = 2,
|
Killed = 2,
|
||||||
DivisionByZero = -1,
|
InvalidEntryPoint = -1,
|
||||||
InvalidEntryPoint = -2,
|
InvalidSpirV = -2,
|
||||||
InvalidSpirV = -3,
|
InvalidValueType = -3,
|
||||||
InvalidValueType = -4,
|
NotFound = -4,
|
||||||
NotFound = -5,
|
OutOfMemory = -5,
|
||||||
OutOfMemory = -6,
|
OutOfBounds = -6,
|
||||||
OutOfBounds = -7,
|
ToDo = -7,
|
||||||
ToDo = -8,
|
Unreachable = -8,
|
||||||
Unreachable = -9,
|
UnsupportedSpirV = -9,
|
||||||
UnsupportedSpirV = -10,
|
UnsupportedExtension = -10,
|
||||||
UnsupportedExtension = -11,
|
UnsupportedEndianness = -11,
|
||||||
UnsupportedEndianness = -12,
|
InvalidMagic = -12,
|
||||||
InvalidMagic = -13,
|
Unknown = -13,
|
||||||
Unknown = -14,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
comptime {
|
comptime {
|
||||||
|
|||||||
+7
-7
@@ -75,6 +75,7 @@ const SampleImageInfo = extern struct {
|
|||||||
x: f32,
|
x: f32,
|
||||||
y: f32,
|
y: f32,
|
||||||
z: f32,
|
z: f32,
|
||||||
|
w: f32,
|
||||||
lod: f32,
|
lod: f32,
|
||||||
has_lod: ffi.SpvCBool,
|
has_lod: ffi.SpvCBool,
|
||||||
offset: ImageOffset,
|
offset: ImageOffset,
|
||||||
@@ -124,7 +125,6 @@ const ImageAPI = extern struct {
|
|||||||
fn toCResult(err: spv.Runtime.RuntimeError) ffi.Result {
|
fn toCResult(err: spv.Runtime.RuntimeError) ffi.Result {
|
||||||
return switch (err) {
|
return switch (err) {
|
||||||
spv.Runtime.RuntimeError.Barrier => ffi.Result.Barrier,
|
spv.Runtime.RuntimeError.Barrier => ffi.Result.Barrier,
|
||||||
spv.Runtime.RuntimeError.DivisionByZero => ffi.Result.DivisionByZero,
|
|
||||||
spv.Runtime.RuntimeError.InvalidEntryPoint => ffi.Result.InvalidEntryPoint,
|
spv.Runtime.RuntimeError.InvalidEntryPoint => ffi.Result.InvalidEntryPoint,
|
||||||
spv.Runtime.RuntimeError.InvalidSpirV => ffi.Result.InvalidSpirV,
|
spv.Runtime.RuntimeError.InvalidSpirV => ffi.Result.InvalidSpirV,
|
||||||
spv.Runtime.RuntimeError.InvalidValueType => ffi.Result.InvalidValueType,
|
spv.Runtime.RuntimeError.InvalidValueType => ffi.Result.InvalidValueType,
|
||||||
@@ -143,7 +143,6 @@ fn toCResult(err: spv.Runtime.RuntimeError) ffi.Result {
|
|||||||
fn fromCResult(res: ffi.Result) spv.Runtime.RuntimeError!void {
|
fn fromCResult(res: ffi.Result) spv.Runtime.RuntimeError!void {
|
||||||
return switch (res) {
|
return switch (res) {
|
||||||
ffi.Result.Barrier => spv.Runtime.RuntimeError.Barrier,
|
ffi.Result.Barrier => spv.Runtime.RuntimeError.Barrier,
|
||||||
ffi.Result.DivisionByZero => spv.Runtime.RuntimeError.DivisionByZero,
|
|
||||||
ffi.Result.InvalidEntryPoint => spv.Runtime.RuntimeError.InvalidEntryPoint,
|
ffi.Result.InvalidEntryPoint => spv.Runtime.RuntimeError.InvalidEntryPoint,
|
||||||
ffi.Result.InvalidSpirV => spv.Runtime.RuntimeError.InvalidSpirV,
|
ffi.Result.InvalidSpirV => spv.Runtime.RuntimeError.InvalidSpirV,
|
||||||
ffi.Result.InvalidValueType => spv.Runtime.RuntimeError.InvalidValueType,
|
ffi.Result.InvalidValueType => spv.Runtime.RuntimeError.InvalidValueType,
|
||||||
@@ -205,7 +204,7 @@ const ImageAPIBridge = struct {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn sampleImageInfo(driver_image: *anyopaque, driver_sampler: *anyopaque, dim: spv.spv.SpvDim, x: f32, y: f32, z: f32, lod: ?f32, offset: spv.Runtime.ImageOffset) SampleImageInfo {
|
fn sampleImageInfo(driver_image: *anyopaque, driver_sampler: *anyopaque, dim: spv.spv.SpvDim, x: f32, y: f32, z: f32, w: f32, lod: ?f32, offset: spv.Runtime.ImageOffset) SampleImageInfo {
|
||||||
return .{
|
return .{
|
||||||
.driver_image = driver_image,
|
.driver_image = driver_image,
|
||||||
.driver_sampler = driver_sampler,
|
.driver_sampler = driver_sampler,
|
||||||
@@ -213,6 +212,7 @@ const ImageAPIBridge = struct {
|
|||||||
.x = x,
|
.x = x,
|
||||||
.y = y,
|
.y = y,
|
||||||
.z = z,
|
.z = z,
|
||||||
|
.w = w,
|
||||||
.lod = lod orelse 0.0,
|
.lod = lod orelse 0.0,
|
||||||
.has_lod = if (lod == null) 0 else 1,
|
.has_lod = if (lod == null) 0 else 1,
|
||||||
.offset = toCImageOffset(offset),
|
.offset = toCImageOffset(offset),
|
||||||
@@ -279,7 +279,7 @@ const ImageAPIBridge = struct {
|
|||||||
const image_api = try getImageAPI();
|
const image_api = try getImageAPI();
|
||||||
|
|
||||||
var dst: Vec4f = undefined;
|
var dst: Vec4f = undefined;
|
||||||
const result = image_api.sampleImageFloat4(sampleImageInfo(driver_image, driver_sampler, dim, x, y, z, lod, offset), &dst);
|
const result = image_api.sampleImageFloat4(sampleImageInfo(driver_image, driver_sampler, dim, x, y, z, 1.0, lod, offset), &dst);
|
||||||
|
|
||||||
try fromCResult(result);
|
try fromCResult(result);
|
||||||
|
|
||||||
@@ -295,7 +295,7 @@ const ImageAPIBridge = struct {
|
|||||||
const image_api = try getImageAPI();
|
const image_api = try getImageAPI();
|
||||||
|
|
||||||
var dst: Vec4u = undefined;
|
var dst: Vec4u = undefined;
|
||||||
const result = image_api.sampleImageInt4(sampleImageInfo(driver_image, driver_sampler, dim, x, y, z, lod, offset), &dst);
|
const result = image_api.sampleImageInt4(sampleImageInfo(driver_image, driver_sampler, dim, x, y, z, 1.0, lod, offset), &dst);
|
||||||
|
|
||||||
try fromCResult(result);
|
try fromCResult(result);
|
||||||
|
|
||||||
@@ -307,11 +307,11 @@ const ImageAPIBridge = struct {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn sampleImageDref(driver_image: *anyopaque, driver_sampler: *anyopaque, dim: spv.spv.SpvDim, x: f32, y: f32, z: f32, dref: f32, lod: ?f32, offset: spv.Runtime.ImageOffset) spv.Runtime.RuntimeError!f32 {
|
fn sampleImageDref(driver_image: *anyopaque, driver_sampler: *anyopaque, dim: spv.spv.SpvDim, x: f32, y: f32, z: f32, w: f32, dref: f32, lod: ?f32, offset: spv.Runtime.ImageOffset) spv.Runtime.RuntimeError!f32 {
|
||||||
const image_api = try getImageAPI();
|
const image_api = try getImageAPI();
|
||||||
|
|
||||||
var dst: f32 = undefined;
|
var dst: f32 = undefined;
|
||||||
const result = image_api.sampleImageDref(sampleImageInfo(driver_image, driver_sampler, dim, x, y, z, lod, offset), dref, &dst);
|
const result = image_api.sampleImageDref(sampleImageInfo(driver_image, driver_sampler, dim, x, y, z, w, lod, offset), dref, &dst);
|
||||||
|
|
||||||
try fromCResult(result);
|
try fromCResult(result);
|
||||||
|
|
||||||
|
|||||||
@@ -889,11 +889,8 @@ fn opModfStruct(_: std.mem.Allocator, _: SpvWord, id: SpvWord, _: SpvWord, rt: *
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn frexpScalar(comptime T: type, x: T) struct { sig: T, exp: i32 } {
|
fn frexpScalar(comptime T: type, x: T) struct { sig: T, exp: i32 } {
|
||||||
if (x == 0.0)
|
const result = std.math.frexp(x);
|
||||||
return .{ .sig = 0.0, .exp = 0 };
|
return .{ .sig = result.significand, .exp = result.exponent };
|
||||||
|
|
||||||
const exp = @as(i32, @intFromFloat(@floor(@log2(@abs(x))))) + 1;
|
|
||||||
return .{ .sig = x / @exp2(@as(T, @floatFromInt(exp))), .exp = exp };
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn opFrexp(_: std.mem.Allocator, target_type_id: SpvWord, id: SpvWord, _: SpvWord, rt: *Runtime) RuntimeError!void {
|
fn opFrexp(_: std.mem.Allocator, target_type_id: SpvWord, id: SpvWord, _: SpvWord, rt: *Runtime) RuntimeError!void {
|
||||||
@@ -951,8 +948,9 @@ fn opLdexp(_: std.mem.Allocator, target_type_id: SpvWord, id: SpvWord, _: SpvWor
|
|||||||
inline 16, 32, 64 => |bits| for (0..lane_count) |lane_index| {
|
inline 16, 32, 64 => |bits| for (0..lane_count) |lane_index| {
|
||||||
const exp_lane = if (exp_lane_count == 1) 0 else lane_index;
|
const exp_lane = if (exp_lane_count == 1) 0 else lane_index;
|
||||||
const exponent = try readIntegralLaneAsI32(exp_value, exp_lane);
|
const exponent = try readIntegralLaneAsI32(exp_value, exp_lane);
|
||||||
const scale = @exp2(@as(std.meta.Float(bits), @floatFromInt(exponent)));
|
const value = try Value.readLane(.Float, bits, x, lane_index);
|
||||||
try writeFloatLane(bits, dst, lane_index, try Value.readLane(.Float, bits, x, lane_index) * scale);
|
const result = if (value == 0.0) value else std.math.ldexp(value, exponent);
|
||||||
|
try writeFloatLane(bits, dst, lane_index, result);
|
||||||
},
|
},
|
||||||
else => return RuntimeError.InvalidSpirV,
|
else => return RuntimeError.InvalidSpirV,
|
||||||
}
|
}
|
||||||
@@ -1121,7 +1119,51 @@ fn matrixSize(matrix: *const Value) RuntimeError!usize {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn determinant3Values(comptime T: type, a00: T, a01: T, a02: T, a10: T, a11: T, a12: T, a20: T, a21: T, a22: T) T {
|
||||||
|
return a00 * ((a11 * a22) - (a12 * a21)) -
|
||||||
|
a01 * ((a10 * a22) - (a12 * a20)) +
|
||||||
|
a02 * ((a10 * a21) - (a11 * a20));
|
||||||
|
}
|
||||||
|
|
||||||
fn determinant(comptime bits: u32, src: *const Value, n: usize) RuntimeError!std.meta.Float(bits) {
|
fn determinant(comptime bits: u32, src: *const Value, n: usize) RuntimeError!std.meta.Float(bits) {
|
||||||
|
const FloatT = std.meta.Float(bits);
|
||||||
|
if (n == 2) {
|
||||||
|
const a00 = try readMatrixElement(bits, src, 0, 0);
|
||||||
|
const a01 = try readMatrixElement(bits, src, 0, 1);
|
||||||
|
const a10 = try readMatrixElement(bits, src, 1, 0);
|
||||||
|
const a11 = try readMatrixElement(bits, src, 1, 1);
|
||||||
|
return (a00 * a11) - (a10 * a01);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (n == 3) {
|
||||||
|
return determinant3Values(
|
||||||
|
FloatT,
|
||||||
|
try readMatrixElement(bits, src, 0, 0),
|
||||||
|
try readMatrixElement(bits, src, 0, 1),
|
||||||
|
try readMatrixElement(bits, src, 0, 2),
|
||||||
|
try readMatrixElement(bits, src, 1, 0),
|
||||||
|
try readMatrixElement(bits, src, 1, 1),
|
||||||
|
try readMatrixElement(bits, src, 1, 2),
|
||||||
|
try readMatrixElement(bits, src, 2, 0),
|
||||||
|
try readMatrixElement(bits, src, 2, 1),
|
||||||
|
try readMatrixElement(bits, src, 2, 2),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (n == 4) {
|
||||||
|
var m: [4][4]FloatT = undefined;
|
||||||
|
for (0..4) |row| {
|
||||||
|
for (0..4) |col| {
|
||||||
|
m[row][col] = try readMatrixElement(bits, src, row, col);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return m[0][0] * determinant3Values(FloatT, m[1][1], m[1][2], m[1][3], m[2][1], m[2][2], m[2][3], m[3][1], m[3][2], m[3][3]) -
|
||||||
|
m[0][1] * determinant3Values(FloatT, m[1][0], m[1][2], m[1][3], m[2][0], m[2][2], m[2][3], m[3][0], m[3][2], m[3][3]) +
|
||||||
|
m[0][2] * determinant3Values(FloatT, m[1][0], m[1][1], m[1][3], m[2][0], m[2][1], m[2][3], m[3][0], m[3][1], m[3][3]) -
|
||||||
|
m[0][3] * determinant3Values(FloatT, m[1][0], m[1][1], m[1][2], m[2][0], m[2][1], m[2][2], m[3][0], m[3][1], m[3][2]);
|
||||||
|
}
|
||||||
|
|
||||||
var m: [16]std.meta.Float(bits) = undefined;
|
var m: [16]std.meta.Float(bits) = undefined;
|
||||||
for (0..n) |row| {
|
for (0..n) |row| {
|
||||||
for (0..n) |col| {
|
for (0..n) |col| {
|
||||||
@@ -1186,6 +1228,19 @@ fn opMatrixInverse(_: std.mem.Allocator, target_type_id: SpvWord, id: SpvWord, _
|
|||||||
|
|
||||||
switch (lane_bits) {
|
switch (lane_bits) {
|
||||||
inline 16, 32, 64 => |bits| {
|
inline 16, 32, 64 => |bits| {
|
||||||
|
if (n == 2) {
|
||||||
|
const a00 = try readMatrixElement(bits, src, 0, 0);
|
||||||
|
const a01 = try readMatrixElement(bits, src, 0, 1);
|
||||||
|
const a10 = try readMatrixElement(bits, src, 1, 0);
|
||||||
|
const a11 = try readMatrixElement(bits, src, 1, 1);
|
||||||
|
const inv_det = 1.0 / ((a00 * a11) - (a10 * a01));
|
||||||
|
try writeMatrixElement(bits, dst, 0, 0, a11 * inv_det);
|
||||||
|
try writeMatrixElement(bits, dst, 0, 1, -a01 * inv_det);
|
||||||
|
try writeMatrixElement(bits, dst, 1, 0, -a10 * inv_det);
|
||||||
|
try writeMatrixElement(bits, dst, 1, 1, a00 * inv_det);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
var aug: [32]std.meta.Float(bits) = undefined;
|
var aug: [32]std.meta.Float(bits) = undefined;
|
||||||
const width = n * 2;
|
const width = n * 2;
|
||||||
for (0..n) |row| {
|
for (0..n) |row| {
|
||||||
|
|||||||
+2
-1
@@ -21,7 +21,6 @@ const Self = @This();
|
|||||||
|
|
||||||
pub const RuntimeError = error{
|
pub const RuntimeError = error{
|
||||||
Barrier,
|
Barrier,
|
||||||
DivisionByZero,
|
|
||||||
InvalidEntryPoint,
|
InvalidEntryPoint,
|
||||||
InvalidSpirV,
|
InvalidSpirV,
|
||||||
InvalidValueType,
|
InvalidValueType,
|
||||||
@@ -428,6 +427,8 @@ pub fn setDerivativeFromMemory(self: *Self, allocator: std.mem.Allocator, result
|
|||||||
|
|
||||||
var dx_value = try Value.init(allocator, self.results, target_type, false);
|
var dx_value = try Value.init(allocator, self.results, target_type, false);
|
||||||
defer dx_value.deinit(allocator);
|
defer dx_value.deinit(allocator);
|
||||||
|
const memory_size = try dx_value.getPlainMemorySize();
|
||||||
|
if (dx.len < memory_size or dy.len < memory_size) return RuntimeError.OutOfBounds;
|
||||||
_ = try dx_value.write(dx);
|
_ = try dx_value.write(dx);
|
||||||
|
|
||||||
var dy_value = try Value.init(allocator, self.results, target_type, false);
|
var dy_value = try Value.init(allocator, self.results, target_type, false);
|
||||||
|
|||||||
+89
-18
@@ -1849,9 +1849,21 @@ fn ImageEngine(comptime Op: ImageOp) type {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn explicitSampleLod(rt: *Runtime, driver_image: *anyopaque, driver_sampler: *anyopaque, dim: spv.SpvDim, parsed: ParsedImageOperands) RuntimeError!?f32 {
|
fn explicitSampleLod(rt: *Runtime, driver_image: *anyopaque, driver_sampler: *anyopaque, dim: spv.SpvDim, x: f32, y: f32, z: f32, parsed: ParsedImageOperands) RuntimeError!?f32 {
|
||||||
if (parsed.grad) |derivatives| {
|
if (parsed.grad) |derivatives| {
|
||||||
const lod = try rt.image_api.queryImageLod(driver_image, driver_sampler, dim, derivatives);
|
const lod_dim, const lod_derivatives = if (dim == .Cube) blk: {
|
||||||
|
const center = cubeFaceCoord(x, y, z);
|
||||||
|
const dx = cubeFaceCoordForFace(center.face, x + derivatives.dx.x, y + derivatives.dx.y, z + derivatives.dx.z);
|
||||||
|
const dy = cubeFaceCoordForFace(center.face, x + derivatives.dy.x, y + derivatives.dy.y, z + derivatives.dy.z);
|
||||||
|
break :blk .{
|
||||||
|
spv.SpvDim.@"2D",
|
||||||
|
Runtime.ImageDerivatives{
|
||||||
|
.dx = .{ .x = dx.u - center.u, .y = dx.v - center.v, .z = 0.0, .w = 0.0 },
|
||||||
|
.dy = .{ .x = dy.u - center.u, .y = dy.v - center.v, .z = 0.0, .w = 0.0 },
|
||||||
|
},
|
||||||
|
};
|
||||||
|
} else .{ dim, derivatives };
|
||||||
|
const lod = try rt.image_api.queryImageLod(driver_image, driver_sampler, lod_dim, lod_derivatives);
|
||||||
return lod.y;
|
return lod.y;
|
||||||
}
|
}
|
||||||
return parsed.lod;
|
return parsed.lod;
|
||||||
@@ -2054,20 +2066,49 @@ fn ImageEngine(comptime Op: ImageOp) type {
|
|||||||
|
|
||||||
fn queryImageLod(rt: *Runtime, dst: *Value, coordinate_id: SpvWord, image_operand: SampledImageOperand) RuntimeError!void {
|
fn queryImageLod(rt: *Runtime, dst: *Value, coordinate_id: SpvWord, image_operand: SampledImageOperand) RuntimeError!void {
|
||||||
const coord_derivative = rt.derivatives.get(coordinate_id) orelse return RuntimeError.InvalidValueType;
|
const coord_derivative = rt.derivatives.get(coordinate_id) orelse return RuntimeError.InvalidValueType;
|
||||||
const lod = try rt.image_api.queryImageLod(image_operand.driver_image, image_operand.driver_sampler, image_operand.dim, .{
|
const coord = try rt.results[coordinate_id].getValue();
|
||||||
.dx = .{
|
const dim, const derivatives = if (image_operand.dim == .Cube) blk: {
|
||||||
.x = try readSampleCoordLane(&coord_derivative.dx, 0),
|
const x = try readSampleCoordLane(coord, 0);
|
||||||
.y = readSampleCoordLane(&coord_derivative.dx, 1) catch 0.0,
|
const y = try readSampleCoordLane(coord, 1);
|
||||||
.z = readSampleCoordLane(&coord_derivative.dx, 2) catch 0.0,
|
const z = try readSampleCoordLane(coord, 2);
|
||||||
.w = readSampleCoordLane(&coord_derivative.dx, 3) catch 0.0,
|
const center = cubeFaceCoord(x, y, z);
|
||||||
|
const dx = cubeFaceCoordForFace(
|
||||||
|
center.face,
|
||||||
|
x + try readSampleCoordLane(&coord_derivative.dx, 0),
|
||||||
|
y + (readSampleCoordLane(&coord_derivative.dx, 1) catch 0.0),
|
||||||
|
z + (readSampleCoordLane(&coord_derivative.dx, 2) catch 0.0),
|
||||||
|
);
|
||||||
|
const dy = cubeFaceCoordForFace(
|
||||||
|
center.face,
|
||||||
|
x + try readSampleCoordLane(&coord_derivative.dy, 0),
|
||||||
|
y + (readSampleCoordLane(&coord_derivative.dy, 1) catch 0.0),
|
||||||
|
z + (readSampleCoordLane(&coord_derivative.dy, 2) catch 0.0),
|
||||||
|
);
|
||||||
|
break :blk .{
|
||||||
|
spv.SpvDim.@"2D",
|
||||||
|
Runtime.ImageDerivatives{
|
||||||
|
.dx = .{ .x = dx.u - center.u, .y = dx.v - center.v, .z = 0.0, .w = 0.0 },
|
||||||
|
.dy = .{ .x = dy.u - center.u, .y = dy.v - center.v, .z = 0.0, .w = 0.0 },
|
||||||
|
},
|
||||||
|
};
|
||||||
|
} else .{
|
||||||
|
image_operand.dim,
|
||||||
|
Runtime.ImageDerivatives{
|
||||||
|
.dx = .{
|
||||||
|
.x = try readSampleCoordLane(&coord_derivative.dx, 0),
|
||||||
|
.y = readSampleCoordLane(&coord_derivative.dx, 1) catch 0.0,
|
||||||
|
.z = readSampleCoordLane(&coord_derivative.dx, 2) catch 0.0,
|
||||||
|
.w = readSampleCoordLane(&coord_derivative.dx, 3) catch 0.0,
|
||||||
|
},
|
||||||
|
.dy = .{
|
||||||
|
.x = try readSampleCoordLane(&coord_derivative.dy, 0),
|
||||||
|
.y = readSampleCoordLane(&coord_derivative.dy, 1) catch 0.0,
|
||||||
|
.z = readSampleCoordLane(&coord_derivative.dy, 2) catch 0.0,
|
||||||
|
.w = readSampleCoordLane(&coord_derivative.dy, 3) catch 0.0,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
.dy = .{
|
};
|
||||||
.x = try readSampleCoordLane(&coord_derivative.dy, 0),
|
const lod = try rt.image_api.queryImageLod(image_operand.driver_image, image_operand.driver_sampler, dim, derivatives);
|
||||||
.y = readSampleCoordLane(&coord_derivative.dy, 1) catch 0.0,
|
|
||||||
.z = readSampleCoordLane(&coord_derivative.dy, 2) catch 0.0,
|
|
||||||
.w = readSampleCoordLane(&coord_derivative.dy, 3) catch 0.0,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
switch (dst.*) {
|
switch (dst.*) {
|
||||||
.Vector2f32 => |*v| v.* = .{ lod.x, lod.y },
|
.Vector2f32 => |*v| v.* = .{ lod.x, lod.y },
|
||||||
@@ -2302,6 +2343,9 @@ fn ImageEngine(comptime Op: ImageOp) type {
|
|||||||
sampled_image_operand.driver_image,
|
sampled_image_operand.driver_image,
|
||||||
sampled_image_operand.driver_sampler,
|
sampled_image_operand.driver_sampler,
|
||||||
sampled_image_operand.dim,
|
sampled_image_operand.dim,
|
||||||
|
coords.x,
|
||||||
|
coords.y,
|
||||||
|
coords.z,
|
||||||
parsed_operands,
|
parsed_operands,
|
||||||
),
|
),
|
||||||
parsed_operands.offset,
|
parsed_operands.offset,
|
||||||
@@ -2345,6 +2389,9 @@ fn ImageEngine(comptime Op: ImageOp) type {
|
|||||||
sampled_image_operand.driver_image,
|
sampled_image_operand.driver_image,
|
||||||
sampled_image_operand.driver_sampler,
|
sampled_image_operand.driver_sampler,
|
||||||
sampled_image_operand.dim,
|
sampled_image_operand.dim,
|
||||||
|
coords.x,
|
||||||
|
coords.y,
|
||||||
|
coords.z,
|
||||||
parsed_operands,
|
parsed_operands,
|
||||||
),
|
),
|
||||||
parsed_operands.offset,
|
parsed_operands.offset,
|
||||||
@@ -2695,6 +2742,30 @@ fn MathEngine(comptime T: PrimitiveType, comptime Op: MathOp, comptime IsAtomic:
|
|||||||
fn operation(comptime TT: type, op1: TT, op2: TT) RuntimeError!TT {
|
fn operation(comptime TT: type, op1: TT, op2: TT) RuntimeError!TT {
|
||||||
const is_int = @typeInfo(TT) == .int or (@typeInfo(TT) == .vector and @typeInfo(std.meta.Child(TT)) == .int);
|
const is_int = @typeInfo(TT) == .int or (@typeInfo(TT) == .vector and @typeInfo(std.meta.Child(TT)) == .int);
|
||||||
const op2_is_zero = if (@typeInfo(TT) == .vector) std.simd.countElementsWithValue(op2, 0) != 0 else op2 == 0;
|
const op2_is_zero = if (@typeInfo(TT) == .vector) std.simd.countElementsWithValue(op2, 0) != 0 else op2 == 0;
|
||||||
|
const zero: TT = switch (@typeInfo(TT)) {
|
||||||
|
.vector => @splat(0),
|
||||||
|
else => 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (@typeInfo(TT) == .vector) {
|
||||||
|
switch (Op) {
|
||||||
|
.Div, .Mod, .Rem => {
|
||||||
|
var result: TT = undefined;
|
||||||
|
inline for (0..@typeInfo(TT).vector.len) |i| {
|
||||||
|
result[i] = if (op2[i] == 0)
|
||||||
|
0
|
||||||
|
else switch (Op) {
|
||||||
|
.Div => if (comptime is_int) @divTrunc(op1[i], op2[i]) else op1[i] / op2[i],
|
||||||
|
.Mod => @mod(op1[i], op2[i]),
|
||||||
|
.Rem => @rem(op1[i], op2[i]),
|
||||||
|
else => unreachable,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
},
|
||||||
|
else => {},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return switch (Op) {
|
return switch (Op) {
|
||||||
.Add => if (comptime is_int) @addWithOverflow(op1, op2)[0] else op1 + op2,
|
.Add => if (comptime is_int) @addWithOverflow(op1, op2)[0] else op1 + op2,
|
||||||
@@ -2707,12 +2778,12 @@ fn MathEngine(comptime T: PrimitiveType, comptime Op: MathOp, comptime IsAtomic:
|
|||||||
=> if (comptime is_int) @mulWithOverflow(op1, op2)[0] else op1 * op2,
|
=> if (comptime is_int) @mulWithOverflow(op1, op2)[0] else op1 * op2,
|
||||||
.Div => blk: {
|
.Div => blk: {
|
||||||
if (comptime is_int) {
|
if (comptime is_int) {
|
||||||
if (op2_is_zero) return RuntimeError.DivisionByZero;
|
if (op2_is_zero) return zero;
|
||||||
}
|
}
|
||||||
break :blk if (comptime is_int) @divTrunc(op1, op2) else op1 / op2;
|
break :blk if (comptime is_int) @divTrunc(op1, op2) else op1 / op2;
|
||||||
},
|
},
|
||||||
.Mod => if (op2_is_zero) return RuntimeError.DivisionByZero else @mod(op1, op2),
|
.Mod => if (op2_is_zero) zero else @mod(op1, op2),
|
||||||
.Rem => if (op2_is_zero) return RuntimeError.DivisionByZero else @rem(op1, op2),
|
.Rem => if (op2_is_zero) zero else @rem(op1, op2),
|
||||||
else => return RuntimeError.InvalidSpirV,
|
else => return RuntimeError.InvalidSpirV,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -48,7 +48,7 @@ fn sampleImageInt4(_: *anyopaque, _: *anyopaque, _: spv.spv.SpvDim, _: f32, _: f
|
|||||||
return spv.Runtime.RuntimeError.UnsupportedSpirV;
|
return spv.Runtime.RuntimeError.UnsupportedSpirV;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn sampleImageDref(driver_image: *anyopaque, driver_sampler: *anyopaque, _: spv.spv.SpvDim, x: f32, y: f32, z: f32, dref: f32, lod: ?f32, offset: spv.Runtime.ImageOffset) spv.Runtime.RuntimeError!f32 {
|
fn sampleImageDref(driver_image: *anyopaque, driver_sampler: *anyopaque, _: spv.spv.SpvDim, x: f32, y: f32, z: f32, _: f32, dref: f32, lod: ?f32, offset: spv.Runtime.ImageOffset) spv.Runtime.RuntimeError!f32 {
|
||||||
const state: *ImageState = @ptrCast(@alignCast(driver_image));
|
const state: *ImageState = @ptrCast(@alignCast(driver_image));
|
||||||
if (state.expected_sampler != driver_sampler) return spv.Runtime.RuntimeError.InvalidSpirV;
|
if (state.expected_sampler != driver_sampler) return spv.Runtime.RuntimeError.InvalidSpirV;
|
||||||
state.dref_calls += 1;
|
state.dref_calls += 1;
|
||||||
|
|||||||
Reference in New Issue
Block a user