Preallocate texture VRAM, move files around

This commit is contained in:
2026-05-22 23:38:16 +02:00
parent fd311b97e7
commit c971443b02
12 changed files with 237 additions and 85 deletions

View File

@@ -6,6 +6,7 @@ const ctx = @import("../AppContext.zig");
const glfw = @import("zglfw");
const vk = @import("vulkan");
const DeviceAllocation = @import("DeviceAllocation.zig");
const Queue = @import("Queue.zig");
const QueueType = @import("QueueType.zig").QueueType;
const VkAllocator = @import("VkAllocator.zig");
@@ -418,18 +419,46 @@ pub fn deinit(self: *Engine) void {
}
pub fn allocate(self: *const Engine, memory_requirements: vk.MemoryRequirements, memory_property_flags: vk.MemoryPropertyFlags) !vk.DeviceMemory {
for (self.memory_types.items, 0..) |memory_type, i| {
const is_type = memory_requirements.memory_type_bits & (@as(u32, 1) << @truncate(i)) != 0;
const has_flags = memory_type.property_flags.contains(memory_property_flags);
if (is_type and has_flags) {
return try self.device.allocateMemory(&.{
.allocation_size = memory_requirements.size,
.memory_type_index = @truncate(i),
}, ctx.vk_allocator.capture());
}
}
const memory_type_index = try self.findMemoryTypeIndex(memory_requirements.memory_type_bits, memory_property_flags);
return error.NoSuitableMemoryType;
return self.device.allocateMemory(&.{
.allocation_size = memory_requirements.size,
.memory_type_index = memory_type_index,
}, ctx.vk_allocator.capture());
}
/// Allocate `vk.DeviceMemory` suitable for image created by given
/// `create_info`, except the allocation is `size` bytes large.
pub fn allocateForImage(
self: *const Engine,
create_info: ImageCreateInfo,
plane_aspect: vk.ImageAspectFlags,
size: usize,
memory_property_flags: vk.MemoryPropertyFlags,
) !DeviceAllocation {
const create_info_vk = try create_info.toVk();
var memory_requirements2: vk.MemoryRequirements2 = .{
.memory_requirements = undefined,
};
self.device.getDeviceImageMemoryRequirements(&.{
.p_create_info = &create_info_vk,
.plane_aspect = plane_aspect,
}, &memory_requirements2);
const memory_requirements = memory_requirements2.memory_requirements;
const memory_type_index = try self.findMemoryTypeIndex(memory_requirements.memory_type_bits, memory_property_flags);
const device_memory = try self.device.allocateMemory(&.{
.allocation_size = size,
.memory_type_index = memory_type_index,
}, ctx.vk_allocator.capture());
return .{
.device_memory = device_memory,
.allocated = 0,
.capacity = size,
.memory_type_index = memory_type_index,
};
}
pub fn setObjectName(self: *const Engine, handle: anytype, comptime fmt: []const u8, args: anytype) void {
@@ -663,8 +692,16 @@ fn findPresentationQueueFamily(queue_families_properties: []const vk.QueueFamily
return null;
}
fn makeArena(self: *const Engine) std.heap.ArenaAllocator {
return .init(self.vk_allocator.allocator);
fn findMemoryTypeIndex(self: *const Engine, memory_type_bits: u32, memory_property_flags: vk.MemoryPropertyFlags) !u32 {
for (self.memory_types.items, 0..) |memory_type, i| {
const is_type = memory_type_bits & (@as(u32, 1) << @truncate(i)) != 0;
const has_flags = memory_type.property_flags.contains(memory_property_flags);
if (is_type and has_flags) {
return @truncate(i);
}
}
return error.NoSuitableMemoryType;
}
fn resolveCommandPool(self: *const Engine, queue_type: QueueType) vk.CommandPool {
@@ -769,6 +806,33 @@ pub const ImageCreateInfo = struct {
usage: vk.ImageUsageFlags,
queue_family_indices: []const u32 = &.{},
initial_layout: vk.ImageLayout,
pub fn toVk(self: ImageCreateInfo) !vk.ImageCreateInfo {
const allocator_frame = ctx.allocator_frame;
var queue_family_indices_set: std.AutoArrayHashMapUnmanaged(u32, void) = .{};
for (self.queue_family_indices) |queue_family_index| {
try queue_family_indices_set.put(allocator_frame, queue_family_index, {});
}
const queue_family_indices = queue_family_indices_set.keys();
return .{
.flags = self.flags,
.image_type = self.image_type,
.format = self.format,
.extent = self.extent,
.mip_levels = self.mip_levels,
.array_layers = self.array_layers,
.samples = self.samples,
.tiling = self.tiling,
.usage = self.usage,
.sharing_mode = if (queue_family_indices.len > 1) .concurrent else .exclusive,
.queue_family_index_count = if (queue_family_indices.len > 1) @intCast(queue_family_indices.len) else 0,
.p_queue_family_indices = if (queue_family_indices.len > 1) queue_family_indices.ptr else null,
.initial_layout = self.initial_layout,
};
}
};
pub const ImageViewCreateInfo = struct {
@@ -1110,31 +1174,8 @@ pub fn createGraphicsPipeline(self: *Engine, create_info: GraphicsPipelineCreate
}
pub fn createImage(self: *Engine, create_info: ImageCreateInfo) !vk.Image {
const allocator_frame = ctx.allocator_frame;
var queue_family_indices_set: std.AutoArrayHashMapUnmanaged(u32, void) = .{};
for (create_info.queue_family_indices) |queue_family_index| {
try queue_family_indices_set.put(allocator_frame, queue_family_index, {});
}
const queue_family_indices = queue_family_indices_set.keys();
const image = self.device.createImage(&.{
.flags = create_info.flags,
.image_type = create_info.image_type,
.format = create_info.format,
.extent = create_info.extent,
.mip_levels = create_info.mip_levels,
.array_layers = create_info.array_layers,
.samples = create_info.samples,
.tiling = create_info.tiling,
.usage = create_info.usage,
.sharing_mode = if (queue_family_indices.len > 1) .concurrent else .exclusive,
.queue_family_index_count = if (queue_family_indices.len > 1) @intCast(queue_family_indices.len) else 0,
.p_queue_family_indices = if (queue_family_indices.len > 1) queue_family_indices.ptr else null,
.initial_layout = create_info.initial_layout,
}, ctx.vk_allocator.capture());
return image;
const create_info_vk = try create_info.toVk();
return self.device.createImage(&create_info_vk, ctx.vk_allocator.capture());
}
pub fn createImageView(self: *Engine, create_info: ImageViewCreateInfo) !vk.ImageView {