adding command buffer pool logic
This commit is contained in:
@@ -2,9 +2,12 @@ const std = @import("std");
|
|||||||
const vk = @import("vulkan");
|
const vk = @import("vulkan");
|
||||||
const base = @import("base");
|
const base = @import("base");
|
||||||
|
|
||||||
|
const NonDispatchable = base.NonDispatchable;
|
||||||
const VkError = base.VkError;
|
const VkError = base.VkError;
|
||||||
const Device = base.Device;
|
const Device = base.Device;
|
||||||
|
|
||||||
|
const SoftCommandBuffer = @import("SoftCommandBuffer.zig");
|
||||||
|
|
||||||
const Self = @This();
|
const Self = @This();
|
||||||
pub const Interface = base.CommandPool;
|
pub const Interface = base.CommandPool;
|
||||||
|
|
||||||
@@ -28,10 +31,18 @@ pub fn create(device: *base.Device, allocator: std.mem.Allocator, info: *const v
|
|||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn allocateCommandBuffers(interface: *Interface, info: *const vk.CommandBufferAllocateInfo) VkError![]*base.CommandBuffer {
|
pub fn allocateCommandBuffers(interface: *Interface, info: *const vk.CommandBufferAllocateInfo) VkError!void {
|
||||||
_ = interface;
|
const allocator = interface.host_allocator.allocator();
|
||||||
_ = info;
|
|
||||||
return VkError.FeatureNotPresent;
|
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 {
|
pub fn destroy(interface: *Interface, allocator: std.mem.Allocator) void {
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ const cpuinfo = @import("cpuinfo");
|
|||||||
const SoftDevice = @import("SoftDevice.zig");
|
const SoftDevice = @import("SoftDevice.zig");
|
||||||
|
|
||||||
const VkError = base.VkError;
|
const VkError = base.VkError;
|
||||||
|
const VulkanAllocator = base.VulkanAllocator;
|
||||||
|
|
||||||
const Self = @This();
|
const Self = @This();
|
||||||
pub const Interface = base.PhysicalDevice;
|
pub const Interface = base.PhysicalDevice;
|
||||||
@@ -14,6 +15,8 @@ pub const Interface = base.PhysicalDevice;
|
|||||||
interface: Interface,
|
interface: Interface,
|
||||||
|
|
||||||
pub fn create(allocator: std.mem.Allocator, instance: *const base.Instance) VkError!*Self {
|
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;
|
const self = allocator.create(Self) catch return VkError.OutOfHostMemory;
|
||||||
errdefer allocator.destroy(self);
|
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;
|
interface.queue_family_props.appendSlice(allocator, queue_family_props[0..]) catch return VkError.OutOfHostMemory;
|
||||||
|
|
||||||
// TODO: use Pytorch's cpuinfo someday
|
// TODO: use Pytorch's cpuinfo someday
|
||||||
const info = cpuinfo.get(allocator) catch return VkError.InitializationFailed;
|
const info = cpuinfo.get(command_allocator) catch return VkError.InitializationFailed;
|
||||||
defer info.deinit(allocator);
|
defer info.deinit(command_allocator);
|
||||||
|
|
||||||
var writer = std.Io.Writer.fixed(interface.props.device_name[0 .. vk.MAX_PHYSICAL_DEVICE_NAME_SIZE - 1]);
|
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;
|
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 {
|
pub inline fn destroy(self: *Self, allocator: std.mem.Allocator) void {
|
||||||
|
std.debug.print("{any}\n", .{self});
|
||||||
self.vtable.destroy(self, allocator);
|
self.vtable.destroy(self, allocator);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,25 +3,32 @@ const vk = @import("vulkan");
|
|||||||
|
|
||||||
const VkError = @import("error_set.zig").VkError;
|
const VkError = @import("error_set.zig").VkError;
|
||||||
const VulkanAllocator = @import("VulkanAllocator.zig");
|
const VulkanAllocator = @import("VulkanAllocator.zig");
|
||||||
|
const NonDispatchable = @import("NonDispatchable.zig").NonDispatchable;
|
||||||
|
|
||||||
const CommandBuffer = @import("CommandBuffer.zig");
|
const CommandBuffer = @import("CommandBuffer.zig");
|
||||||
const Device = @import("Device.zig");
|
const Device = @import("Device.zig");
|
||||||
|
|
||||||
const Self = @This();
|
const Self = @This();
|
||||||
pub const ObjectType: vk.ObjectType = .command_pool;
|
pub const ObjectType: vk.ObjectType = .command_pool;
|
||||||
|
|
||||||
const BUFFER_POOL_BASE_CAPACITY = 64;
|
pub const BUFFER_POOL_BASE_CAPACITY = 64;
|
||||||
|
|
||||||
owner: *Device,
|
owner: *Device,
|
||||||
flags: vk.CommandPoolCreateFlags,
|
flags: vk.CommandPoolCreateFlags,
|
||||||
queue_family_index: u32,
|
queue_family_index: u32,
|
||||||
buffers: std.ArrayList(*CommandBuffer),
|
|
||||||
first_free_buffer_index: usize,
|
|
||||||
host_allocator: VulkanAllocator,
|
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,
|
vtable: *const VTable,
|
||||||
|
|
||||||
pub const VTable = struct {
|
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,
|
destroy: *const fn (*Self, std.mem.Allocator) void,
|
||||||
reset: *const fn (*Self, vk.CommandPoolResetFlags) VkError!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,
|
.owner = device,
|
||||||
.flags = info.flags,
|
.flags = info.flags,
|
||||||
.queue_family_index = info.queue_family_index,
|
.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(),
|
.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,
|
.first_free_buffer_index = 0,
|
||||||
.vtable = undefined,
|
.vtable = undefined,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub inline fn allocateCommandBuffers(self: *Self, info: *const vk.CommandBufferAllocateInfo) VkError![]*CommandBuffer {
|
pub fn allocateCommandBuffers(self: *Self, info: *const vk.CommandBufferAllocateInfo) VkError![]*NonDispatchable(CommandBuffer) {
|
||||||
return self.vtable.allocateCommandBuffers(self, info);
|
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 {
|
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.buffers.deinit(allocator);
|
||||||
self.vtable.destroy(self, allocator);
|
self.vtable.destroy(self, allocator);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ const std = @import("std");
|
|||||||
const vk = @import("vulkan");
|
const vk = @import("vulkan");
|
||||||
|
|
||||||
const Dispatchable = @import("Dispatchable.zig").Dispatchable;
|
const Dispatchable = @import("Dispatchable.zig").Dispatchable;
|
||||||
|
const NonDispatchable = @import("NonDispatchable.zig").NonDispatchable;
|
||||||
const VulkanAllocator = @import("VulkanAllocator.zig");
|
const VulkanAllocator = @import("VulkanAllocator.zig");
|
||||||
const VkError = @import("error_set.zig").VkError;
|
const VkError = @import("error_set.zig").VkError;
|
||||||
|
|
||||||
@@ -29,7 +30,7 @@ pub const VTable = struct {
|
|||||||
};
|
};
|
||||||
|
|
||||||
pub const DispatchTable = 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,
|
allocateMemory: *const fn (*Self, std.mem.Allocator, *const vk.MemoryAllocateInfo) VkError!*DeviceMemory,
|
||||||
createCommandPool: *const fn (*Self, std.mem.Allocator, *const vk.CommandPoolCreateInfo) VkError!*CommandPool,
|
createCommandPool: *const fn (*Self, std.mem.Allocator, *const vk.CommandPoolCreateInfo) VkError!*CommandPool,
|
||||||
createFence: *const fn (*Self, std.mem.Allocator, *const vk.FenceCreateInfo) VkError!*Fence,
|
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 ============================================================================================================================
|
// 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);
|
return self.dispatch_table.allocateCommandBuffers(self, info);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const builtin = @import("builtin");
|
const builtin = @import("builtin");
|
||||||
const vk = @import("vulkan");
|
const vk = @import("vulkan");
|
||||||
|
|
||||||
const VkError = @import("error_set.zig").VkError;
|
const VkError = @import("error_set.zig").VkError;
|
||||||
const Dispatchable = @import("Dispatchable.zig").Dispatchable;
|
const Dispatchable = @import("Dispatchable.zig").Dispatchable;
|
||||||
const PhysicalDevice = @import("PhysicalDevice.zig");
|
const PhysicalDevice = @import("PhysicalDevice.zig");
|
||||||
|
|||||||
@@ -36,16 +36,16 @@ pub fn NonDispatchable(comptime T: type) type {
|
|||||||
if (handle == 0) {
|
if (handle == 0) {
|
||||||
return VkError.Unknown;
|
return VkError.Unknown;
|
||||||
}
|
}
|
||||||
const nondispatchable: *Self = @ptrFromInt(handle);
|
const non_dispatchable: *Self = @ptrFromInt(handle);
|
||||||
if (nondispatchable.object_type != T.ObjectType) {
|
if (non_dispatchable.object_type != T.ObjectType) {
|
||||||
return VkError.Unknown;
|
return VkError.Unknown;
|
||||||
}
|
}
|
||||||
return nondispatchable;
|
return non_dispatchable;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub inline fn fromHandleObject(handle: anytype) VkError!*T {
|
pub inline fn fromHandleObject(handle: anytype) VkError!*T {
|
||||||
const nondispatchable_handle = try Self.fromHandle(handle);
|
const non_dispatchable_handle = try Self.fromHandle(handle);
|
||||||
return nondispatchable_handle.object;
|
return non_dispatchable_handle.object;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -290,12 +290,9 @@ pub export fn strollAllocateCommandBuffers(p_device: vk.Device, p_info: ?*const
|
|||||||
return .error_validation_failed;
|
return .error_validation_failed;
|
||||||
}
|
}
|
||||||
const device = Dispatchable(Device).fromHandleObject(p_device) catch |err| return toVkResult(err);
|
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);
|
const cmds = device.allocateCommandBuffers(info) catch |err| return toVkResult(err);
|
||||||
for (cmds[0..info.command_buffer_count], 0..) |cmd, i| {
|
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;
|
return .success;
|
||||||
}
|
}
|
||||||
@@ -336,6 +333,15 @@ pub export fn strollCreateFence(p_device: vk.Device, p_info: ?*const vk.FenceCre
|
|||||||
return .success;
|
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 {
|
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 allocator = VulkanAllocator.init(callbacks, .object).allocator();
|
||||||
const dispatchable = Dispatchable(Device).fromHandle(p_device) catch return;
|
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);
|
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 {
|
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 allocator = VulkanAllocator.init(callbacks, .object).allocator();
|
||||||
const device = Dispatchable(Device).fromHandleObject(p_device) catch return;
|
const device = Dispatchable(Device).fromHandleObject(p_device) catch return;
|
||||||
|
|||||||
Reference in New Issue
Block a user