const StagingBuffer = @This(); const std = @import("std"); const vk = @import("vulkan"); const Engine = @import("Engine.zig"); const TargetQueue = @import("TargetQueue.zig").TargetQueue; buffer: vk.Buffer, device_memory: vk.DeviceMemory, capacity: u32, pub const InitInfo = struct { target_queue: TargetQueue, capacity: u32, }; pub fn init(engine: *Engine, init_info: InitInfo) !StagingBuffer { const target_queue_family = switch (init_info.target_queue) { .graphics => engine.graphics_queue.allocation.family, .compute => engine.compute_queue.allocation.family, }; const transfer_queue_family = engine.transfer_queue.allocation.family; const buffer = try engine.createBuffer(.{ .size = init_info.capacity, .usage = .{ .transfer_src_bit = true, }, .queue_family_indices = &.{ target_queue_family, transfer_queue_family }, }); errdefer engine.destroyBuffer(buffer); const memory_requirements = engine.device.getBufferMemoryRequirements(buffer); const device_memory = try engine.allocate( memory_requirements, .{ .host_visible_bit = true, .host_coherent_bit = true, }, ); errdefer engine.freeMemory(device_memory); try engine.device.bindBufferMemory(buffer, device_memory, 0); return .{ .buffer = buffer, .device_memory = device_memory, .capacity = init_info.capacity, }; } pub fn deinit(self: *StagingBuffer, engine: *Engine) void { std.log.scoped(.deinit).debug("Deinitializing {*} with {*}", .{ self, engine }); engine.freeMemory(self.device_memory); engine.destroyBuffer(self.buffer); self.* = undefined; } pub fn map(self: StagingBuffer, engine: *Engine) ![]u8 { const mapped_memory = try self.mapPartial(engine, 0, self.capacity); return mapped_memory; } pub fn mapPartial(self: StagingBuffer, engine: *Engine, offset: u32, len: u32) ![]u8 { const mapped_memory = try engine.device.mapMemory(self.device_memory, offset, len, .{}); return @as([*]u8, @ptrCast(mapped_memory))[0..len]; } pub fn unmap(self: StagingBuffer, engine: *Engine) void { engine.device.unmapMemory(self.device_memory); }