55523c50
Fix renderer merge blockers
a73x 2026-04-08 15:29
diff --git a/src/renderer.zig b/src/renderer.zig index 12003ef..682b8be 100644 --- a/src/renderer.zig +++ b/src/renderer.zig @@ -91,6 +91,7 @@ fn createSwapchain( device: vk.Device, width: u32, height: u32, old_swapchain: vk.SwapchainKHR, ) !SwapchainResult { const caps = try vki.getPhysicalDeviceSurfaceCapabilitiesKHR(pd_info.physical, surface); @@ -154,6 +155,7 @@ fn createSwapchain( .composite_alpha = .{ .opaque_bit_khr = true }, .present_mode = present_mode, .clipped = .true, .old_swapchain = old_swapchain, }, null); var sc_count: u32 = 0; @@ -303,6 +305,14 @@ fn findMemoryType( return error.NoSuitableMemoryType; } fn nextInstanceCapacity(current: u32, needed: u32) u32 { var capacity = @max(current, 1); while (capacity < needed) { capacity = std.math.mul(u32, capacity, 2) catch return needed; } return capacity; } pub const Context = struct { alloc: std.mem.Allocator, vkb: vk.BaseWrapper, @@ -433,7 +443,7 @@ pub const Context = struct { const present_queue = vkd.getDeviceQueue(device, pd_info.present_queue_family, 0); // Create swapchain const sc = try createSwapchain(alloc, vki, vkd, pd_info, surface, device, width, height); const sc = try createSwapchain(alloc, vki, vkd, pd_info, surface, device, width, height, .null_handle); errdefer { for (sc.image_views) |view| vkd.destroyImageView(device, view, null); alloc.free(sc.image_views); @@ -898,8 +908,6 @@ pub const Context = struct { } pub fn recreateSwapchain(self: *Context, width: u32, height: u32) !void { self.destroySwapchainResources(); const sc = try createSwapchain( self.alloc, self.vki, @@ -913,6 +921,7 @@ pub const Context = struct { self.device, width, height, self.swapchain, ); errdefer { for (sc.image_views) |view| self.vkd.destroyImageView(self.device, view, null); @@ -934,12 +943,50 @@ pub const Context = struct { self.alloc.free(framebuffers); } const old_swapchain = self.swapchain; const old_images = self.swapchain_images; const old_image_views = self.swapchain_image_views; const old_framebuffers = self.framebuffers; self.swapchain = sc.swapchain; self.swapchain_format = sc.format; self.swapchain_extent = sc.extent; self.swapchain_images = sc.images; self.swapchain_image_views = sc.image_views; self.framebuffers = framebuffers; for (old_framebuffers) |fb| self.vkd.destroyFramebuffer(self.device, fb, null); self.alloc.free(old_framebuffers); for (old_image_views) |view| self.vkd.destroyImageView(self.device, view, null); self.alloc.free(old_image_views); self.alloc.free(old_images); self.vkd.destroySwapchainKHR(self.device, old_swapchain, null); } fn ensureInstanceCapacity(self: *Context, needed: u32) !void { if (needed <= self.instance_capacity) return; const new_capacity = nextInstanceCapacity(self.instance_capacity, needed); const replacement = try createHostVisibleBuffer( self.vki, self.physical_device, self.vkd, self.device, @as(vk.DeviceSize, @sizeOf(Instance)) * new_capacity, .{ .vertex_buffer_bit = true }, ); errdefer { self.vkd.destroyBuffer(self.device, replacement.buffer, null); self.vkd.freeMemory(self.device, replacement.memory, null); } _ = try self.vkd.deviceWaitIdle(self.device); self.vkd.destroyBuffer(self.device, self.instance_buffer, null); self.vkd.freeMemory(self.device, self.instance_memory, null); self.instance_buffer = replacement.buffer; self.instance_memory = replacement.memory; self.instance_capacity = new_capacity; } /// Record a command buffer that begins the render pass with the given clear color and presents. @@ -1127,7 +1174,7 @@ pub const Context = struct { /// Map the instance buffer, copy instances in, unmap. pub fn uploadInstances(self: *Context, instances: []const Instance) !void { if (instances.len > self.instance_capacity) return error.TooManyInstances; try self.ensureInstanceCapacity(@intCast(instances.len)); const size: vk.DeviceSize = @sizeOf(Instance) * instances.len; const mapped = try self.vkd.mapMemory(self.device, self.instance_memory, 0, size, .{}); @memcpy(@as([*]Instance, @ptrCast(@alignCast(mapped)))[0..instances.len], instances); @@ -1135,7 +1182,12 @@ pub const Context = struct { } /// Full draw pass: bind pipeline, push constants, vertex + instance buffers, draw, present. pub fn drawCells(self: *Context, instance_count: u32, cell_size: [2]f32) !void { pub fn drawCells( self: *Context, instance_count: u32, cell_size: [2]f32, clear_color: [4]f32, ) !void { // Wait for previous frame to finish _ = try self.vkd.waitForFences(self.device, 1, @ptrCast(&self.in_flight_fence), .true, std.math.maxInt(u64)); try self.vkd.resetFences(self.device, 1, @ptrCast(&self.in_flight_fence)); @@ -1156,9 +1208,7 @@ pub const Context = struct { .flags = .{ .one_time_submit_bit = true }, }); const clear_value = vk.ClearValue{ .color = .{ .float_32 = .{ 0.08, 0.08, 0.08, 1.0 } }, }; const clear_value = vk.ClearValue{ .color = .{ .float_32 = clear_color } }; self.vkd.cmdBeginRenderPass(self.command_buffer, &vk.RenderPassBeginInfo{ .render_pass = self.render_pass, @@ -1264,3 +1314,9 @@ test "shaders are embedded with SPIR-V magic" { const magic2: u32 = std.mem.readInt(u32, cell_frag_spv[0..4], .little); try std.testing.expectEqual(@as(u32, 0x07230203), magic2); } test "nextInstanceCapacity grows geometrically" { try std.testing.expectEqual(@as(u32, 16_000), nextInstanceCapacity(16_000, 8_000)); try std.testing.expectEqual(@as(u32, 32_000), nextInstanceCapacity(16_000, 16_001)); try std.testing.expectEqual(@as(u32, 4), nextInstanceCapacity(1, 3)); }