Actual deleak, debug object names
This commit is contained in:
22
src/Game.zig
22
src/Game.zig
@@ -226,6 +226,7 @@ pub fn init(allocator: std.mem.Allocator, engine: *Engine, swapchain: *Swapchain
|
||||
},
|
||||
});
|
||||
errdefer engine.destroyDescriptorSetLayout(global_descriptor_set_layout);
|
||||
engine.setObjectName(global_descriptor_set_layout, "DSL Global", .{});
|
||||
|
||||
const per_batch_descriptor_set_layout = try engine.createDescriptorSetLayout(.{
|
||||
.bindings = &.{
|
||||
@@ -238,6 +239,7 @@ pub fn init(allocator: std.mem.Allocator, engine: *Engine, swapchain: *Swapchain
|
||||
},
|
||||
});
|
||||
errdefer engine.destroyDescriptorSetLayout(per_batch_descriptor_set_layout);
|
||||
engine.setObjectName(per_batch_descriptor_set_layout, "DSL PerBatch", .{});
|
||||
|
||||
const pipeline_layout = try engine.createPipelineLayout(.{
|
||||
.set_layouts = &.{
|
||||
@@ -246,17 +248,21 @@ pub fn init(allocator: std.mem.Allocator, engine: *Engine, swapchain: *Swapchain
|
||||
},
|
||||
});
|
||||
errdefer engine.destroyPipelineLayout(pipeline_layout);
|
||||
engine.setObjectName(pipeline_layout, "PL", .{});
|
||||
|
||||
const vertex_shader = try engine.createShaderModule(.{ .code = &main_vert_spv });
|
||||
defer engine.destroyShaderModule(vertex_shader);
|
||||
engine.setObjectName(vertex_shader, "SM main_vert", .{});
|
||||
|
||||
const fragment_shader = try engine.createShaderModule(.{ .code = &main_frag_spv });
|
||||
defer engine.destroyShaderModule(fragment_shader);
|
||||
engine.setObjectName(fragment_shader, "SM main_frag", .{});
|
||||
|
||||
var vertex_buffer = try VertexBuffer.init(engine, .{
|
||||
.usage = .vertex,
|
||||
.target_queue = .graphics,
|
||||
.array_capacity = 4,
|
||||
.name = "QuadVB",
|
||||
});
|
||||
errdefer vertex_buffer.deinit(engine);
|
||||
try vertex_buffer.write(engine, .{
|
||||
@@ -292,6 +298,7 @@ pub fn init(allocator: std.mem.Allocator, engine: *Engine, swapchain: *Swapchain
|
||||
.usage = .index,
|
||||
.target_queue = .graphics,
|
||||
.array_capacity = 6,
|
||||
.name = "QuadIB",
|
||||
});
|
||||
errdefer index_buffer.deinit(engine);
|
||||
try index_buffer.write(engine, .{
|
||||
@@ -301,6 +308,7 @@ pub fn init(allocator: std.mem.Allocator, engine: *Engine, swapchain: *Swapchain
|
||||
var global_uniforms = try GlobalUniformsBuffer.init(engine, .{
|
||||
.usage = .uniform,
|
||||
.target_queue = .graphics,
|
||||
.name = "GlobalUniforms",
|
||||
});
|
||||
errdefer global_uniforms.deinit(engine);
|
||||
|
||||
@@ -333,8 +341,10 @@ pub fn init(allocator: std.mem.Allocator, engine: *Engine, swapchain: *Swapchain
|
||||
|
||||
errdefer for (semaphores.items) |x| engine.destroySemaphore(x);
|
||||
|
||||
for (0..swapchain.swapchain_images.len) |_| {
|
||||
semaphores.appendAssumeCapacity(try engine.createSemaphore());
|
||||
for (0..swapchain.swapchain_images.len) |i| {
|
||||
const semaphore = try engine.createSemaphore();
|
||||
engine.setObjectName(semaphore, "S Transfer[{d}]", .{i});
|
||||
semaphores.appendAssumeCapacity(semaphore);
|
||||
}
|
||||
|
||||
break :blk try semaphores.toOwnedSlice(allocator);
|
||||
@@ -346,13 +356,11 @@ pub fn init(allocator: std.mem.Allocator, engine: *Engine, swapchain: *Swapchain
|
||||
allocator.free(global_uniforms_transfer_semaphores);
|
||||
}
|
||||
|
||||
const global_uniforms_transfer_semaphore = try engine.createSemaphore();
|
||||
errdefer engine.destroySemaphore(global_uniforms_transfer_semaphore);
|
||||
|
||||
var point_lights = try PointLightBuffer.init(engine, .{
|
||||
.usage = .storage,
|
||||
.target_queue = .graphics,
|
||||
.array_capacity = max_point_lights,
|
||||
.name = "PointLights",
|
||||
});
|
||||
errdefer point_lights.deinit(engine);
|
||||
|
||||
@@ -360,6 +368,7 @@ pub fn init(allocator: std.mem.Allocator, engine: *Engine, swapchain: *Swapchain
|
||||
.usage = .storage,
|
||||
.target_queue = .graphics,
|
||||
.array_capacity = max_directional_lights,
|
||||
.name = "DirectionalLights",
|
||||
});
|
||||
errdefer directional_lights.deinit(engine);
|
||||
|
||||
@@ -479,6 +488,7 @@ pub fn init(allocator: std.mem.Allocator, engine: *Engine, swapchain: *Swapchain
|
||||
.subpass = 0,
|
||||
});
|
||||
errdefer engine.destroyPipeline(pipeline);
|
||||
engine.setObjectName(pipeline, "P", .{});
|
||||
|
||||
const descriptor_pool = try engine.createDescriptorPool(.{
|
||||
.max_sets = 1 + 256,
|
||||
@@ -502,12 +512,14 @@ pub fn init(allocator: std.mem.Allocator, engine: *Engine, swapchain: *Swapchain
|
||||
},
|
||||
});
|
||||
errdefer engine.destroyDescriptorPool(descriptor_pool);
|
||||
engine.setObjectName(descriptor_pool, "DP", .{});
|
||||
|
||||
const global_descriptor_set = try engine.allocateDescriptorSet(.{
|
||||
.descriptor_pool = descriptor_pool,
|
||||
.set_layout = global_descriptor_set_layout,
|
||||
.variable_descriptor_count = @intCast(textures.textures.items.len),
|
||||
});
|
||||
engine.setObjectName(global_descriptor_set, "DS Global", .{});
|
||||
|
||||
const descriptor_images = try allocator.alloc(vk.DescriptorImageInfo, textures.textures.items.len);
|
||||
for (textures.textures.items, descriptor_images) |texture, *info| {
|
||||
|
||||
@@ -18,12 +18,14 @@ const Vector3 = math.Vector3;
|
||||
pub const chunk_size = 16;
|
||||
|
||||
const initial_capacity = 256;
|
||||
var next_chunk_id: std.atomic.Value(u64) = .init(0);
|
||||
|
||||
blocks: [chunk_size][chunk_size][chunk_size]Blocks.Id,
|
||||
origin: Vector3,
|
||||
descriptor_set: vk.DescriptorSet,
|
||||
object_buffer: ObjectUniformsBuffer,
|
||||
object_count: u32,
|
||||
chunk_id: u64,
|
||||
|
||||
pub const InitInfo = struct {
|
||||
origin: Vector3,
|
||||
@@ -65,12 +67,18 @@ pub fn init(engine: *Engine, init_info: InitInfo) !Chunk {
|
||||
},
|
||||
});
|
||||
|
||||
const chunk_id = next_chunk_id.fetchAdd(1, .monotonic);
|
||||
engine.setObjectName(descriptor_set, "DS Chunk[{d}]", .{chunk_id});
|
||||
engine.setObjectName(object_buffer.buffer, "B Chunk[{d}]", .{chunk_id});
|
||||
engine.setObjectName(object_buffer.device_memory, "DM Chunk[{d}]", .{chunk_id});
|
||||
|
||||
return .{
|
||||
.blocks = .{.{[_]Blocks.Id{.air} ** chunk_size} ** chunk_size} ** chunk_size,
|
||||
.origin = init_info.origin,
|
||||
.descriptor_set = descriptor_set,
|
||||
.object_buffer = object_buffer,
|
||||
.object_count = 0,
|
||||
.chunk_id = chunk_id,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -128,6 +136,8 @@ pub fn refresh(self: *Chunk, engine: *Engine, blocks: *const Blocks, temp_alloca
|
||||
|
||||
self.object_buffer.deinit(engine);
|
||||
self.object_buffer = new_object_buffer;
|
||||
engine.setObjectName(new_object_buffer.buffer, "B Chunk[{d}]", .{self.chunk_id});
|
||||
engine.setObjectName(new_object_buffer.device_memory, "DM Chunk[{d}]", .{self.chunk_id});
|
||||
}
|
||||
|
||||
const uniforms = try temp_allocator.alloc(Game.ObjectUniforms, object_count);
|
||||
|
||||
@@ -53,6 +53,7 @@ pub fn init(engine: *Engine, allocator: std.mem.Allocator) !Materials {
|
||||
.usage = .storage,
|
||||
.target_queue = .graphics,
|
||||
.array_capacity = capacity,
|
||||
.name = "Materials",
|
||||
});
|
||||
errdefer material_buffer.deinit(engine);
|
||||
|
||||
|
||||
@@ -50,6 +50,7 @@ pub fn init(engine: *Engine, allocator: std.mem.Allocator) !Textures {
|
||||
.height = 1,
|
||||
.usage = .base_color,
|
||||
.target_queue = .graphics,
|
||||
.name = "@Empty",
|
||||
});
|
||||
textures.appendAssumeCapacity(empty_base_color_texture);
|
||||
|
||||
@@ -58,6 +59,7 @@ pub fn init(engine: *Engine, allocator: std.mem.Allocator) !Textures {
|
||||
.height = 1,
|
||||
.usage = .emissive,
|
||||
.target_queue = .graphics,
|
||||
.name = "@Empty",
|
||||
});
|
||||
textures.appendAssumeCapacity(empty_emissive_texture);
|
||||
|
||||
@@ -66,6 +68,7 @@ pub fn init(engine: *Engine, allocator: std.mem.Allocator) !Textures {
|
||||
.height = 1,
|
||||
.usage = .normal,
|
||||
.target_queue = .graphics,
|
||||
.name = "@Empty",
|
||||
});
|
||||
textures.appendAssumeCapacity(empty_normal_texture);
|
||||
|
||||
@@ -74,6 +77,7 @@ pub fn init(engine: *Engine, allocator: std.mem.Allocator) !Textures {
|
||||
.height = 1,
|
||||
.usage = .occlusion_roughness_metallic,
|
||||
.target_queue = .graphics,
|
||||
.name = "@Empty",
|
||||
});
|
||||
textures.appendAssumeCapacity(empty_occlusuion_roughness_metallic_texture);
|
||||
|
||||
@@ -176,6 +180,7 @@ fn loadTexture(engine: *Engine, filename: []const u8, usage: Texture.Usage, temp
|
||||
.height = img.height,
|
||||
.usage = usage,
|
||||
.target_queue = .graphics,
|
||||
.name = filename,
|
||||
});
|
||||
errdefer texture.deinit(engine);
|
||||
|
||||
|
||||
@@ -447,6 +447,65 @@ pub fn allocate(self: *const Engine, memory_requirements: vk.MemoryRequirements,
|
||||
return error.NoSuitableMemoryType;
|
||||
}
|
||||
|
||||
pub fn setObjectName(self: *const Engine, handle: anytype, comptime fmt: []const u8, args: anytype) void {
|
||||
if (debug) {
|
||||
const HandleType = @TypeOf(handle);
|
||||
const type_name = @typeName(HandleType);
|
||||
|
||||
if (@as(std.builtin.TypeId, @typeInfo(HandleType)) != .@"enum") {
|
||||
@compileError("Cannot set object name for a handle of type " ++ type_name ++ ", which is not an enum.");
|
||||
}
|
||||
|
||||
const object_type: vk.ObjectType = switch (HandleType) {
|
||||
vk.Instance => .instance,
|
||||
vk.PhysicalDevice => .physical_device,
|
||||
vk.Device => .device,
|
||||
vk.Queue => .queue,
|
||||
vk.Semaphore => .semaphore,
|
||||
vk.CommandBuffer => .command_buffer,
|
||||
vk.Fence => .fence,
|
||||
vk.DeviceMemory => .device_memory,
|
||||
vk.Buffer => .buffer,
|
||||
vk.Image => .image,
|
||||
vk.Event => .event,
|
||||
vk.QueryPool => .query_pool,
|
||||
vk.BufferView => .buffer_view,
|
||||
vk.ImageView => .image_view,
|
||||
vk.ShaderModule => .shader_module,
|
||||
vk.PipelineCache => .pipeline_cache,
|
||||
vk.PipelineLayout => .pipeline_layout,
|
||||
vk.RenderPass => .render_pass,
|
||||
vk.Pipeline => .pipeline,
|
||||
vk.DescriptorSetLayout => .descriptor_set_layout,
|
||||
vk.Sampler => .sampler,
|
||||
vk.DescriptorPool => .descriptor_pool,
|
||||
vk.DescriptorSet => .descriptor_set,
|
||||
vk.Framebuffer => .framebuffer,
|
||||
vk.CommandPool => .command_pool,
|
||||
vk.SurfaceKHR => .surface_khr,
|
||||
vk.SwapchainKHR => .swapchain_khr,
|
||||
else => @compileError("Unsupported type " ++ type_name ++ " for setting and object name"),
|
||||
};
|
||||
|
||||
const handle_value: u64 = @intFromEnum(handle);
|
||||
|
||||
var buf: [256]u8 = undefined;
|
||||
const name = std.fmt.bufPrintZ(&buf, fmt, args) catch |err| {
|
||||
std.log.debug("Failed to set object name for {s}#{X}: {s}", .{ type_name, handle_value, @errorName(err) });
|
||||
return;
|
||||
};
|
||||
|
||||
self.device.setDebugUtilsObjectNameEXT(&.{
|
||||
.object_type = object_type,
|
||||
.object_handle = handle_value,
|
||||
.p_object_name = name.ptr,
|
||||
}) catch |err| {
|
||||
std.log.debug("Failed to set object name for {s}#{X}: {s}", .{ type_name, handle_value, @errorName(err) });
|
||||
return;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
fn debugUtilsMessengerCallback(
|
||||
severity: vk.DebugUtilsMessageSeverityFlagsEXT,
|
||||
message_type: vk.DebugUtilsMessageTypeFlagsEXT,
|
||||
|
||||
@@ -29,6 +29,7 @@ pub const InitInfo = struct {
|
||||
usage: Usage,
|
||||
target_queue: TargetQueue,
|
||||
array_capacity: u32 = 0,
|
||||
name: ?[]const u8 = null,
|
||||
};
|
||||
|
||||
pub fn GenericBuffer(comptime Header: type, comptime Element: type) type {
|
||||
@@ -66,10 +67,16 @@ pub fn GenericBuffer(comptime Header: type, comptime Element: type) type {
|
||||
.queue_family_indices = &.{ target_queue_family, transfer_queue_family },
|
||||
});
|
||||
errdefer engine.destroyBuffer(buffer);
|
||||
if (init_info.name) |name| {
|
||||
engine.setObjectName(buffer, "B {s} [{s}, {s}]", .{ name, @typeName(Header), @typeName(Element) });
|
||||
}
|
||||
|
||||
const memory_requirements = engine.device.getBufferMemoryRequirements(buffer);
|
||||
const device_memory = try engine.allocate(memory_requirements, .{ .device_local_bit = true });
|
||||
errdefer engine.freeMemory(device_memory);
|
||||
if (init_info.name) |name| {
|
||||
engine.setObjectName(device_memory, "DM {s} [{s}, {s}]", .{ name, @typeName(Header), @typeName(Element) });
|
||||
}
|
||||
|
||||
try engine.device.bindBufferMemory(buffer, device_memory, 0);
|
||||
|
||||
|
||||
@@ -104,6 +104,7 @@ pub fn init(engine: *Engine) !Swapchain {
|
||||
}, &engine.vk_allocator.interface);
|
||||
};
|
||||
errdefer engine.device.destroyRenderPass(render_pass, &engine.vk_allocator.interface);
|
||||
engine.setObjectName(render_pass, "RP", .{});
|
||||
|
||||
var swapchain: Swapchain = .{
|
||||
.params = params,
|
||||
@@ -133,6 +134,7 @@ pub fn deinit(self: *Swapchain, engine: *Engine) void {
|
||||
}
|
||||
|
||||
engine.device.destroyRenderPass(self.render_pass, &engine.vk_allocator.interface);
|
||||
engine.destroySemaphore(self.semaphore_image_acquired);
|
||||
|
||||
self.* = undefined;
|
||||
}
|
||||
@@ -173,6 +175,7 @@ pub fn recreate(self: *Swapchain, engine: *Engine) !void {
|
||||
.old_swapchain = old_swapchain,
|
||||
}, &engine.vk_allocator.interface);
|
||||
errdefer engine.device.destroySwapchainKHR(new_swapchain, &engine.vk_allocator.interface);
|
||||
engine.setObjectName(new_swapchain, "SC {d}×{d}", .{ extent.width, extent.height });
|
||||
|
||||
// --- DESTROY OLD SWAPCHAIN AND ITS IMAGES --------------------------------
|
||||
|
||||
@@ -209,6 +212,7 @@ pub fn recreate(self: *Swapchain, engine: *Engine) !void {
|
||||
.height = extent.height,
|
||||
.target_queue = .graphics,
|
||||
.usage = .depth,
|
||||
.name = "@Depth",
|
||||
});
|
||||
errdefer new_depth_texture.deinit(engine);
|
||||
|
||||
@@ -223,13 +227,14 @@ pub fn recreate(self: *Swapchain, engine: *Engine) !void {
|
||||
|
||||
errdefer for (swapchain_images.items) |*x| x.deinit(engine);
|
||||
|
||||
for (images) |image| {
|
||||
for (images, 0..) |image, index| {
|
||||
swapchain_images.appendAssumeCapacity(try SwapchainImage.init(engine, .{
|
||||
.image = image,
|
||||
.format = self.params.surface_format.format,
|
||||
.render_pass = self.render_pass,
|
||||
.extent = extent,
|
||||
.depth_stencil_image_view = new_depth_texture.image_view,
|
||||
.index = index,
|
||||
}));
|
||||
}
|
||||
|
||||
@@ -246,6 +251,7 @@ pub fn recreate(self: *Swapchain, engine: *Engine) !void {
|
||||
|
||||
var semaphore_image_acquired = try engine.createSemaphore();
|
||||
errdefer engine.destroySemaphore(semaphore_image_acquired);
|
||||
engine.setObjectName(semaphore_image_acquired, "S Acquired[E]", .{});
|
||||
|
||||
const res = try engine.device.acquireNextImageKHR(new_swapchain, std.math.maxInt(u64), semaphore_image_acquired, .null_handle);
|
||||
if (res.result == .not_ready or res.result == .timeout) {
|
||||
@@ -407,6 +413,8 @@ const SwapchainImage = struct {
|
||||
render_pass: vk.RenderPass,
|
||||
extent: vk.Extent2D,
|
||||
depth_stencil_image_view: vk.ImageView,
|
||||
|
||||
index: usize,
|
||||
};
|
||||
|
||||
fn init(engine: *Engine, props: InitProps) !SwapchainImage {
|
||||
@@ -423,17 +431,21 @@ const SwapchainImage = struct {
|
||||
},
|
||||
});
|
||||
errdefer engine.destroyImageView(image_view);
|
||||
engine.setObjectName(image_view, "IV Swapchain[{d}]", .{props.index});
|
||||
|
||||
const semaphore_image_acquired = try engine.createSemaphore();
|
||||
errdefer engine.destroySemaphore(semaphore_image_acquired);
|
||||
engine.setObjectName(image_view, "S Acquired[{d}]", .{props.index});
|
||||
|
||||
const semaphore_render_finished = try engine.createSemaphore();
|
||||
errdefer engine.destroySemaphore(semaphore_render_finished);
|
||||
engine.setObjectName(image_view, "S Rendered[{d}]", .{props.index});
|
||||
|
||||
const fence = try engine.createFence(.{
|
||||
.flags = .{ .signaled_bit = true },
|
||||
});
|
||||
errdefer engine.destroyFence(fence);
|
||||
engine.setObjectName(image_view, "F Rendered[{d}]", .{props.index});
|
||||
|
||||
const framebuffer = try engine.createFramebuffer(.{
|
||||
.render_pass = props.render_pass,
|
||||
@@ -443,6 +455,7 @@ const SwapchainImage = struct {
|
||||
.layers = 1,
|
||||
});
|
||||
errdefer engine.destroyFramebuffer(framebuffer);
|
||||
engine.setObjectName(image_view, "FB Swapchain[{d}]", .{props.index});
|
||||
|
||||
return .{
|
||||
.image = props.image,
|
||||
|
||||
@@ -67,6 +67,7 @@ pub const InitInfo = struct {
|
||||
height: u32,
|
||||
usage: Usage,
|
||||
target_queue: TargetQueue,
|
||||
name: ?[]const u8 = null,
|
||||
};
|
||||
|
||||
image: vk.Image,
|
||||
@@ -111,10 +112,16 @@ pub fn init(engine: *Engine, init_info: InitInfo) !Texture {
|
||||
.initial_layout = .undefined,
|
||||
});
|
||||
errdefer engine.destroyImage(image);
|
||||
if (init_info.name) |name| {
|
||||
engine.setObjectName(image, "I {s} [{s}]", .{ name, @tagName(init_info.usage) });
|
||||
}
|
||||
|
||||
const memory_requirements = engine.device.getImageMemoryRequirements(image);
|
||||
const device_memory = try engine.allocate(memory_requirements, .{ .device_local_bit = true });
|
||||
errdefer engine.freeMemory(device_memory);
|
||||
if (init_info.name) |name| {
|
||||
engine.setObjectName(device_memory, "DM {s} [{s}]", .{ name, @tagName(init_info.usage) });
|
||||
}
|
||||
|
||||
try engine.device.bindImageMemory(image, device_memory, 0);
|
||||
|
||||
@@ -134,6 +141,9 @@ pub fn init(engine: *Engine, init_info: InitInfo) !Texture {
|
||||
},
|
||||
});
|
||||
errdefer engine.destroyImageView(image_view);
|
||||
if (init_info.name) |name| {
|
||||
engine.setObjectName(image_view, "IV {s} [{s}]", .{ name, @tagName(init_info.usage) });
|
||||
}
|
||||
|
||||
return .{
|
||||
.image = image,
|
||||
|
||||
Reference in New Issue
Block a user