[Phi] implementing fully async queues, fences and semaphores
Mirror Gitea refs to GitHub / mirror (push) Successful in 15s
Build / build (push) Failing after 1m1s
Test / build_and_test (push) Successful in 6m8s

This commit is contained in:
2026-08-20 14:11:12 +02:00
parent 35e6c1d099
commit 3e12e97fe2
16 changed files with 1075 additions and 101 deletions
+76 -5
View File
@@ -9,6 +9,10 @@ const Self = @This();
pub const Interface = base.Fence;
interface: Interface,
mutex: std.Io.Mutex,
condition: std.Io.Condition,
is_signaled: bool,
is_failed: bool,
pub fn create(device: *Device, allocator: std.mem.Allocator, info: *const vk.FenceCreateInfo) VkError!*Self {
const self = allocator.create(Self) catch return VkError.OutOfHostMemory;
@@ -26,6 +30,10 @@ pub fn create(device: *Device, allocator: std.mem.Allocator, info: *const vk.Fen
self.* = .{
.interface = interface,
.mutex = .init,
.condition = .init,
.is_signaled = info.flags.signaled_bit,
.is_failed = false,
};
return self;
}
@@ -37,21 +45,84 @@ pub fn destroy(interface: *Interface, allocator: std.mem.Allocator) void {
pub fn getStatus(interface: *Interface) VkError!void {
const self: *Self = @alignCast(@fieldParentPtr("interface", interface));
_ = self;
const io = interface.owner.io();
self.mutex.lock(io) catch return VkError.DeviceLost;
defer self.mutex.unlock(io);
if (self.is_failed) return VkError.DeviceLost;
if (!self.is_signaled) return VkError.NotReady;
}
pub fn reset(interface: *Interface) VkError!void {
const self: *Self = @alignCast(@fieldParentPtr("interface", interface));
_ = self;
const io = interface.owner.io();
self.mutex.lock(io) catch return VkError.DeviceLost;
defer self.mutex.unlock(io);
if (self.is_failed) return VkError.DeviceLost;
self.is_signaled = false;
}
pub fn signal(interface: *Interface) VkError!void {
const self: *Self = @alignCast(@fieldParentPtr("interface", interface));
_ = self;
const io = interface.owner.io();
self.mutex.lock(io) catch return VkError.DeviceLost;
defer self.mutex.unlock(io);
if (self.is_failed) return VkError.DeviceLost;
self.is_signaled = true;
self.condition.broadcast(io);
}
/// Latch an asynchronous queue/device failure and wake all host waiters
pub fn fail(interface: *Interface) void {
const self: *Self = @alignCast(@fieldParentPtr("interface", interface));
const io = interface.owner.io();
self.mutex.lock(io) catch return;
defer self.mutex.unlock(io);
self.is_failed = true;
self.condition.broadcast(io);
}
pub fn wait(interface: *Interface, timeout: u64) VkError!void {
const self: *Self = @alignCast(@fieldParentPtr("interface", interface));
_ = self;
_ = timeout;
const io = interface.owner.io();
if (timeout == std.math.maxInt(@TypeOf(timeout))) {
self.mutex.lock(io) catch return VkError.DeviceLost;
defer self.mutex.unlock(io);
while (!self.is_signaled and !self.is_failed) {
self.condition.wait(io, &self.mutex) catch return VkError.DeviceLost;
}
if (self.is_failed) return VkError.DeviceLost;
return;
}
const deadline = std.Io.Clock.Timestamp.fromNow(io, .{
.raw = .fromNanoseconds(@intCast(timeout)),
.clock = .awake,
});
while (true) {
{
self.mutex.lock(io) catch return VkError.DeviceLost;
defer self.mutex.unlock(io);
if (self.is_failed) return VkError.DeviceLost;
if (self.is_signaled) return;
}
const remaining = deadline.durationFromNow(io);
if (remaining.raw.nanoseconds <= 0) return VkError.Timeout;
(std.Io.Clock.Duration{
.raw = .fromNanoseconds(@min(remaining.raw.nanoseconds, std.time.ns_per_ms)),
.clock = .awake,
}).sleep(io) catch return VkError.DeviceLost;
}
}