More wrappers, more cleanup

This commit is contained in:
2025-12-04 00:27:10 +01:00
parent be4ae4f1a7
commit d885fbea43
16 changed files with 419 additions and 368 deletions

View File

@@ -1,30 +1,28 @@
const Game = @This(); const Game = @This();
const std = @import("std"); const std = @import("std");
const math = @import("math.zig");
const glfw = @import("zglfw"); const glfw = @import("zglfw");
const vk = @import("vulkan"); const vk = @import("vulkan");
const math = @import("math.zig");
const worldgen = @import("worldgen.zig"); const worldgen = @import("worldgen.zig");
const Blocks = @import("assets/Blocks.zig"); const Blocks = @import("assets/Blocks.zig");
const Chunk = @import("assets/Chunk.zig"); const Chunk = @import("assets/Chunk.zig");
const Materials = @import("assets/Materials.zig"); const CommandBuffer = @import("engine/CommandBuffer.zig");
const Textures = @import("assets/Textures.zig");
const CommandBuffer = @import("engine/CommandBuffer.zig").CommandBuffer;
const Engine = @import("engine/Engine.zig"); const Engine = @import("engine/Engine.zig");
const GenericBuffer = @import("engine/GenericBuffer.zig").GenericBuffer; 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 StagingBuffer = @import("engine/StagingBuffer.zig");
const Swapchain = @import("engine/Swapchain.zig"); const Swapchain = @import("engine/Swapchain.zig");
const Player = @import("Player.zig"); const Textures = @import("assets/Textures.zig");
const Interator2 = math.Interator2;
const Matrix4x4 = math.Matrix4x4;
const Quaternion = math.Quaternion;
const Vector2 = math.Vector2; const Vector2 = math.Vector2;
const Vector2x8 = math.Vector2x8; const Vector2x8 = math.Vector2x8;
const Vector3 = math.Vector3; const Vector3 = math.Vector3;
const Vector4 = math.Vector4; const Vector4 = math.Vector4;
const ps = math.ps;
const PointLight = extern struct { const PointLight = extern struct {
positionWS: [3]f32, positionWS: [3]f32,
@@ -121,7 +119,7 @@ index_buffer: IndexBuffer,
global_uniforms: GlobalUniformsBuffer, global_uniforms: GlobalUniformsBuffer,
global_uniforms_staging_buffer: StagingBuffer, 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, global_uniforms_transfer_semaphores: []vk.Semaphore,
point_lights: PointLightBuffer, point_lights: PointLightBuffer,
directional_lights: DirectionalLightBuffer, 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); 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); 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_transfer_command_buffer.copyBuffer(
global_uniforms_staging_buffer.buffer, global_uniforms_staging_buffer.buffer,
global_uniforms.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); const world_seed = engine.random.int(u64);
std.log.info("Using world seed 0x{x:0<16}", .{world_seed}); 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| { while (it.next()) |chunk_coords2| {
const chunk_coords3 = chunk_coords2 ++ [_]i16{0}; const chunk_coords3 = chunk_coords2 ++ [_]i16{0};
@@ -852,10 +852,10 @@ fn render(self: *Game) !void {
const extent = self.swapchain.extent; 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 // NOTE Do not free command buffer yet
try command_buffer.beginCommandBuffer(.{}); try command_buffer.beginCommandBuffer();
{ {
command_buffer.beginRenderPass(.{ command_buffer.beginRenderPass(.{
.render_pass = self.swapchain.render_pass, .render_pass = self.swapchain.render_pass,

View File

@@ -6,7 +6,7 @@ const vk = @import("vulkan");
const math = @import("../math.zig"); const math = @import("../math.zig");
const Blocks = @import("Blocks.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 Engine = @import("../engine/Engine.zig");
const Game = @import("../Game.zig"); const Game = @import("../Game.zig");
const GenericBuffer = @import("../engine/GenericBuffer.zig").GenericBuffer; 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; 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.bindDescriptorSets(.graphics, layout, 1, &.{self.descriptor_set}, &.{});
command_buffer.drawIndexed(.{ .index_count = 6, .instance_count = self.object_count }); command_buffer.drawIndexed(.{ .index_count = 6, .instance_count = self.object_count });
} }

View File

@@ -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 std = @import("std");
const vk = @import("vulkan"); const vk = @import("vulkan");
@@ -7,6 +16,42 @@ const QueueType = @import("QueueType.zig").QueueType;
const Transient = @import("Transient.zig").Transient; const Transient = @import("Transient.zig").Transient;
const WaitSemaphore = @import("WaitSemaphore.zig"); 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 { pub const DrawIndexed = struct {
index_count: u32, index_count: u32,
instance_count: u32 = 1, instance_count: u32 = 1,
@@ -42,47 +87,18 @@ pub const VertexBufferBinding = struct {
offset: usize, offset: usize,
}; };
pub fn CommandBuffer(comptime queue_type: QueueType, comptime transient: Transient) type { pub fn beginCommandBuffer(self: CommandBuffer) !void {
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,
},
},
inheritance_info: ?vk.CommandBufferInheritanceInfo = null,
};
pub fn beginCommandBuffer(self: Self, begin_info: CommandBufferBeginInfo) !void {
try self.proxy.beginCommandBuffer(&.{ try self.proxy.beginCommandBuffer(&.{
.flags = begin_info.flags, .flags = .{
.p_inheritance_info = if (begin_info.inheritance_info) |*x| x else null, .one_time_submit_bit = switch (self.transient) {
.persistent => true,
.transient => false,
},
},
}); });
} }
pub inline fn beginRenderPass(self: Self, render_pass_begin: RenderPassBeginInfo, contents: vk.SubpassContents) void { pub fn beginRenderPass(self: CommandBuffer, render_pass_begin: RenderPassBeginInfo, contents: vk.SubpassContents) void {
self.proxy.beginRenderPass(&.{ self.proxy.beginRenderPass(&.{
.render_pass = render_pass_begin.render_pass, .render_pass = render_pass_begin.render_pass,
.framebuffer = render_pass_begin.framebuffer, .framebuffer = render_pass_begin.framebuffer,
@@ -90,16 +106,16 @@ pub fn CommandBuffer(comptime queue_type: QueueType, comptime transient: Transie
.clear_value_count = @intCast(render_pass_begin.clear_values.len), .clear_value_count = @intCast(render_pass_begin.clear_values.len),
.p_clear_values = render_pass_begin.clear_values.ptr, .p_clear_values = render_pass_begin.clear_values.ptr,
}, contents); }, contents);
} }
pub inline fn bindDescriptorSet( pub fn bindDescriptorSet(
self: Self, self: CommandBuffer,
pipeline_bind_point: vk.PipelineBindPoint, pipeline_bind_point: vk.PipelineBindPoint,
layout: vk.PipelineLayout, layout: vk.PipelineLayout,
set: u32, set: u32,
descriptor_set: vk.DescriptorSet, descriptor_set: vk.DescriptorSet,
dynamic_offset: ?u32, dynamic_offset: ?u32,
) void { ) void {
self.bindDescriptorSets( self.bindDescriptorSets(
pipeline_bind_point, pipeline_bind_point,
layout, layout,
@@ -107,16 +123,16 @@ pub fn CommandBuffer(comptime queue_type: QueueType, comptime transient: Transie
&.{descriptor_set}, &.{descriptor_set},
if (dynamic_offset) |x| &.{x} else &.{}, if (dynamic_offset) |x| &.{x} else &.{},
); );
} }
pub inline fn bindDescriptorSets( pub fn bindDescriptorSets(
self: Self, self: CommandBuffer,
pipeline_bind_point: vk.PipelineBindPoint, pipeline_bind_point: vk.PipelineBindPoint,
layout: vk.PipelineLayout, layout: vk.PipelineLayout,
first_set: u32, first_set: u32,
descriptor_sets: []const vk.DescriptorSet, descriptor_sets: []const vk.DescriptorSet,
dynamic_offsets: []const u32, dynamic_offsets: []const u32,
) void { ) void {
self.proxy.bindDescriptorSets( self.proxy.bindDescriptorSets(
pipeline_bind_point, pipeline_bind_point,
layout, layout,
@@ -126,17 +142,17 @@ pub fn CommandBuffer(comptime queue_type: QueueType, comptime transient: Transie
@intCast(dynamic_offsets.len), @intCast(dynamic_offsets.len),
dynamic_offsets.ptr, dynamic_offsets.ptr,
); );
} }
pub inline fn bindPipeline(self: Self, pipeline_bind_point: vk.PipelineBindPoint, pipeline: vk.Pipeline) void { pub fn bindPipeline(self: CommandBuffer, pipeline_bind_point: vk.PipelineBindPoint, pipeline: vk.Pipeline) void {
self.proxy.bindPipeline(pipeline_bind_point, pipeline); self.proxy.bindPipeline(pipeline_bind_point, pipeline);
} }
pub inline fn bindIndexBuffer(self: Self, buffer: vk.Buffer, offset: u64, index_type: vk.IndexType) void { pub fn bindIndexBuffer(self: CommandBuffer, buffer: vk.Buffer, offset: u64, index_type: vk.IndexType) void {
self.proxy.bindIndexBuffer(buffer, offset, index_type); self.proxy.bindIndexBuffer(buffer, offset, index_type);
} }
pub inline fn bindVertexBuffers(self: Self, first_binding: u32, bindings: []const VertexBufferBinding) !void { pub fn bindVertexBuffers(self: CommandBuffer, first_binding: u32, bindings: []const VertexBufferBinding) !void {
var vertex_buffer_bindings = std.MultiArrayList(VertexBufferBinding){}; var vertex_buffer_bindings = std.MultiArrayList(VertexBufferBinding){};
defer vertex_buffer_bindings.deinit(self.allocator); defer vertex_buffer_bindings.deinit(self.allocator);
try vertex_buffer_bindings.ensureTotalCapacity(self.allocator, bindings.len); try vertex_buffer_bindings.ensureTotalCapacity(self.allocator, bindings.len);
@@ -151,9 +167,9 @@ pub fn CommandBuffer(comptime queue_type: QueueType, comptime transient: Transie
vertex_buffer_bindings.items(.buffer).ptr, vertex_buffer_bindings.items(.buffer).ptr,
vertex_buffer_bindings.items(.offset).ptr, vertex_buffer_bindings.items(.offset).ptr,
); );
} }
pub inline fn drawIndexed(self: Self, draw_indexed: DrawIndexed) void { pub fn drawIndexed(self: CommandBuffer, draw_indexed: DrawIndexed) void {
self.proxy.drawIndexed( self.proxy.drawIndexed(
draw_indexed.index_count, draw_indexed.index_count,
draw_indexed.instance_count, draw_indexed.instance_count,
@@ -161,36 +177,36 @@ pub fn CommandBuffer(comptime queue_type: QueueType, comptime transient: Transie
draw_indexed.vertex_offset, draw_indexed.vertex_offset,
draw_indexed.first_instance, draw_indexed.first_instance,
); );
} }
pub inline fn endCommandBuffer(self: Self) !void { pub fn endCommandBuffer(self: CommandBuffer) !void {
try self.proxy.endCommandBuffer(); try self.proxy.endCommandBuffer();
} }
pub inline fn endRenderPass(self: Self) void { pub fn endRenderPass(self: CommandBuffer) void {
self.proxy.endRenderPass(); self.proxy.endRenderPass();
} }
pub inline fn copyBuffer( pub fn copyBuffer(
self: Self, self: CommandBuffer,
src_buffer: vk.Buffer, src_buffer: vk.Buffer,
dst_buffer: vk.Buffer, dst_buffer: vk.Buffer,
regions: []const vk.BufferCopy, regions: []const vk.BufferCopy,
) void { ) void {
self.proxy.copyBuffer(src_buffer, dst_buffer, @intCast(regions.len), regions.ptr); self.proxy.copyBuffer(src_buffer, dst_buffer, @intCast(regions.len), regions.ptr);
} }
pub inline fn copyBufferToImage( pub fn copyBufferToImage(
self: Self, self: CommandBuffer,
src_buffer: vk.Buffer, src_buffer: vk.Buffer,
dst_image: vk.Image, dst_image: vk.Image,
dst_image_layout: vk.ImageLayout, dst_image_layout: vk.ImageLayout,
regions: []const vk.BufferImageCopy, regions: []const vk.BufferImageCopy,
) void { ) 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, @intCast(regions.len), regions.ptr);
} }
pub inline fn pipelineBarrier(self: Self, barrier: PipelineBarrier) void { pub fn pipelineBarrier(self: CommandBuffer, barrier: PipelineBarrier) void {
self.proxy.pipelineBarrier( self.proxy.pipelineBarrier(
barrier.src_stage_mask, barrier.src_stage_mask,
barrier.dst_stage_mask, barrier.dst_stage_mask,
@@ -202,58 +218,21 @@ pub fn CommandBuffer(comptime queue_type: QueueType, comptime transient: Transie
@intCast(barrier.image_memory_barriers.len), @intCast(barrier.image_memory_barriers.len),
barrier.image_memory_barriers.ptr, barrier.image_memory_barriers.ptr,
); );
} }
pub inline fn setScissor(self: Self, first_scissor: u32, scissors: []const vk.Rect2D) void { 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, @intCast(scissors.len), scissors.ptr);
} }
pub inline fn setViewport(self: Self, first_viewport: u32, viewports: []const vk.Viewport) void { 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, @intCast(viewports.len), viewports.ptr);
}
};
} }
inline fn resolveCommandPool(self: *const Engine, comptime queue_type: QueueType, comptime transient: Transient) vk.CommandPool { // --- HELPER FUNCTIONS --------------------------------------------------------
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];
}
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);
}
fn submitCommandBuffer( fn submitCommandBuffer(
engine: *const Engine, engine: *Engine,
comptime queue_type: QueueType, queue_type: QueueType,
command_buffer: vk.CommandBuffer, command_buffer: vk.CommandBuffer,
submit_info: SubmitInfo, submit_info: SubmitInfo,
) !void { ) !void {

View File

@@ -7,6 +7,7 @@ const vk = @import("vulkan");
const Queue = @import("Queue.zig"); const Queue = @import("Queue.zig");
const QueueType = @import("QueueType.zig").QueueType; const QueueType = @import("QueueType.zig").QueueType;
const Transient = @import("Transient.zig").Transient;
const VkAllocator = @import("VkAllocator.zig"); const VkAllocator = @import("VkAllocator.zig");
pub const Mode = union(enum) { pub const Mode = union(enum) {
@@ -347,10 +348,34 @@ pub fn init(allocator: std.mem.Allocator, maybe_window: ?*glfw.Window) !Engine {
}, &vk_allocator.interface); }, &vk_allocator.interface);
errdefer device.destroyCommandPool(transient_transfer_command_pool, &vk_allocator.interface); errdefer device.destroyCommandPool(transient_transfer_command_pool, &vk_allocator.interface);
const graphics_queue: Queue = .initAllocation(device, queue_allocations.graphics_queue); const graphics_queue: Queue = .init(
const compute_queue: Queue = .initAllocation(device, queue_allocations.compute_queue); device.getDeviceQueue(
const transfer_queue: Queue = .initAllocation(device, queue_allocations.transfer_queue); queue_allocations.graphics_queue.family,
const presentation_queue: Queue = if (maybe_window != null) .initAllocation(device, queue_allocations.presentation_queue) else undefined; 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 ------------------------------------------------- // --- CREATE AND SEED RNG -------------------------------------------------
@@ -613,6 +638,23 @@ fn findPresentationQueueFamily(queue_families_properties: []const vk.QueueFamily
return null; 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 --------------------------------------------------------- // --- VULKAN WRAPPERS ---------------------------------------------------------
pub const BufferCreateInfo = struct { pub const BufferCreateInfo = struct {
@@ -622,6 +664,18 @@ pub const BufferCreateInfo = struct {
queue_family_indices: []const u32 = &.{}, 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 { pub const DescriptorPoolCreateInfo = struct {
flags: vk.DescriptorPoolCreateFlags = .{}, flags: vk.DescriptorPoolCreateFlags = .{},
max_sets: u32, max_sets: u32,
@@ -798,6 +852,17 @@ pub fn createBuffer(self: *Engine, create_info: BufferCreateInfo) !vk.Buffer {
return 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 { pub fn allocateDescriptorSet(self: *Engine, allocate_info: DescriptorSetAllocateInfo) !vk.DescriptorSet {
var descriptor_sets: [1]vk.DescriptorSet = undefined; var descriptor_sets: [1]vk.DescriptorSet = undefined;
try self.allocateDescriptorSets(.{ try self.allocateDescriptorSets(.{
@@ -831,6 +896,14 @@ pub fn allocateDescriptorSets(self: *Engine, allocate_info: DescriptorSetsAlloca
}, descriptor_sets.ptr); }, 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 { pub fn createDescriptorSetLayout(self: *Engine, create_info: DescriptorSetLayoutCreateInfo) !vk.DescriptorSetLayout {
var arena: std.heap.ArenaAllocator = .init(self.vk_allocator.allocator); var arena: std.heap.ArenaAllocator = .init(self.vk_allocator.allocator);
defer arena.deinit(); 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); 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 { pub fn freeDescriptorSet(self: *Engine, descriptor_pool: vk.DescriptorPool, descriptor_set: vk.DescriptorSet) void {
const descriptor_sets = [_]vk.DescriptorSet{descriptor_set}; 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.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); 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 { pub fn resetFence(self: *Engine, fence: vk.Fence) !void {
try self.device.resetFences(1, @ptrCast(&fence)); 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 { pub fn updateDescriptorSets(self: *Engine, update_info: DescriptorSetsUpdateInfo) !void {
var arena: std.heap.ArenaAllocator = .init(self.vk_allocator.allocator); var arena: std.heap.ArenaAllocator = .init(self.vk_allocator.allocator);
defer arena.deinit(); defer arena.deinit();

View File

@@ -2,7 +2,7 @@ const std = @import("std");
const vk = @import("vulkan"); const vk = @import("vulkan");
const CommandBuffer = @import("CommandBuffer.zig").CommandBuffer; const CommandBuffer = @import("CommandBuffer.zig");
const Engine = @import("Engine.zig"); const Engine = @import("Engine.zig");
const StagingBuffer = @import("StagingBuffer.zig"); const StagingBuffer = @import("StagingBuffer.zig");
const TargetQueue = @import("TargetQueue.zig").TargetQueue; 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) }); 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 }); const device_memory = try engine.allocate(memory_requirements, .{ .device_local_bit = true });
errdefer engine.freeMemory(device_memory); errdefer engine.freeMemory(device_memory);
if (init_info.name) |name| { if (init_info.name) |name| {
engine.setObjectName(device_memory, "DM {s} [{s}, {s}]", .{ name, @typeName(Header), @typeName(Element) }); 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 .{ return .{
.buffer = buffer, .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)); @memcpy(staging_memory[array_write_offset..write_size], std.mem.sliceAsBytes(write_info.elements));
staging_buffer.unmap(engine); 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); defer command_buffer.deinit(engine);
try command_buffer.beginCommandBuffer(.{}); try command_buffer.beginCommandBuffer();
command_buffer.copyBuffer(staging_buffer.buffer, self.buffer, regions.items); command_buffer.copyBuffer(staging_buffer.buffer, self.buffer, regions.items);
try command_buffer.endCommandBuffer(); try command_buffer.endCommandBuffer();

View File

@@ -11,9 +11,9 @@ pub const Allocation = struct {
handle: vk.Queue, handle: vk.Queue,
allocation: Allocation, allocation: Allocation,
pub fn initAllocation(device: vk.DeviceProxy, allocation: Allocation) Queue { pub fn init(handle: vk.Queue, allocation: Allocation) Queue {
return .{ return .{
.handle = device.getDeviceQueue(allocation.family, allocation.index), .handle = handle,
.allocation = allocation, .allocation = allocation,
}; };
} }

View File

@@ -31,7 +31,7 @@ pub fn init(engine: *Engine, init_info: InitInfo) !StagingBuffer {
}); });
errdefer engine.destroyBuffer(buffer); errdefer engine.destroyBuffer(buffer);
const memory_requirements = engine.device.getBufferMemoryRequirements(buffer); const memory_requirements = engine.getBufferMemoryRequirements(buffer);
const device_memory = try engine.allocate( const device_memory = try engine.allocate(
memory_requirements, memory_requirements,
.{ .{
@@ -41,7 +41,7 @@ pub fn init(engine: *Engine, init_info: InitInfo) !StagingBuffer {
); );
errdefer engine.freeMemory(device_memory); errdefer engine.freeMemory(device_memory);
try engine.device.bindBufferMemory(buffer, device_memory, 0); try engine.bindBufferMemory(buffer, device_memory, 0);
return .{ return .{
.buffer = buffer, .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 { pub fn mapPartial(self: StagingBuffer, engine: *Engine, offset: u32, len: u32) ![]u8 {
const mapped_memory = try engine.device.mapMemory(self.device_memory, offset, len, .{}); const mapped_memory = try engine.mapMemory(self.device_memory, offset, len, .{});
return @as([*]u8, @ptrCast(mapped_memory))[0..len]; return mapped_memory;
} }
pub fn unmap(self: StagingBuffer, engine: *Engine) void { pub fn unmap(self: StagingBuffer, engine: *Engine) void {
engine.device.unmapMemory(self.device_memory); engine.unmapMemory(self.device_memory);
} }

View File

@@ -3,7 +3,7 @@ const std = @import("std");
const vk = @import("vulkan"); const vk = @import("vulkan");
const CommandBuffer = @import("CommandBuffer.zig").CommandBuffer; const CommandBuffer = @import("CommandBuffer.zig");
const Engine = @import("Engine.zig"); const Engine = @import("Engine.zig");
const QSM = @import("QueueSharingMode.zig"); const QSM = @import("QueueSharingMode.zig");
const Texture = @import("Texture.zig"); const Texture = @import("Texture.zig");
@@ -271,7 +271,7 @@ pub fn recreate(self: *Swapchain, engine: *Engine) !void {
} }
pub const PresentInfo = struct { pub const PresentInfo = struct {
command_buffer: CommandBuffer(.graphics, .transient), command_buffer: CommandBuffer,
wait_semaphores: []const WaitSemaphore = &.{}, wait_semaphores: []const WaitSemaphore = &.{},
}; };
@@ -411,7 +411,7 @@ const SwapchainImage = struct {
semaphore_render_finished: vk.Semaphore, semaphore_render_finished: vk.Semaphore,
fence: vk.Fence, fence: vk.Fence,
framebuffer: vk.Framebuffer, framebuffer: vk.Framebuffer,
command_buffer: ?CommandBuffer(.graphics, .transient), command_buffer: ?CommandBuffer,
const InitProps = struct { const InitProps = struct {
image: vk.Image, image: vk.Image,

View File

@@ -3,7 +3,7 @@ const std = @import("std");
const vk = @import("vulkan"); const vk = @import("vulkan");
const CommandBuffer = @import("CommandBuffer.zig").CommandBuffer; const CommandBuffer = @import("CommandBuffer.zig");
const Engine = @import("Engine.zig"); const Engine = @import("Engine.zig");
const StagingBuffer = @import("StagingBuffer.zig"); const StagingBuffer = @import("StagingBuffer.zig");
const TargetQueue = @import("TargetQueue.zig").TargetQueue; 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) }); 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 }); const device_memory = try engine.allocate(memory_requirements, .{ .device_local_bit = true });
errdefer engine.freeMemory(device_memory); errdefer engine.freeMemory(device_memory);
if (init_info.name) |name| { if (init_info.name) |name| {
engine.setObjectName(device_memory, "DM {s} [{s}]", .{ name, @tagName(init_info.usage) }); 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(.{ const image_view = try engine.createImageView(.{
.image = image, .image = image,
@@ -205,10 +205,10 @@ pub fn writeRaw(self: Texture, engine: *Engine, data: []const u8) !void {
// --- TRANSITION TO TRANSFER_DST_OPTIMAL AND COPY ----------------- // --- 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); defer transfer_command_buffer.deinit(engine);
try transfer_command_buffer.beginCommandBuffer(.{}); try transfer_command_buffer.beginCommandBuffer();
transfer_command_buffer.pipelineBarrier(.{ transfer_command_buffer.pipelineBarrier(.{
.src_stage_mask = .{ .top_of_pipe_bit = true }, .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 ---------------------- // --- 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); defer graphics_command_buffer.deinit(engine);
try graphics_command_buffer.beginCommandBuffer(.{}); try graphics_command_buffer.beginCommandBuffer();
graphics_command_buffer.pipelineBarrier(.{ graphics_command_buffer.pipelineBarrier(.{
.src_stage_mask = .{ .transfer_bit = true }, .src_stage_mask = .{ .transfer_bit = true },

View File

@@ -101,7 +101,7 @@ pub fn main() !void {
std.log.debug("Exitted the game loop", .{}); std.log.debug("Exitted the game loop", .{});
for (swapchain.swapchain_images) |x| engine.waitForFence(x.fence) catch {}; for (swapchain.swapchain_images) |x| engine.waitForFence(x.fence) catch {};
engine.device.deviceWaitIdle() catch {}; engine.deviceWaitIdle() catch {};
} }
const CallbackContext = struct { const CallbackContext = struct {

View File

@@ -1,6 +1,5 @@
pub const Interator2 = @import("math/Interator2.zig").Interator2; pub const Iterator2 = @import("math/Iterator2.zig").Iterator2;
pub const Interator3 = @import("math/Interator3.zig").Interator3; pub const Iterator3 = @import("math/Iterator3.zig").Iterator3;
pub const Iterator3 = @import("math/Iterator3.zig");
pub const Matrix4x4 = @import("math/Matrix4x4.zig").Matrix4x4; pub const Matrix4x4 = @import("math/Matrix4x4.zig").Matrix4x4;
pub const Quaternion = @import("math/Quaternion.zig").Quaternion; pub const Quaternion = @import("math/Quaternion.zig").Quaternion;
pub const Vector2 = @import("math/Vector2.zig").Vector2; pub const Vector2 = @import("math/Vector2.zig").Vector2;

View File

@@ -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;
}
};
}

View File

@@ -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;
}
};
}

44
src/math/Iterator2.zig Normal file
View File

@@ -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;
}
};
}

View File

@@ -1,32 +1,40 @@
const Vector3 = @import("Vector3.zig").Vector3; pub fn Iterator3(comptime T: type) type {
return struct {
const Self = @This();
const Array = [3]T;
min: Vector3, min: Array,
max: Vector3, max: Array,
step: Vector3, step: Array,
current: ?Vector3, current: ?Array,
pub fn init(min: Vector3, max: Vector3, step: Vector3) @This() { pub const InitInfo = struct {
return .{ min: Array,
.min = min, max: Array,
.max = max, step: Array = .{ 1, 1, 1 },
.step = step,
.current = min,
}; };
}
pub fn next(self: *@This()) ?Vector3 { 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; const current = self.current orelse return null;
var next_current = current; var next_current = current;
next_current = next_current.setX(next_current.getX() + self.step.getX()); next_current[0] = next_current[0] + self.step[0];
if (next_current.getX() > self.max.getX()) { if (next_current[0] > self.max[0]) {
next_current = next_current.setX(self.min.getX()); next_current[0] = self.min[0];
next_current = next_current.setY(next_current.getY() + self.step.getY()); next_current[1] = next_current[1] + self.step[1];
if (next_current.getY() > self.max.getY()) { if (next_current[1] > self.max[1]) {
next_current = next_current.setY(self.min.getY()); next_current[1] = self.min[1];
next_current = next_current.setZ(next_current.getZ() + self.step.getZ()); next_current[2] = next_current[2] + self.step[2];
if (next_current.getZ() > self.max.getZ()) { if (next_current[2] > self.max[2]) {
self.current = null; self.current = null;
return current; return current;
} }
@@ -35,4 +43,6 @@ pub fn next(self: *@This()) ?Vector3 {
self.current = next_current; self.current = next_current;
return current; return current;
}
};
} }

View File

@@ -1,10 +1,9 @@
const std = @import("std"); const std = @import("std");
const math = @import("../math.zig"); const math = @import("../math.zig");
const Vector2 = math.Vector2; const Vector2 = @import("Vector2.zig").Vector2;
const f32x8 = math.f32x8; const f32x8 = math.f32x8;
const ps = math.ps; const ps = math.ps;
pub const Vector2x8 = extern struct { pub const Vector2x8 = extern struct {