adding more image queries
This commit is contained in:
+11
-3
@@ -87,15 +87,23 @@ pub const ImageOffset = struct {
|
|||||||
z: i32 = 0,
|
z: i32 = 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
pub const ImageDerivatives = struct {
|
||||||
|
dx: Vec4(f32),
|
||||||
|
dy: Vec4(f32),
|
||||||
|
};
|
||||||
|
|
||||||
pub const ImageAPI = struct {
|
pub const ImageAPI = struct {
|
||||||
readImageFloat4: *const fn (driver_image: *anyopaque, dim: spv.SpvDim, x: i32, y: i32, z: i32) RuntimeError!Vec4(f32),
|
readImageFloat4: *const fn (driver_image: *anyopaque, dim: spv.SpvDim, x: i32, y: i32, z: i32, lod: ?i32) RuntimeError!Vec4(f32),
|
||||||
readImageInt4: *const fn (driver_image: *anyopaque, dim: spv.SpvDim, x: i32, y: i32, z: i32) RuntimeError!Vec4(u32),
|
readImageInt4: *const fn (driver_image: *anyopaque, dim: spv.SpvDim, x: i32, y: i32, z: i32, lod: ?i32) RuntimeError!Vec4(u32),
|
||||||
writeImageFloat4: *const fn (driver_image: *anyopaque, dim: spv.SpvDim, x: i32, y: i32, z: i32, pixel: Vec4(f32)) RuntimeError!void,
|
writeImageFloat4: *const fn (driver_image: *anyopaque, dim: spv.SpvDim, x: i32, y: i32, z: i32, pixel: Vec4(f32)) RuntimeError!void,
|
||||||
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, dref: f32, lod: ?f32, offset: ImageOffset) RuntimeError!f32,
|
||||||
queryImageSize: *const fn (driver_image: *anyopaque, dim: spv.SpvDim, arrayed: bool) 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,
|
||||||
|
queryImageSamples: *const fn (driver_image: *anyopaque) RuntimeError!u32,
|
||||||
|
queryImageLod: *const fn (driver_image: *anyopaque, driver_sampler: *anyopaque, dim: spv.SpvDim, derivatives: ImageDerivatives) RuntimeError!Vec4(f32),
|
||||||
};
|
};
|
||||||
|
|
||||||
mod: *Module,
|
mod: *Module,
|
||||||
|
|||||||
+102
-18
@@ -70,6 +70,9 @@ const BitOp = enum {
|
|||||||
|
|
||||||
const ImageOp = enum {
|
const ImageOp = enum {
|
||||||
Fetch,
|
Fetch,
|
||||||
|
QueryLevels,
|
||||||
|
QueryLod,
|
||||||
|
QuerySamples,
|
||||||
QuerySize,
|
QuerySize,
|
||||||
QuerySizeLod,
|
QuerySizeLod,
|
||||||
Read,
|
Read,
|
||||||
@@ -199,6 +202,9 @@ pub const SetupDispatcher = block: {
|
|||||||
.ISubBorrow = autoSetupConstant,
|
.ISubBorrow = autoSetupConstant,
|
||||||
.Image = autoSetupConstant,
|
.Image = autoSetupConstant,
|
||||||
.ImageFetch = autoSetupConstant,
|
.ImageFetch = autoSetupConstant,
|
||||||
|
.ImageQueryLevels = autoSetupConstant,
|
||||||
|
.ImageQueryLod = opDerivativeSetup,
|
||||||
|
.ImageQuerySamples = autoSetupConstant,
|
||||||
.ImageQuerySize = autoSetupConstant,
|
.ImageQuerySize = autoSetupConstant,
|
||||||
.ImageQuerySizeLod = autoSetupConstant,
|
.ImageQuerySizeLod = autoSetupConstant,
|
||||||
.ImageRead = autoSetupConstant,
|
.ImageRead = autoSetupConstant,
|
||||||
@@ -373,6 +379,9 @@ pub fn initRuntimeDispatcher() void {
|
|||||||
runtime_dispatcher[@intFromEnum(spv.SpvOp.ISubBorrow)] = opISubBorrow;
|
runtime_dispatcher[@intFromEnum(spv.SpvOp.ISubBorrow)] = opISubBorrow;
|
||||||
runtime_dispatcher[@intFromEnum(spv.SpvOp.Image)] = ImageEngine(.Resolve).op;
|
runtime_dispatcher[@intFromEnum(spv.SpvOp.Image)] = ImageEngine(.Resolve).op;
|
||||||
runtime_dispatcher[@intFromEnum(spv.SpvOp.ImageFetch)] = ImageEngine(.Fetch).op;
|
runtime_dispatcher[@intFromEnum(spv.SpvOp.ImageFetch)] = ImageEngine(.Fetch).op;
|
||||||
|
runtime_dispatcher[@intFromEnum(spv.SpvOp.ImageQueryLevels)] = ImageEngine(.QueryLevels).op;
|
||||||
|
runtime_dispatcher[@intFromEnum(spv.SpvOp.ImageQueryLod)] = ImageEngine(.QueryLod).op;
|
||||||
|
runtime_dispatcher[@intFromEnum(spv.SpvOp.ImageQuerySamples)] = ImageEngine(.QuerySamples).op;
|
||||||
runtime_dispatcher[@intFromEnum(spv.SpvOp.ImageQuerySize)] = ImageEngine(.QuerySize).op;
|
runtime_dispatcher[@intFromEnum(spv.SpvOp.ImageQuerySize)] = ImageEngine(.QuerySize).op;
|
||||||
runtime_dispatcher[@intFromEnum(spv.SpvOp.ImageQuerySizeLod)] = ImageEngine(.QuerySizeLod).op;
|
runtime_dispatcher[@intFromEnum(spv.SpvOp.ImageQuerySizeLod)] = ImageEngine(.QuerySizeLod).op;
|
||||||
runtime_dispatcher[@intFromEnum(spv.SpvOp.ImageRead)] = ImageEngine(.Read).op;
|
runtime_dispatcher[@intFromEnum(spv.SpvOp.ImageRead)] = ImageEngine(.Read).op;
|
||||||
@@ -1397,6 +1406,7 @@ fn ImageEngine(comptime Op: ImageOp) type {
|
|||||||
|
|
||||||
const ParsedImageOperands = struct {
|
const ParsedImageOperands = struct {
|
||||||
lod: ?f32 = null,
|
lod: ?f32 = null,
|
||||||
|
image_lod: ?i32 = null,
|
||||||
offset: Runtime.ImageOffset = .{},
|
offset: Runtime.ImageOffset = .{},
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1407,7 +1417,9 @@ fn ImageEngine(comptime Op: ImageOp) type {
|
|||||||
_ = try rt.it.next();
|
_ = try rt.it.next();
|
||||||
}
|
}
|
||||||
if (imageOperandPresent(image_operands, .LodMask)) {
|
if (imageOperandPresent(image_operands, .LodMask)) {
|
||||||
parsed.lod = try readFloatLane(try rt.results[try rt.it.next()].getValue(), 0);
|
const lod_value = try rt.results[try rt.it.next()].getValue();
|
||||||
|
parsed.lod = try readSampleCoordLane(lod_value, 0);
|
||||||
|
parsed.image_lod = readImageQueryLod(lod_value) catch null;
|
||||||
}
|
}
|
||||||
if (imageOperandPresent(image_operands, .GradMask)) {
|
if (imageOperandPresent(image_operands, .GradMask)) {
|
||||||
_ = try rt.it.next();
|
_ = try rt.it.next();
|
||||||
@@ -1497,12 +1509,12 @@ fn ImageEngine(comptime Op: ImageOp) type {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn readImage(rt: *Runtime, dst: *Value, driver_image: *anyopaque, dim: spv.SpvDim, x: i32, y: i32, z: i32) RuntimeError!void {
|
fn readImage(rt: *Runtime, dst: *Value, driver_image: *anyopaque, dim: spv.SpvDim, x: i32, y: i32, z: i32, lod: ?i32) RuntimeError!void {
|
||||||
switch (dst.*) {
|
switch (dst.*) {
|
||||||
.Vector4f32,
|
.Vector4f32,
|
||||||
.Vector3f32,
|
.Vector3f32,
|
||||||
.Vector2f32,
|
.Vector2f32,
|
||||||
=> try writeFloatTexel(dst, try rt.image_api.readImageFloat4(driver_image, dim, x, y, z)),
|
=> try writeFloatTexel(dst, try rt.image_api.readImageFloat4(driver_image, dim, x, y, z, lod)),
|
||||||
|
|
||||||
.Vector4i32,
|
.Vector4i32,
|
||||||
.Vector3i32,
|
.Vector3i32,
|
||||||
@@ -1510,13 +1522,13 @@ fn ImageEngine(comptime Op: ImageOp) type {
|
|||||||
.Vector4u32,
|
.Vector4u32,
|
||||||
.Vector3u32,
|
.Vector3u32,
|
||||||
.Vector2u32,
|
.Vector2u32,
|
||||||
=> try writeIntTexel(dst, try rt.image_api.readImageInt4(driver_image, dim, x, y, z)),
|
=> try writeIntTexel(dst, try rt.image_api.readImageInt4(driver_image, dim, x, y, z, lod)),
|
||||||
|
|
||||||
.Vector => |lanes| {
|
.Vector => |lanes| {
|
||||||
if (lanes.len == 0) return RuntimeError.InvalidSpirV;
|
if (lanes.len == 0) return RuntimeError.InvalidSpirV;
|
||||||
switch (lanes[0]) {
|
switch (lanes[0]) {
|
||||||
.Float => try writeFloatTexel(dst, try rt.image_api.readImageFloat4(driver_image, dim, x, y, z)),
|
.Float => try writeFloatTexel(dst, try rt.image_api.readImageFloat4(driver_image, dim, x, y, z, lod)),
|
||||||
.Int => try writeIntTexel(dst, try rt.image_api.readImageInt4(driver_image, dim, x, y, z)),
|
.Int => try writeIntTexel(dst, try rt.image_api.readImageInt4(driver_image, dim, x, y, z, lod)),
|
||||||
else => return RuntimeError.InvalidValueType,
|
else => return RuntimeError.InvalidValueType,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -1673,8 +1685,15 @@ fn ImageEngine(comptime Op: ImageOp) type {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn queryImageSize(rt: *Runtime, dst: *Value, image_operand: ImageOperand) RuntimeError!void {
|
fn readImageQueryLod(value: *const Value) RuntimeError!i32 {
|
||||||
const size = try rt.image_api.queryImageSize(image_operand.driver_image, image_operand.dim, image_operand.arrayed);
|
return switch (value.*) {
|
||||||
|
.Int => |i| if (i.is_signed) i.value.sint32 else @intCast(i.value.uint32),
|
||||||
|
else => return RuntimeError.InvalidValueType,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
fn queryImageSize(rt: *Runtime, dst: *Value, image_operand: ImageOperand, lod: ?i32) RuntimeError!void {
|
||||||
|
const size = try rt.image_api.queryImageSize(image_operand.driver_image, image_operand.dim, image_operand.arrayed, lod);
|
||||||
switch (dst.*) {
|
switch (dst.*) {
|
||||||
.Int => |*v| v.value.uint32 = size.x,
|
.Int => |*v| v.value.uint32 = size.x,
|
||||||
.Vector2i32 => |*v| v.* = .{ @bitCast(size.x), @bitCast(size.y) },
|
.Vector2i32 => |*v| v.* = .{ @bitCast(size.x), @bitCast(size.y) },
|
||||||
@@ -1697,6 +1716,57 @@ fn ImageEngine(comptime Op: ImageOp) type {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn queryImageSamples(rt: *Runtime, dst: *Value, image_operand: ImageOperand) RuntimeError!void {
|
||||||
|
const samples = try rt.image_api.queryImageSamples(image_operand.driver_image);
|
||||||
|
switch (dst.*) {
|
||||||
|
.Int => |*v| v.value.uint32 = samples,
|
||||||
|
else => return RuntimeError.InvalidValueType,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn queryImageLevels(rt: *Runtime, dst: *Value, image_operand: ImageOperand) RuntimeError!void {
|
||||||
|
const levels = try rt.image_api.queryImageLevels(image_operand.driver_image);
|
||||||
|
switch (dst.*) {
|
||||||
|
.Int => |*v| v.value.uint32 = levels,
|
||||||
|
else => return RuntimeError.InvalidValueType,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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 lod = try rt.image_api.queryImageLod(image_operand.driver_image, image_operand.driver_sampler, image_operand.dim, .{
|
||||||
|
.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,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
switch (dst.*) {
|
||||||
|
.Vector2f32 => |*v| v.* = .{ lod.x, lod.y },
|
||||||
|
.Vector3f32 => |*v| v.* = .{ lod.x, lod.y, lod.z },
|
||||||
|
.Vector4f32 => |*v| v.* = .{ lod.x, lod.y, lod.z, lod.w },
|
||||||
|
.Vector => |lanes| {
|
||||||
|
const values = [_]f32{ lod.x, lod.y, lod.z, lod.w };
|
||||||
|
for (lanes, 0..) |*lane, i| {
|
||||||
|
if (i >= values.len) return RuntimeError.InvalidSpirV;
|
||||||
|
switch (lane.*) {
|
||||||
|
.Float => |*float| float.value.float32 = values[i],
|
||||||
|
else => return RuntimeError.InvalidValueType,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
else => return RuntimeError.InvalidValueType,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn op(allocator: std.mem.Allocator, word_count: SpvWord, rt: *Runtime) RuntimeError!void {
|
fn op(allocator: std.mem.Allocator, word_count: SpvWord, rt: *Runtime) RuntimeError!void {
|
||||||
if (comptime Op == .Resolve) {
|
if (comptime Op == .Resolve) {
|
||||||
_ = try rt.it.next(); // result type
|
_ = try rt.it.next(); // result type
|
||||||
@@ -1729,13 +1799,20 @@ fn ImageEngine(comptime Op: ImageOp) type {
|
|||||||
const result_type_word = try rt.it.next();
|
const result_type_word = try rt.it.next();
|
||||||
const result_id = try rt.it.next();
|
const result_id = try rt.it.next();
|
||||||
const image = &rt.results[try rt.it.next()];
|
const image = &rt.results[try rt.it.next()];
|
||||||
if (comptime Op == .QuerySize or Op == .QuerySizeLod) {
|
if (comptime Op == .QuerySize or Op == .QuerySizeLod or Op == .QuerySamples or Op == .QueryLevels) {
|
||||||
const image_operand = try resolveImageForQuery(image, rt);
|
const image_operand = try resolveImageForQuery(image, rt);
|
||||||
if (comptime Op == .QuerySizeLod) {
|
|
||||||
_ = try rt.it.next(); // LOD operand; ImageAPI currently exposes base size only.
|
|
||||||
}
|
|
||||||
const dst = try rt.results[result_id].getValue();
|
const dst = try rt.results[result_id].getValue();
|
||||||
return try queryImageSize(rt, dst, image_operand);
|
if (comptime Op == .QuerySamples) {
|
||||||
|
return try queryImageSamples(rt, dst, image_operand);
|
||||||
|
}
|
||||||
|
if (comptime Op == .QueryLevels) {
|
||||||
|
return try queryImageLevels(rt, dst, image_operand);
|
||||||
|
}
|
||||||
|
var lod: ?i32 = null;
|
||||||
|
if (comptime Op == .QuerySizeLod) {
|
||||||
|
lod = try readImageQueryLod(try rt.results[try rt.it.next()].getValue());
|
||||||
|
}
|
||||||
|
return try queryImageSize(rt, dst, image_operand, lod);
|
||||||
}
|
}
|
||||||
|
|
||||||
const coordinate_id = try rt.it.next();
|
const coordinate_id = try rt.it.next();
|
||||||
@@ -1743,15 +1820,22 @@ fn ImageEngine(comptime Op: ImageOp) type {
|
|||||||
const dst = try rt.results[result_id].getValue();
|
const dst = try rt.results[result_id].getValue();
|
||||||
|
|
||||||
switch (Op) {
|
switch (Op) {
|
||||||
|
.QueryLod => {
|
||||||
|
const sampled_image_operand = try resolveSampledImage(image, rt);
|
||||||
|
return try queryImageLod(rt, dst, coordinate_id, sampled_image_operand);
|
||||||
|
},
|
||||||
|
|
||||||
.Fetch,
|
.Fetch,
|
||||||
.Read,
|
.Read,
|
||||||
=> {
|
=> {
|
||||||
const image_operand = try resolveImage(image, rt);
|
const image_operand = try resolveImage(image, rt);
|
||||||
const x = try readStorageCoordLane(coordinate, 0);
|
const image_operands = if (word_count > 4) try rt.it.next() else 0;
|
||||||
const y = readStorageCoordLane(coordinate, 1) catch 0;
|
const parsed_operands = try parseImageOperands(rt, image_operands);
|
||||||
const z = readStorageCoordLane(coordinate, 2) catch 0;
|
const x = try readStorageCoordLane(coordinate, 0) + parsed_operands.offset.x;
|
||||||
|
const y = (readStorageCoordLane(coordinate, 1) catch 0) + parsed_operands.offset.y;
|
||||||
|
const z = (readStorageCoordLane(coordinate, 2) catch 0) + parsed_operands.offset.z;
|
||||||
|
|
||||||
try readImage(rt, dst, image_operand.driver_image, image_operand.dim, x, y, z);
|
try readImage(rt, dst, image_operand.driver_image, image_operand.dim, x, y, z, parsed_operands.image_lod);
|
||||||
},
|
},
|
||||||
|
|
||||||
.SampleImplicitLod,
|
.SampleImplicitLod,
|
||||||
@@ -1967,7 +2051,7 @@ fn opImageTexelPointer(allocator: std.mem.Allocator, word_count: SpvWord, rt: *R
|
|||||||
const x = try readStorageCoordLaneForTexelPointer(coord, 0);
|
const x = try readStorageCoordLaneForTexelPointer(coord, 0);
|
||||||
const y = readStorageCoordLaneForTexelPointer(coord, 1) catch 0;
|
const y = readStorageCoordLaneForTexelPointer(coord, 1) catch 0;
|
||||||
const z = readStorageCoordLaneForTexelPointer(coord, 2) catch 0;
|
const z = readStorageCoordLaneForTexelPointer(coord, 2) catch 0;
|
||||||
const texel = try rt.image_api.readImageInt4(image.driver_image, dim, x, y, z);
|
const texel = try rt.image_api.readImageInt4(image.driver_image, dim, x, y, z, null);
|
||||||
|
|
||||||
const pointer_type = switch ((try rt.results[result_type].getConstVariant()).*) {
|
const pointer_type = switch ((try rt.results[result_type].getConstVariant()).*) {
|
||||||
.Type => |t| switch (t) {
|
.Type => |t| switch (t) {
|
||||||
|
|||||||
Reference in New Issue
Block a user