Complete all Vulkan wrappers. Maybe worth it.
This commit is contained in:
1
.vscode/extensions.json
vendored
1
.vscode/extensions.json
vendored
@@ -1,5 +1,6 @@
|
||||
{
|
||||
"recommendations": [
|
||||
"vadimcn.vscode-lldb",
|
||||
"ziglang.vscode-zig",
|
||||
],
|
||||
}
|
||||
|
||||
130
src/Game.zig
130
src/Game.zig
@@ -686,9 +686,62 @@ pub fn deinit(self: *Game) void {
|
||||
pub fn update(self: *Game, dt: f32) void {
|
||||
self.player.update(dt);
|
||||
|
||||
self.render() catch |err| {
|
||||
std.log.err("Failed to render: {s}", .{@errorName(err)});
|
||||
@panic("Frame update failed");
|
||||
};
|
||||
}
|
||||
|
||||
pub fn onKeyDown(self: *Game, key: glfw.Key) void {
|
||||
self.player.onKeyDown(key);
|
||||
}
|
||||
|
||||
pub fn onKeyUp(self: *Game, key: glfw.Key) void {
|
||||
self.player.onKeyUp(key);
|
||||
}
|
||||
|
||||
pub fn onMouseMove(self: *Game, dx: f32, dy: f32) void {
|
||||
self.player.onMouseMove(dx, dy);
|
||||
}
|
||||
|
||||
pub fn onMouseDown(self: *Game, button: glfw.MouseButton) void {
|
||||
_ = self;
|
||||
_ = button;
|
||||
}
|
||||
|
||||
pub fn onMouseUp(self: *Game, button: glfw.MouseButton) void {
|
||||
_ = self;
|
||||
_ = button;
|
||||
}
|
||||
|
||||
fn render(self: *Game) !void {
|
||||
const framebuffer_width, const framebuffer_height = blk: {
|
||||
const w, const h = self.engine.mode.surface.window.getFramebufferSize();
|
||||
break :blk [_]u32{ @intCast(w), @intCast(h) };
|
||||
};
|
||||
|
||||
if (framebuffer_width == 0 or framebuffer_height == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (framebuffer_width != self.swapchain.extent.width or framebuffer_height != self.swapchain.extent.height) {
|
||||
try self.recreateSwapchain();
|
||||
}
|
||||
|
||||
if (self.swapchain.swapchain == .null_handle) {
|
||||
return;
|
||||
}
|
||||
|
||||
self.swapchain.acquire(self.engine) catch |err| switch (err) {
|
||||
error.OutOfDateKHR => return self.recreateSwapchain(),
|
||||
else => return err,
|
||||
};
|
||||
|
||||
const extent = self.swapchain.extent;
|
||||
|
||||
const framebuffer_size = Vector2.init(
|
||||
@floatFromInt(self.swapchain.extent.width),
|
||||
@floatFromInt(self.swapchain.extent.height),
|
||||
@floatFromInt(extent.width),
|
||||
@floatFromInt(extent.height),
|
||||
);
|
||||
|
||||
const camera_position = self.player.position.add(.init(0, 0, Player.camera_height));
|
||||
@@ -722,63 +775,22 @@ pub fn update(self: *Game, dt: f32) void {
|
||||
.ambientLight = ambient_light.asArray(),
|
||||
};
|
||||
|
||||
const staging_memory = self.global_uniforms_staging_buffer.map(self.engine) catch |err| {
|
||||
std.log.err("Failed to map global uniforms staging buffer: {s}", .{@errorName(err)});
|
||||
@panic("Frame update failed");
|
||||
};
|
||||
const staging_memory = try self.global_uniforms_staging_buffer.map(self.engine);
|
||||
@memcpy(staging_memory, std.mem.asBytes(&global_uniforms_data));
|
||||
self.global_uniforms_staging_buffer.unmap(self.engine);
|
||||
|
||||
self.global_uniforms_transfer_command_buffer.submit(self.engine, .{
|
||||
.signal_semaphores = &.{self.global_uniforms_transfer_semaphores[self.swapchain.image_index]},
|
||||
}) catch |err| {
|
||||
std.log.err("Failed to submit global uniforms transfer: {s}", .{@errorName(err)});
|
||||
@panic("Frame update failed");
|
||||
};
|
||||
try self.global_uniforms_transfer_command_buffer.submit(self.engine, .{
|
||||
.signal_semaphores = &.{self.global_uniforms_transfer_semaphores[self.swapchain.image_index.?]},
|
||||
});
|
||||
|
||||
self.render() catch |err| {
|
||||
std.log.err("Failed to render: {s}", .{@errorName(err)});
|
||||
@panic("Frame update failed");
|
||||
};
|
||||
}
|
||||
|
||||
pub fn onKeyDown(self: *Game, key: glfw.Key) void {
|
||||
self.player.onKeyDown(key);
|
||||
}
|
||||
|
||||
pub fn onKeyUp(self: *Game, key: glfw.Key) void {
|
||||
self.player.onKeyUp(key);
|
||||
}
|
||||
|
||||
pub fn onMouseMove(self: *Game, dx: f32, dy: f32) void {
|
||||
self.player.onMouseMove(dx, dy);
|
||||
}
|
||||
|
||||
pub fn onMouseDown(self: *Game, button: glfw.MouseButton) void {
|
||||
_ = self;
|
||||
_ = button;
|
||||
}
|
||||
|
||||
pub fn onMouseUp(self: *Game, button: glfw.MouseButton) void {
|
||||
_ = self;
|
||||
_ = button;
|
||||
}
|
||||
|
||||
fn render(self: *Game) !void {
|
||||
if (self.swapchain.swapchain == .null_handle) {
|
||||
return;
|
||||
}
|
||||
|
||||
const extent = self.swapchain.extent;
|
||||
|
||||
const command_buffer: CommandBuffer = try .init(self.engine, .graphics, .transient);
|
||||
// NOTE Do not free command buffer yet
|
||||
var command_buffer: CommandBuffer = try .init(self.engine, .graphics, .transient);
|
||||
defer command_buffer.deinit(self.engine);
|
||||
|
||||
try command_buffer.beginCommandBuffer();
|
||||
{
|
||||
command_buffer.beginRenderPass(.{
|
||||
.render_pass = self.swapchain.render_pass,
|
||||
.framebuffer = self.swapchain.swapchain_images[self.swapchain.image_index].framebuffer,
|
||||
.framebuffer = self.swapchain.swapchain_images[self.swapchain.image_index.?].framebuffer,
|
||||
.render_area = .{
|
||||
.offset = .{ .x = 0, .y = 0 },
|
||||
.extent = extent,
|
||||
@@ -833,26 +845,22 @@ fn render(self: *Game) !void {
|
||||
}
|
||||
try command_buffer.endCommandBuffer();
|
||||
|
||||
const res = try self.swapchain.present(self.engine, .{
|
||||
self.swapchain.present(self.engine, .{
|
||||
.command_buffer = command_buffer,
|
||||
.wait_semaphores = &.{
|
||||
.{
|
||||
.semaphore = self.global_uniforms_transfer_semaphores[self.swapchain.image_index],
|
||||
.semaphore = self.global_uniforms_transfer_semaphores[self.swapchain.image_index.?],
|
||||
.stage_flags = .{ .vertex_shader_bit = true },
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
if (res == .suboptimal) {
|
||||
try self.recreateSwapchain();
|
||||
}
|
||||
}
|
||||
|
||||
fn recreateSwapchain(self: *Game) !void {
|
||||
self.swapchain.recreate(self.engine) catch |err| switch (err) {
|
||||
}) catch |err| switch (err) {
|
||||
error.OutOfDateKHR => return self.recreateSwapchain(),
|
||||
else => return err,
|
||||
};
|
||||
}
|
||||
|
||||
fn recreateSwapchain(self: *Game) !void {
|
||||
try self.swapchain.recreate(self.engine);
|
||||
for (self.global_uniforms_transfer_semaphores, 0..) |*semaphore, i| {
|
||||
self.engine.destroySemaphore(semaphore.*);
|
||||
semaphore.* = try self.engine.createSemaphore();
|
||||
|
||||
@@ -131,5 +131,5 @@ pub fn update(self: *Player, dt: f32) void {
|
||||
|
||||
const displacement = horizontal_velocity.asVector3(vertical_velocity).mulScalar(dt);
|
||||
|
||||
self.position = Vector3.add(self.position, displacement);
|
||||
self.position = .add(self.position, displacement);
|
||||
}
|
||||
|
||||
@@ -39,14 +39,7 @@ pub const InitInfo = struct {
|
||||
per_batch_descriptor_set_layout: vk.DescriptorSetLayout,
|
||||
};
|
||||
|
||||
pub const Neighbors = struct {
|
||||
positive_x: ?*const Chunk,
|
||||
negative_x: ?*const Chunk,
|
||||
positive_y: ?*const Chunk,
|
||||
negative_y: ?*const Chunk,
|
||||
positive_z: ?*const Chunk,
|
||||
negative_z: ?*const Chunk,
|
||||
};
|
||||
pub const Neighbors = std.enums.EnumFieldStruct(voxels.Orientation, ?*const Chunk, null);
|
||||
|
||||
pub fn init(engine: *Engine, init_info: InitInfo) !Chunk {
|
||||
const descriptor_set = try engine.allocateDescriptorSet(.{
|
||||
|
||||
@@ -14,7 +14,6 @@ const vk = @import("vulkan");
|
||||
const Engine = @import("Engine.zig");
|
||||
const QueueType = @import("QueueType.zig").QueueType;
|
||||
const Transient = @import("Transient.zig").Transient;
|
||||
const WaitSemaphore = @import("WaitSemaphore.zig");
|
||||
|
||||
proxy: vk.CommandBufferProxy,
|
||||
allocator: std.mem.Allocator,
|
||||
@@ -46,8 +45,8 @@ pub fn deinit(self: *CommandBuffer, engine: *Engine) void {
|
||||
self.* = undefined;
|
||||
}
|
||||
|
||||
pub fn submit(self: CommandBuffer, engine: *Engine, submit_info: SubmitInfo) !void {
|
||||
try submitCommandBuffer(engine, self.queue_type, self.proxy.handle, submit_info);
|
||||
pub fn submit(self: CommandBuffer, engine: *Engine, submit_info: Engine.SubmitInfo) !void {
|
||||
try engine.queueSubmit(self.queue_type, self.proxy.handle, submit_info);
|
||||
}
|
||||
|
||||
// --- VULKAN WRAPPERS ---------------------------------------------------------
|
||||
@@ -76,12 +75,6 @@ pub const RenderPassBeginInfo = struct {
|
||||
clear_values: []const vk.ClearValue = &.{},
|
||||
};
|
||||
|
||||
pub const SubmitInfo = struct {
|
||||
wait_semaphores: []const WaitSemaphore = &.{},
|
||||
signal_semaphores: []const vk.Semaphore = &.{},
|
||||
fence: vk.Fence = .null_handle,
|
||||
};
|
||||
|
||||
pub const VertexBufferBinding = struct {
|
||||
buffer: vk.Buffer,
|
||||
offset: usize,
|
||||
@@ -227,42 +220,3 @@ pub fn setScissor(self: CommandBuffer, first_scissor: u32, scissors: []const vk.
|
||||
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: *Engine,
|
||||
queue_type: QueueType,
|
||||
command_buffer: vk.CommandBuffer,
|
||||
submit_info: SubmitInfo,
|
||||
) !void {
|
||||
const queue = switch (queue_type) {
|
||||
.graphics => engine.graphics_queue.handle,
|
||||
.compute => engine.compute_queue.handle,
|
||||
.transfer => engine.transfer_queue.handle,
|
||||
};
|
||||
|
||||
const command_buffers = [_]vk.CommandBuffer{command_buffer};
|
||||
|
||||
var wait_semaphores = std.MultiArrayList(WaitSemaphore){};
|
||||
defer wait_semaphores.deinit(engine.vk_allocator.allocator);
|
||||
try wait_semaphores.ensureTotalCapacity(engine.vk_allocator.allocator, submit_info.wait_semaphores.len);
|
||||
|
||||
for (submit_info.wait_semaphores) |wait_semaphore| {
|
||||
wait_semaphores.appendAssumeCapacity(wait_semaphore);
|
||||
}
|
||||
|
||||
const submits = [_]vk.SubmitInfo{
|
||||
.{
|
||||
.wait_semaphore_count = @intCast(wait_semaphores.len),
|
||||
.p_wait_semaphores = wait_semaphores.items(.semaphore).ptr,
|
||||
.p_wait_dst_stage_mask = wait_semaphores.items(.stage_flags).ptr,
|
||||
.command_buffer_count = command_buffers.len,
|
||||
.p_command_buffers = &command_buffers,
|
||||
.signal_semaphore_count = @intCast(submit_info.signal_semaphores.len),
|
||||
.p_signal_semaphores = submit_info.signal_semaphores.ptr,
|
||||
},
|
||||
};
|
||||
|
||||
try engine.device.queueSubmit(queue, submits.len, &submits, submit_info.fence);
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ const Queue = @import("Queue.zig");
|
||||
const QueueType = @import("QueueType.zig").QueueType;
|
||||
const Transient = @import("Transient.zig").Transient;
|
||||
const VkAllocator = @import("VkAllocator.zig");
|
||||
const WaitSemaphore = @import("WaitSemaphore.zig");
|
||||
|
||||
pub const Mode = union(enum) {
|
||||
headless: void,
|
||||
@@ -531,6 +532,69 @@ pub fn setObjectName(self: *const Engine, handle: anytype, comptime fmt: []const
|
||||
}
|
||||
}
|
||||
|
||||
pub const SubmitInfo = struct {
|
||||
wait_semaphores: []const WaitSemaphore = &.{},
|
||||
signal_semaphores: []const vk.Semaphore = &.{},
|
||||
fence: vk.Fence = .null_handle,
|
||||
};
|
||||
|
||||
pub fn queueSubmit(
|
||||
self: *const Engine,
|
||||
queue_type: QueueType,
|
||||
command_buffer: vk.CommandBuffer,
|
||||
submit_info: SubmitInfo,
|
||||
) !void {
|
||||
const queue = switch (queue_type) {
|
||||
.graphics => self.graphics_queue.handle,
|
||||
.compute => self.compute_queue.handle,
|
||||
.transfer => self.transfer_queue.handle,
|
||||
};
|
||||
|
||||
const command_buffers = [_]vk.CommandBuffer{command_buffer};
|
||||
|
||||
var wait_semaphores = std.MultiArrayList(WaitSemaphore){};
|
||||
defer wait_semaphores.deinit(self.vk_allocator.allocator);
|
||||
try wait_semaphores.ensureTotalCapacity(self.vk_allocator.allocator, submit_info.wait_semaphores.len);
|
||||
|
||||
for (submit_info.wait_semaphores) |wait_semaphore| {
|
||||
wait_semaphores.appendAssumeCapacity(wait_semaphore);
|
||||
}
|
||||
|
||||
const submits = [_]vk.SubmitInfo{
|
||||
.{
|
||||
.wait_semaphore_count = @intCast(wait_semaphores.len),
|
||||
.p_wait_semaphores = wait_semaphores.items(.semaphore).ptr,
|
||||
.p_wait_dst_stage_mask = wait_semaphores.items(.stage_flags).ptr,
|
||||
.command_buffer_count = command_buffers.len,
|
||||
.p_command_buffers = &command_buffers,
|
||||
.signal_semaphore_count = @intCast(submit_info.signal_semaphores.len),
|
||||
.p_signal_semaphores = submit_info.signal_semaphores.ptr,
|
||||
},
|
||||
};
|
||||
|
||||
try self.device.queueSubmit(queue, submits.len, &submits, submit_info.fence);
|
||||
}
|
||||
|
||||
pub const PresentInfo = struct {
|
||||
wait_semaphores: []const vk.Semaphore = &.{},
|
||||
image_index: u32,
|
||||
swapchain: vk.SwapchainKHR,
|
||||
};
|
||||
|
||||
pub fn queuePresent(self: *Engine, present_info: PresentInfo) !vk.Result {
|
||||
const swapchains = [_]vk.SwapchainKHR{present_info.swapchain};
|
||||
const image_indices = [_]u32{present_info.image_index};
|
||||
|
||||
const res = try self.device.queuePresentKHR(self.mode.surface.presentation_queue.handle, &.{
|
||||
.wait_semaphore_count = @intCast(present_info.wait_semaphores.len),
|
||||
.p_wait_semaphores = present_info.wait_semaphores.ptr,
|
||||
.swapchain_count = swapchains.len,
|
||||
.p_swapchains = &swapchains,
|
||||
.p_image_indices = &image_indices,
|
||||
});
|
||||
return res;
|
||||
}
|
||||
|
||||
fn debugUtilsMessengerCallback(
|
||||
severity: vk.DebugUtilsMessageSeverityFlagsEXT,
|
||||
message_type: vk.DebugUtilsMessageTypeFlagsEXT,
|
||||
@@ -657,6 +721,12 @@ fn resolveCommandPool(self: *const Engine, queue_type: QueueType, transient: Tra
|
||||
|
||||
// --- VULKAN WRAPPERS ---------------------------------------------------------
|
||||
|
||||
pub const AcquireInfo = struct {
|
||||
timeout: u64 = std.math.maxInt(u64),
|
||||
semaphore: vk.Semaphore = .null_handle,
|
||||
fence: vk.Fence = .null_handle,
|
||||
};
|
||||
|
||||
pub const BufferCreateInfo = struct {
|
||||
flags: vk.BufferCreateFlags = .{},
|
||||
size: vk.DeviceSize,
|
||||
@@ -807,6 +877,13 @@ pub const PipelineViewportStateCreateInfo = struct {
|
||||
scissors: []const vk.Rect2D = &.{},
|
||||
};
|
||||
|
||||
pub const RenderPassCreateInfo = struct {
|
||||
flags: vk.RenderPassCreateFlags = .{},
|
||||
attachments: []const vk.AttachmentDescription = &.{},
|
||||
subpasses: []const SubpassDescription,
|
||||
dependencies: []const vk.SubpassDependency = &.{},
|
||||
};
|
||||
|
||||
pub const ShaderModuleCreateInfo = struct {
|
||||
flags: vk.ShaderModuleCreateFlags = .{},
|
||||
code: []align(@alignOf(u32)) const u8,
|
||||
@@ -817,6 +894,33 @@ pub const SpecializationInfo = struct {
|
||||
data: []const u8 = &.{},
|
||||
};
|
||||
|
||||
pub const SubpassDescription = struct {
|
||||
flags: vk.SubpassDescriptionFlags = .{},
|
||||
pipeline_bind_point: vk.PipelineBindPoint,
|
||||
input_attachments: []const vk.AttachmentReference = &.{},
|
||||
color_attachments: []const vk.AttachmentReference = &.{},
|
||||
resolve_attachments: ?[]const vk.AttachmentReference = null,
|
||||
depth_stencil_attachment: ?vk.AttachmentReference = null,
|
||||
preserve_attachments: []const u32 = &.{},
|
||||
};
|
||||
|
||||
pub const SwapchainCreateInfo = struct {
|
||||
flags: vk.SwapchainCreateFlagsKHR = .{},
|
||||
surface: vk.SurfaceKHR,
|
||||
min_image_count: u32,
|
||||
image_format: vk.Format,
|
||||
image_color_space: vk.ColorSpaceKHR,
|
||||
image_extent: vk.Extent2D,
|
||||
image_array_layers: u32,
|
||||
image_usage: vk.ImageUsageFlags,
|
||||
queue_family_indices: []const u32 = &.{},
|
||||
pre_transform: vk.SurfaceTransformFlagsKHR,
|
||||
composite_alpha: vk.CompositeAlphaFlagsKHR,
|
||||
present_mode: vk.PresentModeKHR,
|
||||
clipped: vk.Bool32,
|
||||
old_swapchain: vk.SwapchainKHR = .null_handle,
|
||||
};
|
||||
|
||||
pub const WriteDescriptorSet = struct {
|
||||
dst_set: vk.DescriptorSet,
|
||||
dst_binding: u32,
|
||||
@@ -829,27 +933,14 @@ pub const WriteDescriptorSet = struct {
|
||||
},
|
||||
};
|
||||
|
||||
pub fn createBuffer(self: *Engine, create_info: BufferCreateInfo) !vk.Buffer {
|
||||
var arena: std.heap.ArenaAllocator = .init(self.vk_allocator.allocator);
|
||||
defer arena.deinit();
|
||||
const allocator = arena.allocator();
|
||||
|
||||
var queue_family_indices_set: std.AutoArrayHashMapUnmanaged(u32, void) = .{};
|
||||
for (create_info.queue_family_indices) |queue_family_index| {
|
||||
try queue_family_indices_set.put(allocator, queue_family_index, {});
|
||||
}
|
||||
|
||||
const queue_family_indices = queue_family_indices_set.keys();
|
||||
|
||||
const buffer = self.device.createBuffer(&.{
|
||||
.flags = create_info.flags,
|
||||
.size = create_info.size,
|
||||
.usage = create_info.usage,
|
||||
.sharing_mode = if (queue_family_indices.len > 1) .concurrent else .exclusive,
|
||||
.queue_family_index_count = if (queue_family_indices.len > 1) @intCast(queue_family_indices.len) else 0,
|
||||
.p_queue_family_indices = if (queue_family_indices.len > 1) queue_family_indices.ptr else null,
|
||||
}, &self.vk_allocator.interface);
|
||||
return buffer;
|
||||
pub fn acquireNextImage(self: *Engine, swapchain: vk.SwapchainKHR, acquire_info: AcquireInfo) !vk.DeviceProxy.AcquireNextImageKHRResult {
|
||||
const res = try self.device.acquireNextImageKHR(
|
||||
swapchain,
|
||||
acquire_info.timeout,
|
||||
acquire_info.semaphore,
|
||||
acquire_info.fence,
|
||||
);
|
||||
return res;
|
||||
}
|
||||
|
||||
pub fn allocateCommandBuffer(self: *Engine, allocate_info: CommandBufferAllocateInfo) !vk.CommandBuffer {
|
||||
@@ -904,6 +995,29 @@ pub fn bindImageMemory(self: *Engine, image: vk.Image, memory: vk.DeviceMemory,
|
||||
try self.device.bindImageMemory(image, memory, memory_offset);
|
||||
}
|
||||
|
||||
pub fn createBuffer(self: *Engine, create_info: BufferCreateInfo) !vk.Buffer {
|
||||
var arena: std.heap.ArenaAllocator = .init(self.vk_allocator.allocator);
|
||||
defer arena.deinit();
|
||||
const allocator = arena.allocator();
|
||||
|
||||
var queue_family_indices_set: std.AutoArrayHashMapUnmanaged(u32, void) = .{};
|
||||
for (create_info.queue_family_indices) |queue_family_index| {
|
||||
try queue_family_indices_set.put(allocator, queue_family_index, {});
|
||||
}
|
||||
|
||||
const queue_family_indices = queue_family_indices_set.keys();
|
||||
|
||||
const buffer = self.device.createBuffer(&.{
|
||||
.flags = create_info.flags,
|
||||
.size = create_info.size,
|
||||
.usage = create_info.usage,
|
||||
.sharing_mode = if (queue_family_indices.len > 1) .concurrent else .exclusive,
|
||||
.queue_family_index_count = if (queue_family_indices.len > 1) @intCast(queue_family_indices.len) else 0,
|
||||
.p_queue_family_indices = if (queue_family_indices.len > 1) queue_family_indices.ptr else null,
|
||||
}, &self.vk_allocator.interface);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
pub fn createDescriptorSetLayout(self: *Engine, create_info: DescriptorSetLayoutCreateInfo) !vk.DescriptorSetLayout {
|
||||
var arena: std.heap.ArenaAllocator = .init(self.vk_allocator.allocator);
|
||||
defer arena.deinit();
|
||||
@@ -986,7 +1100,7 @@ pub fn createGraphicsPipeline(self: *Engine, create_info: GraphicsPipelineCreate
|
||||
const allocator = arena.allocator();
|
||||
|
||||
const stages = try allocator.alloc(vk.PipelineShaderStageCreateInfo, create_info.stages.len);
|
||||
for (stages, create_info.stages) |*x, *stage| {
|
||||
for (stages, create_info.stages) |*x, stage| {
|
||||
x.* = .{
|
||||
.flags = stage.flags,
|
||||
.stage = stage.stage,
|
||||
@@ -1112,6 +1226,39 @@ pub fn createPipelineLayout(self: *Engine, create_info: PipelineLayoutCreateInfo
|
||||
return pipeline_layout;
|
||||
}
|
||||
|
||||
pub fn createRenderPass(self: *Engine, create_info: RenderPassCreateInfo) !vk.RenderPass {
|
||||
var arena: std.heap.ArenaAllocator = .init(self.vk_allocator.allocator);
|
||||
defer arena.deinit();
|
||||
const allocator = arena.allocator();
|
||||
|
||||
const subpasses = try allocator.alloc(vk.SubpassDescription, create_info.subpasses.len);
|
||||
for (subpasses, create_info.subpasses) |*x, *subpass| {
|
||||
x.* = .{
|
||||
.flags = subpass.flags,
|
||||
.pipeline_bind_point = subpass.pipeline_bind_point,
|
||||
.input_attachment_count = @intCast(subpass.input_attachments.len),
|
||||
.p_input_attachments = subpass.input_attachments.ptr,
|
||||
.color_attachment_count = @intCast(subpass.color_attachments.len),
|
||||
.p_color_attachments = subpass.color_attachments.ptr,
|
||||
.p_resolve_attachments = if (subpass.resolve_attachments) |resolve_attachments| resolve_attachments.ptr else null,
|
||||
.p_depth_stencil_attachment = if (subpass.depth_stencil_attachment) |*y| y else null,
|
||||
.preserve_attachment_count = @intCast(subpass.preserve_attachments.len),
|
||||
.p_preserve_attachments = subpass.preserve_attachments.ptr,
|
||||
};
|
||||
}
|
||||
|
||||
const render_pass = try self.device.createRenderPass(&.{
|
||||
.flags = create_info.flags,
|
||||
.attachment_count = @intCast(create_info.attachments.len),
|
||||
.p_attachments = create_info.attachments.ptr,
|
||||
.subpass_count = @intCast(subpasses.len),
|
||||
.p_subpasses = subpasses.ptr,
|
||||
.dependency_count = @intCast(create_info.dependencies.len),
|
||||
.p_dependencies = create_info.dependencies.ptr,
|
||||
}, &self.vk_allocator.interface);
|
||||
return render_pass;
|
||||
}
|
||||
|
||||
pub fn createSampler(self: *Engine, create_info: vk.SamplerCreateInfo) !vk.Sampler {
|
||||
const sampler = try self.device.createSampler(&create_info, &self.vk_allocator.interface);
|
||||
return sampler;
|
||||
@@ -1131,6 +1278,39 @@ pub fn createShaderModule(self: *Engine, create_info: ShaderModuleCreateInfo) !v
|
||||
return shader_module;
|
||||
}
|
||||
|
||||
pub fn createSwapchain(self: *Engine, create_info: SwapchainCreateInfo) !vk.SwapchainKHR {
|
||||
var arena: std.heap.ArenaAllocator = .init(self.vk_allocator.allocator);
|
||||
defer arena.deinit();
|
||||
const allocator = arena.allocator();
|
||||
|
||||
var queue_family_indices_set: std.AutoArrayHashMapUnmanaged(u32, void) = .{};
|
||||
for (create_info.queue_family_indices) |queue_family_index| {
|
||||
try queue_family_indices_set.put(allocator, queue_family_index, {});
|
||||
}
|
||||
|
||||
const queue_family_indices = queue_family_indices_set.keys();
|
||||
|
||||
const swapchain = try self.device.createSwapchainKHR(&.{
|
||||
.flags = create_info.flags,
|
||||
.surface = create_info.surface,
|
||||
.min_image_count = create_info.min_image_count,
|
||||
.image_format = create_info.image_format,
|
||||
.image_color_space = create_info.image_color_space,
|
||||
.image_extent = create_info.image_extent,
|
||||
.image_array_layers = create_info.image_array_layers,
|
||||
.image_usage = create_info.image_usage,
|
||||
.image_sharing_mode = if (queue_family_indices.len > 1) .concurrent else .exclusive,
|
||||
.queue_family_index_count = if (queue_family_indices.len > 1) @intCast(queue_family_indices.len) else 0,
|
||||
.p_queue_family_indices = if (queue_family_indices.len > 1) queue_family_indices.ptr else null,
|
||||
.pre_transform = create_info.pre_transform,
|
||||
.composite_alpha = create_info.composite_alpha,
|
||||
.present_mode = create_info.present_mode,
|
||||
.clipped = create_info.clipped,
|
||||
.old_swapchain = create_info.old_swapchain,
|
||||
}, &self.vk_allocator.interface);
|
||||
return swapchain;
|
||||
}
|
||||
|
||||
pub fn destroyBuffer(self: *Engine, buffer: vk.Buffer) void {
|
||||
self.device.destroyBuffer(buffer, &self.vk_allocator.interface);
|
||||
}
|
||||
@@ -1167,6 +1347,10 @@ pub fn destroyPipelineLayout(self: *Engine, pipeline_layout: vk.PipelineLayout)
|
||||
self.device.destroyPipelineLayout(pipeline_layout, &self.vk_allocator.interface);
|
||||
}
|
||||
|
||||
pub fn destroyRenderPass(self: *Engine, render_pass: vk.RenderPass) void {
|
||||
self.device.destroyRenderPass(render_pass, &self.vk_allocator.interface);
|
||||
}
|
||||
|
||||
pub fn destroySampler(self: *Engine, sampler: vk.Sampler) void {
|
||||
self.device.destroySampler(sampler, &self.vk_allocator.interface);
|
||||
}
|
||||
@@ -1179,6 +1363,10 @@ pub fn destroyShaderModule(self: *Engine, shader_module: vk.ShaderModule) void {
|
||||
self.device.destroyShaderModule(shader_module, &self.vk_allocator.interface);
|
||||
}
|
||||
|
||||
pub fn destroySwapchain(self: *Engine, swapchain: vk.SwapchainKHR) void {
|
||||
self.device.destroySwapchainKHR(swapchain, &self.vk_allocator.interface);
|
||||
}
|
||||
|
||||
pub fn deviceWaitIdle(self: *Engine) !void {
|
||||
try self.device.deviceWaitIdle();
|
||||
}
|
||||
@@ -1206,6 +1394,21 @@ pub fn getImageMemoryRequirements(self: *Engine, image: vk.Image) vk.MemoryRequi
|
||||
return self.device.getImageMemoryRequirements(image);
|
||||
}
|
||||
|
||||
pub fn getPhysicalDeviceSurfaceCapabilities(self: *Engine) !vk.SurfaceCapabilitiesKHR {
|
||||
const surface_capabilities = try self.instance.getPhysicalDeviceSurfaceCapabilitiesKHR(self.physical_device, self.mode.surface.surface);
|
||||
return surface_capabilities;
|
||||
}
|
||||
|
||||
pub fn getPhysicalDeviceSurfaceFormatsAlloc(self: *Engine, allocator: std.mem.Allocator) ![]vk.SurfaceFormatKHR {
|
||||
const surface_formats = try self.instance.getPhysicalDeviceSurfaceFormatsAllocKHR(self.physical_device, self.mode.surface.surface, allocator);
|
||||
return surface_formats;
|
||||
}
|
||||
|
||||
pub fn getSwapchainImagesAlloc(self: *Engine, swapchain: vk.SwapchainKHR, allocator: std.mem.Allocator) ![]vk.Image {
|
||||
const images = try self.device.getSwapchainImagesAllocKHR(swapchain, allocator);
|
||||
return images;
|
||||
}
|
||||
|
||||
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];
|
||||
|
||||
@@ -16,7 +16,8 @@ extent: vk.Extent2D = .{ .width = 0, .height = 0 },
|
||||
swapchain: vk.SwapchainKHR = .null_handle,
|
||||
swapchain_images: []SwapchainImage = &.{},
|
||||
depth_texture: ?Texture = null,
|
||||
image_index: u32 = 0,
|
||||
image_index: ?u32 = null,
|
||||
fence: vk.Fence = .null_handle,
|
||||
semaphore_image_acquired: vk.Semaphore = .null_handle,
|
||||
|
||||
pub const PresentResult = enum {
|
||||
@@ -27,8 +28,8 @@ pub const PresentResult = enum {
|
||||
pub fn init(engine: *Engine) !Swapchain {
|
||||
const params: Params = try .init(engine);
|
||||
|
||||
const render_pass = blk: {
|
||||
const attachments = [_]vk.AttachmentDescription{
|
||||
const render_pass = try engine.createRenderPass(.{
|
||||
.attachments = &.{
|
||||
.{
|
||||
.format = params.surface_format.format,
|
||||
.samples = .{ .@"1_bit" = true },
|
||||
@@ -49,30 +50,23 @@ pub fn init(engine: *Engine) !Swapchain {
|
||||
.initial_layout = .undefined,
|
||||
.final_layout = .depth_stencil_attachment_optimal,
|
||||
},
|
||||
};
|
||||
|
||||
const color_attachments = [_]vk.AttachmentReference{
|
||||
.{
|
||||
.attachment = 0,
|
||||
.layout = .color_attachment_optimal,
|
||||
},
|
||||
};
|
||||
|
||||
const depth_stencil_attachment: vk.AttachmentReference = .{
|
||||
.attachment = 1,
|
||||
.layout = .depth_stencil_attachment_optimal,
|
||||
};
|
||||
|
||||
const subpasses = [_]vk.SubpassDescription{
|
||||
},
|
||||
.subpasses = &.{
|
||||
.{
|
||||
.pipeline_bind_point = .graphics,
|
||||
.color_attachment_count = color_attachments.len,
|
||||
.p_color_attachments = &color_attachments,
|
||||
.p_depth_stencil_attachment = &depth_stencil_attachment,
|
||||
.color_attachments = &.{
|
||||
.{
|
||||
.attachment = 0,
|
||||
.layout = .color_attachment_optimal,
|
||||
},
|
||||
},
|
||||
.depth_stencil_attachment = .{
|
||||
.attachment = 1,
|
||||
.layout = .depth_stencil_attachment_optimal,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const dependencies = [_]vk.SubpassDependency{
|
||||
},
|
||||
.dependencies = &.{
|
||||
.{
|
||||
.src_subpass = 0,
|
||||
.dst_subpass = 0,
|
||||
@@ -92,18 +86,9 @@ pub fn init(engine: *Engine) !Swapchain {
|
||||
.depth_stencil_attachment_write_bit = true,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
break :blk try engine.device.createRenderPass(&.{
|
||||
.attachment_count = attachments.len,
|
||||
.p_attachments = &attachments,
|
||||
.subpass_count = subpasses.len,
|
||||
.p_subpasses = &subpasses,
|
||||
.dependency_count = dependencies.len,
|
||||
.p_dependencies = &dependencies,
|
||||
}, &engine.vk_allocator.interface);
|
||||
};
|
||||
errdefer engine.device.destroyRenderPass(render_pass, &engine.vk_allocator.interface);
|
||||
},
|
||||
});
|
||||
errdefer engine.destroyRenderPass(render_pass);
|
||||
engine.setObjectName(render_pass, "RP", .{});
|
||||
|
||||
var swapchain: Swapchain = .{
|
||||
@@ -130,11 +115,12 @@ pub fn deinit(self: *Swapchain, engine: *Engine) void {
|
||||
}
|
||||
|
||||
if (self.swapchain != .null_handle) {
|
||||
engine.device.destroySwapchainKHR(self.swapchain, &engine.vk_allocator.interface);
|
||||
engine.destroySwapchain(self.swapchain);
|
||||
}
|
||||
|
||||
engine.device.destroyRenderPass(self.render_pass, &engine.vk_allocator.interface);
|
||||
engine.destroyRenderPass(self.render_pass);
|
||||
engine.destroySemaphore(self.semaphore_image_acquired);
|
||||
engine.destroyFence(self.fence);
|
||||
|
||||
self.* = undefined;
|
||||
}
|
||||
@@ -145,8 +131,9 @@ pub fn recreate(self: *Swapchain, engine: *Engine) !void {
|
||||
|
||||
const old_swapchain = self.swapchain;
|
||||
const old_swapchain_images = self.swapchain_images;
|
||||
var old_depth_texture = self.depth_texture;
|
||||
const old_depth_texture = &self.depth_texture;
|
||||
const old_semaphore_image_acquired = self.semaphore_image_acquired;
|
||||
const old_fence = self.fence;
|
||||
|
||||
const extent = try getCurrentExtent(engine);
|
||||
|
||||
@@ -154,10 +141,8 @@ pub fn recreate(self: *Swapchain, engine: *Engine) !void {
|
||||
|
||||
// --- CREATE NEW SWAPCHAIN ------------------------------------------------
|
||||
|
||||
const surface_capabilities = try engine.instance.getPhysicalDeviceSurfaceCapabilitiesKHR(engine.physical_device, mode.surface);
|
||||
|
||||
const qsm = QSM.resolve(engine.graphics_queue.allocation.family, mode.presentation_queue.allocation.family);
|
||||
const new_swapchain = try engine.device.createSwapchainKHR(&.{
|
||||
const surface_capabilities = try engine.getPhysicalDeviceSurfaceCapabilities();
|
||||
const new_swapchain = try engine.createSwapchain(.{
|
||||
.surface = mode.surface,
|
||||
.min_image_count = self.params.image_count,
|
||||
.image_format = self.params.surface_format.format,
|
||||
@@ -165,16 +150,17 @@ pub fn recreate(self: *Swapchain, engine: *Engine) !void {
|
||||
.image_extent = extent,
|
||||
.image_array_layers = 1,
|
||||
.image_usage = .{ .color_attachment_bit = true },
|
||||
.image_sharing_mode = qsm.sharing_mode,
|
||||
.queue_family_index_count = qsm.queue_family_index_count,
|
||||
.p_queue_family_indices = qsm.p_queue_family_indices,
|
||||
.queue_family_indices = &.{
|
||||
engine.graphics_queue.allocation.family,
|
||||
mode.presentation_queue.allocation.family,
|
||||
},
|
||||
.pre_transform = surface_capabilities.current_transform,
|
||||
.composite_alpha = .{ .opaque_bit_khr = true },
|
||||
.present_mode = .fifo_khr,
|
||||
.clipped = .true,
|
||||
.old_swapchain = old_swapchain,
|
||||
}, &engine.vk_allocator.interface);
|
||||
errdefer engine.device.destroySwapchainKHR(new_swapchain, &engine.vk_allocator.interface);
|
||||
});
|
||||
errdefer engine.destroySwapchain(new_swapchain);
|
||||
engine.setObjectName(new_swapchain, "SC {d}×{d}", .{ extent.width, extent.height });
|
||||
|
||||
// --- DESTROY OLD SWAPCHAIN AND ITS IMAGES --------------------------------
|
||||
@@ -189,22 +175,28 @@ pub fn recreate(self: *Swapchain, engine: *Engine) !void {
|
||||
allocator.free(self.swapchain_images);
|
||||
self.swapchain_images = &.{};
|
||||
|
||||
if (old_depth_texture) |*depth_texture| {
|
||||
if (old_depth_texture.*) |*depth_texture| {
|
||||
depth_texture.deinit(engine);
|
||||
}
|
||||
|
||||
if (old_swapchain != .null_handle) {
|
||||
engine.device.destroySwapchainKHR(old_swapchain, &engine.vk_allocator.interface);
|
||||
engine.destroySwapchain(old_swapchain);
|
||||
self.swapchain = .null_handle;
|
||||
}
|
||||
|
||||
self.extent = .{ .width = 0, .height = 0 };
|
||||
self.image_index = null;
|
||||
|
||||
if (old_semaphore_image_acquired != .null_handle) {
|
||||
engine.destroySemaphore(old_semaphore_image_acquired);
|
||||
self.semaphore_image_acquired = .null_handle;
|
||||
}
|
||||
|
||||
if (old_fence != .null_handle) {
|
||||
engine.destroyFence(old_fence);
|
||||
self.fence = .null_handle;
|
||||
}
|
||||
|
||||
// --- CREATE DEPTH TEXTURE ------------------------------------------------
|
||||
|
||||
var new_depth_texture = try Texture.init(engine, .{
|
||||
@@ -219,7 +211,7 @@ pub fn recreate(self: *Swapchain, engine: *Engine) !void {
|
||||
// --- CREATE NEW SWAPCHAIN IMAGES -----------------------------------------
|
||||
|
||||
const new_swapchain_images = blk: {
|
||||
const images = try engine.device.getSwapchainImagesAllocKHR(new_swapchain, allocator);
|
||||
const images = try engine.getSwapchainImagesAlloc(new_swapchain, allocator);
|
||||
defer allocator.free(images);
|
||||
|
||||
var swapchain_images: std.ArrayList(SwapchainImage) = try .initCapacity(allocator, images.len);
|
||||
@@ -247,18 +239,17 @@ pub fn recreate(self: *Swapchain, engine: *Engine) !void {
|
||||
allocator.free(new_swapchain_images);
|
||||
}
|
||||
|
||||
// --- ACQUIRE NEXT IMAGE --------------------------------------------------
|
||||
// --- CREATE SEMAPHORES AND FENCES ----------------------------------------
|
||||
|
||||
var semaphore_image_acquired = try engine.createSemaphore();
|
||||
const semaphore_image_acquired = try engine.createSemaphore();
|
||||
errdefer engine.destroySemaphore(semaphore_image_acquired);
|
||||
engine.setObjectName(semaphore_image_acquired, "S Acquired[E]", .{});
|
||||
|
||||
const res = try engine.device.acquireNextImageKHR(new_swapchain, std.math.maxInt(u64), semaphore_image_acquired, .null_handle);
|
||||
if (res.result == .not_ready or res.result == .timeout) {
|
||||
return error.ImageAcquireFailed;
|
||||
}
|
||||
|
||||
std.mem.swap(vk.Semaphore, &new_swapchain_images[res.image_index].semaphore_image_acquired, &semaphore_image_acquired);
|
||||
const fence = try engine.createFence(.{
|
||||
.flags = .{ .signaled_bit = true },
|
||||
});
|
||||
errdefer engine.destroyFence(fence);
|
||||
engine.setObjectName(fence, "F", .{});
|
||||
|
||||
// --- COMMIT --------------------------------------------------------------
|
||||
|
||||
@@ -266,8 +257,20 @@ pub fn recreate(self: *Swapchain, engine: *Engine) !void {
|
||||
self.swapchain = new_swapchain;
|
||||
self.swapchain_images = new_swapchain_images;
|
||||
self.depth_texture = new_depth_texture;
|
||||
self.image_index = res.image_index;
|
||||
self.image_index = null;
|
||||
self.semaphore_image_acquired = semaphore_image_acquired;
|
||||
self.fence = fence;
|
||||
}
|
||||
|
||||
pub fn acquire(self: *Swapchain, engine: *Engine) !void {
|
||||
try engine.waitForFence(self.fence);
|
||||
try engine.resetFence(self.fence);
|
||||
|
||||
const res = try engine.acquireNextImage(self.swapchain, .{
|
||||
.semaphore = self.semaphore_image_acquired,
|
||||
});
|
||||
std.mem.swap(vk.Semaphore, &self.swapchain_images[res.image_index].semaphore_image_acquired, &self.semaphore_image_acquired);
|
||||
self.image_index = res.image_index;
|
||||
}
|
||||
|
||||
pub const PresentInfo = struct {
|
||||
@@ -275,20 +278,9 @@ pub const PresentInfo = struct {
|
||||
wait_semaphores: []const WaitSemaphore = &.{},
|
||||
};
|
||||
|
||||
pub fn present(self: *Swapchain, engine: *Engine, present_info: PresentInfo) !PresentResult {
|
||||
pub fn present(self: *Swapchain, engine: *Engine, present_info: PresentInfo) !void {
|
||||
const allocator = engine.vk_allocator.allocator;
|
||||
const device = engine.device;
|
||||
const mode = &engine.mode.surface;
|
||||
|
||||
// --- WAIT FOR CURRENT FRAME TO FINISH ------------------------------------
|
||||
|
||||
const current_swapchain_image = &self.swapchain_images[self.image_index];
|
||||
try engine.waitForFence(current_swapchain_image.fence);
|
||||
if (current_swapchain_image.command_buffer) |*command_buffer| {
|
||||
command_buffer.deinit(engine);
|
||||
current_swapchain_image.command_buffer = null;
|
||||
}
|
||||
try engine.resetFence(current_swapchain_image.fence);
|
||||
const current_swapchain_image = &self.swapchain_images[self.image_index.?];
|
||||
|
||||
// --- SUBMIT COMMAND BUFFER -----------------------------------------------
|
||||
|
||||
@@ -301,45 +293,24 @@ pub fn present(self: *Swapchain, engine: *Engine, present_info: PresentInfo) !Pr
|
||||
});
|
||||
wait_semaphores.appendSliceAssumeCapacity(present_info.wait_semaphores);
|
||||
|
||||
current_swapchain_image.command_buffer = present_info.command_buffer;
|
||||
try present_info.command_buffer.submit(engine, .{
|
||||
.wait_semaphores = wait_semaphores.items,
|
||||
.signal_semaphores = &.{current_swapchain_image.semaphore_render_finished},
|
||||
.fence = current_swapchain_image.fence,
|
||||
.fence = self.fence,
|
||||
});
|
||||
|
||||
// --- PRESENT CURRENT FRAME -----------------------------------------------
|
||||
|
||||
_ = device.queuePresentKHR(mode.presentation_queue.handle, &.{
|
||||
.wait_semaphore_count = 1,
|
||||
.p_wait_semaphores = @ptrCast(¤t_swapchain_image.semaphore_render_finished),
|
||||
.swapchain_count = 1,
|
||||
.p_swapchains = @ptrCast(&self.swapchain),
|
||||
.p_image_indices = @ptrCast(&self.image_index),
|
||||
}) catch |err| switch (err) {
|
||||
error.OutOfDateKHR => return .suboptimal,
|
||||
else => return err,
|
||||
};
|
||||
|
||||
// --- ACQUIRE NEXT FRAME --------------------------------------------------
|
||||
|
||||
const res = device.acquireNextImageKHR(self.swapchain, std.math.maxInt(u64), self.semaphore_image_acquired, .null_handle) catch |err| switch (err) {
|
||||
error.OutOfDateKHR => return .suboptimal,
|
||||
else => return err,
|
||||
};
|
||||
std.mem.swap(vk.Semaphore, &self.swapchain_images[res.image_index].semaphore_image_acquired, &self.semaphore_image_acquired);
|
||||
self.image_index = res.image_index;
|
||||
|
||||
return switch (res.result) {
|
||||
.success => .optimal,
|
||||
.suboptimal_khr => .suboptimal,
|
||||
else => unreachable,
|
||||
};
|
||||
_ = try engine.queuePresent(.{
|
||||
.wait_semaphores = &.{current_swapchain_image.semaphore_render_finished},
|
||||
.swapchain = self.swapchain,
|
||||
.image_index = self.image_index.?,
|
||||
});
|
||||
}
|
||||
|
||||
fn getCurrentExtent(engine: *Engine) !vk.Extent2D {
|
||||
const mode = &engine.mode.surface;
|
||||
const surface_capabilities = try engine.instance.getPhysicalDeviceSurfaceCapabilitiesKHR(engine.physical_device, mode.surface);
|
||||
const surface_capabilities = try engine.getPhysicalDeviceSurfaceCapabilities();
|
||||
|
||||
if (surface_capabilities.current_extent.width != std.math.maxInt(u32) and surface_capabilities.current_extent.height != std.math.maxInt(u32)) {
|
||||
return surface_capabilities.current_extent;
|
||||
@@ -366,13 +337,12 @@ const Params = struct {
|
||||
image_count: u32,
|
||||
|
||||
pub fn init(engine: *Engine) !Params {
|
||||
const mode = &engine.mode.surface;
|
||||
const allocator = engine.vk_allocator.allocator;
|
||||
|
||||
const surface_capabilities = try engine.instance.getPhysicalDeviceSurfaceCapabilitiesKHR(engine.physical_device, mode.surface);
|
||||
const surface_capabilities = try engine.getPhysicalDeviceSurfaceCapabilities();
|
||||
|
||||
const surface_format = blk: {
|
||||
const surface_formats = try engine.instance.getPhysicalDeviceSurfaceFormatsAllocKHR(engine.physical_device, mode.surface, allocator);
|
||||
const surface_formats = try engine.getPhysicalDeviceSurfaceFormatsAlloc(allocator);
|
||||
defer allocator.free(surface_formats);
|
||||
|
||||
// Look for 8-bit BGRA sRGB surface format.
|
||||
@@ -409,9 +379,7 @@ const SwapchainImage = struct {
|
||||
image_view: vk.ImageView,
|
||||
semaphore_image_acquired: vk.Semaphore,
|
||||
semaphore_render_finished: vk.Semaphore,
|
||||
fence: vk.Fence,
|
||||
framebuffer: vk.Framebuffer,
|
||||
command_buffer: ?CommandBuffer,
|
||||
|
||||
const InitProps = struct {
|
||||
image: vk.Image,
|
||||
@@ -447,12 +415,6 @@ const SwapchainImage = struct {
|
||||
errdefer engine.destroySemaphore(semaphore_render_finished);
|
||||
engine.setObjectName(image_view, "S Rendered[{d}]", .{props.index});
|
||||
|
||||
const fence = try engine.createFence(.{
|
||||
.flags = .{ .signaled_bit = true },
|
||||
});
|
||||
errdefer engine.destroyFence(fence);
|
||||
engine.setObjectName(image_view, "F Rendered[{d}]", .{props.index});
|
||||
|
||||
const framebuffer = try engine.createFramebuffer(.{
|
||||
.render_pass = props.render_pass,
|
||||
.attachments = &.{ image_view, props.depth_stencil_image_view },
|
||||
@@ -468,21 +430,14 @@ const SwapchainImage = struct {
|
||||
.image_view = image_view,
|
||||
.semaphore_image_acquired = semaphore_image_acquired,
|
||||
.semaphore_render_finished = semaphore_render_finished,
|
||||
.fence = fence,
|
||||
.framebuffer = framebuffer,
|
||||
.command_buffer = null,
|
||||
};
|
||||
}
|
||||
|
||||
fn deinit(self: *SwapchainImage, engine: *Engine) void {
|
||||
std.log.scoped(.deinit).debug("Deinitializing {*} with {*}", .{ self, engine });
|
||||
|
||||
engine.waitForFence(self.fence) catch {};
|
||||
if (self.command_buffer) |*command_buffer| {
|
||||
command_buffer.deinit(engine);
|
||||
}
|
||||
engine.destroyFramebuffer(self.framebuffer);
|
||||
engine.destroyFence(self.fence);
|
||||
engine.destroySemaphore(self.semaphore_render_finished);
|
||||
engine.destroySemaphore(self.semaphore_image_acquired);
|
||||
engine.destroyImageView(self.image_view);
|
||||
|
||||
@@ -100,7 +100,7 @@ pub fn main() !void {
|
||||
|
||||
std.log.debug("Exitted the game loop", .{});
|
||||
|
||||
for (swapchain.swapchain_images) |x| engine.waitForFence(x.fence) catch {};
|
||||
engine.waitForFence(swapchain.fence) catch {};
|
||||
engine.deviceWaitIdle() catch {};
|
||||
}
|
||||
|
||||
|
||||
@@ -109,9 +109,9 @@ pub const Matrix4x4 = extern struct {
|
||||
const rotation_k = Vector4.init(2 * (xz + yw), 2 * (yz - xw), (1 - 2 * (xx + yy)), 0);
|
||||
|
||||
return .initVector4(
|
||||
Vector4.mulScalar(rotation_i, scale.getX()),
|
||||
Vector4.mulScalar(rotation_j, scale.getY()),
|
||||
Vector4.mulScalar(rotation_k, scale.getZ()),
|
||||
.mulScalar(rotation_i, scale.getX()),
|
||||
.mulScalar(rotation_j, scale.getY()),
|
||||
.mulScalar(rotation_k, scale.getZ()),
|
||||
translation.asVector4(1),
|
||||
);
|
||||
}
|
||||
@@ -130,47 +130,47 @@ pub const Matrix4x4 = extern struct {
|
||||
|
||||
pub inline fn add(self: Matrix4x4, other: Matrix4x4) Matrix4x4 {
|
||||
return .initVector4(
|
||||
Vector4.add(self.i, other.i),
|
||||
Vector4.add(self.j, other.j),
|
||||
Vector4.add(self.k, other.k),
|
||||
Vector4.add(self.t, other.t),
|
||||
.add(self.i, other.i),
|
||||
.add(self.j, other.j),
|
||||
.add(self.k, other.k),
|
||||
.add(self.t, other.t),
|
||||
);
|
||||
}
|
||||
|
||||
pub inline fn sub(self: Matrix4x4, other: Matrix4x4) Matrix4x4 {
|
||||
return .initVector4(
|
||||
Vector4.sub(self.i, other.i),
|
||||
Vector4.sub(self.j, other.j),
|
||||
Vector4.sub(self.k, other.k),
|
||||
Vector4.sub(self.t, other.t),
|
||||
.sub(self.i, other.i),
|
||||
.sub(self.j, other.j),
|
||||
.sub(self.k, other.k),
|
||||
.sub(self.t, other.t),
|
||||
);
|
||||
}
|
||||
|
||||
pub inline fn negate(self: Matrix4x4) Matrix4x4 {
|
||||
return .initVector4(
|
||||
Vector4.negate(self.i),
|
||||
Vector4.negate(self.j),
|
||||
Vector4.negate(self.k),
|
||||
Vector4.negate(self.t),
|
||||
.negate(self.i),
|
||||
.negate(self.j),
|
||||
.negate(self.k),
|
||||
.negate(self.t),
|
||||
);
|
||||
}
|
||||
|
||||
pub inline fn mulScalar(self: Matrix4x4, scalar: f32) Matrix4x4 {
|
||||
return .initVector4(
|
||||
Vector4.mulScalar(self.i, scalar),
|
||||
Vector4.mulScalar(self.j, scalar),
|
||||
Vector4.mulScalar(self.k, scalar),
|
||||
Vector4.mulScalar(self.t, scalar),
|
||||
.mulScalar(self.i, scalar),
|
||||
.mulScalar(self.j, scalar),
|
||||
.mulScalar(self.k, scalar),
|
||||
.mulScalar(self.t, scalar),
|
||||
);
|
||||
}
|
||||
|
||||
pub inline fn divScalar(self: Matrix4x4, scalar: f32) Matrix4x4 {
|
||||
const inv_scalar = 1 / scalar;
|
||||
return .initVector4(
|
||||
Vector4.mulScalar(self.i, inv_scalar),
|
||||
Vector4.mulScalar(self.j, inv_scalar),
|
||||
Vector4.mulScalar(self.k, inv_scalar),
|
||||
Vector4.mulScalar(self.t, inv_scalar),
|
||||
.mulScalar(self.i, inv_scalar),
|
||||
.mulScalar(self.j, inv_scalar),
|
||||
.mulScalar(self.k, inv_scalar),
|
||||
.mulScalar(self.t, inv_scalar),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -97,27 +97,27 @@ pub const Quaternion = extern struct {
|
||||
// --- COMPONENT-WISE ---
|
||||
|
||||
pub inline fn add(self: Quaternion, other: Quaternion) Quaternion {
|
||||
return .initVector4(Vector4.add(self.vector, other.vector));
|
||||
return .initVector4(.add(self.vector, other.vector));
|
||||
}
|
||||
|
||||
pub inline fn sub(self: Quaternion, other: Quaternion) Quaternion {
|
||||
return .initVector4(Vector4.sub(self.vector, other.vector));
|
||||
return .initVector4(.sub(self.vector, other.vector));
|
||||
}
|
||||
|
||||
pub inline fn negate(self: Quaternion) Quaternion {
|
||||
return .initVector4(Vector4.negate(self.vector));
|
||||
return .initVector4(.negate(self.vector));
|
||||
}
|
||||
|
||||
pub inline fn conjugate(self: Quaternion) Quaternion {
|
||||
return .initVector4(Vector4.mul(self.vector, Vector4.init(-1, -1, -1, 1)));
|
||||
return .initVector4(.mul(self.vector, .init(-1, -1, -1, 1)));
|
||||
}
|
||||
|
||||
pub inline fn mulScalar(self: Quaternion, scalar: f32) Quaternion {
|
||||
return .initVector4(Vector4.mulScalar(self.vector, scalar));
|
||||
return .initVector4(.mulScalar(self.vector, scalar));
|
||||
}
|
||||
|
||||
pub inline fn divScalar(self: Quaternion, scalar: f32) Quaternion {
|
||||
return .initVector4(Vector4.divScalar(self.vector, scalar));
|
||||
return .initVector4(.divScalar(self.vector, scalar));
|
||||
}
|
||||
|
||||
// --- OTHER ---
|
||||
@@ -131,7 +131,7 @@ pub const Quaternion = extern struct {
|
||||
}
|
||||
|
||||
pub inline fn normalize(self: Quaternion) Quaternion {
|
||||
return .initVector4(Vector4.normalize(self.vector));
|
||||
return .initVector4(.normalize(self.vector));
|
||||
}
|
||||
|
||||
pub inline fn dot(self: Quaternion, other: Quaternion) f32 {
|
||||
@@ -139,7 +139,7 @@ pub const Quaternion = extern struct {
|
||||
}
|
||||
|
||||
pub inline fn lerp(self: Quaternion, other: Quaternion, t: f32) Quaternion {
|
||||
return .initVector4(Vector4.lerp(self.vector, other.vector, t));
|
||||
return .initVector4(.lerp(self.vector, other.vector, t));
|
||||
}
|
||||
|
||||
pub inline fn mulQuaternion(self: Quaternion, other: Quaternion) Quaternion {
|
||||
|
||||
@@ -157,19 +157,13 @@ pub const Vector3 = extern struct {
|
||||
return .{ .vector = self * s_vector + other * t_vector };
|
||||
}
|
||||
|
||||
pub inline fn rotate(self: Vector3, quaternion: Quaternion) Vector2 {
|
||||
pub inline fn rotate(self: Vector3, quaternion: Quaternion) Vector3 {
|
||||
const quaternion_scalar = quaternion.getScalar();
|
||||
const quaternion_vector = quaternion.getVector();
|
||||
|
||||
return Vector3.add(
|
||||
self,
|
||||
Vector3.cross(
|
||||
Vector3.add(quaternion_vector, quaternion_vector),
|
||||
Vector3.add(
|
||||
Vector3.cross(quaternion_vector, self),
|
||||
Vector3.mulScalar(self, quaternion_scalar),
|
||||
),
|
||||
),
|
||||
);
|
||||
return .add(self, .cross(
|
||||
.add(quaternion_vector, quaternion_vector),
|
||||
.add(.cross(quaternion_vector, self), .mulScalar(self, quaternion_scalar)),
|
||||
));
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user