adding command buffer states

This commit is contained in:
2025-11-18 00:00:11 +01:00
parent 5661505bef
commit 5bfc0e6254
9 changed files with 88 additions and 17 deletions

View File

@@ -23,6 +23,7 @@ pub fn create(device: *base.Device, allocator: std.mem.Allocator, info: *const v
interface.dispatch_table = &.{
.begin = begin,
.end = end,
.reset = reset,
};
self.* = .{
@@ -44,3 +45,8 @@ pub fn begin(interface: *Interface, info: *const vk.CommandBufferBeginInfo) VkEr
pub fn end(interface: *Interface) VkError!void {
_ = interface;
}
pub fn reset(interface: *Interface, flags: vk.CommandBufferResetFlags) VkError!void {
_ = interface;
_ = flags;
}

View File

@@ -23,6 +23,10 @@ pub const DEVICE_ID = 0x600DCAFE;
pub const std_options = base.std_options;
comptime {
_ = base;
}
test {
std.testing.refAllDeclsRecursive(@This());
}

View File

@@ -2,12 +2,25 @@ const std = @import("std");
const vk = @import("vulkan");
const VkError = @import("error_set.zig").VkError;
const CommandPool = @import("CommandPool.zig");
const Device = @import("Device.zig");
const NonDispatchable = @import("NonDispatchable.zig").NonDispatchable;
const State = enum {
Initial,
Recording,
Executable,
Pending,
Invalid,
};
const Self = @This();
pub const ObjectType: vk.ObjectType = .command_buffer;
owner: *Device,
pool: *CommandPool,
state: State,
begin_info: ?vk.CommandBufferBeginInfo,
vtable: *const VTable,
dispatch_table: *const DispatchTable,
@@ -15,6 +28,7 @@ dispatch_table: *const DispatchTable,
pub const DispatchTable = struct {
begin: *const fn (*Self, *const vk.CommandBufferBeginInfo) VkError!void,
end: *const fn (*Self) VkError!void,
reset: *const fn (*Self, vk.CommandBufferResetFlags) VkError!void,
};
pub const VTable = struct {
@@ -23,22 +37,62 @@ pub const VTable = struct {
pub fn init(device: *Device, allocator: std.mem.Allocator, info: *const vk.CommandBufferAllocateInfo) VkError!Self {
_ = allocator;
_ = info;
return .{
.owner = device,
.pool = try NonDispatchable(CommandPool).fromHandleObject(info.command_pool),
.state = .Initial,
.begin_info = null,
.vtable = undefined,
.dispatch_table = undefined,
};
}
inline fn transitionState(self: *Self, target: State, from_allowed: std.EnumSet(State)) error{NotAllowed}!void {
if (!from_allowed.contains(self.state)) {
return error.NotAllowed;
}
self.state = target;
}
inline fn transitionStateNotAllowed(self: *Self, target: State, from_not_allowed: std.EnumSet(State)) error{NotAllowed}!void {
if (from_not_allowed.contains(self.state)) {
return error.NotAllowed;
}
self.state = target;
}
pub inline fn destroy(self: *Self, allocator: std.mem.Allocator) void {
self.vtable.destroy(self, allocator);
}
pub inline fn begin(self: *Self, info: *const vk.CommandBufferBeginInfo) VkError!void {
if (!self.pool.flags.reset_command_buffer_bit) {
self.transitionState(.Recording, .initOne(.Initial)) catch return VkError.ValidationFailed;
} else {
self.transitionStateNotAllowed(.Recording, .initMany(&.{ .Recording, .Pending })) catch return VkError.ValidationFailed;
}
try self.dispatch_table.begin(self, info);
self.begin_info = info.*;
}
pub inline fn end(self: *Self) VkError!void {
self.transitionState(.Executable, .initOne(.Recording)) catch return VkError.ValidationFailed;
try self.dispatch_table.end(self);
}
pub inline fn reset(self: *Self, flags: vk.CommandBufferResetFlags) VkError!void {
if (!self.pool.flags.reset_command_buffer_bit) {
return VkError.ValidationFailed;
}
self.transitionStateNotAllowed(.Initial, .initOne(.Pending)) catch return VkError.ValidationFailed;
try self.dispatch_table.reset(self, flags);
}
pub inline fn submit(self: *Self) VkError!void {
self.transitionState(.Initial, .initMany(&.{ .Pending, .Executable })) catch return VkError.ValidationFailed;
if (self.begin_info) |begin_info| {
if (!begin_info.flags.simultaneous_use_bit) {
self.transitionStateNotAllowed(.Initial, .initOne(.Pending)) catch return VkError.ValidationFailed;
}
}
}

View File

@@ -39,11 +39,11 @@ pub fn Dispatchable(comptime T: type) type {
pub inline fn fromHandle(vk_handle: anytype) VkError!*Self {
const handle = @intFromEnum(vk_handle);
if (handle == 0) {
return VkError.Unknown;
return VkError.ValidationFailed;
}
const dispatchable: *Self = @ptrFromInt(handle);
if (dispatchable.object_type != T.ObjectType) {
return VkError.Unknown;
return VkError.ValidationFailed;
}
return dispatchable;
}

View File

@@ -34,11 +34,11 @@ pub fn NonDispatchable(comptime T: type) type {
pub inline fn fromHandle(vk_handle: anytype) VkError!*Self {
const handle = @intFromEnum(vk_handle);
if (handle == 0) {
return VkError.Unknown;
return VkError.ValidationFailed;
}
const non_dispatchable: *Self = @ptrFromInt(handle);
if (non_dispatchable.object_type != T.ObjectType) {
return VkError.Unknown;
return VkError.ValidationFailed;
}
return non_dispatchable;
}

View File

@@ -2,7 +2,9 @@ const std = @import("std");
const vk = @import("vulkan");
const VkError = @import("error_set.zig").VkError;
const CommandBuffer = @import("CommandBuffer.zig");
const Device = @import("Device.zig");
const Dispatchable = @import("Dispatchable.zig").Dispatchable;
const Fence = @import("Fence.zig");
const Self = @This();
@@ -39,6 +41,14 @@ pub inline fn bindSparse(self: *Self, info: []const vk.BindSparseInfo, fence: ?*
pub inline fn submit(self: *Self, info: []const vk.SubmitInfo, fence: ?*Fence) VkError!void {
try self.dispatch_table.submit(self, info, fence);
for (info) |submit_info| {
if (submit_info.p_command_buffers) |p_command_buffers| {
for (p_command_buffers[0..submit_info.command_buffer_count]) |p_cmd| {
const cmd = try Dispatchable(CommandBuffer).fromHandleObject(p_cmd);
try cmd.submit();
}
}
}
}
pub inline fn waitIdle(self: *Self) VkError!void {

View File

@@ -21,9 +21,6 @@ pub const Fence = @import("Fence.zig");
pub const VULKAN_VENDOR_ID = @typeInfo(vk.VendorId).@"enum".fields[@typeInfo(vk.VendorId).@"enum".fields.len - 1].value + 1;
pub const DRIVER_NAME = "VulkanBase";
pub const VULKAN_VERSION = vk.makeApiVersion(0, 1, 0, 0);
pub const DRIVER_LOGS_ENV_NAME = "STROLL_LOGS_LEVEL";
pub const DRIVER_DEBUG_ALLOCATOR_ENV_NAME = "STROLL_DEBUG_ALLOCATOR";

View File

@@ -89,6 +89,7 @@ const device_pfn_map = std.StaticStringMap(vk.PfnVoidFunction).initComptime(.{
functionMapEntryPoint("vkGetFenceStatus"),
functionMapEntryPoint("vkMapMemory"),
functionMapEntryPoint("vkUnmapMemory"),
functionMapEntryPoint("vkResetCommandBuffer"),
functionMapEntryPoint("vkResetFences"),
functionMapEntryPoint("vkQueueBindSparse"),
functionMapEntryPoint("vkQueueSubmit"),
@@ -495,3 +496,9 @@ pub export fn strollEndCommandBuffer(p_cmd: vk.CommandBuffer) callconv(vk.vulkan
cmd.end() catch |err| return toVkResult(err);
return .success;
}
pub export fn strollResetCommandBuffer(p_cmd: vk.CommandBuffer, flags: vk.CommandBufferResetFlags) callconv(vk.vulkan_call_conv) vk.Result {
const cmd = Dispatchable(CommandBuffer).fromHandleObject(p_cmd) catch |err| return toVkResult(err);
cmd.reset(flags) catch |err| return toVkResult(err);
return .success;
}

View File

@@ -20,15 +20,6 @@
#define KVF_NO_KHR
#include <kvf.h>
#define CheckVk(x) \
do { \
if((x) != VK_SUCCESS) \
{ \
fprintf(stderr, "Vulkan call failed %d\n", (x)); \
abort(); \
} \
} while(0)
int main(void)
{
volkInitialize();
@@ -65,10 +56,12 @@ int main(void)
VkFence fence = kvfCreateFence(device);
VkCommandBuffer cmd = kvfCreateCommandBuffer(device);
kvfBeginCommandBuffer(cmd, 0);
kvfEndCommandBuffer(cmd);
kvfSubmitCommandBuffer(device, cmd, KVF_GRAPHICS_QUEUE, VK_NULL_HANDLE, VK_NULL_HANDLE, fence, NULL);
kvfCheckVk(vkResetCommandBuffer(cmd, 0));
kvfWaitForFence(device, fence);
kvfDestroyFence(device, fence);