implementing queries
This commit is contained in:
@@ -50,7 +50,7 @@ vkAllocateMemory | ✅ Implemented
|
|||||||
vkBeginCommandBuffer | ✅ Implemented
|
vkBeginCommandBuffer | ✅ Implemented
|
||||||
vkBindBufferMemory | ✅ Implemented
|
vkBindBufferMemory | ✅ Implemented
|
||||||
vkBindImageMemory | ✅ Implemented
|
vkBindImageMemory | ✅ Implemented
|
||||||
vkCmdBeginQuery | ⚙️ WIP
|
vkCmdBeginQuery | ✅ Implemented
|
||||||
vkCmdBeginRenderPass | ✅ Implemented
|
vkCmdBeginRenderPass | ✅ Implemented
|
||||||
vkCmdBindDescriptorSets | ✅ Implemented
|
vkCmdBindDescriptorSets | ✅ Implemented
|
||||||
vkCmdBindIndexBuffer | ✅ Implemented
|
vkCmdBindIndexBuffer | ✅ Implemented
|
||||||
@@ -64,14 +64,14 @@ vkCmdCopyBuffer | ✅ Implemented
|
|||||||
vkCmdCopyBufferToImage | ✅ Implemented
|
vkCmdCopyBufferToImage | ✅ Implemented
|
||||||
vkCmdCopyImage | ✅ Implemented
|
vkCmdCopyImage | ✅ Implemented
|
||||||
vkCmdCopyImageToBuffer | ✅ Implemented
|
vkCmdCopyImageToBuffer | ✅ Implemented
|
||||||
vkCmdCopyQueryPoolResults | ⚙️ WIP
|
vkCmdCopyQueryPoolResults | ✅ Implemented
|
||||||
vkCmdDispatch | ✅ Implemented
|
vkCmdDispatch | ✅ Implemented
|
||||||
vkCmdDispatchIndirect | ✅ Implemented
|
vkCmdDispatchIndirect | ✅ Implemented
|
||||||
vkCmdDraw | ✅ Implemented
|
vkCmdDraw | ✅ Implemented
|
||||||
vkCmdDrawIndexed | ✅ Implemented
|
vkCmdDrawIndexed | ✅ Implemented
|
||||||
vkCmdDrawIndexedIndirect | ✅ Implemented
|
vkCmdDrawIndexedIndirect | ✅ Implemented
|
||||||
vkCmdDrawIndirect | ✅ Implemented
|
vkCmdDrawIndirect | ✅ Implemented
|
||||||
vkCmdEndQuery | ⚙️ WIP
|
vkCmdEndQuery | ✅ Implemented
|
||||||
vkCmdEndRenderPass | ✅ Implemented
|
vkCmdEndRenderPass | ✅ Implemented
|
||||||
vkCmdExecuteCommands | ✅ Implemented
|
vkCmdExecuteCommands | ✅ Implemented
|
||||||
vkCmdFillBuffer | ✅ Implemented
|
vkCmdFillBuffer | ✅ Implemented
|
||||||
@@ -79,7 +79,7 @@ vkCmdNextSubpass | ✅ Implemented
|
|||||||
vkCmdPipelineBarrier | ✅ Implemented
|
vkCmdPipelineBarrier | ✅ Implemented
|
||||||
vkCmdPushConstants | ✅ Implemented
|
vkCmdPushConstants | ✅ Implemented
|
||||||
vkCmdResetEvent | ✅ Implemented
|
vkCmdResetEvent | ✅ Implemented
|
||||||
vkCmdResetQueryPool | ⚙️ WIP
|
vkCmdResetQueryPool | ✅ Implemented
|
||||||
vkCmdResolveImage | ✅ Implemented
|
vkCmdResolveImage | ✅ Implemented
|
||||||
vkCmdSetBlendConstants | ✅ Implemented
|
vkCmdSetBlendConstants | ✅ Implemented
|
||||||
vkCmdSetDepthBias | ⚙️ WIP
|
vkCmdSetDepthBias | ⚙️ WIP
|
||||||
@@ -110,7 +110,7 @@ vkCreateImageView | ✅ Implemented
|
|||||||
vkCreateInstance | ✅ Implemented
|
vkCreateInstance | ✅ Implemented
|
||||||
vkCreatePipelineCache | ⚙️ WIP
|
vkCreatePipelineCache | ⚙️ WIP
|
||||||
vkCreatePipelineLayout | ✅ Implemented
|
vkCreatePipelineLayout | ✅ Implemented
|
||||||
vkCreateQueryPool | ⚙️ WIP
|
vkCreateQueryPool | ✅ Implemented
|
||||||
vkCreateRenderPass | ✅ Implemented
|
vkCreateRenderPass | ✅ Implemented
|
||||||
vkCreateSampler | ✅ Implemented
|
vkCreateSampler | ✅ Implemented
|
||||||
vkCreateSemaphore | ⚙️ WIP
|
vkCreateSemaphore | ⚙️ WIP
|
||||||
@@ -194,6 +194,7 @@ vkResetCommandPool | ✅ Implemented
|
|||||||
vkResetDescriptorPool | ✅ Implemented
|
vkResetDescriptorPool | ✅ Implemented
|
||||||
vkResetEvent | ✅ Implemented
|
vkResetEvent | ✅ Implemented
|
||||||
vkResetFences | ✅ Implemented
|
vkResetFences | ✅ Implemented
|
||||||
|
vkResetQueryPool | ✅ Implemented
|
||||||
vkSetEvent | ✅ Implemented
|
vkSetEvent | ✅ Implemented
|
||||||
vkUnmapMemory | ✅ Implemented
|
vkUnmapMemory | ✅ Implemented
|
||||||
vkUpdateDescriptorSets | ✅ Implemented
|
vkUpdateDescriptorSets | ✅ Implemented
|
||||||
|
|||||||
+2
-2
@@ -26,8 +26,8 @@
|
|||||||
.hash = "N-V-__8AAMpOQxkHCKTw9i-NwmmQ3ks1ndFDXcVLlic4KjK3",
|
.hash = "N-V-__8AAMpOQxkHCKTw9i-NwmmQ3ks1ndFDXcVLlic4KjK3",
|
||||||
},
|
},
|
||||||
.SPIRV_Interpreter = .{
|
.SPIRV_Interpreter = .{
|
||||||
.url = "git+https://git.kbz8.me/kbz_8/SPIRV-Interpreter#ee5a400010b3a5852606b2f8593bd5c745bf0a26",
|
.url = "git+https://git.kbz8.me/kbz_8/SPIRV-Interpreter#fb6e5beefffe3608173bdda62dc0a922f02ba447",
|
||||||
.hash = "SPIRV_Interpreter-0.0.1-ajmpn4f_BQB4RtnZdTQZgWOBNcE7-J2Ij3zbV0qI0SKy",
|
.hash = "SPIRV_Interpreter-0.0.1-ajmpn3cFBgALga_tgLo12tFEVRlR8m6fIjFIv41KVCcn",
|
||||||
.lazy = true,
|
.lazy = true,
|
||||||
},
|
},
|
||||||
//.SPIRV_Interpreter = .{
|
//.SPIRV_Interpreter = .{
|
||||||
|
|||||||
@@ -45,6 +45,7 @@ pub fn create(device: *base.Device, allocator: std.mem.Allocator, info: *const v
|
|||||||
|
|
||||||
interface.dispatch_table = &.{
|
interface.dispatch_table = &.{
|
||||||
.begin = begin,
|
.begin = begin,
|
||||||
|
.beginQuery = beginQuery,
|
||||||
.beginRenderPass = beginRenderPass,
|
.beginRenderPass = beginRenderPass,
|
||||||
.bindDescriptorSets = bindDescriptorSets,
|
.bindDescriptorSets = bindDescriptorSets,
|
||||||
.bindPipeline = bindPipeline,
|
.bindPipeline = bindPipeline,
|
||||||
@@ -58,6 +59,7 @@ pub fn create(device: *base.Device, allocator: std.mem.Allocator, info: *const v
|
|||||||
.copyBufferToImage = copyBufferToImage,
|
.copyBufferToImage = copyBufferToImage,
|
||||||
.copyImage = copyImage,
|
.copyImage = copyImage,
|
||||||
.copyImageToBuffer = copyImageToBuffer,
|
.copyImageToBuffer = copyImageToBuffer,
|
||||||
|
.copyQueryPoolResults = copyQueryPoolResults,
|
||||||
.dispatch = dispatch,
|
.dispatch = dispatch,
|
||||||
.dispatchIndirect = dispatchIndirect,
|
.dispatchIndirect = dispatchIndirect,
|
||||||
.draw = draw,
|
.draw = draw,
|
||||||
@@ -65,6 +67,7 @@ pub fn create(device: *base.Device, allocator: std.mem.Allocator, info: *const v
|
|||||||
.drawIndexedIndirect = drawIndexedIndirect,
|
.drawIndexedIndirect = drawIndexedIndirect,
|
||||||
.drawIndirect = drawIndirect,
|
.drawIndirect = drawIndirect,
|
||||||
.end = end,
|
.end = end,
|
||||||
|
.endQuery = endQuery,
|
||||||
.endRenderPass = endRenderPass,
|
.endRenderPass = endRenderPass,
|
||||||
.executeCommands = executeCommands,
|
.executeCommands = executeCommands,
|
||||||
.fillBuffer = fillBuffer,
|
.fillBuffer = fillBuffer,
|
||||||
@@ -72,6 +75,7 @@ pub fn create(device: *base.Device, allocator: std.mem.Allocator, info: *const v
|
|||||||
.pipelineBarrier = pipelineBarrier,
|
.pipelineBarrier = pipelineBarrier,
|
||||||
.pushConstants = pushConstants,
|
.pushConstants = pushConstants,
|
||||||
.reset = reset,
|
.reset = reset,
|
||||||
|
.resetQueryPool = resetQueryPool,
|
||||||
.resetEvent = resetEvent,
|
.resetEvent = resetEvent,
|
||||||
.resolveImage = resolveImage,
|
.resolveImage = resolveImage,
|
||||||
.setEvent = setEvent,
|
.setEvent = setEvent,
|
||||||
@@ -134,6 +138,116 @@ pub fn reset(interface: *Interface, _: vk.CommandBufferResetFlags) VkError!void
|
|||||||
|
|
||||||
// Commands ====================================================================================================
|
// Commands ====================================================================================================
|
||||||
|
|
||||||
|
pub fn beginQuery(interface: *Interface, pool: *base.QueryPool, query: u32, _: vk.QueryControlFlags) VkError!void {
|
||||||
|
const self: *Self = @alignCast(@fieldParentPtr("interface", interface));
|
||||||
|
const allocator = self.command_allocator.allocator();
|
||||||
|
|
||||||
|
const CommandImpl = struct {
|
||||||
|
const Impl = @This();
|
||||||
|
|
||||||
|
pool: *base.QueryPool,
|
||||||
|
query: u32,
|
||||||
|
|
||||||
|
pub fn execute(context: *anyopaque, device: *ExecutionDevice) VkError!void {
|
||||||
|
const impl: *Impl = @ptrCast(@alignCast(context));
|
||||||
|
try impl.pool.begin(impl.query);
|
||||||
|
if (impl.pool.query_type == .occlusion) {
|
||||||
|
for (device.active_occlusion_queries.items) |active| {
|
||||||
|
if (active.pool == impl.pool and active.query == impl.query)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
device.active_occlusion_queries.append(device.renderer.device.device_allocator.allocator(), .{
|
||||||
|
.pool = impl.pool,
|
||||||
|
.query = impl.query,
|
||||||
|
}) catch return VkError.OutOfDeviceMemory;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const cmd = allocator.create(CommandImpl) catch return VkError.OutOfHostMemory;
|
||||||
|
errdefer allocator.destroy(cmd);
|
||||||
|
cmd.* = .{
|
||||||
|
.pool = pool,
|
||||||
|
.query = query,
|
||||||
|
};
|
||||||
|
self.commands.append(allocator, .{ .ptr = cmd, .vtable = &.{ .execute = CommandImpl.execute } }) catch return VkError.OutOfHostMemory;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn endQuery(interface: *Interface, pool: *base.QueryPool, query: u32) VkError!void {
|
||||||
|
const self: *Self = @alignCast(@fieldParentPtr("interface", interface));
|
||||||
|
const allocator = self.command_allocator.allocator();
|
||||||
|
|
||||||
|
const CommandImpl = struct {
|
||||||
|
const Impl = @This();
|
||||||
|
|
||||||
|
pool: *base.QueryPool,
|
||||||
|
query: u32,
|
||||||
|
|
||||||
|
pub fn execute(context: *anyopaque, device: *ExecutionDevice) VkError!void {
|
||||||
|
const impl: *Impl = @ptrCast(@alignCast(context));
|
||||||
|
try impl.pool.end(impl.query);
|
||||||
|
|
||||||
|
var i: usize = 0;
|
||||||
|
while (i < device.active_occlusion_queries.items.len) {
|
||||||
|
const active = device.active_occlusion_queries.items[i];
|
||||||
|
if (active.pool == impl.pool and active.query == impl.query) {
|
||||||
|
_ = device.active_occlusion_queries.swapRemove(i);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
i += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const cmd = allocator.create(CommandImpl) catch return VkError.OutOfHostMemory;
|
||||||
|
errdefer allocator.destroy(cmd);
|
||||||
|
cmd.* = .{
|
||||||
|
.pool = pool,
|
||||||
|
.query = query,
|
||||||
|
};
|
||||||
|
self.commands.append(allocator, .{ .ptr = cmd, .vtable = &.{ .execute = CommandImpl.execute } }) catch return VkError.OutOfHostMemory;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn resetQueryPool(interface: *Interface, pool: *base.QueryPool, first: u32, count: u32) VkError!void {
|
||||||
|
const self: *Self = @alignCast(@fieldParentPtr("interface", interface));
|
||||||
|
const allocator = self.command_allocator.allocator();
|
||||||
|
|
||||||
|
const CommandImpl = struct {
|
||||||
|
const Impl = @This();
|
||||||
|
|
||||||
|
pool: *base.QueryPool,
|
||||||
|
first: u32,
|
||||||
|
count: u32,
|
||||||
|
|
||||||
|
pub fn execute(context: *anyopaque, device: *ExecutionDevice) VkError!void {
|
||||||
|
const impl: *Impl = @ptrCast(@alignCast(context));
|
||||||
|
try impl.pool.reset(impl.first, impl.count);
|
||||||
|
|
||||||
|
var i: usize = 0;
|
||||||
|
while (i < device.active_occlusion_queries.items.len) {
|
||||||
|
const active = device.active_occlusion_queries.items[i];
|
||||||
|
if (active.pool == impl.pool and
|
||||||
|
active.query >= impl.first and
|
||||||
|
active.query < impl.first + impl.count)
|
||||||
|
{
|
||||||
|
_ = device.active_occlusion_queries.swapRemove(i);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
i += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const cmd = allocator.create(CommandImpl) catch return VkError.OutOfHostMemory;
|
||||||
|
errdefer allocator.destroy(cmd);
|
||||||
|
cmd.* = .{
|
||||||
|
.pool = pool,
|
||||||
|
.first = first,
|
||||||
|
.count = count,
|
||||||
|
};
|
||||||
|
self.commands.append(allocator, .{ .ptr = cmd, .vtable = &.{ .execute = CommandImpl.execute } }) catch return VkError.OutOfHostMemory;
|
||||||
|
}
|
||||||
|
|
||||||
pub fn beginRenderPass(interface: *Interface, render_pass: *base.RenderPass, framebuffer: *base.Framebuffer, render_area: vk.Rect2D, clear_values: ?[]const vk.ClearValue) VkError!void {
|
pub fn beginRenderPass(interface: *Interface, render_pass: *base.RenderPass, framebuffer: *base.Framebuffer, render_area: vk.Rect2D, clear_values: ?[]const vk.ClearValue) VkError!void {
|
||||||
const self: *Self = @alignCast(@fieldParentPtr("interface", interface));
|
const self: *Self = @alignCast(@fieldParentPtr("interface", interface));
|
||||||
const allocator = self.command_allocator.allocator();
|
const allocator = self.command_allocator.allocator();
|
||||||
@@ -627,6 +741,45 @@ pub fn copyImageToBuffer(interface: *Interface, src: *base.Image, src_layout: vk
|
|||||||
self.commands.append(allocator, .{ .ptr = cmd, .vtable = &.{ .execute = CommandImpl.execute } }) catch return VkError.OutOfHostMemory;
|
self.commands.append(allocator, .{ .ptr = cmd, .vtable = &.{ .execute = CommandImpl.execute } }) catch return VkError.OutOfHostMemory;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn copyQueryPoolResults(interface: *Interface, pool: *base.QueryPool, first: u32, count: u32, dst: *base.Buffer, offset: vk.DeviceSize, stride: vk.DeviceSize, flags: vk.QueryResultFlags) VkError!void {
|
||||||
|
const self: *Self = @alignCast(@fieldParentPtr("interface", interface));
|
||||||
|
const allocator = self.command_allocator.allocator();
|
||||||
|
|
||||||
|
const CommandImpl = struct {
|
||||||
|
const Impl = @This();
|
||||||
|
|
||||||
|
pool: *base.QueryPool,
|
||||||
|
dst: *SoftBuffer,
|
||||||
|
first: u32,
|
||||||
|
count: u32,
|
||||||
|
offset: vk.DeviceSize,
|
||||||
|
stride: vk.DeviceSize,
|
||||||
|
flags: vk.QueryResultFlags,
|
||||||
|
|
||||||
|
pub fn execute(context: *anyopaque, _: *ExecutionDevice) VkError!void {
|
||||||
|
const impl: *Impl = @ptrCast(@alignCast(context));
|
||||||
|
const value_size: vk.DeviceSize = if (impl.flags.@"64_bit") 8 else 4;
|
||||||
|
const item_size = value_size * (1 + @as(vk.DeviceSize, @intFromBool(impl.flags.with_availability_bit)));
|
||||||
|
const byte_size = if (impl.count == 0) 0 else (impl.count - 1) * impl.stride + item_size;
|
||||||
|
const map = try impl.dst.mapAsSliceWithAddedOffset(u8, impl.offset, byte_size);
|
||||||
|
try impl.pool.copyResults(impl.first, impl.count, map, impl.stride, impl.flags);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const cmd = allocator.create(CommandImpl) catch return VkError.OutOfHostMemory;
|
||||||
|
errdefer allocator.destroy(cmd);
|
||||||
|
cmd.* = .{
|
||||||
|
.pool = pool,
|
||||||
|
.dst = @alignCast(@fieldParentPtr("interface", dst)),
|
||||||
|
.first = first,
|
||||||
|
.count = count,
|
||||||
|
.offset = offset,
|
||||||
|
.stride = stride,
|
||||||
|
.flags = flags,
|
||||||
|
};
|
||||||
|
self.commands.append(allocator, .{ .ptr = cmd, .vtable = &.{ .execute = CommandImpl.execute } }) catch return VkError.OutOfHostMemory;
|
||||||
|
}
|
||||||
|
|
||||||
pub fn dispatch(interface: *Interface, group_count_x: u32, group_count_y: u32, group_count_z: u32) VkError!void {
|
pub fn dispatch(interface: *Interface, group_count_x: u32, group_count_y: u32, group_count_z: u32) VkError!void {
|
||||||
const self: *Self = @alignCast(@fieldParentPtr("interface", interface));
|
const self: *Self = @alignCast(@fieldParentPtr("interface", interface));
|
||||||
const allocator = self.command_allocator.allocator();
|
const allocator = self.command_allocator.allocator();
|
||||||
|
|||||||
+1
-241
@@ -378,228 +378,6 @@ fn writeImageInt4(context: *anyopaque, dim: spv.SpvDim, x: i32, y: i32, z: i32,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const CubeCoordinate = struct {
|
|
||||||
face: u32,
|
|
||||||
u: f32,
|
|
||||||
v: f32,
|
|
||||||
w: f32 = 0.0,
|
|
||||||
};
|
|
||||||
|
|
||||||
fn resolveCubeCoordinate(x: f32, y: f32, z: f32) CubeCoordinate {
|
|
||||||
const ax = @abs(x);
|
|
||||||
const ay = @abs(y);
|
|
||||||
const az = @abs(z);
|
|
||||||
|
|
||||||
var face: u32 = 0;
|
|
||||||
var sc: f32 = 0.0;
|
|
||||||
var tc: f32 = 0.0;
|
|
||||||
var ma: f32 = 1.0;
|
|
||||||
|
|
||||||
if (ax >= ay and ax >= az) {
|
|
||||||
ma = ax;
|
|
||||||
if (x >= 0.0) {
|
|
||||||
face = 0;
|
|
||||||
sc = -z;
|
|
||||||
tc = -y;
|
|
||||||
} else {
|
|
||||||
face = 1;
|
|
||||||
sc = z;
|
|
||||||
tc = -y;
|
|
||||||
}
|
|
||||||
} else if (ay >= ax and ay >= az) {
|
|
||||||
ma = ay;
|
|
||||||
if (y >= 0.0) {
|
|
||||||
face = 2;
|
|
||||||
sc = x;
|
|
||||||
tc = z;
|
|
||||||
} else {
|
|
||||||
face = 3;
|
|
||||||
sc = x;
|
|
||||||
tc = -z;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
ma = az;
|
|
||||||
if (z >= 0.0) {
|
|
||||||
face = 4;
|
|
||||||
sc = x;
|
|
||||||
tc = -y;
|
|
||||||
} else {
|
|
||||||
face = 5;
|
|
||||||
sc = -x;
|
|
||||||
tc = -y;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const inv_ma = if (ma == 0.0) 0.0 else 1.0 / ma;
|
|
||||||
return .{
|
|
||||||
.face = face,
|
|
||||||
.u = (sc * inv_ma + 1.0) * 0.5,
|
|
||||||
.v = (tc * inv_ma + 1.0) * 0.5,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
fn cubeDirection(face: u32, u: f32, v: f32) struct { x: f32, y: f32, z: f32 } {
|
|
||||||
const sc = u * 2.0 - 1.0;
|
|
||||||
const tc = v * 2.0 - 1.0;
|
|
||||||
|
|
||||||
return switch (face) {
|
|
||||||
0 => .{ .x = 1.0, .y = -tc, .z = -sc },
|
|
||||||
1 => .{ .x = -1.0, .y = -tc, .z = sc },
|
|
||||||
2 => .{ .x = sc, .y = 1.0, .z = tc },
|
|
||||||
3 => .{ .x = sc, .y = -1.0, .z = -tc },
|
|
||||||
4 => .{ .x = sc, .y = -tc, .z = 1.0 },
|
|
||||||
5 => .{ .x = -sc, .y = -tc, .z = -1.0 },
|
|
||||||
else => .{ .x = 0.0, .y = 0.0, .z = 0.0 },
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
fn readSampledFloat4(
|
|
||||||
image: *SoftImage,
|
|
||||||
image_view: *SoftImageView,
|
|
||||||
sampler: *SoftSampler,
|
|
||||||
dim: spv.SpvDim,
|
|
||||||
coord: CubeCoordinate,
|
|
||||||
ix: i32,
|
|
||||||
iy: i32,
|
|
||||||
iz: i32,
|
|
||||||
) VkError!zm.F32x4 {
|
|
||||||
const range = image_view.interface.subresource_range;
|
|
||||||
const extent = image.getMipLevelExtent(range.base_mip_level);
|
|
||||||
const width_f: f32 = @floatFromInt(extent.width);
|
|
||||||
const height_f: f32 = @floatFromInt(extent.height);
|
|
||||||
|
|
||||||
const texel = if (dim == .Cube) blk: {
|
|
||||||
const dir = cubeDirection(
|
|
||||||
coord.face,
|
|
||||||
(@as(f32, @floatFromInt(ix)) + 0.5) / width_f,
|
|
||||||
(@as(f32, @floatFromInt(iy)) + 0.5) / height_f,
|
|
||||||
);
|
|
||||||
break :blk resolveCubeCoordinate(dir.x, dir.y, dir.z);
|
|
||||||
} else coord;
|
|
||||||
|
|
||||||
const z: i32, const layer: u32 = switch (image_view.interface.view_type) {
|
|
||||||
.@"1d_array" => .{ 0, range.base_array_layer + @as(u32, @intCast(sampleAddress(@intFromFloat(coord.v), viewLayerCount(image, range), .clamp_to_edge))) },
|
|
||||||
.@"2d_array", .cube_array => .{ 0, range.base_array_layer + @as(u32, @intCast(sampleAddress(@intFromFloat(coord.w), viewLayerCount(image, range), .clamp_to_edge))) },
|
|
||||||
.@"3d" => .{ sampleAddressOrBorder(iz, extent.depth, sampler.interface.address_mode_w) orelse return samplerBorderColor(sampler), range.base_array_layer },
|
|
||||||
.cube => .{ 0, range.base_array_layer + texel.face },
|
|
||||||
else => .{ 0, range.base_array_layer },
|
|
||||||
};
|
|
||||||
|
|
||||||
const sx = if (dim == .Cube)
|
|
||||||
std.math.clamp(@as(i32, @intFromFloat(texel.u * width_f)), 0, @as(i32, @intCast(extent.width)) - 1)
|
|
||||||
else
|
|
||||||
sampleAddressOrBorder(ix, extent.width, sampler.interface.address_mode_u) orelse return samplerBorderColor(sampler);
|
|
||||||
const sy = if (dim == .Cube)
|
|
||||||
std.math.clamp(@as(i32, @intFromFloat(texel.v * height_f)), 0, @as(i32, @intCast(extent.height)) - 1)
|
|
||||||
else
|
|
||||||
sampleAddressOrBorder(iy, extent.height, sampler.interface.address_mode_v) orelse return samplerBorderColor(sampler);
|
|
||||||
|
|
||||||
const result = try image.readFloat4(
|
|
||||||
.{
|
|
||||||
.x = sx,
|
|
||||||
.y = sy,
|
|
||||||
.z = z,
|
|
||||||
},
|
|
||||||
.{
|
|
||||||
.aspect_mask = range.aspect_mask,
|
|
||||||
.mip_level = range.base_mip_level,
|
|
||||||
.array_layer = layer,
|
|
||||||
},
|
|
||||||
image_view.interface.format,
|
|
||||||
);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn sampleAddress(coord: i32, extent: u32, mode: vk.SamplerAddressMode) i32 {
|
|
||||||
return sampleAddressOrBorder(coord, extent, mode).?;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn sampleAddressOrBorder(coord: i32, extent: u32, mode: vk.SamplerAddressMode) ?i32 {
|
|
||||||
const extent_i: i32 = @intCast(extent);
|
|
||||||
return switch (mode) {
|
|
||||||
.repeat => @mod(coord, extent_i),
|
|
||||||
.mirrored_repeat => blk: {
|
|
||||||
const period = extent_i * 2;
|
|
||||||
const mirrored = @mod(coord, period);
|
|
||||||
break :blk if (mirrored < extent_i) mirrored else period - mirrored - 1;
|
|
||||||
},
|
|
||||||
.clamp_to_border => if (coord < 0 or coord >= extent_i) null else coord,
|
|
||||||
else => std.math.clamp(coord, 0, extent_i - 1),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
fn samplerBorderColor(sampler: *SoftSampler) zm.F32x4 {
|
|
||||||
return switch (sampler.interface.border_color) {
|
|
||||||
.float_opaque_white, .int_opaque_white => .{ 1.0, 1.0, 1.0, 1.0 },
|
|
||||||
.float_opaque_black, .int_opaque_black => .{ 0.0, 0.0, 0.0, 1.0 },
|
|
||||||
else => .{ 0.0, 0.0, 0.0, 0.0 },
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
fn viewLayerCount(image: *SoftImage, range: vk.ImageSubresourceRange) u32 {
|
|
||||||
return if (range.layer_count == vk.REMAINING_ARRAY_LAYERS)
|
|
||||||
image.interface.array_layers - range.base_array_layer
|
|
||||||
else
|
|
||||||
range.layer_count;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn sampleNearestFloat4(image: *SoftImage, image_view: *SoftImageView, sampler: *SoftSampler, dim: spv.SpvDim, coord: CubeCoordinate) VkError!zm.F32x4 {
|
|
||||||
const extent = image.getMipLevelExtent(image_view.interface.subresource_range.base_mip_level);
|
|
||||||
const width_f: f32 = @floatFromInt(extent.width);
|
|
||||||
const height_f: f32 = @floatFromInt(extent.height);
|
|
||||||
return readSampledFloat4(
|
|
||||||
image,
|
|
||||||
image_view,
|
|
||||||
sampler,
|
|
||||||
dim,
|
|
||||||
coord,
|
|
||||||
@intFromFloat(coord.u * width_f),
|
|
||||||
@intFromFloat(coord.v * height_f),
|
|
||||||
@intFromFloat(coord.w * @as(f32, @floatFromInt(extent.depth))),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn sampleLinearFloat4(image: *SoftImage, image_view: *SoftImageView, sampler: *SoftSampler, dim: spv.SpvDim, coord: CubeCoordinate) VkError!zm.F32x4 {
|
|
||||||
const extent = image.getMipLevelExtent(image_view.interface.subresource_range.base_mip_level);
|
|
||||||
const width_f: f32 = @floatFromInt(extent.width);
|
|
||||||
const height_f: f32 = @floatFromInt(extent.height);
|
|
||||||
const x = coord.u * width_f - 0.5;
|
|
||||||
const y = coord.v * height_f - 0.5;
|
|
||||||
const z = coord.w * @as(f32, @floatFromInt(extent.depth)) - 0.5;
|
|
||||||
const x0: i32 = @intFromFloat(@floor(x));
|
|
||||||
const y0: i32 = @intFromFloat(@floor(y));
|
|
||||||
const z0: i32 = @intFromFloat(@floor(z));
|
|
||||||
const x1 = x0 + 1;
|
|
||||||
const y1 = y0 + 1;
|
|
||||||
const z1 = z0 + 1;
|
|
||||||
const wx = x - @as(f32, @floatFromInt(x0));
|
|
||||||
const wy = y - @as(f32, @floatFromInt(y0));
|
|
||||||
const wz = z - @as(f32, @floatFromInt(z0));
|
|
||||||
|
|
||||||
const p000 = try readSampledFloat4(image, image_view, sampler, dim, coord, x0, y0, z0);
|
|
||||||
const p100 = try readSampledFloat4(image, image_view, sampler, dim, coord, x1, y0, z0);
|
|
||||||
const p010 = try readSampledFloat4(image, image_view, sampler, dim, coord, x0, y1, z0);
|
|
||||||
const p110 = try readSampledFloat4(image, image_view, sampler, dim, coord, x1, y1, z0);
|
|
||||||
|
|
||||||
const row00 = p000 * zm.f32x4s(1.0 - wx) + p100 * zm.f32x4s(wx);
|
|
||||||
const row10 = p010 * zm.f32x4s(1.0 - wx) + p110 * zm.f32x4s(wx);
|
|
||||||
const slice0 = row00 * zm.f32x4s(1.0 - wy) + row10 * zm.f32x4s(wy);
|
|
||||||
|
|
||||||
if (image_view.interface.view_type != .@"3d")
|
|
||||||
return slice0;
|
|
||||||
|
|
||||||
const p001 = try readSampledFloat4(image, image_view, sampler, dim, coord, x0, y0, z1);
|
|
||||||
const p101 = try readSampledFloat4(image, image_view, sampler, dim, coord, x1, y0, z1);
|
|
||||||
const p011 = try readSampledFloat4(image, image_view, sampler, dim, coord, x0, y1, z1);
|
|
||||||
const p111 = try readSampledFloat4(image, image_view, sampler, dim, coord, x1, y1, z1);
|
|
||||||
|
|
||||||
const row01 = p001 * zm.f32x4s(1.0 - wx) + p101 * zm.f32x4s(wx);
|
|
||||||
const row11 = p011 * zm.f32x4s(1.0 - wx) + p111 * zm.f32x4s(wx);
|
|
||||||
const slice1 = row01 * zm.f32x4s(1.0 - wy) + row11 * zm.f32x4s(wy);
|
|
||||||
|
|
||||||
return slice0 * zm.f32x4s(1.0 - wz) + slice1 * zm.f32x4s(wz);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn sampleImageFloat4(context: *anyopaque, context2: *anyopaque, dim: spv.SpvDim, x: f32, y: f32, z: f32) SpvRuntimeError!spv.Runtime.Vec4(f32) {
|
fn sampleImageFloat4(context: *anyopaque, context2: *anyopaque, dim: spv.SpvDim, x: f32, y: f32, z: f32) SpvRuntimeError!spv.Runtime.Vec4(f32) {
|
||||||
var pixel = zm.f32x4s(0.0);
|
var pixel = zm.f32x4s(0.0);
|
||||||
|
|
||||||
@@ -613,25 +391,7 @@ fn sampleImageFloat4(context: *anyopaque, context2: *anyopaque, dim: spv.SpvDim,
|
|||||||
const image: *SoftImage = @alignCast(@fieldParentPtr("interface", image_view.interface.image));
|
const image: *SoftImage = @alignCast(@fieldParentPtr("interface", image_view.interface.image));
|
||||||
|
|
||||||
const sampler: *SoftSampler = @ptrCast(@alignCast(context2));
|
const sampler: *SoftSampler = @ptrCast(@alignCast(context2));
|
||||||
|
pixel = SoftSampler.sampleImageFloat4(image, image_view, sampler, dim, x, y, z) catch return SpvRuntimeError.Unknown;
|
||||||
if (dim == .Cube) {
|
|
||||||
const coord = resolveCubeCoordinate(x, y, z);
|
|
||||||
pixel = switch (sampler.interface.mag_filter) {
|
|
||||||
.linear => sampleLinearFloat4(image, image_view, sampler, dim, coord),
|
|
||||||
else => sampleNearestFloat4(image, image_view, sampler, dim, coord),
|
|
||||||
} catch return SpvRuntimeError.Unknown;
|
|
||||||
} else {
|
|
||||||
const coord: CubeCoordinate = .{
|
|
||||||
.u = x,
|
|
||||||
.v = y,
|
|
||||||
.w = z,
|
|
||||||
.face = 0,
|
|
||||||
};
|
|
||||||
pixel = switch (sampler.interface.mag_filter) {
|
|
||||||
.linear => sampleLinearFloat4(image, image_view, sampler, dim, coord),
|
|
||||||
else => sampleNearestFloat4(image, image_view, sampler, dim, coord),
|
|
||||||
} catch return SpvRuntimeError.Unknown;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return .{
|
return .{
|
||||||
|
|||||||
@@ -28,5 +28,6 @@ pub fn create(device: *base.Device, allocator: std.mem.Allocator, info: *const v
|
|||||||
|
|
||||||
pub fn destroy(interface: *Interface, allocator: std.mem.Allocator) void {
|
pub fn destroy(interface: *Interface, allocator: std.mem.Allocator) void {
|
||||||
const self: *Self = @alignCast(@fieldParentPtr("interface", interface));
|
const self: *Self = @alignCast(@fieldParentPtr("interface", interface));
|
||||||
|
allocator.free(interface.queries);
|
||||||
allocator.destroy(self);
|
allocator.destroy(self);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -96,6 +96,7 @@ fn taskRunner(self: *Self, info: Interface.SubmitInfo, p_fence: ?*base.Fence, ru
|
|||||||
|
|
||||||
var execution_device: ExecutionDevice = undefined;
|
var execution_device: ExecutionDevice = undefined;
|
||||||
execution_device.setup(soft_device);
|
execution_device.setup(soft_device);
|
||||||
|
defer execution_device.deinit(soft_device.device_allocator.allocator());
|
||||||
|
|
||||||
for (info.command_buffers.items) |command_buffer| {
|
for (info.command_buffers.items) |command_buffer| {
|
||||||
const soft_command_buffer: *SoftCommandBuffer = @alignCast(@fieldParentPtr("interface", command_buffer));
|
const soft_command_buffer: *SoftCommandBuffer = @alignCast(@fieldParentPtr("interface", command_buffer));
|
||||||
|
|||||||
@@ -1,13 +1,34 @@
|
|||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const vk = @import("vulkan");
|
const vk = @import("vulkan");
|
||||||
const base = @import("base");
|
const base = @import("base");
|
||||||
|
const spv = @import("spv");
|
||||||
|
const zm = base.zm;
|
||||||
|
|
||||||
const VkError = base.VkError;
|
const VkError = base.VkError;
|
||||||
const Device = base.Device;
|
const Device = base.Device;
|
||||||
|
const F32x4 = zm.F32x4;
|
||||||
|
|
||||||
|
const SoftImage = @import("SoftImage.zig");
|
||||||
|
const SoftImageView = @import("SoftImageView.zig");
|
||||||
|
|
||||||
const Self = @This();
|
const Self = @This();
|
||||||
pub const Interface = base.Sampler;
|
pub const Interface = base.Sampler;
|
||||||
|
|
||||||
|
const CubeCoordinate = struct {
|
||||||
|
face: u32,
|
||||||
|
u: f32,
|
||||||
|
v: f32,
|
||||||
|
w: f32 = 0.0,
|
||||||
|
};
|
||||||
|
|
||||||
|
const ImageSamplingContext = struct {
|
||||||
|
image: *SoftImage,
|
||||||
|
image_view: *SoftImageView,
|
||||||
|
sampler: *Self,
|
||||||
|
dim: spv.SpvDim,
|
||||||
|
coord: CubeCoordinate,
|
||||||
|
};
|
||||||
|
|
||||||
interface: Interface,
|
interface: Interface,
|
||||||
|
|
||||||
pub fn create(device: *base.Device, allocator: std.mem.Allocator, info: *const vk.SamplerCreateInfo) VkError!*Self {
|
pub fn create(device: *base.Device, allocator: std.mem.Allocator, info: *const vk.SamplerCreateInfo) VkError!*Self {
|
||||||
@@ -30,3 +51,286 @@ pub fn destroy(interface: *Interface, allocator: std.mem.Allocator) void {
|
|||||||
const self: *Self = @alignCast(@fieldParentPtr("interface", interface));
|
const self: *Self = @alignCast(@fieldParentPtr("interface", interface));
|
||||||
allocator.destroy(self);
|
allocator.destroy(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn resolveCubeCoordinate(x: f32, y: f32, z: f32) CubeCoordinate {
|
||||||
|
const ax = @abs(x);
|
||||||
|
const ay = @abs(y);
|
||||||
|
const az = @abs(z);
|
||||||
|
|
||||||
|
var face: u32 = 0;
|
||||||
|
var sc: f32 = 0.0;
|
||||||
|
var tc: f32 = 0.0;
|
||||||
|
var ma: f32 = 1.0;
|
||||||
|
|
||||||
|
if (ax >= ay and ax >= az) {
|
||||||
|
ma = ax;
|
||||||
|
if (x >= 0.0) {
|
||||||
|
face = 0;
|
||||||
|
sc = -z;
|
||||||
|
tc = -y;
|
||||||
|
} else {
|
||||||
|
face = 1;
|
||||||
|
sc = z;
|
||||||
|
tc = -y;
|
||||||
|
}
|
||||||
|
} else if (ay >= ax and ay >= az) {
|
||||||
|
ma = ay;
|
||||||
|
if (y >= 0.0) {
|
||||||
|
face = 2;
|
||||||
|
sc = x;
|
||||||
|
tc = z;
|
||||||
|
} else {
|
||||||
|
face = 3;
|
||||||
|
sc = x;
|
||||||
|
tc = -z;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ma = az;
|
||||||
|
if (z >= 0.0) {
|
||||||
|
face = 4;
|
||||||
|
sc = x;
|
||||||
|
tc = -y;
|
||||||
|
} else {
|
||||||
|
face = 5;
|
||||||
|
sc = -x;
|
||||||
|
tc = -y;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const inv_ma = if (ma == 0.0) 0.0 else 1.0 / ma;
|
||||||
|
return .{
|
||||||
|
.face = face,
|
||||||
|
.u = (sc * inv_ma + 1.0) * 0.5,
|
||||||
|
.v = (tc * inv_ma + 1.0) * 0.5,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
fn cubeDirection(face: u32, u: f32, v: f32) struct { x: f32, y: f32, z: f32 } {
|
||||||
|
const sc = u * 2.0 - 1.0;
|
||||||
|
const tc = v * 2.0 - 1.0;
|
||||||
|
|
||||||
|
return switch (face) {
|
||||||
|
0 => .{ .x = 1.0, .y = -tc, .z = -sc },
|
||||||
|
1 => .{ .x = -1.0, .y = -tc, .z = sc },
|
||||||
|
2 => .{ .x = sc, .y = 1.0, .z = tc },
|
||||||
|
3 => .{ .x = sc, .y = -1.0, .z = -tc },
|
||||||
|
4 => .{ .x = sc, .y = -tc, .z = 1.0 },
|
||||||
|
5 => .{ .x = -sc, .y = -tc, .z = -1.0 },
|
||||||
|
else => .{ .x = 0.0, .y = 0.0, .z = 0.0 },
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
inline fn sampleAddress(coord: i32, extent: u32, mode: vk.SamplerAddressMode) i32 {
|
||||||
|
return sampleAddressOrBorder(coord, extent, mode).?;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn sampleAddressOrBorder(coord: i32, extent: u32, mode: vk.SamplerAddressMode) ?i32 {
|
||||||
|
const extent_i: i32 = @intCast(extent);
|
||||||
|
return switch (mode) {
|
||||||
|
.repeat => @mod(coord, extent_i),
|
||||||
|
.mirrored_repeat => blk: {
|
||||||
|
const period = extent_i * 2;
|
||||||
|
const mirrored = @mod(coord, period);
|
||||||
|
break :blk if (mirrored < extent_i) mirrored else period - mirrored - 1;
|
||||||
|
},
|
||||||
|
.clamp_to_border => if (coord < 0 or coord >= extent_i) null else coord,
|
||||||
|
else => std.math.clamp(coord, 0, extent_i - 1),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
fn samplerBorderColor(sampler: *Self) F32x4 {
|
||||||
|
return switch (sampler.interface.border_color) {
|
||||||
|
.float_opaque_white, .int_opaque_white => .{ 1.0, 1.0, 1.0, 1.0 },
|
||||||
|
.float_opaque_black, .int_opaque_black => .{ 0.0, 0.0, 0.0, 1.0 },
|
||||||
|
else => .{ 0.0, 0.0, 0.0, 0.0 },
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
fn viewLayerCount(image: *SoftImage, range: vk.ImageSubresourceRange) u32 {
|
||||||
|
return if (range.layer_count == vk.REMAINING_ARRAY_LAYERS)
|
||||||
|
image.interface.array_layers - range.base_array_layer
|
||||||
|
else
|
||||||
|
range.layer_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn sampleArrayLayer(coord: f32, layer_count: u32) u32 {
|
||||||
|
const layer_coord: i32 = @intFromFloat(@floor(coord + 0.5));
|
||||||
|
return @intCast(sampleAddress(layer_coord, layer_count, .clamp_to_edge));
|
||||||
|
}
|
||||||
|
|
||||||
|
fn readSampledFloat4(
|
||||||
|
image: *SoftImage,
|
||||||
|
image_view: *SoftImageView,
|
||||||
|
sampler: *Self,
|
||||||
|
dim: spv.SpvDim,
|
||||||
|
coord: CubeCoordinate,
|
||||||
|
ix: i32,
|
||||||
|
iy: i32,
|
||||||
|
iz: i32,
|
||||||
|
) VkError!F32x4 {
|
||||||
|
const range = image_view.interface.subresource_range;
|
||||||
|
const extent = image.getMipLevelExtent(range.base_mip_level);
|
||||||
|
const width_f: f32 = @floatFromInt(extent.width);
|
||||||
|
const height_f: f32 = @floatFromInt(extent.height);
|
||||||
|
|
||||||
|
const texel = if (dim == .Cube) blk: {
|
||||||
|
const dir = cubeDirection(
|
||||||
|
coord.face,
|
||||||
|
(@as(f32, @floatFromInt(ix)) + 0.5) / width_f,
|
||||||
|
(@as(f32, @floatFromInt(iy)) + 0.5) / height_f,
|
||||||
|
);
|
||||||
|
break :blk resolveCubeCoordinate(dir.x, dir.y, dir.z);
|
||||||
|
} else coord;
|
||||||
|
|
||||||
|
const z: i32, const layer: u32 = switch (image_view.interface.view_type) {
|
||||||
|
.@"1d_array" => .{ 0, range.base_array_layer + sampleArrayLayer(coord.v, viewLayerCount(image, range)) },
|
||||||
|
.@"2d_array" => .{ 0, range.base_array_layer + sampleArrayLayer(coord.w, viewLayerCount(image, range)) },
|
||||||
|
.cube_array => .{ 0, range.base_array_layer + sampleArrayLayer(coord.w, @divTrunc(viewLayerCount(image, range), 6)) * 6 + texel.face },
|
||||||
|
.@"3d" => .{ sampleAddressOrBorder(iz, extent.depth, sampler.interface.address_mode_w) orelse return samplerBorderColor(sampler), range.base_array_layer },
|
||||||
|
.cube => .{ 0, range.base_array_layer + texel.face },
|
||||||
|
else => .{ 0, range.base_array_layer },
|
||||||
|
};
|
||||||
|
|
||||||
|
const sx = if (dim == .Cube)
|
||||||
|
std.math.clamp(@as(i32, @intFromFloat(texel.u * width_f)), 0, @as(i32, @intCast(extent.width)) - 1)
|
||||||
|
else
|
||||||
|
sampleAddressOrBorder(ix, extent.width, sampler.interface.address_mode_u) orelse return samplerBorderColor(sampler);
|
||||||
|
const sy = if (dim == .Cube)
|
||||||
|
std.math.clamp(@as(i32, @intFromFloat(texel.v * height_f)), 0, @as(i32, @intCast(extent.height)) - 1)
|
||||||
|
else
|
||||||
|
sampleAddressOrBorder(iy, extent.height, sampler.interface.address_mode_v) orelse return samplerBorderColor(sampler);
|
||||||
|
|
||||||
|
return image.readFloat4(
|
||||||
|
.{
|
||||||
|
.x = sx,
|
||||||
|
.y = sy,
|
||||||
|
.z = z,
|
||||||
|
},
|
||||||
|
.{
|
||||||
|
.aspect_mask = range.aspect_mask,
|
||||||
|
.mip_level = range.base_mip_level,
|
||||||
|
.array_layer = layer,
|
||||||
|
},
|
||||||
|
image_view.interface.format,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn readSampledFloat4At(context: *const ImageSamplingContext, ix: i32, iy: i32, iz: i32) VkError!F32x4 {
|
||||||
|
return readSampledFloat4(
|
||||||
|
context.image,
|
||||||
|
context.image_view,
|
||||||
|
context.sampler,
|
||||||
|
context.dim,
|
||||||
|
context.coord,
|
||||||
|
ix,
|
||||||
|
iy,
|
||||||
|
iz,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn sampleImageFloat4(image: *SoftImage, image_view: *SoftImageView, sampler: *Self, dim: spv.SpvDim, x: f32, y: f32, z: f32) VkError!F32x4 {
|
||||||
|
const extent = image.getMipLevelExtent(image_view.interface.subresource_range.base_mip_level);
|
||||||
|
const coord: CubeCoordinate = switch (image_view.interface.view_type) {
|
||||||
|
.@"1d_array" => .{
|
||||||
|
.u = x,
|
||||||
|
.v = y,
|
||||||
|
.face = 0,
|
||||||
|
},
|
||||||
|
.@"1d" => .{
|
||||||
|
.u = x,
|
||||||
|
.v = 0.0,
|
||||||
|
.face = 0,
|
||||||
|
},
|
||||||
|
.@"2d_array" => .{
|
||||||
|
.u = x,
|
||||||
|
.v = y,
|
||||||
|
.w = z,
|
||||||
|
.face = 0,
|
||||||
|
},
|
||||||
|
.cube, .cube_array => resolveCubeCoordinate(x, y, z),
|
||||||
|
else => .{
|
||||||
|
.u = x,
|
||||||
|
.v = y,
|
||||||
|
.w = z,
|
||||||
|
.face = 0,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const context: ImageSamplingContext = .{
|
||||||
|
.image = image,
|
||||||
|
.image_view = image_view,
|
||||||
|
.sampler = sampler,
|
||||||
|
.dim = dim,
|
||||||
|
.coord = coord,
|
||||||
|
};
|
||||||
|
|
||||||
|
return sampleFloat4(
|
||||||
|
*const ImageSamplingContext,
|
||||||
|
&context,
|
||||||
|
zm.f32x4(
|
||||||
|
coord.u * @as(f32, @floatFromInt(extent.width)),
|
||||||
|
coord.v * @as(f32, @floatFromInt(extent.height)),
|
||||||
|
coord.w * @as(f32, @floatFromInt(extent.depth)),
|
||||||
|
0.0,
|
||||||
|
),
|
||||||
|
switch (sampler.interface.mag_filter) {
|
||||||
|
.linear => .linear,
|
||||||
|
else => .nearest,
|
||||||
|
},
|
||||||
|
image_view.interface.view_type == .@"3d",
|
||||||
|
readSampledFloat4At,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn sampleFloat4(
|
||||||
|
comptime Context: type,
|
||||||
|
context: Context,
|
||||||
|
pos: F32x4,
|
||||||
|
filter: vk.Filter,
|
||||||
|
filter_3D: bool,
|
||||||
|
comptime read: fn (Context, i32, i32, i32) VkError!F32x4,
|
||||||
|
) VkError!F32x4 {
|
||||||
|
if (filter == .nearest) {
|
||||||
|
return read(
|
||||||
|
context,
|
||||||
|
@intFromFloat(pos[0]),
|
||||||
|
@intFromFloat(pos[1]),
|
||||||
|
@intFromFloat(pos[2]),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const x = pos[0] - 0.5;
|
||||||
|
const y = pos[1] - 0.5;
|
||||||
|
const z = pos[2] - 0.5;
|
||||||
|
const x0: i32 = @intFromFloat(@floor(x));
|
||||||
|
const y0: i32 = @intFromFloat(@floor(y));
|
||||||
|
const z0: i32 = @intFromFloat(@floor(z));
|
||||||
|
const x1 = x0 + 1;
|
||||||
|
const y1 = y0 + 1;
|
||||||
|
const z1 = z0 + 1;
|
||||||
|
const wx = x - @as(f32, @floatFromInt(x0));
|
||||||
|
const wy = y - @as(f32, @floatFromInt(y0));
|
||||||
|
const wz = z - @as(f32, @floatFromInt(z0));
|
||||||
|
|
||||||
|
const p000 = try read(context, x0, y0, z0);
|
||||||
|
const p100 = try read(context, x1, y0, z0);
|
||||||
|
const p010 = try read(context, x0, y1, z0);
|
||||||
|
const p110 = try read(context, x1, y1, z0);
|
||||||
|
|
||||||
|
const row00 = p000 * zm.f32x4s(1.0 - wx) + p100 * zm.f32x4s(wx);
|
||||||
|
const row10 = p010 * zm.f32x4s(1.0 - wx) + p110 * zm.f32x4s(wx);
|
||||||
|
const slice0 = row00 * zm.f32x4s(1.0 - wy) + row10 * zm.f32x4s(wy);
|
||||||
|
|
||||||
|
if (!filter_3D)
|
||||||
|
return slice0;
|
||||||
|
|
||||||
|
const p001 = try read(context, x0, y0, z1);
|
||||||
|
const p101 = try read(context, x1, y0, z1);
|
||||||
|
const p011 = try read(context, x0, y1, z1);
|
||||||
|
const p111 = try read(context, x1, y1, z1);
|
||||||
|
|
||||||
|
const row01 = p001 * zm.f32x4s(1.0 - wx) + p101 * zm.f32x4s(wx);
|
||||||
|
const row11 = p011 * zm.f32x4s(1.0 - wx) + p111 * zm.f32x4s(wx);
|
||||||
|
const slice1 = row01 * zm.f32x4s(1.0 - wy) + row11 * zm.f32x4s(wy);
|
||||||
|
|
||||||
|
return slice0 * zm.f32x4s(1.0 - wz) + slice1 * zm.f32x4s(wz);
|
||||||
|
}
|
||||||
|
|||||||
@@ -21,6 +21,11 @@ pub const GRAPHICS_PIPELINE_STATE = 0;
|
|||||||
pub const COMPUTE_PIPELINE_STATE = 1;
|
pub const COMPUTE_PIPELINE_STATE = 1;
|
||||||
pub const MAX_DYNAMIC_DESCRIPTORS_PER_SET = 64;
|
pub const MAX_DYNAMIC_DESCRIPTORS_PER_SET = 64;
|
||||||
|
|
||||||
|
pub const ActiveOcclusionQuery = struct {
|
||||||
|
pool: *base.QueryPool,
|
||||||
|
query: u32,
|
||||||
|
};
|
||||||
|
|
||||||
pub const PipelineState = struct {
|
pub const PipelineState = struct {
|
||||||
pipeline: ?*SoftPipeline,
|
pipeline: ?*SoftPipeline,
|
||||||
sets: [base.VULKAN_MAX_DESCRIPTOR_SETS]?*SoftDescriptorSet,
|
sets: [base.VULKAN_MAX_DESCRIPTOR_SETS]?*SoftDescriptorSet,
|
||||||
@@ -39,6 +44,7 @@ compute: ComputeDispatcher,
|
|||||||
renderer: Renderer,
|
renderer: Renderer,
|
||||||
|
|
||||||
pipeline_states: [2]PipelineState,
|
pipeline_states: [2]PipelineState,
|
||||||
|
active_occlusion_queries: std.ArrayList(ActiveOcclusionQuery),
|
||||||
|
|
||||||
/// Initializating an execution device and
|
/// Initializating an execution device and
|
||||||
/// not creating one to avoid dangling pointers
|
/// not creating one to avoid dangling pointers
|
||||||
@@ -61,8 +67,13 @@ pub fn setup(self: *Self, device: *SoftDevice) void {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
self.active_occlusion_queries = .empty;
|
||||||
self.compute = .init(device, &self.pipeline_states[@intFromEnum(vk.PipelineBindPoint.compute)]);
|
self.compute = .init(device, &self.pipeline_states[@intFromEnum(vk.PipelineBindPoint.compute)]);
|
||||||
self.renderer = .init(device, &self.pipeline_states[@intFromEnum(vk.PipelineBindPoint.graphics)]);
|
self.renderer = .init(device, &self.pipeline_states[@intFromEnum(vk.PipelineBindPoint.graphics)], &self.active_occlusion_queries);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn deinit(self: *Self, allocator: std.mem.Allocator) void {
|
||||||
|
self.active_occlusion_queries.deinit(allocator);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn writeDescriptorSets(state: *PipelineState, rt: *spv.Runtime) !void {
|
pub fn writeDescriptorSets(state: *PipelineState, rt: *spv.Runtime) !void {
|
||||||
|
|||||||
@@ -74,7 +74,6 @@ pub const DrawCall = struct {
|
|||||||
render_pass: *SoftRenderPass,
|
render_pass: *SoftRenderPass,
|
||||||
framebuffer: *SoftFramebuffer,
|
framebuffer: *SoftFramebuffer,
|
||||||
|
|
||||||
allocator_mutex: std.Io.Mutex,
|
|
||||||
rasterizer_wait_group: std.Io.Group,
|
rasterizer_wait_group: std.Io.Group,
|
||||||
|
|
||||||
stats: struct {
|
stats: struct {
|
||||||
@@ -94,7 +93,6 @@ pub const DrawCall = struct {
|
|||||||
.depth_attachment = if (render_pass.interface.subpasses[renderer.subpass_index].depth_stencil_attachments) |desc| framebuffer.interface.attachments[desc.attachment] else null,
|
.depth_attachment = if (render_pass.interface.subpasses[renderer.subpass_index].depth_stencil_attachments) |desc| framebuffer.interface.attachments[desc.attachment] else null,
|
||||||
.render_pass = render_pass,
|
.render_pass = render_pass,
|
||||||
.framebuffer = framebuffer,
|
.framebuffer = framebuffer,
|
||||||
.allocator_mutex = .init,
|
|
||||||
.rasterizer_wait_group = .init,
|
.rasterizer_wait_group = .init,
|
||||||
.stats = .{
|
.stats = .{
|
||||||
.polygons_drawn = 0,
|
.polygons_drawn = 0,
|
||||||
@@ -132,8 +130,9 @@ framebuffer: ?*SoftFramebuffer,
|
|||||||
dynamic_state: DynamicState,
|
dynamic_state: DynamicState,
|
||||||
|
|
||||||
subpass_index: usize,
|
subpass_index: usize,
|
||||||
|
active_occlusion_queries: *std.ArrayList(ExecutionDevice.ActiveOcclusionQuery),
|
||||||
|
|
||||||
pub fn init(device: *SoftDevice, state: *PipelineState) Self {
|
pub fn init(device: *SoftDevice, state: *PipelineState, active_occlusion_queries: *std.ArrayList(ExecutionDevice.ActiveOcclusionQuery)) Self {
|
||||||
return .{
|
return .{
|
||||||
.device = device,
|
.device = device,
|
||||||
.state = state,
|
.state = state,
|
||||||
@@ -152,6 +151,7 @@ pub fn init(device: *SoftDevice, state: *PipelineState) Self {
|
|||||||
.stencil_back_reference = null,
|
.stencil_back_reference = null,
|
||||||
},
|
},
|
||||||
.subpass_index = 0,
|
.subpass_index = 0,
|
||||||
|
.active_occlusion_queries = active_occlusion_queries,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -574,7 +574,12 @@ pub fn readFloat4(map: []const u8, src_format: vk.Format) F32x4 {
|
|||||||
=> c[0] = normalizedI8(map[0]),
|
=> c[0] = normalizedI8(map[0]),
|
||||||
|
|
||||||
.r16_snorm => c[0] = normalizedI16(std.mem.bytesToValue(u16, map)),
|
.r16_snorm => c[0] = normalizedI16(std.mem.bytesToValue(u16, map)),
|
||||||
.r16_unorm => c[0] = @as(f32, @floatFromInt(std.mem.bytesToValue(u16, map))) / std.math.maxInt(u16),
|
.r16_unorm,
|
||||||
|
.d16_unorm,
|
||||||
|
=> c[0] = @as(f32, @floatFromInt(std.mem.bytesToValue(u16, map))) / std.math.maxInt(u16),
|
||||||
|
.x8_d24_unorm_pack32,
|
||||||
|
.d24_unorm_s8_uint,
|
||||||
|
=> c[0] = @as(f32, @floatFromInt(std.mem.bytesToValue(u32, map) & 0x00ff_ffff)) / @as(f32, @floatFromInt(0x00ff_ffff)),
|
||||||
|
|
||||||
.r8g8b8a8_sint,
|
.r8g8b8a8_sint,
|
||||||
.r8g8b8a8_uint,
|
.r8g8b8a8_uint,
|
||||||
@@ -856,6 +861,14 @@ pub fn writeFloat4(c: F32x4, map: []u8, dst_format: vk.Format) void {
|
|||||||
.d16_unorm,
|
.d16_unorm,
|
||||||
=> std.mem.bytesAsValue(u16, map).* = @intFromFloat(@round(color[0] * std.math.maxInt(u16))),
|
=> std.mem.bytesAsValue(u16, map).* = @intFromFloat(@round(color[0] * std.math.maxInt(u16))),
|
||||||
|
|
||||||
|
.x8_d24_unorm_pack32,
|
||||||
|
.d24_unorm_s8_uint,
|
||||||
|
=> {
|
||||||
|
const depth: u32 = @intFromFloat(@round(color[0] * @as(f32, @floatFromInt(0x00ff_ffff))));
|
||||||
|
const preserved: u32 = std.mem.bytesToValue(u32, map) & 0xff00_0000;
|
||||||
|
std.mem.bytesAsValue(u32, map).* = preserved | depth;
|
||||||
|
},
|
||||||
|
|
||||||
.r16_sfloat => std.mem.bytesAsValue(f16, map).* = @floatCast(color[0]),
|
.r16_sfloat => std.mem.bytesAsValue(f16, map).* = @floatCast(color[0]),
|
||||||
|
|
||||||
.r32_sint,
|
.r32_sint,
|
||||||
|
|||||||
@@ -72,9 +72,12 @@ pub fn shaderInvocation(
|
|||||||
|
|
||||||
rt.callEntryPoint(allocator, entry) catch |err| switch (err) {
|
rt.callEntryPoint(allocator, entry) catch |err| switch (err) {
|
||||||
// Some errors can be safely ignored
|
// Some errors can be safely ignored
|
||||||
SpvRuntimeError.OutOfBounds,
|
SpvRuntimeError.OutOfBounds => {},
|
||||||
SpvRuntimeError.Killed,
|
SpvRuntimeError.Killed => {
|
||||||
=> {},
|
try rt.flushDescriptorSets(allocator);
|
||||||
|
freeOwnedInputs(allocator, fragment_inputs);
|
||||||
|
return undefined; // FIXME
|
||||||
|
},
|
||||||
else => return err,
|
else => return err,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -173,6 +173,16 @@ inline fn run(data: RunData) !void {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
try common.writeToTargets(outputs, data.draw_call, data.color_attachment_access, data.depth_attachment_access, data.stencil_attachment_access, true, @intCast(pixel_x), @intCast(pixel_y), z);
|
try common.writeToTargets(
|
||||||
|
outputs,
|
||||||
|
data.draw_call,
|
||||||
|
data.color_attachment_access,
|
||||||
|
data.depth_attachment_access,
|
||||||
|
data.stencil_attachment_access,
|
||||||
|
true,
|
||||||
|
@intCast(pixel_x),
|
||||||
|
@intCast(pixel_y),
|
||||||
|
z,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -98,13 +98,7 @@ fn updateStencilValue(stencil: *RenderTargetAccess, offset: usize, state: vk.Ste
|
|||||||
blitter.writeInt4(@splat(new_value), stencil.base[offset..], stencil.format);
|
blitter.writeInt4(@splat(new_value), stencil.base[offset..], stencil.format);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn stencilTestAndUpdate(
|
pub fn stencilTestAndUpdate(stencil: *RenderTargetAccess, x: usize, y: usize, state: vk.StencilOpState, depth_passed: ?bool) bool {
|
||||||
stencil: *RenderTargetAccess,
|
|
||||||
x: usize,
|
|
||||||
y: usize,
|
|
||||||
state: vk.StencilOpState,
|
|
||||||
depth_passed: ?bool,
|
|
||||||
) bool {
|
|
||||||
const offset = targetOffset(stencil.*, x, y) orelse return false;
|
const offset = targetOffset(stencil.*, x, y) orelse return false;
|
||||||
const current = blitter.readInt4(stencil.base[offset..], stencil.format)[0] & std.math.maxInt(u8);
|
const current = blitter.readInt4(stencil.base[offset..], stencil.format)[0] & std.math.maxInt(u8);
|
||||||
const reference = state.reference & std.math.maxInt(u8);
|
const reference = state.reference & std.math.maxInt(u8);
|
||||||
@@ -132,15 +126,27 @@ fn stencilTest(stencil: *RenderTargetAccess, offset: usize, state: vk.StencilOpS
|
|||||||
return compare(u32, state.compare_op, reference & compare_mask, current & compare_mask);
|
return compare(u32, state.compare_op, reference & compare_mask, current & compare_mask);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn quantizeDepthForFormat(format: vk.Format, z: f32) f32 {
|
||||||
|
const clamped = std.math.clamp(z, 0.0, 1.0);
|
||||||
|
return switch (format) {
|
||||||
|
.d16_unorm => @as(f32, @floatFromInt(@as(u16, @intFromFloat(@round(clamped * std.math.maxInt(u16)))))) / std.math.maxInt(u16),
|
||||||
|
.x8_d24_unorm_pack32,
|
||||||
|
.d24_unorm_s8_uint,
|
||||||
|
=> @as(f32, @floatFromInt(@as(u32, @intFromFloat(@round(clamped * @as(f32, @floatFromInt(0x00ff_ffff))))))) / @as(f32, @floatFromInt(0x00ff_ffff)),
|
||||||
|
else => z,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
pub fn depthTestAndUpdate(depth: *RenderTargetAccess, x: usize, y: usize, z: f32, state: vk.PipelineDepthStencilStateCreateInfo) bool {
|
pub fn depthTestAndUpdate(depth: *RenderTargetAccess, x: usize, y: usize, z: f32, state: vk.PipelineDepthStencilStateCreateInfo) bool {
|
||||||
if (state.depth_test_enable == .false)
|
if (state.depth_test_enable == .false)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
const offset = targetOffset(depth.*, x, y) orelse return false;
|
const offset = targetOffset(depth.*, x, y) orelse return false;
|
||||||
|
const reference = quantizeDepthForFormat(depth.format, z);
|
||||||
const depth_value = blitter.readFloat4(depth.base[offset..], depth.format);
|
const depth_value = blitter.readFloat4(depth.base[offset..], depth.format);
|
||||||
const passed = compare(f32, state.depth_compare_op, z, depth_value[0]);
|
const passed = compare(f32, state.depth_compare_op, reference, depth_value[0]);
|
||||||
if (passed and state.depth_write_enable == .true)
|
if (passed and state.depth_write_enable == .true)
|
||||||
blitter.writeFloat4(zm.f32x4s(z), depth.base[offset..], depth.format);
|
blitter.writeFloat4(zm.f32x4s(reference), depth.base[offset..], depth.format);
|
||||||
return passed;
|
return passed;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -312,6 +318,9 @@ pub fn writeToTargets(
|
|||||||
const io = draw_call.renderer.device.interface.io();
|
const io = draw_call.renderer.device.interface.io();
|
||||||
const depth_stencil_state = draw_call.renderer.state.pipeline.?.interface.mode.graphics.depth_stencil;
|
const depth_stencil_state = draw_call.renderer.state.pipeline.?.interface.mode.graphics.depth_stencil;
|
||||||
|
|
||||||
|
if (x >= draw_call.framebuffer.interface.width or y >= draw_call.framebuffer.interface.height)
|
||||||
|
return;
|
||||||
|
|
||||||
var stencil_state: ?vk.StencilOpState = null;
|
var stencil_state: ?vk.StencilOpState = null;
|
||||||
var stencil_offset: ?usize = null;
|
var stencil_offset: ?usize = null;
|
||||||
if (stencil_attachment_access) |stencil| {
|
if (stencil_attachment_access) |stencil| {
|
||||||
@@ -361,6 +370,10 @@ pub fn writeToTargets(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (draw_call.renderer.active_occlusion_queries.items) |active| {
|
||||||
|
try active.pool.addSamples(active.query, 1);
|
||||||
|
}
|
||||||
|
|
||||||
for (color_attachment_access, 0..) |maybe_color, location| {
|
for (color_attachment_access, 0..) |maybe_color, location| {
|
||||||
const color = maybe_color orelse continue;
|
const color = maybe_color orelse continue;
|
||||||
const color_offset = targetOffset(color, x, y) orelse continue;
|
const color_offset = targetOffset(color, x, y) orelse continue;
|
||||||
|
|||||||
@@ -191,7 +191,17 @@ inline fn run(data: RunData) !void {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
try common.writeToTargets(outputs, data.draw_call, data.color_attachment_access, data.depth_attachment_access, data.stencil_attachment_access, data.front_face, @intCast(x), @intCast(y), z);
|
try common.writeToTargets(
|
||||||
|
outputs,
|
||||||
|
data.draw_call,
|
||||||
|
data.color_attachment_access,
|
||||||
|
data.depth_attachment_access,
|
||||||
|
data.stencil_attachment_access,
|
||||||
|
data.front_face,
|
||||||
|
@intCast(x),
|
||||||
|
@intCast(y),
|
||||||
|
z,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,16 +39,18 @@ pub fn runWrapper(data: RunData) void {
|
|||||||
|
|
||||||
inline fn run(data: RunData) !void {
|
inline fn run(data: RunData) !void {
|
||||||
const shader = data.pipeline.stages.getPtrAssertContains(.vertex);
|
const shader = data.pipeline.stages.getPtrAssertContains(.vertex);
|
||||||
const rt = &shader.runtimes[data.batch_id].rt;
|
const runtime = &shader.runtimes[data.batch_id];
|
||||||
|
const mutex = &runtime.mutex;
|
||||||
|
const rt = &runtime.rt;
|
||||||
|
|
||||||
|
const io = data.draw_call.renderer.device.interface.io();
|
||||||
|
mutex.lock(io) catch return VkError.DeviceLost;
|
||||||
|
defer mutex.unlock(io);
|
||||||
|
|
||||||
const entry = try rt.getEntryPointByName(shader.entry);
|
const entry = try rt.getEntryPointByName(shader.entry);
|
||||||
|
|
||||||
var invocation_index: usize = data.batch_id;
|
var invocation_index: usize = data.batch_id;
|
||||||
while (invocation_index < data.vertex_count) : (invocation_index += data.batch_size) {
|
while (invocation_index < data.vertex_count) : (invocation_index += data.batch_size) {
|
||||||
const io = data.draw_call.renderer.device.interface.io();
|
|
||||||
data.draw_call.allocator_mutex.lock(io) catch return VkError.DeviceLost;
|
|
||||||
defer data.draw_call.allocator_mutex.unlock(io);
|
|
||||||
|
|
||||||
rt.resetInvocation(data.allocator);
|
rt.resetInvocation(data.allocator);
|
||||||
try rt.populatePushConstants(data.draw_call.renderer.state.push_constant_blob[0..]);
|
try rt.populatePushConstants(data.draw_call.renderer.state.push_constant_blob[0..]);
|
||||||
|
|
||||||
@@ -78,9 +80,11 @@ inline fn run(data: RunData) !void {
|
|||||||
|
|
||||||
rt.callEntryPoint(data.allocator, entry) catch |err| switch (err) {
|
rt.callEntryPoint(data.allocator, entry) catch |err| switch (err) {
|
||||||
// Some errors can be safely ignored
|
// Some errors can be safely ignored
|
||||||
SpvRuntimeError.OutOfBounds,
|
SpvRuntimeError.OutOfBounds => {},
|
||||||
SpvRuntimeError.Killed,
|
SpvRuntimeError.Killed => {
|
||||||
=> {},
|
try rt.flushDescriptorSets(data.allocator);
|
||||||
|
return;
|
||||||
|
},
|
||||||
else => return err,
|
else => return err,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -95,7 +99,7 @@ inline fn run(data: RunData) !void {
|
|||||||
};
|
};
|
||||||
const memory_size = try rt.getResultMemorySize(result_word);
|
const memory_size = try rt.getResultMemorySize(result_word);
|
||||||
output.outputs[location][component] = .{
|
output.outputs[location][component] = .{
|
||||||
.interpolation_type = if (rt.hasResultDecoration(result_word, .Flat) or resultIsInteger(rt, result_word)) .flat else .smooth, // TODO : handle noperspective
|
.interpolation_type = if (rt.hasResultDecoration(result_word, .Flat) or rt.resultIsInteger(result_word)) .flat else .smooth, // TODO : handle noperspective
|
||||||
.blob = data.allocator.alloc(u8, memory_size + INTERFACE_BLOB_PADDING) catch return VkError.OutOfDeviceMemory,
|
.blob = data.allocator.alloc(u8, memory_size + INTERFACE_BLOB_PADDING) catch return VkError.OutOfDeviceMemory,
|
||||||
.size = memory_size,
|
.size = memory_size,
|
||||||
};
|
};
|
||||||
@@ -116,32 +120,7 @@ fn setupBuiltins(rt: *spv.Runtime, vertex_index: usize, instance_index: usize) !
|
|||||||
try rt.writeBuiltIn(std.mem.asBytes(&instance_index_u32), .InstanceIndex);
|
try rt.writeBuiltIn(std.mem.asBytes(&instance_index_u32), .InstanceIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn resultIsInteger(rt: *spv.Runtime, result_word: spv.SpvWord) bool {
|
fn writeVertexInput(rt: *spv.Runtime, allocator: std.mem.Allocator, raw_input: []const u8, format: vk.Format, location: u32) !void {
|
||||||
const value = rt.results[result_word].getConstValue() catch return false;
|
|
||||||
return switch (value.*) {
|
|
||||||
.Int,
|
|
||||||
.Vector2i32,
|
|
||||||
.Vector3i32,
|
|
||||||
.Vector4i32,
|
|
||||||
.Vector2u32,
|
|
||||||
.Vector3u32,
|
|
||||||
.Vector4u32,
|
|
||||||
=> true,
|
|
||||||
.Vector => |lanes| lanes.len != 0 and switch (lanes[0]) {
|
|
||||||
.Int => true,
|
|
||||||
else => false,
|
|
||||||
},
|
|
||||||
else => false,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
fn writeVertexInput(
|
|
||||||
rt: *spv.Runtime,
|
|
||||||
allocator: std.mem.Allocator,
|
|
||||||
raw_input: []const u8,
|
|
||||||
format: vk.Format,
|
|
||||||
location: u32,
|
|
||||||
) !void {
|
|
||||||
var has_split_components = false;
|
var has_split_components = false;
|
||||||
for (1..4) |component| {
|
for (1..4) |component| {
|
||||||
_ = rt.getResultByLocationComponent(location, @intCast(component), .input) catch |err| switch (err) {
|
_ = rt.getResultByLocationComponent(location, @intCast(component), .input) catch |err| switch (err) {
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ const Event = @import("Event.zig");
|
|||||||
const Framebuffer = @import("Framebuffer.zig");
|
const Framebuffer = @import("Framebuffer.zig");
|
||||||
const Image = @import("Image.zig");
|
const Image = @import("Image.zig");
|
||||||
const Pipeline = @import("Pipeline.zig");
|
const Pipeline = @import("Pipeline.zig");
|
||||||
|
const QueryPool = @import("QueryPool.zig");
|
||||||
const RenderPass = @import("RenderPass.zig");
|
const RenderPass = @import("RenderPass.zig");
|
||||||
|
|
||||||
const State = enum {
|
const State = enum {
|
||||||
@@ -39,6 +40,7 @@ dispatch_table: *const DispatchTable,
|
|||||||
|
|
||||||
pub const DispatchTable = struct {
|
pub const DispatchTable = struct {
|
||||||
begin: *const fn (*Self, *const vk.CommandBufferBeginInfo) VkError!void,
|
begin: *const fn (*Self, *const vk.CommandBufferBeginInfo) VkError!void,
|
||||||
|
beginQuery: *const fn (*Self, *QueryPool, u32, vk.QueryControlFlags) VkError!void,
|
||||||
beginRenderPass: *const fn (*Self, *RenderPass, *Framebuffer, vk.Rect2D, ?[]const vk.ClearValue) VkError!void,
|
beginRenderPass: *const fn (*Self, *RenderPass, *Framebuffer, vk.Rect2D, ?[]const vk.ClearValue) VkError!void,
|
||||||
bindDescriptorSets: *const fn (*Self, vk.PipelineBindPoint, u32, [lib.VULKAN_MAX_DESCRIPTOR_SETS]?*DescriptorSet, []const u32) VkError!void,
|
bindDescriptorSets: *const fn (*Self, vk.PipelineBindPoint, u32, [lib.VULKAN_MAX_DESCRIPTOR_SETS]?*DescriptorSet, []const u32) VkError!void,
|
||||||
bindPipeline: *const fn (*Self, vk.PipelineBindPoint, *Pipeline) VkError!void,
|
bindPipeline: *const fn (*Self, vk.PipelineBindPoint, *Pipeline) VkError!void,
|
||||||
@@ -52,6 +54,7 @@ pub const DispatchTable = struct {
|
|||||||
copyBufferToImage: *const fn (*Self, *Buffer, *Image, vk.ImageLayout, []const vk.BufferImageCopy) VkError!void,
|
copyBufferToImage: *const fn (*Self, *Buffer, *Image, vk.ImageLayout, []const vk.BufferImageCopy) VkError!void,
|
||||||
copyImage: *const fn (*Self, *Image, vk.ImageLayout, *Image, vk.ImageLayout, []const vk.ImageCopy) VkError!void,
|
copyImage: *const fn (*Self, *Image, vk.ImageLayout, *Image, vk.ImageLayout, []const vk.ImageCopy) VkError!void,
|
||||||
copyImageToBuffer: *const fn (*Self, *Image, vk.ImageLayout, *Buffer, []const vk.BufferImageCopy) VkError!void,
|
copyImageToBuffer: *const fn (*Self, *Image, vk.ImageLayout, *Buffer, []const vk.BufferImageCopy) VkError!void,
|
||||||
|
copyQueryPoolResults: *const fn (*Self, *QueryPool, u32, u32, *Buffer, vk.DeviceSize, vk.DeviceSize, vk.QueryResultFlags) VkError!void,
|
||||||
dispatch: *const fn (*Self, u32, u32, u32) VkError!void,
|
dispatch: *const fn (*Self, u32, u32, u32) VkError!void,
|
||||||
dispatchIndirect: *const fn (*Self, *Buffer, vk.DeviceSize) VkError!void,
|
dispatchIndirect: *const fn (*Self, *Buffer, vk.DeviceSize) VkError!void,
|
||||||
draw: *const fn (*Self, usize, usize, usize, usize) VkError!void,
|
draw: *const fn (*Self, usize, usize, usize, usize) VkError!void,
|
||||||
@@ -59,6 +62,7 @@ pub const DispatchTable = struct {
|
|||||||
drawIndexedIndirect: *const fn (*Self, *Buffer, usize, usize, usize) VkError!void,
|
drawIndexedIndirect: *const fn (*Self, *Buffer, usize, usize, usize) VkError!void,
|
||||||
drawIndirect: *const fn (*Self, *Buffer, usize, usize, usize) VkError!void,
|
drawIndirect: *const fn (*Self, *Buffer, usize, usize, usize) VkError!void,
|
||||||
end: *const fn (*Self) VkError!void,
|
end: *const fn (*Self) VkError!void,
|
||||||
|
endQuery: *const fn (*Self, *QueryPool, u32) VkError!void,
|
||||||
endRenderPass: *const fn (*Self) VkError!void,
|
endRenderPass: *const fn (*Self) VkError!void,
|
||||||
executeCommands: *const fn (*Self, *Self) VkError!void,
|
executeCommands: *const fn (*Self, *Self) VkError!void,
|
||||||
fillBuffer: *const fn (*Self, *Buffer, vk.DeviceSize, vk.DeviceSize, u32) VkError!void,
|
fillBuffer: *const fn (*Self, *Buffer, vk.DeviceSize, vk.DeviceSize, u32) VkError!void,
|
||||||
@@ -66,6 +70,7 @@ pub const DispatchTable = struct {
|
|||||||
pipelineBarrier: *const fn (*Self, vk.PipelineStageFlags, vk.PipelineStageFlags, vk.DependencyFlags, []const vk.MemoryBarrier, []const vk.BufferMemoryBarrier, []const vk.ImageMemoryBarrier) VkError!void,
|
pipelineBarrier: *const fn (*Self, vk.PipelineStageFlags, vk.PipelineStageFlags, vk.DependencyFlags, []const vk.MemoryBarrier, []const vk.BufferMemoryBarrier, []const vk.ImageMemoryBarrier) VkError!void,
|
||||||
pushConstants: *const fn (*Self, vk.ShaderStageFlags, u32, []const u8) VkError!void,
|
pushConstants: *const fn (*Self, vk.ShaderStageFlags, u32, []const u8) VkError!void,
|
||||||
reset: *const fn (*Self, vk.CommandBufferResetFlags) VkError!void,
|
reset: *const fn (*Self, vk.CommandBufferResetFlags) VkError!void,
|
||||||
|
resetQueryPool: *const fn (*Self, *QueryPool, u32, u32) VkError!void,
|
||||||
resetEvent: *const fn (*Self, *Event, vk.PipelineStageFlags) VkError!void,
|
resetEvent: *const fn (*Self, *Event, vk.PipelineStageFlags) VkError!void,
|
||||||
resolveImage: *const fn (*Self, *Image, vk.ImageLayout, *Image, vk.ImageLayout, vk.ImageResolve) VkError!void,
|
resolveImage: *const fn (*Self, *Image, vk.ImageLayout, *Image, vk.ImageLayout, vk.ImageResolve) VkError!void,
|
||||||
setEvent: *const fn (*Self, *Event, vk.PipelineStageFlags) VkError!void,
|
setEvent: *const fn (*Self, *Event, vk.PipelineStageFlags) VkError!void,
|
||||||
@@ -165,6 +170,10 @@ pub inline fn beginRenderPass(self: *Self, render_pass: *RenderPass, framebuffer
|
|||||||
try self.dispatch_table.beginRenderPass(self, render_pass, framebuffer, render_area, clear_values);
|
try self.dispatch_table.beginRenderPass(self, render_pass, framebuffer, render_area, clear_values);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub inline fn beginQuery(self: *Self, pool: *QueryPool, query: u32, flags: vk.QueryControlFlags) VkError!void {
|
||||||
|
try self.dispatch_table.beginQuery(self, pool, query, flags);
|
||||||
|
}
|
||||||
|
|
||||||
pub fn bindDescriptorSets(self: *Self, bind_point: vk.PipelineBindPoint, first_set: u32, sets: []const vk.DescriptorSet, dynamic_offsets: []const u32) VkError!void {
|
pub fn bindDescriptorSets(self: *Self, bind_point: vk.PipelineBindPoint, first_set: u32, sets: []const vk.DescriptorSet, dynamic_offsets: []const u32) VkError!void {
|
||||||
if (sets.len > lib.VULKAN_MAX_DESCRIPTOR_SETS or first_set > lib.VULKAN_MAX_DESCRIPTOR_SETS or first_set + sets.len > lib.VULKAN_MAX_DESCRIPTOR_SETS)
|
if (sets.len > lib.VULKAN_MAX_DESCRIPTOR_SETS or first_set > lib.VULKAN_MAX_DESCRIPTOR_SETS or first_set + sets.len > lib.VULKAN_MAX_DESCRIPTOR_SETS)
|
||||||
return VkError.ValidationFailed;
|
return VkError.ValidationFailed;
|
||||||
@@ -224,6 +233,10 @@ pub inline fn copyImageToBuffer(self: *Self, src: *Image, src_layout: vk.ImageLa
|
|||||||
try self.dispatch_table.copyImageToBuffer(self, src, src_layout, dst, regions);
|
try self.dispatch_table.copyImageToBuffer(self, src, src_layout, dst, regions);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub inline fn copyQueryPoolResults(self: *Self, pool: *QueryPool, first: u32, count: u32, dst: *Buffer, offset: vk.DeviceSize, stride: vk.DeviceSize, flags: vk.QueryResultFlags) VkError!void {
|
||||||
|
try self.dispatch_table.copyQueryPoolResults(self, pool, first, count, dst, offset, stride, flags);
|
||||||
|
}
|
||||||
|
|
||||||
pub inline fn dispatch(self: *Self, group_count_x: u32, group_count_y: u32, group_count_z: u32) VkError!void {
|
pub inline fn dispatch(self: *Self, group_count_x: u32, group_count_y: u32, group_count_z: u32) VkError!void {
|
||||||
try self.dispatch_table.dispatch(self, group_count_x, group_count_y, group_count_z);
|
try self.dispatch_table.dispatch(self, group_count_x, group_count_y, group_count_z);
|
||||||
}
|
}
|
||||||
@@ -252,6 +265,10 @@ pub inline fn endRenderPass(self: *Self) VkError!void {
|
|||||||
try self.dispatch_table.endRenderPass(self);
|
try self.dispatch_table.endRenderPass(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub inline fn endQuery(self: *Self, pool: *QueryPool, query: u32) VkError!void {
|
||||||
|
try self.dispatch_table.endQuery(self, pool, query);
|
||||||
|
}
|
||||||
|
|
||||||
pub inline fn executeCommands(self: *Self, commands: *Self) VkError!void {
|
pub inline fn executeCommands(self: *Self, commands: *Self) VkError!void {
|
||||||
try self.dispatch_table.executeCommands(self, commands);
|
try self.dispatch_table.executeCommands(self, commands);
|
||||||
}
|
}
|
||||||
@@ -280,6 +297,10 @@ pub inline fn pushConstants(self: *Self, stages: vk.ShaderStageFlags, offset: u3
|
|||||||
try self.dispatch_table.pushConstants(self, stages, offset, blob);
|
try self.dispatch_table.pushConstants(self, stages, offset, blob);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub inline fn resetQueryPool(self: *Self, pool: *QueryPool, first: u32, count: u32) VkError!void {
|
||||||
|
try self.dispatch_table.resetQueryPool(self, pool, first, count);
|
||||||
|
}
|
||||||
|
|
||||||
pub inline fn resetEvent(self: *Self, event: *Event, stage: vk.PipelineStageFlags) VkError!void {
|
pub inline fn resetEvent(self: *Self, event: *Event, stage: vk.PipelineStageFlags) VkError!void {
|
||||||
try self.dispatch_table.resetEvent(self, event, stage);
|
try self.dispatch_table.resetEvent(self, event, stage);
|
||||||
}
|
}
|
||||||
|
|||||||
+112
-2
@@ -11,18 +11,32 @@ const Self = @This();
|
|||||||
pub const ObjectType: vk.ObjectType = .query_pool;
|
pub const ObjectType: vk.ObjectType = .query_pool;
|
||||||
|
|
||||||
owner: *Device,
|
owner: *Device,
|
||||||
|
query_type: vk.QueryType,
|
||||||
|
queries: []Query,
|
||||||
|
|
||||||
vtable: *const VTable,
|
vtable: *const VTable,
|
||||||
|
|
||||||
|
const Query = struct {
|
||||||
|
value: std.atomic.Value(u64) = std.atomic.Value(u64).init(0),
|
||||||
|
available: bool = false,
|
||||||
|
active: bool = false,
|
||||||
|
};
|
||||||
|
|
||||||
pub const VTable = struct {
|
pub const VTable = struct {
|
||||||
destroy: *const fn (*Self, std.mem.Allocator) void,
|
destroy: *const fn (*Self, std.mem.Allocator) void,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn init(device: *Device, allocator: std.mem.Allocator, info: *const vk.QueryPoolCreateInfo) VkError!Self {
|
pub fn init(device: *Device, allocator: std.mem.Allocator, info: *const vk.QueryPoolCreateInfo) VkError!Self {
|
||||||
_ = allocator;
|
const queries = allocator.alloc(Query, info.query_count) catch return VkError.OutOfHostMemory;
|
||||||
_ = info;
|
errdefer allocator.free(queries);
|
||||||
|
for (queries) |*query| {
|
||||||
|
query.* = .{};
|
||||||
|
}
|
||||||
|
|
||||||
return .{
|
return .{
|
||||||
.owner = device,
|
.owner = device,
|
||||||
|
.query_type = info.query_type,
|
||||||
|
.queries = queries,
|
||||||
.vtable = undefined,
|
.vtable = undefined,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -30,3 +44,99 @@ pub fn init(device: *Device, allocator: std.mem.Allocator, info: *const vk.Query
|
|||||||
pub inline fn destroy(self: *Self, allocator: std.mem.Allocator) void {
|
pub inline fn destroy(self: *Self, allocator: std.mem.Allocator) void {
|
||||||
self.vtable.destroy(self, allocator);
|
self.vtable.destroy(self, allocator);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn reset(self: *Self, first: u32, count: u32) VkError!void {
|
||||||
|
const range = try self.queryRange(first, count);
|
||||||
|
for (range) |*query| {
|
||||||
|
query.value.store(0, .seq_cst);
|
||||||
|
query.available = false;
|
||||||
|
query.active = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn begin(self: *Self, query: u32) VkError!void {
|
||||||
|
if (self.query_type != .occlusion)
|
||||||
|
return VkError.FeatureNotPresent;
|
||||||
|
const q = try self.queryAt(query);
|
||||||
|
q.value.store(0, .seq_cst);
|
||||||
|
q.available = false;
|
||||||
|
q.active = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn end(self: *Self, query: u32) VkError!void {
|
||||||
|
const q = try self.queryAt(query);
|
||||||
|
q.active = false;
|
||||||
|
q.available = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn addSamples(self: *Self, query: u32, samples: u64) VkError!void {
|
||||||
|
const q = try self.queryAt(query);
|
||||||
|
if (q.active)
|
||||||
|
_ = q.value.fetchAdd(samples, .seq_cst);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn writeResults(self: *Self, first: u32, count: u32, bytes: []u8, stride: vk.DeviceSize, flags: vk.QueryResultFlags) VkError!void {
|
||||||
|
return self.writeResultsImpl(first, count, bytes, stride, flags, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn copyResults(self: *Self, first: u32, count: u32, bytes: []u8, stride: vk.DeviceSize, flags: vk.QueryResultFlags) VkError!void {
|
||||||
|
return self.writeResultsImpl(first, count, bytes, stride, flags, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn writeResultsImpl(self: *Self, first: u32, count: u32, bytes: []u8, stride: vk.DeviceSize, flags: vk.QueryResultFlags, report_not_ready: bool) VkError!void {
|
||||||
|
_ = try self.queryRange(first, count);
|
||||||
|
if (count == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
const value_size: usize = if (flags.@"64_bit") 8 else 4;
|
||||||
|
const item_size = value_size * (1 + @as(usize, @intFromBool(flags.with_availability_bit)));
|
||||||
|
if (count > 1 and stride < item_size)
|
||||||
|
return VkError.ValidationFailed;
|
||||||
|
|
||||||
|
var not_ready = false;
|
||||||
|
for (0..count) |i| {
|
||||||
|
const query = &self.queries[first + i];
|
||||||
|
if (flags.wait_bit) {
|
||||||
|
while (!query.available) {
|
||||||
|
std.Thread.yield() catch std.atomic.spinLoopHint();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const offset: usize = @intCast(@as(vk.DeviceSize, @intCast(i)) * stride);
|
||||||
|
if (offset + item_size > bytes.len)
|
||||||
|
return VkError.Incomplete;
|
||||||
|
|
||||||
|
if (query.available or flags.partial_bit) {
|
||||||
|
writeInt(bytes[offset..][0..value_size], query.value.load(.seq_cst), flags);
|
||||||
|
} else {
|
||||||
|
not_ready = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flags.with_availability_bit) {
|
||||||
|
writeInt(bytes[offset + value_size ..][0..value_size], @intFromBool(query.available), flags);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (not_ready and report_not_ready)
|
||||||
|
return VkError.NotReady;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn writeInt(bytes: []u8, value: u64, flags: vk.QueryResultFlags) void {
|
||||||
|
if (flags.@"64_bit") {
|
||||||
|
std.mem.writeInt(u64, bytes[0..8], value, .little);
|
||||||
|
} else {
|
||||||
|
std.mem.writeInt(u32, bytes[0..4], @truncate(value), .little);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn queryAt(self: *Self, query: u32) VkError!*Query {
|
||||||
|
if (query >= self.queries.len)
|
||||||
|
return VkError.ValidationFailed;
|
||||||
|
return &self.queries[query];
|
||||||
|
}
|
||||||
|
|
||||||
|
fn queryRange(self: *Self, first: u32, count: u32) VkError![]Query {
|
||||||
|
if (first > self.queries.len or count > self.queries.len - first)
|
||||||
|
return VkError.ValidationFailed;
|
||||||
|
return self.queries[first .. first + count];
|
||||||
|
}
|
||||||
|
|||||||
+13
-43
@@ -1451,18 +1451,11 @@ pub export fn apeGetQueryPoolResults(
|
|||||||
defer entryPointEndLogTrace();
|
defer entryPointEndLogTrace();
|
||||||
|
|
||||||
Dispatchable(Device).checkHandleValidity(p_device) catch |err| return toVkResult(err);
|
Dispatchable(Device).checkHandleValidity(p_device) catch |err| return toVkResult(err);
|
||||||
|
const pool = NonDispatchable(QueryPool).fromHandleObject(p_pool) catch |err| return toVkResult(err);
|
||||||
|
|
||||||
notImplementedWarning();
|
const bytes = @as([*]u8, @ptrCast(data))[0..size];
|
||||||
|
pool.writeResults(first, count, bytes, stride, flags) catch |err| return toVkResult(err);
|
||||||
_ = p_pool;
|
return .success;
|
||||||
_ = first;
|
|
||||||
_ = count;
|
|
||||||
_ = size;
|
|
||||||
_ = data;
|
|
||||||
_ = stride;
|
|
||||||
_ = flags;
|
|
||||||
|
|
||||||
return .error_unknown;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub export fn apeGetRenderAreaGranularity(p_device: vk.Device, p_pass: vk.RenderPass, granularity: *vk.Extent2D) callconv(vk.vulkan_call_conv) void {
|
pub export fn apeGetRenderAreaGranularity(p_device: vk.Device, p_pass: vk.RenderPass, granularity: *vk.Extent2D) callconv(vk.vulkan_call_conv) void {
|
||||||
@@ -1630,13 +1623,8 @@ pub export fn apeCmdBeginQuery(p_cmd: vk.CommandBuffer, p_pool: vk.QueryPool, qu
|
|||||||
defer entryPointEndLogTrace();
|
defer entryPointEndLogTrace();
|
||||||
|
|
||||||
const cmd = Dispatchable(CommandBuffer).fromHandleObject(p_cmd) catch |err| return errorLogger(err);
|
const cmd = Dispatchable(CommandBuffer).fromHandleObject(p_cmd) catch |err| return errorLogger(err);
|
||||||
|
const pool = NonDispatchable(QueryPool).fromHandleObject(p_pool) catch |err| return errorLogger(err);
|
||||||
notImplementedWarning();
|
cmd.beginQuery(pool, query, flags) catch |err| return errorLogger(err);
|
||||||
|
|
||||||
_ = cmd;
|
|
||||||
_ = p_pool;
|
|
||||||
_ = query;
|
|
||||||
_ = flags;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub export fn apeCmdBeginRenderPass(p_cmd: vk.CommandBuffer, info: *const vk.RenderPassBeginInfo, contents: vk.SubpassContents) callconv(vk.vulkan_call_conv) void {
|
pub export fn apeCmdBeginRenderPass(p_cmd: vk.CommandBuffer, info: *const vk.RenderPassBeginInfo, contents: vk.SubpassContents) callconv(vk.vulkan_call_conv) void {
|
||||||
@@ -1799,18 +1787,9 @@ pub export fn apeCmdCopyQueryPoolResults(p_cmd: vk.CommandBuffer, p_pool: vk.Que
|
|||||||
defer entryPointEndLogTrace();
|
defer entryPointEndLogTrace();
|
||||||
|
|
||||||
const cmd = Dispatchable(CommandBuffer).fromHandleObject(p_cmd) catch |err| return errorLogger(err);
|
const cmd = Dispatchable(CommandBuffer).fromHandleObject(p_cmd) catch |err| return errorLogger(err);
|
||||||
const dst = NonDispatchable(Image).fromHandleObject(p_dst) catch |err| return errorLogger(err);
|
const pool = NonDispatchable(QueryPool).fromHandleObject(p_pool) catch |err| return errorLogger(err);
|
||||||
|
const dst = NonDispatchable(Buffer).fromHandleObject(p_dst) catch |err| return errorLogger(err);
|
||||||
notImplementedWarning();
|
cmd.copyQueryPoolResults(pool, first, count, dst, offset, stride, flags) catch |err| return errorLogger(err);
|
||||||
|
|
||||||
_ = cmd;
|
|
||||||
_ = p_pool;
|
|
||||||
_ = first;
|
|
||||||
_ = count;
|
|
||||||
_ = dst;
|
|
||||||
_ = offset;
|
|
||||||
_ = stride;
|
|
||||||
_ = flags;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub export fn apeCmdDispatch(p_cmd: vk.CommandBuffer, group_count_x: u32, group_count_y: u32, group_count_z: u32) callconv(vk.vulkan_call_conv) void {
|
pub export fn apeCmdDispatch(p_cmd: vk.CommandBuffer, group_count_x: u32, group_count_y: u32, group_count_z: u32) callconv(vk.vulkan_call_conv) void {
|
||||||
@@ -1869,12 +1848,8 @@ pub export fn apeCmdEndQuery(p_cmd: vk.CommandBuffer, p_pool: vk.QueryPool, quer
|
|||||||
defer entryPointEndLogTrace();
|
defer entryPointEndLogTrace();
|
||||||
|
|
||||||
const cmd = Dispatchable(CommandBuffer).fromHandleObject(p_cmd) catch |err| return errorLogger(err);
|
const cmd = Dispatchable(CommandBuffer).fromHandleObject(p_cmd) catch |err| return errorLogger(err);
|
||||||
|
const pool = NonDispatchable(QueryPool).fromHandleObject(p_pool) catch |err| return errorLogger(err);
|
||||||
notImplementedWarning();
|
cmd.endQuery(pool, query) catch |err| return errorLogger(err);
|
||||||
|
|
||||||
_ = cmd;
|
|
||||||
_ = p_pool;
|
|
||||||
_ = query;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub export fn apeCmdEndRenderPass(p_cmd: vk.CommandBuffer) callconv(vk.vulkan_call_conv) void {
|
pub export fn apeCmdEndRenderPass(p_cmd: vk.CommandBuffer) callconv(vk.vulkan_call_conv) void {
|
||||||
@@ -1954,13 +1929,8 @@ pub export fn apeCmdResetQueryPool(p_cmd: vk.CommandBuffer, p_pool: vk.QueryPool
|
|||||||
defer entryPointEndLogTrace();
|
defer entryPointEndLogTrace();
|
||||||
|
|
||||||
const cmd = Dispatchable(CommandBuffer).fromHandleObject(p_cmd) catch |err| return errorLogger(err);
|
const cmd = Dispatchable(CommandBuffer).fromHandleObject(p_cmd) catch |err| return errorLogger(err);
|
||||||
|
const pool = NonDispatchable(QueryPool).fromHandleObject(p_pool) catch |err| return errorLogger(err);
|
||||||
notImplementedWarning();
|
cmd.resetQueryPool(pool, first, count) catch |err| return errorLogger(err);
|
||||||
|
|
||||||
_ = cmd;
|
|
||||||
_ = p_pool;
|
|
||||||
_ = first;
|
|
||||||
_ = count;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub export fn apeCmdResetEvent(p_cmd: vk.CommandBuffer, p_event: vk.Event, stage_mask: vk.PipelineStageFlags) callconv(vk.vulkan_call_conv) void {
|
pub export fn apeCmdResetEvent(p_cmd: vk.CommandBuffer, p_event: vk.Event, stage_mask: vk.PipelineStageFlags) callconv(vk.vulkan_call_conv) void {
|
||||||
|
|||||||
Reference in New Issue
Block a user