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 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,

View File

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

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 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 {

View File

@@ -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();

View File

@@ -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();

View File

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

View File

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

View File

@@ -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,

View File

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

View File

@@ -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 {

View File

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

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

View File

@@ -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 {