Name vulkan objects for debugging, got first meshes to draw, spirv debug output for Aftermath

This commit is contained in:
sergeypdev 2025-01-01 22:04:44 +04:00
parent bd903da009
commit c1c81ee761
13 changed files with 275 additions and 219 deletions

View File

@ -41,24 +41,10 @@ pub fn build(b: *Build) void {
const vk = buildVulkanWrapper(b, target, optimize);
const vma_dep = b.dependency("vma", .{});
const vma = b.addStaticLibrary(.{
.name = "vma",
.target = target,
.optimize = optimize,
});
vma.linkLibC();
vma.linkLibCpp();
vma.addIncludePath(b.dependency("vulkan_headers", .{}).path("include"));
vma.addIncludePath(vma_dep.path("include"));
vma.installHeadersDirectory(vma_dep.path("include"), "", .{});
vma.addCSourceFile(.{
.file = b.path("libs/vma/vma.cpp"),
});
const tracy = b.dependency("zig-tracy", .{
.target = target,
.optimize = optimize,
.tracy_enable = false,
});
const zalgebra_dep = b.dependency("zalgebra", .{});
@ -102,7 +88,6 @@ pub fn build(b: *Build) void {
l.root_module.addImport("tracy", tracy.module("tracy"));
l.root_module.addImport("vk", vk);
l.linkLibrary(tracy.artifact("tracy"));
l.linkLibrary(vma);
}
const install_lib = b.addInstallArtifact(lib, .{ .dest_dir = .{ .override = .prefix } });

View File

@ -43,10 +43,6 @@
.url = "https://github.com/sinnwrig/mach-dxcompiler/tarball/c3dfe92f3f04d4a3262dbc1a71f0016b9af92eb4",
.hash = "12202f48e7cf06b1f2ecfd84f16effbd5bb9d644ea17e8a6144b4301a4dea198cf9c",
},
.vma = .{
.url = "https://github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator/tarball/1c35ba99ce775f8342d87a83a3f0f696f99c2a39",
.hash = "1220521e256ea64cb942c37cfe08065073f2c71bfaa91d5c929fd382314c73ac0369",
},
.@"spirv-cross" = .{
.url = "https://github.com/hexops/spirv-cross/tarball/872bd405fece4bf6388abdea916356e26cb8fed9",
.hash = "12207bebf82eef06f4f80a7e54c91e4402c0055d04167fdbcf1f350846a350266976",

View File

@ -1,4 +0,0 @@
#define VMA_IMPLEMENTATION
#define VMA_STATIC_VULKAN_FUNCTIONS 0
#define VMA_DYNAMIC_VULKAN_FUNCTIONS 1
#include "vk_mem_alloc.h"

BIN
post_process.glsl.spirv Normal file

Binary file not shown.

View File

@ -100,7 +100,7 @@ const AssetWatcher = struct {
}
pub fn startWatching(self: *AssetWatcher) void {
self.thread = sdl.SDL_CreateThread(watcherThread, "AssetManager Watcher", @ptrCast(self)) orelse {
self.thread = sdl.SDL_CreateThread(watcherThread, "AssetManager Watcher", @ptrCast(self), null, null) orelse {
std.log.err("SDL Error: {s}\n", .{sdl.SDL_GetError()});
@panic("SDL_CreateThread");
};
@ -190,6 +190,9 @@ pub fn init(allocator: std.mem.Allocator, frame_arena: std.mem.Allocator, gc: *G
.command_pool = try queue.createCommandPool(.{ .transient_bit = true }),
};
NullMesh.positions = result.vertex_heap.heap_address;
NullMesh.other_data = result.vertex_heap.heap_address;
result.texture_heap_memory = try gc.device.allocateMemory(&.{
.allocation_size = result.texture_heap.getSize(),
.memory_type_index = gc.memory_config.gpu.type_index,
@ -564,7 +567,7 @@ const NullShaderProgram = LoadedShaderProgram{
.pipeline = .null_handle,
};
const NullMesh = LoadedMesh{
var NullMesh = LoadedMesh{
.aabb = .{},
.allocation = .{},
.positions = 0,
@ -643,7 +646,8 @@ fn loadMeshErr(self: *AssetManager, id: AssetId) !LoadedMesh {
self.gc.device.unmapMemory(staging_mem);
const cmds = try self.command_pool.allocateCommandBuffer();
const cmd_buf_name = try std.fmt.allocPrintZ(self.frame_arena, "MeshLoadCMDBuf ({s})", .{path});
const cmds = try self.command_pool.allocateCommandBuffer(cmd_buf_name);
try cmds.beginCommandBuffer(&.{ .flags = .{ .one_time_submit_bit = true } });
@ -830,6 +834,11 @@ fn loadTextureErr(self: *AssetManager, id: AssetId) !LoadedTexture {
.initial_layout = .undefined,
}, null);
errdefer self.gc.device.destroyImage(image, null);
try self.gc.device.setDebugUtilsObjectNameEXT(&vk.DebugUtilsObjectNameInfoEXT{
.object_type = .image,
.object_handle = @intFromEnum(image),
.p_object_name = @ptrCast(path.ptr),
});
const mem_reqs = self.gc.getImageMemoryRequirements(image);
const allocation = try self.texture_heap.alloc(mem_reqs.size);
@ -853,6 +862,11 @@ fn loadTextureErr(self: *AssetManager, id: AssetId) !LoadedTexture {
.level_count = texture.header.mip_count,
},
}, null);
try self.gc.device.setDebugUtilsObjectNameEXT(&vk.DebugUtilsObjectNameInfoEXT{
.object_type = .image_view,
.object_handle = @intFromEnum(view),
.p_object_name = @ptrCast(path.ptr),
});
errdefer self.gc.device.destroyImageView(view, null);
var data_size: u64 = 0;
@ -889,7 +903,8 @@ fn loadTextureErr(self: *AssetManager, id: AssetId) !LoadedTexture {
self.gc.device.unmapMemory(staging_mem);
const cmds = try self.command_pool.allocateCommandBuffer();
const cmd_buf_name = try std.fmt.allocPrintZ(self.frame_arena, "TextureLoadCMDBuf ({s})", .{path});
const cmds = try self.command_pool.allocateCommandBuffer(cmd_buf_name);
try cmds.beginCommandBuffer(&.{ .flags = .{ .one_time_submit_bit = true } });
@ -1087,7 +1102,7 @@ fn finishLoadingAsset(self: *AssetManager, id: AssetId) void {
.allocation = loading_mesh.allocation,
.positions = self.vertex_heap.heap_address + loading_mesh.allocation.positions.offset,
.other_data = self.vertex_heap.heap_address + loading_mesh.allocation.other_data.offset,
.indices_offset = loading_mesh.allocation.indices.offset,
.indices_offset = loading_mesh.allocation.indices.offset / @sizeOf(formats.Index),
},
}) catch @panic("OOM");
}
@ -1885,6 +1900,11 @@ const VertexBufferHeap = struct {
.sharing_mode = .exclusive,
.usage = .{ .shader_device_address_bit = true, .storage_buffer_bit = true, .transfer_dst_bit = true, .index_buffer_bit = true },
}, null);
try device.setDebugUtilsObjectNameEXT(&vk.DebugUtilsObjectNameInfoEXT{
.object_type = .buffer,
.object_handle = @intFromEnum(heap_buffer),
.p_object_name = "VertexBufferHeap",
});
errdefer device.destroyBuffer(heap_buffer, null);
const mem_reqs = device.getBufferMemoryRequirements(heap_buffer);

View File

@ -329,6 +329,11 @@ pub fn init(gc: *GraphicsContext, frame_allocator: std.mem.Allocator) !Descripto
.p_set_layouts = &.{self.descriptor_set_layouts.global},
}, &descriptor_set_buf);
self.global_descriptor_set = descriptor_set_buf[0];
try gc.device.setDebugUtilsObjectNameEXT(&vk.DebugUtilsObjectNameInfoEXT{
.object_type = .descriptor_set,
.object_handle = @intFromEnum(self.global_descriptor_set),
.p_object_name = "GlobalDescriptorSet",
});
return self;
}

View File

@ -1,7 +1,6 @@
const std = @import("std");
const vk = @import("vk");
const c = @import("sdl.zig");
const vma = @import("vma.zig");
pub const GraphicsContext = @This();
@ -12,6 +11,7 @@ const apis: []const vk.ApiInfo = &.{
vk.features.version_1_3,
vk.extensions.khr_surface,
vk.extensions.khr_swapchain,
vk.extensions.ext_debug_utils,
};
pub const Instance = vk.InstanceProxy(apis);
@ -22,13 +22,17 @@ const BaseDispatch = vk.BaseWrapper(apis);
const InstanceDispatch = vk.InstanceWrapper(apis);
const DeviceDispatch = Device.Wrapper;
const instance_extensions = [_][*:0]const u8{
vk.extensions.ext_debug_utils.name,
};
const device_extensions = [_][:0]const u8{
vk.extensions.khr_swapchain.name,
};
const vk_layers = [_][:0]const u8{"VK_LAYER_KHRONOS_validation"};
const vk_layers = [_][:0]const u8{
// "VK_LAYER_KHRONOS_validation",
};
allocator: std.mem.Allocator = undefined,
vma_allocator: vma.Allocator = null,
window: *c.SDL_Window = undefined,
vkb: BaseDispatch = undefined,
vki: InstanceDispatch = undefined,
@ -49,13 +53,20 @@ pub const CommandPool = struct {
device: Device,
handle: vk.CommandPool,
pub fn allocateCommandBuffer(self: *const CommandPool) !CommandBuffer {
pub fn allocateCommandBuffer(self: *const CommandPool, maybe_debug_name: ?[:0]const u8) !CommandBuffer {
var cmd_bufs = [_]vk.CommandBuffer{.null_handle};
try self.device.allocateCommandBuffers(&.{
.command_pool = self.handle,
.level = .primary,
.command_buffer_count = cmd_bufs.len,
}, &cmd_bufs);
if (maybe_debug_name) |debug_name| {
try self.device.setDebugUtilsObjectNameEXT(&vk.DebugUtilsObjectNameInfoEXT{
.object_type = .command_buffer,
.object_handle = @intFromEnum(cmd_bufs[0]),
.p_object_name = debug_name,
});
}
return CommandBuffer.init(cmd_bufs[0], self.device.wrapper);
}
@ -312,13 +323,14 @@ pub fn init(self: *GraphicsContext, allocator: std.mem.Allocator, window: *c.SDL
return error.GetSDLExtensions;
}
const sdl_instance_ext_names = try fba.allocator().alloc([*:0]const u8, sdl_instance_ext_count);
if (c.SDL_Vulkan_GetInstanceExtensions(window, &sdl_instance_ext_count, @ptrCast(sdl_instance_ext_names.ptr)) == c.SDL_FALSE) {
const instance_ext_names = try fba.allocator().alloc([*:0]const u8, sdl_instance_ext_count + instance_extensions.len);
if (c.SDL_Vulkan_GetInstanceExtensions(window, &sdl_instance_ext_count, @ptrCast(instance_ext_names.ptr)) == c.SDL_FALSE) {
std.debug.print("SDL_Vulkan_GetInstanceExtensions: get names {s}\n", .{c.SDL_GetError()});
return error.GetSDLExtensions;
}
@memcpy(instance_ext_names[sdl_instance_ext_count..], &instance_extensions);
std.debug.print("SDL Extensions: {s}\n", .{sdl_instance_ext_names});
std.debug.print("Instance Extensions: {s}\n", .{instance_ext_names});
self.vkb = try BaseDispatch.load(vkGetInstanceProcAddr);
@ -330,8 +342,8 @@ pub fn init(self: *GraphicsContext, allocator: std.mem.Allocator, window: *c.SDL
},
.pp_enabled_layer_names = @ptrCast((&vk_layers).ptr),
.enabled_layer_count = @intCast(vk_layers.len),
.enabled_extension_count = @intCast(sdl_instance_ext_names.len),
.pp_enabled_extension_names = sdl_instance_ext_names.ptr,
.enabled_extension_count = @intCast(instance_ext_names.len),
.pp_enabled_extension_names = instance_ext_names.ptr,
}, null);
self.vki = try InstanceDispatch.load(instance_handle, vkGetInstanceProcAddr);
@ -415,21 +427,6 @@ pub fn init(self: *GraphicsContext, allocator: std.mem.Allocator, window: *c.SDL
errdefer self.vkd.destroyDevice(device_handle, null);
self.device = Device.init(device_handle, &self.vkd);
self.vma_allocator = vma.createAllocator(&.{
.flags = .{
.buffer_device_address_bit = true,
},
.instance = instance_handle,
.physical_device = self.device_info.physical_device,
.device = device_handle,
.vulkanApiVersion = vk.API_VERSION_1_3,
.pVulkanFunctions = &vma.VulkanFunctions{
.vkGetInstanceProcAddr = @ptrCast(vkGetInstanceProcAddr),
.vkGetDeviceProcAddr = @ptrCast(self.instance.wrapper.dispatch.vkGetDeviceProcAddr),
},
});
std.debug.assert(self.vma_allocator != null);
try self.maybeResizeSwapchain();
errdefer self.device.destroySwapchainKHR(self.swapchain, null);
@ -454,22 +451,14 @@ pub fn init(self: *GraphicsContext, allocator: std.mem.Allocator, window: *c.SDL
self.pipeline_cache = try self.device.createPipelineCache(&.{}, null);
}
pub fn createBuffer(self: *GraphicsContext, create_info: *const vk.BufferCreateInfo, allocation_create_info: *const vma.AllocationCreateInfo) !Buffer {
var result: Buffer = undefined;
result.gc = self;
result.handle = try vma.createBuffer(self.vma_allocator, create_info, allocation_create_info, &result.allocation, &result.allocation_info);
result.sync_state = .{};
return result;
}
pub fn acquireSwapchainImage(self: *GraphicsContext, acuire_semaphore: vk.Semaphore) !u32 {
pub fn acquireSwapchainImage(self: *GraphicsContext, acuire_semaphore: vk.Semaphore, acquire_fence: vk.Fence) !u32 {
var found = false;
var swapchain_img: u32 = 0;
try self.maybeResizeSwapchain();
while (!found) {
const acquire_result = try self.device.acquireNextImageKHR(self.swapchain, std.math.maxInt(u64), acuire_semaphore, .null_handle);
const acquire_result = try self.device.acquireNextImageKHR(self.swapchain, std.math.maxInt(u64), acuire_semaphore, acquire_fence);
switch (acquire_result.result) {
.success, .suboptimal_khr => {
@ -537,6 +526,7 @@ fn maybeResizeSwapchain(self: *GraphicsContext) !void {
self.allocator.free(self.swapchain_images);
self.swapchain_images = &.{};
}
self.swapchain_extent = new_extent;
const surface_caps = self.device_info.surface_capabilities;
self.swapchain = try self.device.createSwapchainKHR(&.{

View File

@ -6,6 +6,7 @@ const vk = @import("vk");
const a = @import("asset_manifest");
const za = @import("zalgebra");
const Vec3 = za.Vec3;
const Vec4 = za.Vec4;
const Mat4 = za.Mat4;
const common = @import("common.zig");
const formats = @import("formats.zig");
@ -313,6 +314,11 @@ fn allocateRenderTarget(self: *Render2) !MainRenderTarget {
.samples = .{ .@"1_bit" = true },
.initial_layout = .undefined,
}, &color_img_address);
try self.gc.device.setDebugUtilsObjectNameEXT(&vk.DebugUtilsObjectNameInfoEXT{
.object_type = .image,
.object_handle = @intFromEnum(color_image),
.p_object_name = "Main RT (Color)",
});
const color_image_view = try self.createPerFrameImageView(&vk.ImageViewCreateInfo{
.image = color_image,
@ -327,6 +333,11 @@ fn allocateRenderTarget(self: *Render2) !MainRenderTarget {
.level_count = 1,
},
});
try self.gc.device.setDebugUtilsObjectNameEXT(&vk.DebugUtilsObjectNameInfoEXT{
.object_type = .image_view,
.object_handle = @intFromEnum(color_image_view),
.p_object_name = "Main RT View (Color)",
});
const depth_image = try self.createPerFrameImage(&.{
.image_type = .@"2d",
@ -340,6 +351,11 @@ fn allocateRenderTarget(self: *Render2) !MainRenderTarget {
.samples = .{ .@"1_bit" = true },
.initial_layout = .undefined,
}, &depth_img_address);
try self.gc.device.setDebugUtilsObjectNameEXT(&vk.DebugUtilsObjectNameInfoEXT{
.object_type = .image,
.object_handle = @intFromEnum(depth_image),
.p_object_name = "Main RT (Depth)",
});
const depth_image_view = try self.createPerFrameImageView(&vk.ImageViewCreateInfo{
.image = depth_image,
.view_type = .@"2d",
@ -353,6 +369,11 @@ fn allocateRenderTarget(self: *Render2) !MainRenderTarget {
.level_count = 1,
},
});
try self.gc.device.setDebugUtilsObjectNameEXT(&vk.DebugUtilsObjectNameInfoEXT{
.object_type = .image_view,
.object_handle = @intFromEnum(depth_image_view),
.p_object_name = "Main RT View (Depth)",
});
return MainRenderTarget{
.color = GraphicsContext.Image{
@ -439,6 +460,8 @@ pub fn draw(self: *Render2, cmd: DrawCommand) void {
self.draw_command_count += 1;
}
const debug_label_color: [4]f32 = .{ 0.15, 0.6, 0.15, 1 };
pub fn finish(self: *Render2) !void {
const gc = self.gc;
const device = gc.device;
@ -446,7 +469,7 @@ pub fn finish(self: *Render2) !void {
try frame.waitForDrawAndReset(self.gc.device, self.descriptorman);
const swapchain_image_index: u32 = try gc.acquireSwapchainImage(frame.acquire_swapchain_image);
const swapchain_image_index: u32 = try gc.acquireSwapchainImage(frame.acquire_swapchain_image, .null_handle);
self.vulkan_frame_arena.startFrame(self.frame_state.frame);
@ -461,7 +484,7 @@ pub fn finish(self: *Render2) !void {
const projection = self.camera.projection().mul(Mat4{
.data = .{
.{ 1, 0, 0, 0 },
.{ 0, 1, 0, 0 },
.{ 0, -1, 0, 0 },
.{ 0, 0, 1, 0 },
.{ 0, 0, 0, 1 },
},
@ -483,19 +506,36 @@ pub fn finish(self: *Render2) !void {
const depth_image: *GraphicsContext.Image = &main_render_target.depth;
var swapchain_image = GraphicsContext.Image{ .handle = gc.swapchain_images[swapchain_image_index], .mip_count = 1, .layer_count = 1, .format = .r8g8b8a8_unorm };
// NOTE: I don't think this is actually needed, but validation is screaming at me
swapchain_image.sync_state.sync_state.last_writer.stage_mask = .{ .color_attachment_output_bit = true };
const swapchain_image_view = try swapchain_image.createView(gc.device, .{ .color_bit = true });
defer gc.device.destroyImageView(swapchain_image_view, null);
const cmds = frame.command_buffer;
try cmds.beginCommandBuffer(&.{});
{
try global_uniform_buffer.sync(cmds, .{ .stage_mask = .{ .copy_bit = true }, .access_mask = .{ .transfer_write_bit = true } });
cmds.updateBuffer(global_uniform_buffer.handle, 0, @sizeOf(GlobalUniform), &global_uniform);
try global_uniform_buffer.sync(cmds, .{ .stage_mask = .{ .vertex_shader_bit = true }, .access_mask = .{ .shader_read_bit = true } });
const global_descriptor_set = self.descriptorman.global_descriptor_set;
{
const cmds = frame.draw_cmdbuf;
try cmds.beginCommandBuffer(&.{});
defer cmds.endCommandBuffer() catch @panic("endCommandBuffer");
// Main Pass
{
cmds.beginDebugUtilsLabelEXT(&vk.DebugUtilsLabelEXT{
.color = debug_label_color,
.p_label_name = "Draw",
});
defer cmds.endDebugUtilsLabelEXT();
{
cmds.beginDebugUtilsLabelEXT(&vk.DebugUtilsLabelEXT{
.color = debug_label_color,
.p_label_name = "UpdateGlobalUniformBuffer",
});
defer cmds.endDebugUtilsLabelEXT();
try global_uniform_buffer.sync(cmds, .{ .stage_mask = .{ .clear_bit = true, .copy_bit = true }, .access_mask = .{ .transfer_write_bit = true } });
cmds.updateBuffer(global_uniform_buffer.handle, 0, @sizeOf(GlobalUniform), &global_uniform);
try global_uniform_buffer.sync(cmds, .{ .stage_mask = .{ .vertex_shader_bit = true, .fragment_shader_bit = true }, .access_mask = .{ .uniform_read_bit = true } });
}
// TODO: move this into descriptorman
device.updateDescriptorSets(1, &.{
vk.WriteDescriptorSet{
@ -542,6 +582,12 @@ pub fn finish(self: *Render2) !void {
// Actual draws
{
cmds.beginDebugUtilsLabelEXT(&vk.DebugUtilsLabelEXT{
.color = debug_label_color,
.p_label_name = "MainPass",
});
defer cmds.endDebugUtilsLabelEXT();
cmds.beginRendering(&vk.RenderingInfo{
.render_area = vk.Rect2D{ .offset = .{ .x = 0, .y = 0 }, .extent = gc.swapchain_extent },
.layer_count = 1,
@ -617,18 +663,10 @@ pub fn finish(self: *Render2) !void {
cmds.drawIndexed(mesh.index_count, 1, mesh.indices_offset, 0, 0);
}
}
}
// Post process and convert from f16 to rgba8_unorm
{
try swapchain_image.sync(
cmds,
.{
.stage_mask = .{ .color_attachment_output_bit = true },
.access_mask = .{ .color_attachment_write_bit = true },
},
.color_attachment_optimal,
.{ .color_bit = true },
);
try color_image.sync(
cmds,
.{
@ -638,6 +676,21 @@ pub fn finish(self: *Render2) !void {
.shader_read_only_optimal,
.{ .color_bit = true },
);
cmds.beginDebugUtilsLabelEXT(&vk.DebugUtilsLabelEXT{
.color = debug_label_color,
.p_label_name = "PostProcess",
});
defer cmds.endDebugUtilsLabelEXT();
try swapchain_image.sync(
cmds,
.{
.stage_mask = .{ .color_attachment_output_bit = true },
.access_mask = .{ .color_attachment_write_bit = true },
},
.color_attachment_optimal,
.{ .color_bit = true },
);
cmds.beginRendering(&.{
.render_area = vk.Rect2D{ .offset = .{ .x = 0, .y = 0 }, .extent = gc.swapchain_extent },
.layer_count = 1,
@ -690,19 +743,21 @@ pub fn finish(self: *Render2) !void {
try swapchain_image.sync(cmds, .{ .stage_mask = .{}, .access_mask = .{} }, .present_src_khr, .{ .color_bit = true });
}
try cmds.endCommandBuffer();
self.draw_command_count = 0;
try gc.queues.graphics.submit(
&GraphicsContext.SubmitInfo{
.wait_semaphores = &.{frame.acquire_swapchain_image},
.wait_dst_stage_mask = &.{vk.PipelineStageFlags{}},
.command_buffers = &.{cmds.handle},
.wait_dst_stage_mask = &.{
vk.PipelineStageFlags{ .color_attachment_output_bit = true }, // Wait for swapchain acquire before rendering into it
},
.command_buffers = &.{frame.draw_cmdbuf.handle},
.signal_semaphores = &.{frame.draw_sema},
},
frame.draw_fence,
frame.end_draw_fence,
);
frame.draw_submitted = true;
_ = try gc.device.queuePresentKHR(gc.queues.graphics.handle, &.{

View File

@ -7,11 +7,12 @@ pub const ShaderPrograms = manifest.ShaderPrograms;
pub const Textures = manifest.Textures;
pub const Materials = manifest.Materials;
const empty: [:0]const u8 = "";
pub fn getPath(asset_id: u64) []const u8 {
manifest.init();
if (asset_id == 0) return "";
if (asset_id == 0) return empty;
return manifest.asset_paths.get(asset_id) orelse "";
return manifest.asset_paths.get(asset_id) orelse empty;
}
pub fn getAssetByPath(path: []const u8) u32 {

View File

@ -71,7 +71,7 @@ pub const FreeLookCamera = struct {
pub fn update(self: *FreeLookCamera, dt: f32, move: Vec3, look: Vec2) void {
self.yaw += look.x();
self.pitch -= look.y();
self.pitch += look.y();
// First rotate pitch, then yaw
const rot = Mat4.fromRotation(self.pitch, Vec3.right()).mul(Mat4.fromRotation(self.yaw, Vec3.up()));

View File

@ -104,11 +104,11 @@ pub const FrameData = struct {
// Sync
acquire_swapchain_image: vk.Semaphore,
draw_sema: vk.Semaphore,
draw_fence: vk.Fence,
end_draw_fence: vk.Fence,
draw_submitted: bool = true,
destroy_queue: DeferredDestroyQueue,
command_buffer: GraphicsContext.CommandBuffer,
draw_cmdbuf: GraphicsContext.CommandBuffer,
pub fn init(gc: *GraphicsContext, command_pool: GraphicsContext.CommandPool) !FrameData {
const fence = try gc.device.createFence(&.{ .flags = .{ .signaled_bit = true } }, null);
@ -116,9 +116,9 @@ pub const FrameData = struct {
return FrameData{
.acquire_swapchain_image = try gc.device.createSemaphore(&.{}, null),
.draw_sema = try gc.device.createSemaphore(&.{}, null),
.draw_fence = fence,
.end_draw_fence = fence,
.command_buffer = try command_pool.allocateCommandBuffer(),
.draw_cmdbuf = try command_pool.allocateCommandBuffer("MainPass"),
.destroy_queue = DeferredDestroyQueue.init(fence),
};
}
@ -127,13 +127,13 @@ pub const FrameData = struct {
if (!self.draw_submitted) return;
self.draw_submitted = false;
_ = try device.waitForFences(1, &.{self.draw_fence}, vk.TRUE, std.math.maxInt(u64));
_ = try device.waitForFences(1, &.{self.end_draw_fence}, vk.TRUE, std.math.maxInt(u64));
try self.destroy_queue.destroy(device, descriptorman);
try device.resetFences(1, &.{self.draw_fence});
try device.resetFences(1, &.{self.end_draw_fence});
try self.command_buffer.resetCommandBuffer(.{ .release_resources_bit = true });
try self.draw_cmdbuf.resetCommandBuffer(.{ .release_resources_bit = true });
}
};

View File

@ -154,7 +154,7 @@ fn writeAssetManifest(arena: std.mem.Allocator, writer: anytype, assets: []Asset
try writer.writeAll(
\\var buf: [1024 * 1024]u8 = undefined;
\\var fba = std.heap.FixedBufferAllocator.init(&buf);
\\pub var asset_paths = std.AutoHashMapUnmanaged(u64, []const u8){};
\\pub var asset_paths = std.AutoHashMapUnmanaged(u64, [:0]const u8){};
\\var initialized = false;
\\
\\// Fill map with data

View File

@ -59,7 +59,6 @@ const Args = struct {
fn parseArgs(allocator: std.mem.Allocator) !Args {
var args = try std.process.argsWithAllocator(allocator);
defer args.deinit();
var result: Args = .{};
@ -138,7 +137,7 @@ pub fn main() !void {
switch (asset_type) {
.Scene => try processScene(allocator, rel_input, output_dir, asset_list_writer),
.ShaderProgram => try processShaderProgram(allocator, rel_input, output_dir, args.dep_file, asset_list_writer),
.ShaderProgram => try processShaderProgram(allocator, rel_input, rel_output, output_dir, args.dep_file, asset_list_writer),
.Texture => try processTextureFromFile(allocator, rel_input, output_dir, asset_list_writer),
else => unreachable,
}
@ -585,22 +584,29 @@ fn readFileContents(allocator: std.mem.Allocator, path: []const u8) ![]u8 {
// Returns spirv binary source
// Caller owns memory
fn processShader(allocator: std.mem.Allocator, flags: []const []const u8, input: []const u8, maybe_dep_file: ?[]const u8) ![]u8 {
// const old_depfile_contents = if (maybe_dep_file) |dep| try readFileContents(allocator, dep) else try allocator.alloc(u8, 0);
// defer allocator.free(old_depfile_contents);
fn processShader(allocator: std.mem.Allocator, rel_output: []const u8, flags: []const []const u8, input: []const u8, stage: []const u8, maybe_dep_file: ?[]const u8) ![]u8 {
// const input_dir = std.fs.path.dirname(input).?;
const basename = std.fs.path.basename(input);
const basename_spirv = try std.mem.concat(allocator, u8, &.{ basename, ".", stage, ".spirv" });
defer allocator.free(basename_spirv);
const out_spirv_path = try std.fs.path.join(allocator, &.{ rel_output, "assets", "shader_debug", basename_spirv });
defer allocator.free(out_spirv_path);
const dirpath = std.fs.path.dirname(out_spirv_path).?;
try std.fs.cwd().makePath(dirpath);
// TODO: make sure output is stdout
const compile_result = try std.process.Child.run(.{
.allocator = allocator,
.argv = try std.mem.concat(allocator, []const u8, &.{
&.{ "glslc", "--target-env=vulkan1.3", "-std=460core", "-g", "-O0", "-o", "-" },
&.{ "glslc", "--target-env=vulkan1.3", "-std=460core", "-g", "-o", out_spirv_path },
if (maybe_dep_file) |dep| &.{ "-MD", "-MF", dep } else &.{},
flags,
&.{input},
}),
});
defer allocator.free(compile_result.stderr);
errdefer allocator.free(compile_result.stdout);
defer allocator.free(compile_result.stdout);
switch (compile_result.term) {
.Exited => |status| {
@ -614,10 +620,12 @@ fn processShader(allocator: std.mem.Allocator, flags: []const []const u8, input:
},
}
return compile_result.stdout;
const spirv = try std.fs.cwd().readFileAlloc(allocator, out_spirv_path, 9999999999999);
return spirv;
}
fn processShaderProgram(allocator: std.mem.Allocator, input: []const u8, output_dir: std.fs.Dir, dep_file: ?[]const u8, asset_list_writer: anytype) !void {
fn processShaderProgram(allocator: std.mem.Allocator, input: []const u8, rel_output: []const u8, output_dir: std.fs.Dir, dep_file: ?[]const u8, asset_list_writer: anytype) !void {
const input_dir = std.fs.path.dirname(input).?;
// Recreate file in case it's not empty
@ -671,7 +679,7 @@ fn processShaderProgram(allocator: std.mem.Allocator, input: []const u8, output_
const shader_source_path = try std.fs.path.resolve(allocator, &.{ input_dir, stage });
const relative_path = try std.fs.path.relative(allocator, try std.fs.cwd().realpathAlloc(allocator, "."), shader_source_path);
const shader = try processShader(allocator, &.{ "-DVERTEX_SHADER=1", "-fshader-stage=vert", "-fpreserve-bindings" }, relative_path, dep_file);
const shader = try processShader(allocator, rel_output, &.{ "-DVERTEX_SHADER=1", "-fshader-stage=vert", "-fpreserve-bindings" }, relative_path, "vert", dep_file);
result.graphics.vertex.source = @alignCast(shader);
}
{
@ -679,7 +687,7 @@ fn processShaderProgram(allocator: std.mem.Allocator, input: []const u8, output_
const shader_source_path = try std.fs.path.resolve(allocator, &.{ input_dir, stage });
const relative_path = try std.fs.path.relative(allocator, try std.fs.cwd().realpathAlloc(allocator, "."), shader_source_path);
const shader = try processShader(allocator, &.{ "-DFRAGMENT_SHADER=1", "-fshader-stage=frag", "-fpreserve-bindings" }, relative_path, dep_file);
const shader = try processShader(allocator, rel_output, &.{ "-DFRAGMENT_SHADER=1", "-fshader-stage=frag", "-fpreserve-bindings" }, relative_path, "frag", dep_file);
result.graphics.fragment.source = @alignCast(shader);
}
} else if (program.value.compute != null) {
@ -689,7 +697,7 @@ fn processShaderProgram(allocator: std.mem.Allocator, input: []const u8, output_
const shader_source_path = try std.fs.path.resolve(allocator, &.{ input_dir, stage });
const relative_path = try std.fs.path.relative(allocator, try std.fs.cwd().realpathAlloc(allocator, "."), shader_source_path);
const shader = try processShader(allocator, &.{ "-DCOMPUTE_SHADER=1", "-fshader-stage=compute" }, relative_path, dep_file);
const shader = try processShader(allocator, rel_output, &.{ "-DCOMPUTE_SHADER=1", "-fshader-stage=compute" }, relative_path, "comp", dep_file);
result.compute.compute.source = @alignCast(shader);
} else {
std.log.err("Provide vertex and fragment shaders for a graphics pipeline or a compute shader for a compute pipeline\n", .{});