adding command buffer pool logic
This commit is contained in:
@@ -2,9 +2,12 @@ const std = @import("std");
|
||||
const vk = @import("vulkan");
|
||||
const base = @import("base");
|
||||
|
||||
const NonDispatchable = base.NonDispatchable;
|
||||
const VkError = base.VkError;
|
||||
const Device = base.Device;
|
||||
|
||||
const SoftCommandBuffer = @import("SoftCommandBuffer.zig");
|
||||
|
||||
const Self = @This();
|
||||
pub const Interface = base.CommandPool;
|
||||
|
||||
@@ -28,10 +31,18 @@ pub fn create(device: *base.Device, allocator: std.mem.Allocator, info: *const v
|
||||
return self;
|
||||
}
|
||||
|
||||
pub fn allocateCommandBuffers(interface: *Interface, info: *const vk.CommandBufferAllocateInfo) VkError![]*base.CommandBuffer {
|
||||
_ = interface;
|
||||
_ = info;
|
||||
return VkError.FeatureNotPresent;
|
||||
pub fn allocateCommandBuffers(interface: *Interface, info: *const vk.CommandBufferAllocateInfo) VkError!void {
|
||||
const allocator = interface.host_allocator.allocator();
|
||||
|
||||
while (interface.buffers.capacity < interface.buffers.items.len + info.command_buffer_count) {
|
||||
interface.buffers.ensureUnusedCapacity(allocator, base.CommandPool.BUFFER_POOL_BASE_CAPACITY) catch return VkError.OutOfHostMemory;
|
||||
}
|
||||
|
||||
for (0..info.command_buffer_count) |_| {
|
||||
const cmd = try SoftCommandBuffer.create(interface.owner, allocator, info);
|
||||
const non_dis_cmd = try NonDispatchable(base.CommandBuffer).wrap(allocator, &cmd.interface);
|
||||
interface.buffers.appendAssumeCapacity(non_dis_cmd);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn destroy(interface: *Interface, allocator: std.mem.Allocator) void {
|
||||
|
||||
@@ -7,6 +7,7 @@ const cpuinfo = @import("cpuinfo");
|
||||
const SoftDevice = @import("SoftDevice.zig");
|
||||
|
||||
const VkError = base.VkError;
|
||||
const VulkanAllocator = base.VulkanAllocator;
|
||||
|
||||
const Self = @This();
|
||||
pub const Interface = base.PhysicalDevice;
|
||||
@@ -14,6 +15,8 @@ pub const Interface = base.PhysicalDevice;
|
||||
interface: Interface,
|
||||
|
||||
pub fn create(allocator: std.mem.Allocator, instance: *const base.Instance) VkError!*Self {
|
||||
const command_allocator = VulkanAllocator.from(allocator).cloneWithScope(.command).allocator();
|
||||
|
||||
const self = allocator.create(Self) catch return VkError.OutOfHostMemory;
|
||||
errdefer allocator.destroy(self);
|
||||
|
||||
@@ -81,8 +84,8 @@ pub fn create(allocator: std.mem.Allocator, instance: *const base.Instance) VkEr
|
||||
interface.queue_family_props.appendSlice(allocator, queue_family_props[0..]) catch return VkError.OutOfHostMemory;
|
||||
|
||||
// TODO: use Pytorch's cpuinfo someday
|
||||
const info = cpuinfo.get(allocator) catch return VkError.InitializationFailed;
|
||||
defer info.deinit(allocator);
|
||||
const info = cpuinfo.get(command_allocator) catch return VkError.InitializationFailed;
|
||||
defer info.deinit(command_allocator);
|
||||
|
||||
var writer = std.Io.Writer.fixed(interface.props.device_name[0 .. vk.MAX_PHYSICAL_DEVICE_NAME_SIZE - 1]);
|
||||
writer.print("{s} [" ++ root.DRIVER_NAME ++ " StrollDriver]", .{info.name}) catch return VkError.InitializationFailed;
|
||||
|
||||
@@ -25,5 +25,6 @@ pub fn init(device: *Device, allocator: std.mem.Allocator, info: *const vk.Comma
|
||||
}
|
||||
|
||||
pub inline fn destroy(self: *Self, allocator: std.mem.Allocator) void {
|
||||
std.debug.print("{any}\n", .{self});
|
||||
self.vtable.destroy(self, allocator);
|
||||
}
|
||||
|
||||
@@ -3,25 +3,32 @@ const vk = @import("vulkan");
|
||||
|
||||
const VkError = @import("error_set.zig").VkError;
|
||||
const VulkanAllocator = @import("VulkanAllocator.zig");
|
||||
const NonDispatchable = @import("NonDispatchable.zig").NonDispatchable;
|
||||
|
||||
const CommandBuffer = @import("CommandBuffer.zig");
|
||||
const Device = @import("Device.zig");
|
||||
|
||||
const Self = @This();
|
||||
pub const ObjectType: vk.ObjectType = .command_pool;
|
||||
|
||||
const BUFFER_POOL_BASE_CAPACITY = 64;
|
||||
pub const BUFFER_POOL_BASE_CAPACITY = 64;
|
||||
|
||||
owner: *Device,
|
||||
flags: vk.CommandPoolCreateFlags,
|
||||
queue_family_index: u32,
|
||||
buffers: std.ArrayList(*CommandBuffer),
|
||||
first_free_buffer_index: usize,
|
||||
host_allocator: VulkanAllocator,
|
||||
|
||||
/// Contiguous dynamic array of command buffers with free ones
|
||||
/// grouped at the end and the first free index being storesd in
|
||||
/// `first_free_buffer_index`
|
||||
/// When freed swaps happen to keep the free buffers at the end
|
||||
buffers: std.ArrayList(*NonDispatchable(CommandBuffer)),
|
||||
first_free_buffer_index: usize,
|
||||
|
||||
vtable: *const VTable,
|
||||
|
||||
pub const VTable = struct {
|
||||
allocateCommandBuffers: *const fn (*Self, *const vk.CommandBufferAllocateInfo) VkError![]*CommandBuffer,
|
||||
allocateCommandBuffers: *const fn (*Self, *const vk.CommandBufferAllocateInfo) VkError!void,
|
||||
destroy: *const fn (*Self, std.mem.Allocator) void,
|
||||
reset: *const fn (*Self, vk.CommandPoolResetFlags) VkError!void,
|
||||
};
|
||||
@@ -31,18 +38,29 @@ pub fn init(device: *Device, allocator: std.mem.Allocator, info: *const vk.Comma
|
||||
.owner = device,
|
||||
.flags = info.flags,
|
||||
.queue_family_index = info.queue_family_index,
|
||||
.buffers = std.ArrayList(*CommandBuffer).initCapacity(allocator, BUFFER_POOL_BASE_CAPACITY) catch return VkError.OutOfHostMemory,
|
||||
.host_allocator = VulkanAllocator.from(allocator).clone(),
|
||||
.buffers = std.ArrayList(*NonDispatchable(CommandBuffer)).initCapacity(allocator, BUFFER_POOL_BASE_CAPACITY) catch return VkError.OutOfHostMemory,
|
||||
.first_free_buffer_index = 0,
|
||||
.vtable = undefined,
|
||||
};
|
||||
}
|
||||
|
||||
pub inline fn allocateCommandBuffers(self: *Self, info: *const vk.CommandBufferAllocateInfo) VkError![]*CommandBuffer {
|
||||
return self.vtable.allocateCommandBuffers(self, info);
|
||||
pub fn allocateCommandBuffers(self: *Self, info: *const vk.CommandBufferAllocateInfo) VkError![]*NonDispatchable(CommandBuffer) {
|
||||
if (self.buffers.items.len < info.command_buffer_count or self.first_free_buffer_index + info.command_buffer_count > self.buffers.items.len) {
|
||||
try self.vtable.allocateCommandBuffers(self, info);
|
||||
}
|
||||
|
||||
const bound_up = self.first_free_buffer_index + info.command_buffer_count;
|
||||
const slice = self.buffers.items[self.first_free_buffer_index..bound_up];
|
||||
self.first_free_buffer_index += info.command_buffer_count;
|
||||
return slice;
|
||||
}
|
||||
|
||||
pub inline fn destroy(self: *Self, allocator: std.mem.Allocator) void {
|
||||
for (self.buffers.items) |non_dis_cmd| {
|
||||
non_dis_cmd.object.destroy(allocator);
|
||||
non_dis_cmd.destroy(allocator);
|
||||
}
|
||||
self.buffers.deinit(allocator);
|
||||
self.vtable.destroy(self, allocator);
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ const std = @import("std");
|
||||
const vk = @import("vulkan");
|
||||
|
||||
const Dispatchable = @import("Dispatchable.zig").Dispatchable;
|
||||
const NonDispatchable = @import("NonDispatchable.zig").NonDispatchable;
|
||||
const VulkanAllocator = @import("VulkanAllocator.zig");
|
||||
const VkError = @import("error_set.zig").VkError;
|
||||
|
||||
@@ -29,7 +30,7 @@ pub const VTable = struct {
|
||||
};
|
||||
|
||||
pub const DispatchTable = struct {
|
||||
allocateCommandBuffers: *const fn (*Self, *const vk.CommandBufferAllocateInfo) VkError![]*CommandBuffer,
|
||||
allocateCommandBuffers: *const fn (*Self, *const vk.CommandBufferAllocateInfo) VkError![]*NonDispatchable(CommandBuffer),
|
||||
allocateMemory: *const fn (*Self, std.mem.Allocator, *const vk.MemoryAllocateInfo) VkError!*DeviceMemory,
|
||||
createCommandPool: *const fn (*Self, std.mem.Allocator, *const vk.CommandPoolCreateInfo) VkError!*CommandPool,
|
||||
createFence: *const fn (*Self, std.mem.Allocator, *const vk.FenceCreateInfo) VkError!*Fence,
|
||||
@@ -112,7 +113,7 @@ pub inline fn waitForFences(self: *Self, fences: []*Fence, waitForAll: bool, tim
|
||||
|
||||
// Command Pool functions ============================================================================================================================
|
||||
|
||||
pub inline fn allocateCommandBuffers(self: *Self, info: *const vk.CommandBufferAllocateInfo) VkError![]*CommandBuffer {
|
||||
pub inline fn allocateCommandBuffers(self: *Self, info: *const vk.CommandBufferAllocateInfo) VkError![]*NonDispatchable(CommandBuffer) {
|
||||
return self.dispatch_table.allocateCommandBuffers(self, info);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
const std = @import("std");
|
||||
const builtin = @import("builtin");
|
||||
const vk = @import("vulkan");
|
||||
|
||||
const VkError = @import("error_set.zig").VkError;
|
||||
const Dispatchable = @import("Dispatchable.zig").Dispatchable;
|
||||
const PhysicalDevice = @import("PhysicalDevice.zig");
|
||||
|
||||
@@ -36,16 +36,16 @@ pub fn NonDispatchable(comptime T: type) type {
|
||||
if (handle == 0) {
|
||||
return VkError.Unknown;
|
||||
}
|
||||
const nondispatchable: *Self = @ptrFromInt(handle);
|
||||
if (nondispatchable.object_type != T.ObjectType) {
|
||||
const non_dispatchable: *Self = @ptrFromInt(handle);
|
||||
if (non_dispatchable.object_type != T.ObjectType) {
|
||||
return VkError.Unknown;
|
||||
}
|
||||
return nondispatchable;
|
||||
return non_dispatchable;
|
||||
}
|
||||
|
||||
pub inline fn fromHandleObject(handle: anytype) VkError!*T {
|
||||
const nondispatchable_handle = try Self.fromHandle(handle);
|
||||
return nondispatchable_handle.object;
|
||||
const non_dispatchable_handle = try Self.fromHandle(handle);
|
||||
return non_dispatchable_handle.object;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -290,12 +290,9 @@ pub export fn strollAllocateCommandBuffers(p_device: vk.Device, p_info: ?*const
|
||||
return .error_validation_failed;
|
||||
}
|
||||
const device = Dispatchable(Device).fromHandleObject(p_device) catch |err| return toVkResult(err);
|
||||
const pool = NonDispatchable(CommandPool).fromHandleObject(info.command_pool) catch |err| return toVkResult(err);
|
||||
const allocator = pool.host_allocator.allocator();
|
||||
|
||||
const cmds = device.allocateCommandBuffers(info) catch |err| return toVkResult(err);
|
||||
for (cmds[0..info.command_buffer_count], 0..) |cmd, i| {
|
||||
p_cmds[i] = (NonDispatchable(CommandBuffer).wrap(allocator, cmd) catch |err| return toVkResult(err)).toVkHandle(vk.CommandBuffer);
|
||||
p_cmds[i] = cmd.toVkHandle(vk.CommandBuffer);
|
||||
}
|
||||
return .success;
|
||||
}
|
||||
@@ -336,6 +333,15 @@ pub export fn strollCreateFence(p_device: vk.Device, p_info: ?*const vk.FenceCre
|
||||
return .success;
|
||||
}
|
||||
|
||||
pub export fn strollDestroyCommandPool(p_device: vk.Device, p_pool: vk.CommandPool, callbacks: ?*const vk.AllocationCallbacks) callconv(vk.vulkan_call_conv) void {
|
||||
const allocator = VulkanAllocator.init(callbacks, .object).allocator();
|
||||
const device = Dispatchable(Device).fromHandleObject(p_device) catch return;
|
||||
const non_dispatchable_pool = NonDispatchable(CommandPool).fromHandle(p_pool) catch return;
|
||||
|
||||
device.destroyCommandPool(allocator, non_dispatchable_pool.object) catch return;
|
||||
non_dispatchable_pool.destroy(allocator);
|
||||
}
|
||||
|
||||
pub export fn strollDestroyDevice(p_device: vk.Device, callbacks: ?*const vk.AllocationCallbacks) callconv(vk.vulkan_call_conv) void {
|
||||
const allocator = VulkanAllocator.init(callbacks, .object).allocator();
|
||||
const dispatchable = Dispatchable(Device).fromHandle(p_device) catch return;
|
||||
@@ -347,15 +353,6 @@ pub export fn strollDestroyDevice(p_device: vk.Device, callbacks: ?*const vk.All
|
||||
dispatchable.destroy(allocator);
|
||||
}
|
||||
|
||||
pub export fn strollDestroyCommandPool(p_device: vk.Device, p_pool: vk.CommandPool, callbacks: ?*const vk.AllocationCallbacks) callconv(vk.vulkan_call_conv) void {
|
||||
const allocator = VulkanAllocator.init(callbacks, .object).allocator();
|
||||
const device = Dispatchable(Device).fromHandleObject(p_device) catch return;
|
||||
const non_dispatchable_pool = NonDispatchable(CommandPool).fromHandle(p_pool) catch return;
|
||||
|
||||
device.destroyCommandPool(allocator, non_dispatchable_pool.object) catch return;
|
||||
non_dispatchable_pool.destroy(allocator);
|
||||
}
|
||||
|
||||
pub export fn strollDestroyFence(p_device: vk.Device, p_fence: vk.Fence, callbacks: ?*const vk.AllocationCallbacks) callconv(vk.vulkan_call_conv) void {
|
||||
const allocator = VulkanAllocator.init(callbacks, .object).allocator();
|
||||
const device = Dispatchable(Device).fromHandleObject(p_device) catch return;
|
||||
|
||||
Reference in New Issue
Block a user