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 = &.{ interface.dispatch_table = &.{
.begin = begin, .begin = begin,
.end = end, .end = end,
.reset = reset,
}; };
self.* = .{ self.* = .{
@@ -44,3 +45,8 @@ pub fn begin(interface: *Interface, info: *const vk.CommandBufferBeginInfo) VkEr
pub fn end(interface: *Interface) VkError!void { pub fn end(interface: *Interface) VkError!void {
_ = interface; _ = 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; pub const std_options = base.std_options;
comptime {
_ = base;
}
test { test {
std.testing.refAllDeclsRecursive(@This()); std.testing.refAllDeclsRecursive(@This());
} }

View File

@@ -2,12 +2,25 @@ const std = @import("std");
const vk = @import("vulkan"); const vk = @import("vulkan");
const VkError = @import("error_set.zig").VkError; const VkError = @import("error_set.zig").VkError;
const CommandPool = @import("CommandPool.zig");
const Device = @import("Device.zig"); const Device = @import("Device.zig");
const NonDispatchable = @import("NonDispatchable.zig").NonDispatchable;
const State = enum {
Initial,
Recording,
Executable,
Pending,
Invalid,
};
const Self = @This(); const Self = @This();
pub const ObjectType: vk.ObjectType = .command_buffer; pub const ObjectType: vk.ObjectType = .command_buffer;
owner: *Device, owner: *Device,
pool: *CommandPool,
state: State,
begin_info: ?vk.CommandBufferBeginInfo,
vtable: *const VTable, vtable: *const VTable,
dispatch_table: *const DispatchTable, dispatch_table: *const DispatchTable,
@@ -15,6 +28,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,
end: *const fn (*Self) VkError!void, end: *const fn (*Self) VkError!void,
reset: *const fn (*Self, vk.CommandBufferResetFlags) VkError!void,
}; };
pub const VTable = struct { 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 { pub fn init(device: *Device, allocator: std.mem.Allocator, info: *const vk.CommandBufferAllocateInfo) VkError!Self {
_ = allocator; _ = allocator;
_ = info;
return .{ return .{
.owner = device, .owner = device,
.pool = try NonDispatchable(CommandPool).fromHandleObject(info.command_pool),
.state = .Initial,
.begin_info = null,
.vtable = undefined, .vtable = undefined,
.dispatch_table = 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 { pub inline fn destroy(self: *Self, allocator: std.mem.Allocator) void {
self.vtable.destroy(self, allocator); self.vtable.destroy(self, allocator);
} }
pub inline fn begin(self: *Self, info: *const vk.CommandBufferBeginInfo) VkError!void { 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); try self.dispatch_table.begin(self, info);
self.begin_info = info.*;
} }
pub inline fn end(self: *Self) VkError!void { pub inline fn end(self: *Self) VkError!void {
self.transitionState(.Executable, .initOne(.Recording)) catch return VkError.ValidationFailed;
try self.dispatch_table.end(self); 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 { pub inline fn fromHandle(vk_handle: anytype) VkError!*Self {
const handle = @intFromEnum(vk_handle); const handle = @intFromEnum(vk_handle);
if (handle == 0) { if (handle == 0) {
return VkError.Unknown; return VkError.ValidationFailed;
} }
const dispatchable: *Self = @ptrFromInt(handle); const dispatchable: *Self = @ptrFromInt(handle);
if (dispatchable.object_type != T.ObjectType) { if (dispatchable.object_type != T.ObjectType) {
return VkError.Unknown; return VkError.ValidationFailed;
} }
return dispatchable; return dispatchable;
} }

View File

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

View File

@@ -2,7 +2,9 @@ const std = @import("std");
const vk = @import("vulkan"); const vk = @import("vulkan");
const VkError = @import("error_set.zig").VkError; const VkError = @import("error_set.zig").VkError;
const CommandBuffer = @import("CommandBuffer.zig");
const Device = @import("Device.zig"); const Device = @import("Device.zig");
const Dispatchable = @import("Dispatchable.zig").Dispatchable;
const Fence = @import("Fence.zig"); const Fence = @import("Fence.zig");
const Self = @This(); 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 { pub inline fn submit(self: *Self, info: []const vk.SubmitInfo, fence: ?*Fence) VkError!void {
try self.dispatch_table.submit(self, info, fence); 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 { 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 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_LOGS_ENV_NAME = "STROLL_LOGS_LEVEL";
pub const DRIVER_DEBUG_ALLOCATOR_ENV_NAME = "STROLL_DEBUG_ALLOCATOR"; 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("vkGetFenceStatus"),
functionMapEntryPoint("vkMapMemory"), functionMapEntryPoint("vkMapMemory"),
functionMapEntryPoint("vkUnmapMemory"), functionMapEntryPoint("vkUnmapMemory"),
functionMapEntryPoint("vkResetCommandBuffer"),
functionMapEntryPoint("vkResetFences"), functionMapEntryPoint("vkResetFences"),
functionMapEntryPoint("vkQueueBindSparse"), functionMapEntryPoint("vkQueueBindSparse"),
functionMapEntryPoint("vkQueueSubmit"), functionMapEntryPoint("vkQueueSubmit"),
@@ -495,3 +496,9 @@ pub export fn strollEndCommandBuffer(p_cmd: vk.CommandBuffer) callconv(vk.vulkan
cmd.end() catch |err| return toVkResult(err); cmd.end() catch |err| return toVkResult(err);
return .success; 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 #define KVF_NO_KHR
#include <kvf.h> #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) int main(void)
{ {
volkInitialize(); volkInitialize();
@@ -65,10 +56,12 @@ int main(void)
VkFence fence = kvfCreateFence(device); VkFence fence = kvfCreateFence(device);
VkCommandBuffer cmd = kvfCreateCommandBuffer(device); VkCommandBuffer cmd = kvfCreateCommandBuffer(device);
kvfBeginCommandBuffer(cmd, 0); kvfBeginCommandBuffer(cmd, 0);
kvfEndCommandBuffer(cmd); kvfEndCommandBuffer(cmd);
kvfSubmitCommandBuffer(device, cmd, KVF_GRAPHICS_QUEUE, VK_NULL_HANDLE, VK_NULL_HANDLE, fence, NULL); kvfSubmitCommandBuffer(device, cmd, KVF_GRAPHICS_QUEUE, VK_NULL_HANDLE, VK_NULL_HANDLE, fence, NULL);
kvfCheckVk(vkResetCommandBuffer(cmd, 0));
kvfWaitForFence(device, fence); kvfWaitForFence(device, fence);
kvfDestroyFence(device, fence); kvfDestroyFence(device, fence);