const IndexBuffer = @This(); const std = @import("std"); const vk = @import("vulkan"); const Engine = @import("Engine.zig"); const StagingBuffer = @import("StagingBuffer.zig"); const QSM = @import("QueueSharingMode.zig"); buffer: vk.Buffer, memory: vk.DeviceMemory, index_count: usize, pub fn init(engine: *Engine, index_count: usize) !IndexBuffer { const size = std.math.mul(usize, index_count, @sizeOf(u16)) catch return error.OutOfMemory; const qsm = QSM.resolve(engine.graphics_queue.allocation.family, engine.transfer_queue.allocation.family); const buffer = try engine.device.createBuffer(&.{ .size = size, .usage = .{ .transfer_dst_bit = true, .index_buffer_bit = true, }, .sharing_mode = qsm.sharing_mode, .queue_family_index_count = qsm.queue_family_index_count, .p_queue_family_indices = qsm.p_queue_family_indices, }, &engine.vk_allocator.interface); errdefer engine.device.destroyBuffer(buffer); const memory_requirements = engine.device.getBufferMemoryRequirements(buffer); const memory = try engine.allocate(memory_requirements, .{ .device_local_bit = true }); errdefer engine.device.freeMemory(memory, &engine.vk_allocator.interface); try engine.device.bindBufferMemory(buffer, memory, 0); return .{ .buffer = buffer, .memory = memory, .index_count = index_count, }; } pub fn deinit(self: *IndexBuffer, engine: *Engine) void { engine.device.freeMemory(self.memory, &engine.vk_allocator.interface); engine.device.destroyBuffer(self.buffer); self.* = undefined; } pub fn write(self: IndexBuffer, engine: *Engine, indices: []const u16) !void { std.debug.assert(indices.len == self.index_count); const fence = try engine.device.createFence(.{}, &engine.vk_allocator.interface); defer engine.device.destroyFence(fence, &engine.vk_allocator.interface); const size = std.mem.sliceAsBytes(indices).len; const staging_buffer: StagingBuffer = .init(engine, std.mem.sliceAsBytes(indices), engine.graphics_queue.allocation.family); defer staging_buffer.deinit(engine); const command_buffer = try engine.allocateTransferCommandBuffer(); defer engine.freeTransferCommandBuffer(command_buffer); try command_buffer.beginCommandBuffer(&.{ .flags = .{ .one_time_submit_bit = true } }); const regions = [_]vk.BufferCopy{ .{ .src_offset = 0, .dst_offset = 0, .size = size, }, }; command_buffer.copyBuffer( staging_buffer.buffer, self.buffer, regions.len, ®ions, ); try command_buffer.endCommandBuffer(); try engine.submitTransferCommandBuffer(command_buffer, fence); _ = try engine.device.waitForFences(1, @ptrCast(&fence), .true, std.math.maxInt(u64)); }