diff --git a/src/Game.zig b/src/Game.zig index bd4293b..321708e 100644 --- a/src/Game.zig +++ b/src/Game.zig @@ -1,30 +1,28 @@ const Game = @This(); const std = @import("std"); +const math = @import("math.zig"); const glfw = @import("zglfw"); const vk = @import("vulkan"); - -const math = @import("math.zig"); const worldgen = @import("worldgen.zig"); const Blocks = @import("assets/Blocks.zig"); const Chunk = @import("assets/Chunk.zig"); -const Materials = @import("assets/Materials.zig"); -const Textures = @import("assets/Textures.zig"); -const CommandBuffer = @import("engine/CommandBuffer.zig").CommandBuffer; +const CommandBuffer = @import("engine/CommandBuffer.zig"); const Engine = @import("engine/Engine.zig"); const GenericBuffer = @import("engine/GenericBuffer.zig").GenericBuffer; +const Iterator2 = math.Iterator2; +const Materials = @import("assets/Materials.zig"); +const Matrix4x4 = math.Matrix4x4; +const Player = @import("Player.zig"); +const Quaternion = math.Quaternion; const StagingBuffer = @import("engine/StagingBuffer.zig"); const Swapchain = @import("engine/Swapchain.zig"); -const Player = @import("Player.zig"); -const Interator2 = math.Interator2; -const Matrix4x4 = math.Matrix4x4; -const Quaternion = math.Quaternion; +const Textures = @import("assets/Textures.zig"); const Vector2 = math.Vector2; const Vector2x8 = math.Vector2x8; const Vector3 = math.Vector3; const Vector4 = math.Vector4; -const ps = math.ps; const PointLight = extern struct { positionWS: [3]f32, @@ -121,7 +119,7 @@ index_buffer: IndexBuffer, global_uniforms: GlobalUniformsBuffer, global_uniforms_staging_buffer: StagingBuffer, -global_uniforms_transfer_command_buffer: CommandBuffer(.transfer, .persistent), +global_uniforms_transfer_command_buffer: CommandBuffer, global_uniforms_transfer_semaphores: []vk.Semaphore, point_lights: PointLightBuffer, directional_lights: DirectionalLightBuffer, @@ -305,10 +303,10 @@ pub fn init(allocator: std.mem.Allocator, engine: *Engine, swapchain: *Swapchain }); errdefer global_uniforms_staging_buffer.deinit(engine); - var global_uniforms_transfer_command_buffer: CommandBuffer(.transfer, .persistent) = try .init(engine); + var global_uniforms_transfer_command_buffer: CommandBuffer = try .init(engine, .transfer, .persistent); errdefer global_uniforms_transfer_command_buffer.deinit(engine); - try global_uniforms_transfer_command_buffer.beginCommandBuffer(.{}); + try global_uniforms_transfer_command_buffer.beginCommandBuffer(); global_uniforms_transfer_command_buffer.copyBuffer( global_uniforms_staging_buffer.buffer, global_uniforms.buffer, @@ -608,8 +606,10 @@ pub fn init(allocator: std.mem.Allocator, engine: *Engine, swapchain: *Swapchain const world_seed = engine.random.int(u64); std.log.info("Using world seed 0x{x:0<16}", .{world_seed}); - var it = Interator2(i16).init(-8, -8, 7, 7); - + var it = Iterator2(i16).init(.{ + .min = .{ -8, -8 }, + .max = .{ 7, 7 }, + }); while (it.next()) |chunk_coords2| { const chunk_coords3 = chunk_coords2 ++ [_]i16{0}; @@ -852,10 +852,10 @@ fn render(self: *Game) !void { const extent = self.swapchain.extent; - const command_buffer: CommandBuffer(.graphics, .transient) = try .init(self.engine); + const command_buffer: CommandBuffer = try .init(self.engine, .graphics, .transient); // NOTE Do not free command buffer yet - try command_buffer.beginCommandBuffer(.{}); + try command_buffer.beginCommandBuffer(); { command_buffer.beginRenderPass(.{ .render_pass = self.swapchain.render_pass, diff --git a/src/assets/Chunk.zig b/src/assets/Chunk.zig index bdcad9b..e1bbe3f 100644 --- a/src/assets/Chunk.zig +++ b/src/assets/Chunk.zig @@ -6,7 +6,7 @@ const vk = @import("vulkan"); const math = @import("../math.zig"); const Blocks = @import("Blocks.zig"); -const CommandBuffer = @import("../engine/CommandBuffer.zig").CommandBuffer; +const CommandBuffer = @import("../engine/CommandBuffer.zig"); const Engine = @import("../engine/Engine.zig"); const Game = @import("../Game.zig"); const GenericBuffer = @import("../engine/GenericBuffer.zig").GenericBuffer; @@ -235,7 +235,7 @@ pub fn refresh(self: *Chunk, engine: *Engine, blocks: *const Blocks, neighbors: self.object_count = object_count; } -pub fn draw(self: *const Chunk, layout: vk.PipelineLayout, command_buffer: CommandBuffer(.graphics, .transient)) void { +pub fn draw(self: *const Chunk, layout: vk.PipelineLayout, command_buffer: CommandBuffer) void { command_buffer.bindDescriptorSets(.graphics, layout, 1, &.{self.descriptor_set}, &.{}); command_buffer.drawIndexed(.{ .index_count = 6, .instance_count = self.object_count }); } diff --git a/src/engine/CommandBuffer.zig b/src/engine/CommandBuffer.zig index 2aa7e42..ead9687 100644 --- a/src/engine/CommandBuffer.zig +++ b/src/engine/CommandBuffer.zig @@ -1,3 +1,12 @@ +//! A thin wrapper around `@import("vk").CommandBufferProxy` that ziggifies +//! arguments by turning pointer-length pairs into slices and integrates with +//! different queues from `Engine` struct. +//! +//! The wrapper retains information about the queue type and whether its +//! transient, such that it can submit to the correct queue preallocated in the +//! `Engine` struct when calling `CommandBuffer.submit`. + +const CommandBuffer = @This(); const std = @import("std"); const vk = @import("vulkan"); @@ -7,6 +16,42 @@ const QueueType = @import("QueueType.zig").QueueType; const Transient = @import("Transient.zig").Transient; const WaitSemaphore = @import("WaitSemaphore.zig"); +proxy: vk.CommandBufferProxy, +allocator: std.mem.Allocator, +queue_type: QueueType, +transient: Transient, + +pub fn init(engine: *Engine, queue_type: QueueType, transient: Transient) !CommandBuffer { + const handle = try engine.allocateCommandBuffer(.{ + .queue_type = queue_type, + .transient = transient, + .level = .primary, + }); + const proxy: vk.CommandBufferProxy = .init(handle, engine.device.wrapper); + const allocator = engine.vk_allocator.allocator; + return .{ + .proxy = proxy, + .allocator = allocator, + .queue_type = queue_type, + .transient = transient, + }; +} + +pub fn deinit(self: *CommandBuffer, engine: *Engine) void { + engine.freeCommandBuffer(.{ + .queue_type = self.queue_type, + .transient = self.transient, + .command_buffer = self.proxy.handle, + }); + self.* = undefined; +} + +pub fn submit(self: CommandBuffer, engine: *Engine, submit_info: SubmitInfo) !void { + try submitCommandBuffer(engine, self.queue_type, self.proxy.handle, submit_info); +} + +// --- VULKAN WRAPPERS --------------------------------------------------------- + pub const DrawIndexed = struct { index_count: u32, instance_count: u32 = 1, @@ -42,218 +87,152 @@ pub const VertexBufferBinding = struct { offset: usize, }; -pub fn CommandBuffer(comptime queue_type: QueueType, comptime transient: Transient) type { - return struct { - const Self = @This(); - - proxy: vk.CommandBufferProxy, - allocator: std.mem.Allocator, - - pub fn init(engine: *const Engine) !Self { - const handle = try allocateCommandBuffer(engine, queue_type, transient); - const proxy: vk.CommandBufferProxy = .init(handle, engine.device.wrapper); - const allocator = engine.vk_allocator.allocator; - return .{ .proxy = proxy, .allocator = allocator }; - } - - pub fn deinit(self: *Self, engine: *const Engine) void { - freeCommandBuffer(engine, queue_type, transient, self.proxy.handle); - self.* = undefined; - } - - pub fn submit(self: Self, engine: *const Engine, submit_info: SubmitInfo) !void { - try submitCommandBuffer(engine, queue_type, self.proxy.handle, submit_info); - } - - pub const CommandBufferBeginInfo = struct { - flags: vk.CommandBufferUsageFlags = .{ - .one_time_submit_bit = switch (transient) { - .persistent => false, - .transient => true, - }, +pub fn beginCommandBuffer(self: CommandBuffer) !void { + try self.proxy.beginCommandBuffer(&.{ + .flags = .{ + .one_time_submit_bit = switch (self.transient) { + .persistent => true, + .transient => false, }, - inheritance_info: ?vk.CommandBufferInheritanceInfo = null, - }; - - pub fn beginCommandBuffer(self: Self, begin_info: CommandBufferBeginInfo) !void { - try self.proxy.beginCommandBuffer(&.{ - .flags = begin_info.flags, - .p_inheritance_info = if (begin_info.inheritance_info) |*x| x else null, - }); - } - - pub inline fn beginRenderPass(self: Self, render_pass_begin: RenderPassBeginInfo, contents: vk.SubpassContents) void { - self.proxy.beginRenderPass(&.{ - .render_pass = render_pass_begin.render_pass, - .framebuffer = render_pass_begin.framebuffer, - .render_area = render_pass_begin.render_area, - .clear_value_count = @intCast(render_pass_begin.clear_values.len), - .p_clear_values = render_pass_begin.clear_values.ptr, - }, contents); - } - - pub inline fn bindDescriptorSet( - self: Self, - pipeline_bind_point: vk.PipelineBindPoint, - layout: vk.PipelineLayout, - set: u32, - descriptor_set: vk.DescriptorSet, - dynamic_offset: ?u32, - ) void { - self.bindDescriptorSets( - pipeline_bind_point, - layout, - set, - &.{descriptor_set}, - if (dynamic_offset) |x| &.{x} else &.{}, - ); - } - - pub inline fn bindDescriptorSets( - self: Self, - pipeline_bind_point: vk.PipelineBindPoint, - layout: vk.PipelineLayout, - first_set: u32, - descriptor_sets: []const vk.DescriptorSet, - dynamic_offsets: []const u32, - ) void { - self.proxy.bindDescriptorSets( - pipeline_bind_point, - layout, - first_set, - @intCast(descriptor_sets.len), - descriptor_sets.ptr, - @intCast(dynamic_offsets.len), - dynamic_offsets.ptr, - ); - } - - pub inline fn bindPipeline(self: Self, pipeline_bind_point: vk.PipelineBindPoint, pipeline: vk.Pipeline) void { - self.proxy.bindPipeline(pipeline_bind_point, pipeline); - } - - pub inline fn bindIndexBuffer(self: Self, buffer: vk.Buffer, offset: u64, index_type: vk.IndexType) void { - self.proxy.bindIndexBuffer(buffer, offset, index_type); - } - - pub inline fn bindVertexBuffers(self: Self, first_binding: u32, bindings: []const VertexBufferBinding) !void { - var vertex_buffer_bindings = std.MultiArrayList(VertexBufferBinding){}; - defer vertex_buffer_bindings.deinit(self.allocator); - try vertex_buffer_bindings.ensureTotalCapacity(self.allocator, bindings.len); - - for (bindings) |binding| { - vertex_buffer_bindings.appendAssumeCapacity(binding); - } - - self.proxy.bindVertexBuffers( - first_binding, - @intCast(vertex_buffer_bindings.len), - vertex_buffer_bindings.items(.buffer).ptr, - vertex_buffer_bindings.items(.offset).ptr, - ); - } - - pub inline fn drawIndexed(self: Self, draw_indexed: DrawIndexed) void { - self.proxy.drawIndexed( - draw_indexed.index_count, - draw_indexed.instance_count, - draw_indexed.first_index, - draw_indexed.vertex_offset, - draw_indexed.first_instance, - ); - } - - pub inline fn endCommandBuffer(self: Self) !void { - try self.proxy.endCommandBuffer(); - } - - pub inline fn endRenderPass(self: Self) void { - self.proxy.endRenderPass(); - } - - pub inline fn copyBuffer( - self: Self, - src_buffer: vk.Buffer, - dst_buffer: vk.Buffer, - regions: []const vk.BufferCopy, - ) void { - self.proxy.copyBuffer(src_buffer, dst_buffer, @intCast(regions.len), regions.ptr); - } - - pub inline fn copyBufferToImage( - self: Self, - src_buffer: vk.Buffer, - dst_image: vk.Image, - 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); - } - - pub inline fn pipelineBarrier(self: Self, barrier: PipelineBarrier) void { - self.proxy.pipelineBarrier( - 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, - ); - } - - pub inline fn setScissor(self: Self, first_scissor: u32, scissors: []const vk.Rect2D) void { - self.proxy.setScissor(first_scissor, @intCast(scissors.len), scissors.ptr); - } - - pub inline fn setViewport(self: Self, first_viewport: u32, viewports: []const vk.Viewport) void { - self.proxy.setViewport(first_viewport, @intCast(viewports.len), viewports.ptr); - } - }; -} - -inline fn resolveCommandPool(self: *const Engine, comptime queue_type: QueueType, comptime transient: Transient) vk.CommandPool { - return switch (queue_type) { - .graphics => switch (transient) { - .persistent => self.graphics_command_pool, - .transient => self.transient_graphics_command_pool, }, - .compute => switch (transient) { - .persistent => self.compute_command_pool, - .transient => self.transient_compute_command_pool, - }, - .transfer => switch (transient) { - .persistent => self.transfer_command_pool, - .transient => self.transient_transfer_command_pool, - }, - }; + }); } -fn allocateCommandBuffer(engine: *const Engine, comptime queue_type: QueueType, comptime transient: Transient) !vk.CommandBuffer { - const command_pool = resolveCommandPool(engine, queue_type, transient); - - var command_buffers: [1]vk.CommandBuffer = undefined; - try engine.device.allocateCommandBuffers(&.{ - .command_pool = command_pool, - .level = .primary, - .command_buffer_count = command_buffers.len, - }, &command_buffers); - - return command_buffers[0]; +pub fn beginRenderPass(self: CommandBuffer, render_pass_begin: RenderPassBeginInfo, contents: vk.SubpassContents) void { + self.proxy.beginRenderPass(&.{ + .render_pass = render_pass_begin.render_pass, + .framebuffer = render_pass_begin.framebuffer, + .render_area = render_pass_begin.render_area, + .clear_value_count = @intCast(render_pass_begin.clear_values.len), + .p_clear_values = render_pass_begin.clear_values.ptr, + }, contents); } -fn freeCommandBuffer(engine: *const Engine, comptime queue_type: QueueType, comptime transient: Transient, command_buffer: vk.CommandBuffer) void { - const command_pool = resolveCommandPool(engine, queue_type, transient); - const command_buffers = [_]vk.CommandBuffer{command_buffer}; - - engine.device.freeCommandBuffers(command_pool, command_buffers.len, &command_buffers); +pub fn bindDescriptorSet( + self: CommandBuffer, + pipeline_bind_point: vk.PipelineBindPoint, + layout: vk.PipelineLayout, + set: u32, + descriptor_set: vk.DescriptorSet, + dynamic_offset: ?u32, +) void { + self.bindDescriptorSets( + pipeline_bind_point, + layout, + set, + &.{descriptor_set}, + if (dynamic_offset) |x| &.{x} else &.{}, + ); } +pub fn bindDescriptorSets( + self: CommandBuffer, + pipeline_bind_point: vk.PipelineBindPoint, + layout: vk.PipelineLayout, + first_set: u32, + descriptor_sets: []const vk.DescriptorSet, + dynamic_offsets: []const u32, +) void { + self.proxy.bindDescriptorSets( + pipeline_bind_point, + layout, + first_set, + @intCast(descriptor_sets.len), + descriptor_sets.ptr, + @intCast(dynamic_offsets.len), + dynamic_offsets.ptr, + ); +} + +pub fn bindPipeline(self: CommandBuffer, pipeline_bind_point: vk.PipelineBindPoint, pipeline: vk.Pipeline) void { + self.proxy.bindPipeline(pipeline_bind_point, pipeline); +} + +pub fn bindIndexBuffer(self: CommandBuffer, buffer: vk.Buffer, offset: u64, index_type: vk.IndexType) void { + self.proxy.bindIndexBuffer(buffer, offset, index_type); +} + +pub fn bindVertexBuffers(self: CommandBuffer, first_binding: u32, bindings: []const VertexBufferBinding) !void { + var vertex_buffer_bindings = std.MultiArrayList(VertexBufferBinding){}; + defer vertex_buffer_bindings.deinit(self.allocator); + try vertex_buffer_bindings.ensureTotalCapacity(self.allocator, bindings.len); + + for (bindings) |binding| { + vertex_buffer_bindings.appendAssumeCapacity(binding); + } + + self.proxy.bindVertexBuffers( + first_binding, + @intCast(vertex_buffer_bindings.len), + vertex_buffer_bindings.items(.buffer).ptr, + vertex_buffer_bindings.items(.offset).ptr, + ); +} + +pub fn drawIndexed(self: CommandBuffer, draw_indexed: DrawIndexed) void { + self.proxy.drawIndexed( + draw_indexed.index_count, + draw_indexed.instance_count, + draw_indexed.first_index, + draw_indexed.vertex_offset, + draw_indexed.first_instance, + ); +} + +pub fn endCommandBuffer(self: CommandBuffer) !void { + try self.proxy.endCommandBuffer(); +} + +pub fn endRenderPass(self: CommandBuffer) void { + self.proxy.endRenderPass(); +} + +pub fn copyBuffer( + self: CommandBuffer, + src_buffer: vk.Buffer, + dst_buffer: vk.Buffer, + regions: []const vk.BufferCopy, +) void { + self.proxy.copyBuffer(src_buffer, dst_buffer, @intCast(regions.len), regions.ptr); +} + +pub fn copyBufferToImage( + self: CommandBuffer, + src_buffer: vk.Buffer, + dst_image: vk.Image, + 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); +} + +pub fn pipelineBarrier(self: CommandBuffer, barrier: PipelineBarrier) void { + self.proxy.pipelineBarrier( + 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, + ); +} + +pub fn setScissor(self: CommandBuffer, first_scissor: u32, scissors: []const vk.Rect2D) void { + self.proxy.setScissor(first_scissor, @intCast(scissors.len), scissors.ptr); +} + +pub fn setViewport(self: CommandBuffer, first_viewport: u32, viewports: []const vk.Viewport) void { + self.proxy.setViewport(first_viewport, @intCast(viewports.len), viewports.ptr); +} + +// --- HELPER FUNCTIONS -------------------------------------------------------- + fn submitCommandBuffer( - engine: *const Engine, - comptime queue_type: QueueType, + engine: *Engine, + queue_type: QueueType, command_buffer: vk.CommandBuffer, submit_info: SubmitInfo, ) !void { diff --git a/src/engine/Engine.zig b/src/engine/Engine.zig index 8e2bd9d..be958c3 100644 --- a/src/engine/Engine.zig +++ b/src/engine/Engine.zig @@ -7,6 +7,7 @@ const vk = @import("vulkan"); const Queue = @import("Queue.zig"); const QueueType = @import("QueueType.zig").QueueType; +const Transient = @import("Transient.zig").Transient; const VkAllocator = @import("VkAllocator.zig"); pub const Mode = union(enum) { @@ -347,10 +348,34 @@ pub fn init(allocator: std.mem.Allocator, maybe_window: ?*glfw.Window) !Engine { }, &vk_allocator.interface); errdefer device.destroyCommandPool(transient_transfer_command_pool, &vk_allocator.interface); - const graphics_queue: Queue = .initAllocation(device, queue_allocations.graphics_queue); - const compute_queue: Queue = .initAllocation(device, queue_allocations.compute_queue); - const transfer_queue: Queue = .initAllocation(device, queue_allocations.transfer_queue); - const presentation_queue: Queue = if (maybe_window != null) .initAllocation(device, queue_allocations.presentation_queue) else undefined; + const graphics_queue: Queue = .init( + device.getDeviceQueue( + queue_allocations.graphics_queue.family, + queue_allocations.graphics_queue.index, + ), + queue_allocations.graphics_queue, + ); + const compute_queue: Queue = .init( + device.getDeviceQueue( + queue_allocations.compute_queue.family, + queue_allocations.compute_queue.index, + ), + queue_allocations.compute_queue, + ); + const transfer_queue: Queue = .init( + device.getDeviceQueue( + queue_allocations.transfer_queue.family, + queue_allocations.transfer_queue.index, + ), + queue_allocations.transfer_queue, + ); + const presentation_queue: Queue = if (maybe_window != null) .init( + device.getDeviceQueue( + queue_allocations.presentation_queue.family, + queue_allocations.presentation_queue.index, + ), + queue_allocations.presentation_queue, + ) else undefined; // --- CREATE AND SEED RNG ------------------------------------------------- @@ -613,6 +638,23 @@ fn findPresentationQueueFamily(queue_families_properties: []const vk.QueueFamily return null; } +fn resolveCommandPool(self: *const Engine, queue_type: QueueType, transient: Transient) vk.CommandPool { + return switch (queue_type) { + .graphics => switch (transient) { + .persistent => self.graphics_command_pool, + .transient => self.transient_graphics_command_pool, + }, + .compute => switch (transient) { + .persistent => self.compute_command_pool, + .transient => self.transient_compute_command_pool, + }, + .transfer => switch (transient) { + .persistent => self.transfer_command_pool, + .transient => self.transient_transfer_command_pool, + }, + }; +} + // --- VULKAN WRAPPERS --------------------------------------------------------- pub const BufferCreateInfo = struct { @@ -622,6 +664,18 @@ pub const BufferCreateInfo = struct { queue_family_indices: []const u32 = &.{}, }; +pub const CommandBufferAllocateInfo = struct { + queue_type: QueueType, + transient: Transient, + level: vk.CommandBufferLevel, +}; + +pub const CommandBufferFreeInfo = struct { + queue_type: QueueType, + transient: Transient, + command_buffer: vk.CommandBuffer, +}; + pub const DescriptorPoolCreateInfo = struct { flags: vk.DescriptorPoolCreateFlags = .{}, max_sets: u32, @@ -798,6 +852,17 @@ pub fn createBuffer(self: *Engine, create_info: BufferCreateInfo) !vk.Buffer { return buffer; } +pub fn allocateCommandBuffer(self: *Engine, allocate_info: CommandBufferAllocateInfo) !vk.CommandBuffer { + const command_pool = self.resolveCommandPool(allocate_info.queue_type, allocate_info.transient); + var command_buffers: [1]vk.CommandBuffer = undefined; + try self.device.allocateCommandBuffers(&.{ + .command_pool = command_pool, + .level = allocate_info.level, + .command_buffer_count = command_buffers.len, + }, &command_buffers); + return command_buffers[0]; +} + pub fn allocateDescriptorSet(self: *Engine, allocate_info: DescriptorSetAllocateInfo) !vk.DescriptorSet { var descriptor_sets: [1]vk.DescriptorSet = undefined; try self.allocateDescriptorSets(.{ @@ -831,6 +896,14 @@ pub fn allocateDescriptorSets(self: *Engine, allocate_info: DescriptorSetsAlloca }, descriptor_sets.ptr); } +pub fn bindBufferMemory(self: *Engine, buffer: vk.Buffer, memory: vk.DeviceMemory, memory_offset: vk.DeviceSize) !void { + try self.device.bindBufferMemory(buffer, memory, memory_offset); +} + +pub fn bindImageMemory(self: *Engine, image: vk.Image, memory: vk.DeviceMemory, memory_offset: vk.DeviceSize) !void { + try self.device.bindImageMemory(image, memory, memory_offset); +} + pub fn createDescriptorSetLayout(self: *Engine, create_info: DescriptorSetLayoutCreateInfo) !vk.DescriptorSetLayout { var arena: std.heap.ArenaAllocator = .init(self.vk_allocator.allocator); defer arena.deinit(); @@ -1106,6 +1179,16 @@ pub fn destroyShaderModule(self: *Engine, shader_module: vk.ShaderModule) void { self.device.destroyShaderModule(shader_module, &self.vk_allocator.interface); } +pub fn deviceWaitIdle(self: *Engine) !void { + try self.device.deviceWaitIdle(); +} + +pub fn freeCommandBuffer(self: *Engine, free_info: CommandBufferFreeInfo) void { + const command_pool = self.resolveCommandPool(free_info.queue_type, free_info.transient); + const command_buffers = [_]vk.CommandBuffer{free_info.command_buffer}; + self.device.freeCommandBuffers(command_pool, command_buffers.len, &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; @@ -1115,10 +1198,27 @@ pub fn freeMemory(self: *Engine, device_memory: vk.DeviceMemory) void { self.device.freeMemory(device_memory, &self.vk_allocator.interface); } +pub fn getBufferMemoryRequirements(self: *Engine, buffer: vk.Buffer) vk.MemoryRequirements { + return self.device.getBufferMemoryRequirements(buffer); +} + +pub fn getImageMemoryRequirements(self: *Engine, image: vk.Image) vk.MemoryRequirements { + return self.device.getImageMemoryRequirements(image); +} + +pub fn mapMemory(self: *Engine, memory: vk.DeviceMemory, offset: vk.DeviceSize, size: vk.DeviceSize, flags: vk.MemoryMapFlags) ![]u8 { + const mapped_memory = try self.device.mapMemory(memory, offset, size, flags); + return @as([*]u8, @ptrCast(mapped_memory))[0..size]; +} + pub fn resetFence(self: *Engine, fence: vk.Fence) !void { try self.device.resetFences(1, @ptrCast(&fence)); } +pub fn unmapMemory(self: *Engine, memory: vk.DeviceMemory) void { + self.device.unmapMemory(memory); +} + pub fn updateDescriptorSets(self: *Engine, update_info: DescriptorSetsUpdateInfo) !void { var arena: std.heap.ArenaAllocator = .init(self.vk_allocator.allocator); defer arena.deinit(); diff --git a/src/engine/GenericBuffer.zig b/src/engine/GenericBuffer.zig index d87071f..7c5cd90 100644 --- a/src/engine/GenericBuffer.zig +++ b/src/engine/GenericBuffer.zig @@ -2,7 +2,7 @@ const std = @import("std"); const vk = @import("vulkan"); -const CommandBuffer = @import("CommandBuffer.zig").CommandBuffer; +const CommandBuffer = @import("CommandBuffer.zig"); const Engine = @import("Engine.zig"); const StagingBuffer = @import("StagingBuffer.zig"); const TargetQueue = @import("TargetQueue.zig").TargetQueue; @@ -71,14 +71,14 @@ pub fn GenericBuffer(comptime Header: type, comptime Element: type) type { engine.setObjectName(buffer, "B {s} [{s}, {s}]", .{ name, @typeName(Header), @typeName(Element) }); } - const memory_requirements = engine.device.getBufferMemoryRequirements(buffer); + const memory_requirements = engine.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); + try engine.bindBufferMemory(buffer, device_memory, 0); return .{ .buffer = buffer, @@ -154,10 +154,10 @@ pub fn GenericBuffer(comptime Header: type, comptime Element: type) type { @memcpy(staging_memory[array_write_offset..write_size], std.mem.sliceAsBytes(write_info.elements)); staging_buffer.unmap(engine); - var command_buffer: CommandBuffer(.transfer, .transient) = try .init(engine); + var command_buffer: CommandBuffer = try .init(engine, .transfer, .transient); defer command_buffer.deinit(engine); - try command_buffer.beginCommandBuffer(.{}); + try command_buffer.beginCommandBuffer(); command_buffer.copyBuffer(staging_buffer.buffer, self.buffer, regions.items); try command_buffer.endCommandBuffer(); diff --git a/src/engine/Queue.zig b/src/engine/Queue.zig index 7d5b36a..65b7545 100644 --- a/src/engine/Queue.zig +++ b/src/engine/Queue.zig @@ -11,9 +11,9 @@ pub const Allocation = struct { handle: vk.Queue, allocation: Allocation, -pub fn initAllocation(device: vk.DeviceProxy, allocation: Allocation) Queue { +pub fn init(handle: vk.Queue, allocation: Allocation) Queue { return .{ - .handle = device.getDeviceQueue(allocation.family, allocation.index), + .handle = handle, .allocation = allocation, }; } diff --git a/src/engine/StagingBuffer.zig b/src/engine/StagingBuffer.zig index 9bc6fd9..a93ff6f 100644 --- a/src/engine/StagingBuffer.zig +++ b/src/engine/StagingBuffer.zig @@ -31,7 +31,7 @@ pub fn init(engine: *Engine, init_info: InitInfo) !StagingBuffer { }); errdefer engine.destroyBuffer(buffer); - const memory_requirements = engine.device.getBufferMemoryRequirements(buffer); + const memory_requirements = engine.getBufferMemoryRequirements(buffer); const device_memory = try engine.allocate( memory_requirements, .{ @@ -41,7 +41,7 @@ pub fn init(engine: *Engine, init_info: InitInfo) !StagingBuffer { ); errdefer engine.freeMemory(device_memory); - try engine.device.bindBufferMemory(buffer, device_memory, 0); + try engine.bindBufferMemory(buffer, device_memory, 0); return .{ .buffer = buffer, @@ -65,10 +65,10 @@ pub fn map(self: StagingBuffer, engine: *Engine) ![]u8 { } pub fn mapPartial(self: StagingBuffer, engine: *Engine, offset: u32, len: u32) ![]u8 { - const mapped_memory = try engine.device.mapMemory(self.device_memory, offset, len, .{}); - return @as([*]u8, @ptrCast(mapped_memory))[0..len]; + const mapped_memory = try engine.mapMemory(self.device_memory, offset, len, .{}); + return mapped_memory; } pub fn unmap(self: StagingBuffer, engine: *Engine) void { - engine.device.unmapMemory(self.device_memory); + engine.unmapMemory(self.device_memory); } diff --git a/src/engine/Swapchain.zig b/src/engine/Swapchain.zig index c9f0eed..194be04 100644 --- a/src/engine/Swapchain.zig +++ b/src/engine/Swapchain.zig @@ -3,7 +3,7 @@ const std = @import("std"); const vk = @import("vulkan"); -const CommandBuffer = @import("CommandBuffer.zig").CommandBuffer; +const CommandBuffer = @import("CommandBuffer.zig"); const Engine = @import("Engine.zig"); const QSM = @import("QueueSharingMode.zig"); const Texture = @import("Texture.zig"); @@ -271,7 +271,7 @@ pub fn recreate(self: *Swapchain, engine: *Engine) !void { } pub const PresentInfo = struct { - command_buffer: CommandBuffer(.graphics, .transient), + command_buffer: CommandBuffer, wait_semaphores: []const WaitSemaphore = &.{}, }; @@ -411,7 +411,7 @@ const SwapchainImage = struct { semaphore_render_finished: vk.Semaphore, fence: vk.Fence, framebuffer: vk.Framebuffer, - command_buffer: ?CommandBuffer(.graphics, .transient), + command_buffer: ?CommandBuffer, const InitProps = struct { image: vk.Image, diff --git a/src/engine/Texture.zig b/src/engine/Texture.zig index bd1f60d..f30bedb 100644 --- a/src/engine/Texture.zig +++ b/src/engine/Texture.zig @@ -3,7 +3,7 @@ const std = @import("std"); const vk = @import("vulkan"); -const CommandBuffer = @import("CommandBuffer.zig").CommandBuffer; +const CommandBuffer = @import("CommandBuffer.zig"); const Engine = @import("Engine.zig"); const StagingBuffer = @import("StagingBuffer.zig"); const TargetQueue = @import("TargetQueue.zig").TargetQueue; @@ -116,14 +116,14 @@ pub fn init(engine: *Engine, init_info: InitInfo) !Texture { engine.setObjectName(image, "I {s} [{s}]", .{ name, @tagName(init_info.usage) }); } - const memory_requirements = engine.device.getImageMemoryRequirements(image); + const memory_requirements = engine.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); + try engine.bindImageMemory(image, device_memory, 0); const image_view = try engine.createImageView(.{ .image = image, @@ -205,10 +205,10 @@ pub fn writeRaw(self: Texture, engine: *Engine, data: []const u8) !void { // --- TRANSITION TO TRANSFER_DST_OPTIMAL AND COPY ----------------- - var transfer_command_buffer: CommandBuffer(.transfer, .transient) = try .init(engine); + var transfer_command_buffer: CommandBuffer = try .init(engine, .transfer, .transient); defer transfer_command_buffer.deinit(engine); - try transfer_command_buffer.beginCommandBuffer(.{}); + try transfer_command_buffer.beginCommandBuffer(); transfer_command_buffer.pipelineBarrier(.{ .src_stage_mask = .{ .top_of_pipe_bit = true }, @@ -265,10 +265,10 @@ pub fn writeRaw(self: Texture, engine: *Engine, data: []const u8) !void { // --- TRANSITION TO SHADER_READ_ONLY_OPTIMAL ---------------------- - var graphics_command_buffer: CommandBuffer(.graphics, .transient) = try .init(engine); + var graphics_command_buffer: CommandBuffer = try .init(engine, .graphics, .transient); defer graphics_command_buffer.deinit(engine); - try graphics_command_buffer.beginCommandBuffer(.{}); + try graphics_command_buffer.beginCommandBuffer(); graphics_command_buffer.pipelineBarrier(.{ .src_stage_mask = .{ .transfer_bit = true }, diff --git a/src/main.zig b/src/main.zig index 632e07b..f388777 100644 --- a/src/main.zig +++ b/src/main.zig @@ -101,7 +101,7 @@ pub fn main() !void { std.log.debug("Exitted the game loop", .{}); for (swapchain.swapchain_images) |x| engine.waitForFence(x.fence) catch {}; - engine.device.deviceWaitIdle() catch {}; + engine.deviceWaitIdle() catch {}; } const CallbackContext = struct { diff --git a/src/math.zig b/src/math.zig index 7d55b18..9e89b01 100644 --- a/src/math.zig +++ b/src/math.zig @@ -1,6 +1,5 @@ -pub const Interator2 = @import("math/Interator2.zig").Interator2; -pub const Interator3 = @import("math/Interator3.zig").Interator3; -pub const Iterator3 = @import("math/Iterator3.zig"); +pub const Iterator2 = @import("math/Iterator2.zig").Iterator2; +pub const Iterator3 = @import("math/Iterator3.zig").Iterator3; pub const Matrix4x4 = @import("math/Matrix4x4.zig").Matrix4x4; pub const Quaternion = @import("math/Quaternion.zig").Quaternion; pub const Vector2 = @import("math/Vector2.zig").Vector2; diff --git a/src/math/Interator2.zig b/src/math/Interator2.zig deleted file mode 100644 index 0031bf4..0000000 --- a/src/math/Interator2.zig +++ /dev/null @@ -1,38 +0,0 @@ -pub fn Interator2(comptime T: type) type { - return struct { - const Self = @This(); - const Vector = @Vector(2, T); - - min: Vector, - max: Vector, - current: ?Vector, - - pub fn init(min_x: T, min_y: T, max_x: T, max_y: T) Self { - const min: Vector = .{ min_x, min_y }; - const max: Vector = .{ max_x, max_y }; - return .{ - .min = min, - .max = max, - .current = min, - }; - } - - pub fn next(self: *Self) ?[2]T { - const current = self.current orelse return null; - var next_current = current; - - next_current[0] = next_current[0] + 1; - if (next_current[0] > self.max[0]) { - next_current[0] = self.min[0]; - next_current[1] = next_current[1] + 1; - if (next_current[1] > self.max[1]) { - self.current = null; - return current; - } - } - - self.current = next_current; - return current; - } - }; -} diff --git a/src/math/Interator3.zig b/src/math/Interator3.zig deleted file mode 100644 index 6b779bc..0000000 --- a/src/math/Interator3.zig +++ /dev/null @@ -1,42 +0,0 @@ -pub fn Interator3(comptime T: type) type { - return struct { - const Self = @This(); - const Vector = @Vector(3, T); - - min: Vector, - max: Vector, - current: ?Vector, - - pub fn init(min_x: T, min_y: T, min_z: T, max_x: T, max_y: T, max_z: T) Self { - const min: Vector = .{ min_x, min_y, min_z }; - const max: Vector = .{ max_x, max_y, max_z }; - return .{ - .min = min, - .max = max, - .current = min, - }; - } - - pub fn next(self: *Self) ?[3]T { - const current = self.current orelse return null; - var next_current = current; - - next_current[0] = next_current[0] + 1; - if (next_current[0] > self.max[0]) { - next_current[0] = self.min[0]; - next_current[1] = next_current[1] + 1; - if (next_current[1] > self.max[1]) { - next_current[1] = self.min[1]; - next_current[2] = next_current[2] + 1; - if (next_current[2] > self.max[2]) { - self.current = null; - return current; - } - } - } - - self.current = next_current; - return current; - } - }; -} diff --git a/src/math/Iterator2.zig b/src/math/Iterator2.zig new file mode 100644 index 0000000..8bdfa44 --- /dev/null +++ b/src/math/Iterator2.zig @@ -0,0 +1,44 @@ +pub fn Iterator2(comptime T: type) type { + return struct { + const Self = @This(); + const Array = [2]T; + + min: Array, + max: Array, + step: Array, + current: ?Array, + + pub const InitInfo = struct { + min: Array, + max: Array, + step: Array = .{ 1, 1 }, + }; + + pub fn init(init_info: InitInfo) Self { + return .{ + .min = init_info.min, + .max = init_info.max, + .step = init_info.step, + .current = init_info.min, + }; + } + + pub fn next(self: *Self) ?Array { + const current = self.current orelse return null; + var next_current = current; + + next_current[0] = next_current[0] + self.step[0]; + if (next_current[0] > self.max[0]) { + next_current[0] = self.min[0]; + next_current[1] = next_current[1] + self.step[1]; + if (next_current[1] > self.max[1]) { + self.current = null; + return current; + } + } + + self.current = next_current; + return current; + } + }; +} diff --git a/src/math/Iterator3.zig b/src/math/Iterator3.zig index fbc5975..2951144 100644 --- a/src/math/Iterator3.zig +++ b/src/math/Iterator3.zig @@ -1,38 +1,48 @@ -const Vector3 = @import("Vector3.zig").Vector3; +pub fn Iterator3(comptime T: type) type { + return struct { + const Self = @This(); + const Array = [3]T; -min: Vector3, -max: Vector3, -step: Vector3, -current: ?Vector3, + min: Array, + max: Array, + step: Array, + current: ?Array, -pub fn init(min: Vector3, max: Vector3, step: Vector3) @This() { - return .{ - .min = min, - .max = max, - .step = step, - .current = min, + pub const InitInfo = struct { + min: Array, + max: Array, + step: Array = .{ 1, 1, 1 }, + }; + + pub fn init(init_info: InitInfo) Self { + return .{ + .min = init_info.min, + .max = init_info.max, + .step = init_info.step, + .current = init_info.min, + }; + } + + pub fn next(self: *Self) ?Array { + const current = self.current orelse return null; + var next_current = current; + + next_current[0] = next_current[0] + self.step[0]; + if (next_current[0] > self.max[0]) { + next_current[0] = self.min[0]; + next_current[1] = next_current[1] + self.step[1]; + if (next_current[1] > self.max[1]) { + next_current[1] = self.min[1]; + next_current[2] = next_current[2] + self.step[2]; + if (next_current[2] > self.max[2]) { + self.current = null; + return current; + } + } + } + + self.current = next_current; + return current; + } }; } - -pub fn next(self: *@This()) ?Vector3 { - const current = self.current orelse return null; - - var next_current = current; - - next_current = next_current.setX(next_current.getX() + self.step.getX()); - if (next_current.getX() > self.max.getX()) { - next_current = next_current.setX(self.min.getX()); - next_current = next_current.setY(next_current.getY() + self.step.getY()); - if (next_current.getY() > self.max.getY()) { - next_current = next_current.setY(self.min.getY()); - next_current = next_current.setZ(next_current.getZ() + self.step.getZ()); - if (next_current.getZ() > self.max.getZ()) { - self.current = null; - return current; - } - } - } - - self.current = next_current; - return current; -} diff --git a/src/math/Vector2x8.zig b/src/math/Vector2x8.zig index af929af..85923ab 100644 --- a/src/math/Vector2x8.zig +++ b/src/math/Vector2x8.zig @@ -1,10 +1,9 @@ const std = @import("std"); const math = @import("../math.zig"); -const Vector2 = math.Vector2; +const Vector2 = @import("Vector2.zig").Vector2; const f32x8 = math.f32x8; - const ps = math.ps; pub const Vector2x8 = extern struct {