Update to zig 0.16.0, update deps, Vulkan validation fixes

This commit is contained in:
2026-05-13 00:43:49 +02:00
parent 39712e359d
commit 79c62141df
16 changed files with 204 additions and 137 deletions

View File

@@ -36,9 +36,9 @@ pub const Atom = enum(u16) {
/// Turn a string into an atom. Returns either an existing atom or makes a
/// new one, if necessary. This will always produce a valid atom. Will not
/// return any error if the atom already exists.
pub fn fromString(string: []const u8) error{ OutOfMemory, OutOfAtoms }!Atom {
mutex.lock();
defer mutex.unlock();
pub fn fromString(string: []const u8, io: std.Io) error{ Canceled, OutOfMemory, OutOfAtoms }!Atom {
try mutex.lock(io);
defer mutex.unlock(io);
std.debug.assert(initialized);
@@ -66,9 +66,9 @@ pub const Atom = enum(u16) {
/// Turn a string into an atom, if the string has been already registered as
/// an atom. Returns `null` otherwise. This will always produce a valid
/// atom.
pub fn fromStringIfExists(string: []const u8) ?Atom {
mutex.lock();
defer mutex.unlock();
pub fn fromStringIfExists(string: []const u8, io: std.Io) error{Canceled}!?Atom {
try mutex.lock(io);
defer mutex.unlock(io);
std.debug.assert(initialized);
@@ -81,9 +81,9 @@ pub const Atom = enum(u16) {
}
/// Cast an atom into a string. The caller asserts that the atom is valid.
pub fn toString(self: Atom) [:0]const u8 {
try mutex.lock();
defer mutex.unlock();
pub fn toString(self: Atom, io: std.Io) error{Canceled}![:0]const u8 {
try mutex.lock(io);
defer mutex.unlock(io);
std.debug.assert(initialized);
@@ -110,11 +110,11 @@ var map: std.StringHashMapUnmanaged(Atom) = undefined;
var array: std.ArrayList([:0]const u8) = undefined;
/// Protects all reads and writes to `map` and `array`.
var mutex: std.Thread.Mutex = .{};
var mutex: std.Io.Mutex = .init;
pub fn init(_allocator: std.mem.Allocator) !void {
mutex.lock();
defer mutex.unlock();
pub fn init(_allocator: std.mem.Allocator, io: std.Io) !void {
try mutex.lock(io);
defer mutex.unlock(io);
std.debug.assert(!initialized);
@@ -129,9 +129,9 @@ pub fn init(_allocator: std.mem.Allocator) !void {
try array.append(allocator, "");
}
pub fn deinit() void {
mutex.lock();
defer mutex.unlock();
pub fn deinit(io: std.Io) void {
mutex.lockUncancelable(io);
defer mutex.unlock(io);
std.log.scoped(.deinit).debug("Deinitializing atoms", .{});
std.debug.assert(initialized);
@@ -149,9 +149,9 @@ pub fn deinit() void {
/// Dump all atoms in a readable format. Use for debugging. Does not flush the
/// writer.
pub fn dump(writer: std.Io.Writer) !void {
mutex.lock();
defer mutex.unlock();
pub fn dump(writer: std.Io.Writer, io: std.Io) void {
mutex.lockUncancelable(io);
defer mutex.unlock(io);
std.debug.assert(initialized);

View File

@@ -120,10 +120,8 @@ pub fn bindDescriptorSets(
pipeline_bind_point,
layout,
first_set,
@intCast(descriptor_sets.len),
descriptor_sets.ptr,
@intCast(dynamic_offsets.len),
dynamic_offsets.ptr,
descriptor_sets,
dynamic_offsets,
);
}
@@ -146,9 +144,8 @@ pub fn bindVertexBuffers(self: CommandBuffer, first_binding: u32, bindings: []co
self.proxy.bindVertexBuffers(
first_binding,
@intCast(vertex_buffer_bindings.len),
vertex_buffer_bindings.items(.buffer).ptr,
vertex_buffer_bindings.items(.offset).ptr,
vertex_buffer_bindings.items(.buffer),
vertex_buffer_bindings.items(.offset),
);
}
@@ -176,7 +173,7 @@ pub fn copyBuffer(
dst_buffer: vk.Buffer,
regions: []const vk.BufferCopy,
) void {
self.proxy.copyBuffer(src_buffer, dst_buffer, @intCast(regions.len), regions.ptr);
self.proxy.copyBuffer(src_buffer, dst_buffer, regions);
}
pub fn copyBufferToImage(
@@ -186,7 +183,7 @@ pub fn copyBufferToImage(
dst_image_layout: vk.ImageLayout,
regions: []const vk.BufferImageCopy,
) void {
self.proxy.copyBufferToImage(src_buffer, dst_image, dst_image_layout, @intCast(regions.len), regions.ptr);
self.proxy.copyBufferToImage(src_buffer, dst_image, dst_image_layout, regions);
}
pub fn pipelineBarrier(self: CommandBuffer, barrier: PipelineBarrier) void {
@@ -194,19 +191,16 @@ pub fn pipelineBarrier(self: CommandBuffer, barrier: PipelineBarrier) void {
barrier.src_stage_mask,
barrier.dst_stage_mask,
barrier.dependency_flags,
@intCast(barrier.memory_barriers.len),
barrier.memory_barriers.ptr,
@intCast(barrier.buffer_memory_barriers.len),
barrier.buffer_memory_barriers.ptr,
@intCast(barrier.image_memory_barriers.len),
barrier.image_memory_barriers.ptr,
barrier.memory_barriers,
barrier.buffer_memory_barriers,
barrier.image_memory_barriers,
);
}
pub fn setScissor(self: CommandBuffer, first_scissor: u32, scissors: []const vk.Rect2D) void {
self.proxy.setScissor(first_scissor, @intCast(scissors.len), scissors.ptr);
self.proxy.setScissor(first_scissor, scissors);
}
pub fn setViewport(self: CommandBuffer, first_viewport: u32, viewports: []const vk.Viewport) void {
self.proxy.setViewport(first_viewport, @intCast(viewports.len), viewports.ptr);
self.proxy.setViewport(first_viewport, viewports);
}

View File

@@ -131,8 +131,8 @@ const vk_version: vk.Version = vk.makeApiVersion(
c.app_version.patch,
);
pub fn init(allocator: std.mem.Allocator, maybe_window: ?*glfw.Window) !Engine {
const vk_allocator = try VkAllocator.init(allocator);
pub fn init(allocator: std.mem.Allocator, io: std.Io, maybe_window: ?*glfw.Window) !Engine {
const vk_allocator = try VkAllocator.init(allocator, io);
errdefer vk_allocator.deinit();
// --- LOAD BASE DISPATCH --------------------------------------------------
@@ -381,8 +381,8 @@ pub fn init(allocator: std.mem.Allocator, maybe_window: ?*glfw.Window) !Engine {
const prng_ptr = try allocator.create(std.Random.Pcg);
errdefer allocator.destroy(prng_ptr);
const timestamp: u128 = @bitCast(std.time.nanoTimestamp());
prng_ptr.* = .init(@truncate(timestamp));
const timestamp: u64 = @bitCast(@as(i64, @truncate(std.Io.Timestamp.now(io, .awake).nanoseconds)));
prng_ptr.* = .init(timestamp);
const random = prng_ptr.random();
// -------------------------------------------------------------------------
@@ -562,7 +562,7 @@ pub fn queueSubmit(
},
};
try self.device.queueSubmit(queue, submits.len, &submits, submit_info.fence);
try self.device.queueSubmit(queue, &submits, submit_info.fence);
}
pub const PresentInfo = struct {
@@ -1152,7 +1152,7 @@ pub fn createGraphicsPipeline(self: *Engine, create_info: GraphicsPipelineCreate
};
var pipelines: [1]vk.Pipeline = undefined;
_ = try self.device.createGraphicsPipelines(.null_handle, graphics_pipeline_create_infos.len, &graphics_pipeline_create_infos, &self.vk_allocator.interface, &pipelines);
_ = try self.device.createGraphicsPipelines(.null_handle, &graphics_pipeline_create_infos, &self.vk_allocator.interface, &pipelines);
return pipelines[0];
}
@@ -1357,12 +1357,12 @@ pub fn deviceWaitIdle(self: *Engine) !void {
pub fn freeCommandBuffer(self: *Engine, free_info: CommandBufferFreeInfo) void {
const command_pool = self.resolveCommandPool(free_info.queue_type);
const command_buffers = [_]vk.CommandBuffer{free_info.command_buffer};
self.device.freeCommandBuffers(command_pool, command_buffers.len, &command_buffers);
self.device.freeCommandBuffers(command_pool, &command_buffers);
}
pub fn freeDescriptorSet(self: *Engine, descriptor_pool: vk.DescriptorPool, descriptor_set: vk.DescriptorSet) void {
const descriptor_sets = [_]vk.DescriptorSet{descriptor_set};
self.device.freeDescriptorSets(descriptor_pool, descriptor_sets.len, &descriptor_sets) catch unreachable;
self.device.freeDescriptorSets(descriptor_pool, &descriptor_sets) catch unreachable;
}
pub fn freeMemory(self: *Engine, device_memory: vk.DeviceMemory) void {
@@ -1398,7 +1398,8 @@ pub fn mapMemory(self: *Engine, memory: vk.DeviceMemory, offset: vk.DeviceSize,
}
pub fn resetFence(self: *Engine, fence: vk.Fence) !void {
try self.device.resetFences(1, @ptrCast(&fence));
const fences = [_]vk.Fence{fence};
try self.device.resetFences(&fences);
}
pub fn unmapMemory(self: *Engine, memory: vk.DeviceMemory) void {
@@ -1446,14 +1447,10 @@ pub fn updateDescriptorSets(self: *Engine, update_info: DescriptorSetsUpdateInfo
};
}
self.device.updateDescriptorSets(
@intCast(descriptor_writes.len),
descriptor_writes.ptr,
@intCast(update_info.copies.len),
update_info.copies.ptr,
);
self.device.updateDescriptorSets(descriptor_writes, update_info.copies);
}
pub fn waitForFence(self: *Engine, fence: vk.Fence) !void {
_ = try self.device.waitForFences(1, @ptrCast(&fence), .true, 1 * std.time.ns_per_s);
const fences = [_]vk.Fence{fence};
_ = try self.device.waitForFences(&fences, .true, 1 * std.time.ns_per_s);
}

View File

@@ -25,17 +25,26 @@ descriptor_set: vk.DescriptorSet,
pipeline_layout: vk.PipelineLayout,
pipeline: vk.Pipeline,
pub fn load(filename: []const u8, engine: *Engine, stbi: *media.stbi, cube_size: u32, global_uniforms_buffer: vk.Buffer, render_pass: vk.RenderPass, temp_allocator: std.mem.Allocator) !Skybox {
pub fn load(
filename: []const u8,
engine: *Engine,
stbi: *media.stbi,
cube_size: u32,
global_uniforms_buffer: vk.Buffer,
render_pass: vk.RenderPass,
temp_allocator: std.mem.Allocator,
io: std.Io,
) !Skybox {
std.log.debug("Loading skybox \"{s}\"...", .{filename});
// --- LOAD IMAGE FROM MEMORY ----------------------------------------------
const cwd = std.fs.cwd();
const cwd = std.Io.Dir.cwd();
var dir = try cwd.openDir("assets", .{});
defer dir.close();
var dir = try cwd.openDir(io, "assets", .{});
defer dir.close(io);
const file_buf = try dir.readFileAlloc(temp_allocator, filename, std.math.maxInt(usize));
const file_buf = try dir.readFileAlloc(io, filename, temp_allocator, .unlimited);
defer temp_allocator.free(file_buf);
const img = try stbi.loadHdrBuf(file_buf);
@@ -169,7 +178,7 @@ pub fn load(filename: []const u8, engine: *Engine, stbi: *media.stbi, cube_size:
// --- TRANSITION TO SHADER_READ_ONLY_OPTIMAL ------------------------------
var transition1_command_buffer = try CommandBuffer.init(engine, .graphics);
var transition1_command_buffer = try CommandBuffer.init(engine, .compute);
defer transition1_command_buffer.deinit(engine);
try transition1_command_buffer.beginCommandBuffer();
@@ -304,7 +313,7 @@ pub fn load(filename: []const u8, engine: *Engine, stbi: *media.stbi, cube_size:
defer engine.destroyShaderModule(compute_shader);
var compute_pipeline: vk.Pipeline = undefined;
_ = try engine.device.createComputePipelines(.null_handle, 1, &.{
_ = try engine.device.createComputePipelines(.null_handle, &.{
.{
.stage = .{
.stage = .{ .compute_bit = true },

View File

@@ -85,6 +85,9 @@ pub fn init(engine: *Engine) !Swapchain {
.color_attachment_write_bit = true,
.depth_stencil_attachment_write_bit = true,
},
.dependency_flags = .{
.by_region_bit = true,
},
},
},
});

View File

@@ -5,8 +5,9 @@ const vk = @import("vulkan");
allocator: std.mem.Allocator,
allocations: std.AutoHashMapUnmanaged(*anyopaque, usize) = .empty,
mutex: std.Thread.Mutex = .{},
mutex: std.Io.Mutex = .init,
allocated_bytes: usize = 0,
io: std.Io,
interface: vk.AllocationCallbacks,
@@ -18,7 +19,7 @@ const actual_alignment: std.mem.Alignment = .@"16";
const log = std.log.scoped(.vk_allocator);
pub fn init(allocator: std.mem.Allocator) !*VkAllocator {
pub fn init(allocator: std.mem.Allocator, io: std.Io) !*VkAllocator {
// NOTE We allocate the structure to pin its address.
const self = try allocator.create(VkAllocator);
@@ -30,6 +31,7 @@ pub fn init(allocator: std.mem.Allocator) !*VkAllocator {
.pfn_reallocation = &reallocationFunction,
.pfn_free = &freeFunction,
},
.io = io,
};
return self;
}
@@ -69,8 +71,8 @@ fn allocationFunction(
const desired_alignment = std.mem.Alignment.fromByteUnits(alignment);
std.debug.assert(std.mem.Alignment.compare(actual_alignment, .gte, desired_alignment));
self.mutex.lock();
defer self.mutex.unlock();
self.mutex.lock(self.io) catch return null;
defer self.mutex.unlock(self.io);
self.allocations.ensureUnusedCapacity(self.allocator, 1) catch return null;
const memory = self.allocator.alignedAlloc(u8, actual_alignment, size) catch return null;
@@ -94,8 +96,8 @@ fn reallocationFunction(
const desired_alignment = std.mem.Alignment.fromByteUnits(alignment);
std.debug.assert(std.mem.Alignment.compare(actual_alignment, .gte, desired_alignment));
self.mutex.lock();
defer self.mutex.unlock();
self.mutex.lock(self.io) catch return null;
defer self.mutex.unlock(self.io);
// NOTE If we were pedantic, we would consider the fact that we might not
// need unused capacity if the memory doesn't get relocated.
@@ -130,8 +132,8 @@ fn freeFunction(
const self: *VkAllocator = @ptrCast(@alignCast(p_user_data.?));
if (maybe_p_memory) |p_memory| {
self.mutex.lock();
defer self.mutex.unlock();
self.mutex.lockUncancelable();
defer self.mutex.unlock(self.io);
const size = self.allocations.fetchRemove(p_memory).?.value;
self.allocated_bytes -= size;