implementing queries
This commit is contained in:
@@ -14,6 +14,7 @@ const Event = @import("Event.zig");
|
||||
const Framebuffer = @import("Framebuffer.zig");
|
||||
const Image = @import("Image.zig");
|
||||
const Pipeline = @import("Pipeline.zig");
|
||||
const QueryPool = @import("QueryPool.zig");
|
||||
const RenderPass = @import("RenderPass.zig");
|
||||
|
||||
const State = enum {
|
||||
@@ -39,6 +40,7 @@ dispatch_table: *const DispatchTable,
|
||||
|
||||
pub const DispatchTable = struct {
|
||||
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,
|
||||
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,
|
||||
@@ -52,6 +54,7 @@ pub const DispatchTable = struct {
|
||||
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,
|
||||
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,
|
||||
dispatchIndirect: *const fn (*Self, *Buffer, vk.DeviceSize) 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,
|
||||
drawIndirect: *const fn (*Self, *Buffer, usize, usize, usize) VkError!void,
|
||||
end: *const fn (*Self) VkError!void,
|
||||
endQuery: *const fn (*Self, *QueryPool, u32) VkError!void,
|
||||
endRenderPass: *const fn (*Self) VkError!void,
|
||||
executeCommands: *const fn (*Self, *Self) 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,
|
||||
pushConstants: *const fn (*Self, vk.ShaderStageFlags, u32, []const u8) 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,
|
||||
resolveImage: *const fn (*Self, *Image, vk.ImageLayout, *Image, vk.ImageLayout, vk.ImageResolve) 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);
|
||||
}
|
||||
|
||||
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 {
|
||||
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;
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
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 {
|
||||
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);
|
||||
}
|
||||
|
||||
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 {
|
||||
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);
|
||||
}
|
||||
|
||||
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 {
|
||||
try self.dispatch_table.resetEvent(self, event, stage);
|
||||
}
|
||||
|
||||
+112
-2
@@ -11,18 +11,32 @@ const Self = @This();
|
||||
pub const ObjectType: vk.ObjectType = .query_pool;
|
||||
|
||||
owner: *Device,
|
||||
query_type: vk.QueryType,
|
||||
queries: []Query,
|
||||
|
||||
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 {
|
||||
destroy: *const fn (*Self, std.mem.Allocator) void,
|
||||
};
|
||||
|
||||
pub fn init(device: *Device, allocator: std.mem.Allocator, info: *const vk.QueryPoolCreateInfo) VkError!Self {
|
||||
_ = allocator;
|
||||
_ = info;
|
||||
const queries = allocator.alloc(Query, info.query_count) catch return VkError.OutOfHostMemory;
|
||||
errdefer allocator.free(queries);
|
||||
for (queries) |*query| {
|
||||
query.* = .{};
|
||||
}
|
||||
|
||||
return .{
|
||||
.owner = device,
|
||||
.query_type = info.query_type,
|
||||
.queries = queries,
|
||||
.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 {
|
||||
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();
|
||||
|
||||
Dispatchable(Device).checkHandleValidity(p_device) catch |err| return toVkResult(err);
|
||||
const pool = NonDispatchable(QueryPool).fromHandleObject(p_pool) catch |err| return toVkResult(err);
|
||||
|
||||
notImplementedWarning();
|
||||
|
||||
_ = p_pool;
|
||||
_ = first;
|
||||
_ = count;
|
||||
_ = size;
|
||||
_ = data;
|
||||
_ = stride;
|
||||
_ = flags;
|
||||
|
||||
return .error_unknown;
|
||||
const bytes = @as([*]u8, @ptrCast(data))[0..size];
|
||||
pool.writeResults(first, count, bytes, stride, flags) catch |err| return toVkResult(err);
|
||||
return .success;
|
||||
}
|
||||
|
||||
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();
|
||||
|
||||
const cmd = Dispatchable(CommandBuffer).fromHandleObject(p_cmd) catch |err| return errorLogger(err);
|
||||
|
||||
notImplementedWarning();
|
||||
|
||||
_ = cmd;
|
||||
_ = p_pool;
|
||||
_ = query;
|
||||
_ = flags;
|
||||
const pool = NonDispatchable(QueryPool).fromHandleObject(p_pool) catch |err| return errorLogger(err);
|
||||
cmd.beginQuery(pool, query, flags) catch |err| return errorLogger(err);
|
||||
}
|
||||
|
||||
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();
|
||||
|
||||
const cmd = Dispatchable(CommandBuffer).fromHandleObject(p_cmd) catch |err| return errorLogger(err);
|
||||
const dst = NonDispatchable(Image).fromHandleObject(p_dst) catch |err| return errorLogger(err);
|
||||
|
||||
notImplementedWarning();
|
||||
|
||||
_ = cmd;
|
||||
_ = p_pool;
|
||||
_ = first;
|
||||
_ = count;
|
||||
_ = dst;
|
||||
_ = offset;
|
||||
_ = stride;
|
||||
_ = flags;
|
||||
const pool = NonDispatchable(QueryPool).fromHandleObject(p_pool) catch |err| return errorLogger(err);
|
||||
const dst = NonDispatchable(Buffer).fromHandleObject(p_dst) catch |err| return errorLogger(err);
|
||||
cmd.copyQueryPoolResults(pool, first, count, dst, offset, stride, flags) catch |err| return errorLogger(err);
|
||||
}
|
||||
|
||||
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();
|
||||
|
||||
const cmd = Dispatchable(CommandBuffer).fromHandleObject(p_cmd) catch |err| return errorLogger(err);
|
||||
|
||||
notImplementedWarning();
|
||||
|
||||
_ = cmd;
|
||||
_ = p_pool;
|
||||
_ = query;
|
||||
const pool = NonDispatchable(QueryPool).fromHandleObject(p_pool) catch |err| return errorLogger(err);
|
||||
cmd.endQuery(pool, query) catch |err| return errorLogger(err);
|
||||
}
|
||||
|
||||
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();
|
||||
|
||||
const cmd = Dispatchable(CommandBuffer).fromHandleObject(p_cmd) catch |err| return errorLogger(err);
|
||||
|
||||
notImplementedWarning();
|
||||
|
||||
_ = cmd;
|
||||
_ = p_pool;
|
||||
_ = first;
|
||||
_ = count;
|
||||
const pool = NonDispatchable(QueryPool).fromHandleObject(p_pool) catch |err| return errorLogger(err);
|
||||
cmd.resetQueryPool(pool, first, count) catch |err| return errorLogger(err);
|
||||
}
|
||||
|
||||
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