swapchain with vulkan-tutorial
This commit is contained in:
@@ -267,7 +267,7 @@ pub fn find_swap_image_count(
|
||||
surface: vk.SurfaceKHR,
|
||||
) !u32 {
|
||||
const caps = try vki.getPhysicalDeviceSurfaceCapabilitiesKHR(pdev, surface);
|
||||
var count = caps.min_image_count + 1;
|
||||
var count = @max(3, caps.min_image_count + 1);
|
||||
if (caps.max_image_count > 0) {
|
||||
count = @min(count, caps.max_image_count);
|
||||
}
|
||||
|
325
src/main.zig
325
src/main.zig
@@ -84,6 +84,11 @@ pub fn main() !void {
|
||||
|
||||
const queue = vkd.getDeviceQueue(dev, family, 0);
|
||||
|
||||
const pool = try vkd.createCommandPool(dev, &.{
|
||||
.queue_family_index = family,
|
||||
}, null);
|
||||
defer vkd.destroyCommandPool(dev, pool, null);
|
||||
|
||||
const preferred_format: vk.SurfaceFormatKHR = .{
|
||||
.format = .b8g8r8a8_srgb,
|
||||
.color_space = .srgb_nonlinear_khr,
|
||||
@@ -98,12 +103,29 @@ pub fn main() !void {
|
||||
var swapchain: vk.SwapchainKHR = .null_handle;
|
||||
defer vkd.destroySwapchainKHR(dev, swapchain, null);
|
||||
|
||||
var image_buf: [8]vk.Image = undefined;
|
||||
@memset(&image_buf, .null_handle);
|
||||
var images: []vk.Image = &.{};
|
||||
var image_views_buf: [8]vk.ImageView = undefined;
|
||||
@memset(&image_views_buf, .null_handle);
|
||||
var image_views: []vk.ImageView = &.{};
|
||||
const ChainImage = struct {
|
||||
image: vk.Image = .null_handle,
|
||||
view: vk.ImageView = .null_handle,
|
||||
cmdbuf: vk.CommandBuffer = .null_handle,
|
||||
// fence: vk.Fence = .null_handle,
|
||||
// image_available: vk.Semaphore = .null_handle,
|
||||
// render_finished: vk.Semaphore = .null_handle,
|
||||
};
|
||||
|
||||
var chain = std.MultiArrayList(ChainImage){};
|
||||
defer chain.deinit(ally);
|
||||
defer vkd.freeCommandBuffers(dev, pool, @intCast(chain.len), chain.items(.cmdbuf).ptr);
|
||||
defer for (chain.items(.view)) |view| vkd.destroyImageView(dev, view, null);
|
||||
// defer for (chain.items(.fence)) |fence| vkd.destroyFence(dev, fence, null);
|
||||
// defer for (chain.items(.image_available)) |sem| vkd.destroySemaphore(dev, sem, null);
|
||||
// defer for (chain.items(.render_finished)) |sem| vkd.destroySemaphore(dev, sem, null);
|
||||
|
||||
const frame_fence = try vkd.createFence(dev, &.{ .flags = .{ .signaled_bit = true } }, null);
|
||||
defer vkd.destroyFence(dev, frame_fence, null);
|
||||
const image_available = try vkd.createSemaphore(dev, &.{}, null);
|
||||
defer vkd.destroySemaphore(dev, image_available, null);
|
||||
const render_finished = try vkd.createSemaphore(dev, &.{}, null);
|
||||
defer vkd.destroySemaphore(dev, render_finished, null);
|
||||
|
||||
swapchain = try vkd.createSwapchainKHR(dev, &.{
|
||||
.surface = surface,
|
||||
@@ -121,13 +143,12 @@ pub fn main() !void {
|
||||
.old_swapchain = swapchain,
|
||||
}, null);
|
||||
|
||||
var image_count: u32 = @intCast(image_buf.len);
|
||||
_ = try vkd.getSwapchainImagesKHR(dev, swapchain, &image_count, &image_buf);
|
||||
images = image_buf[0..image_count];
|
||||
image_views = image_views_buf[0..image_count];
|
||||
defer for (image_views) |view| vkd.destroyImageView(dev, view, null);
|
||||
var image_count: u32 = undefined;
|
||||
_ = try vkd.getSwapchainImagesKHR(dev, swapchain, &image_count, null);
|
||||
try chain.resize(ally, image_count);
|
||||
_ = try vkd.getSwapchainImagesKHR(dev, swapchain, &image_count, chain.items(.image).ptr);
|
||||
|
||||
for (images, image_views) |image, *view| {
|
||||
for (chain.items(.image), chain.items(.view)) |image, *view| {
|
||||
view.* = try vkd.createImageView(dev, &.{
|
||||
.image = image,
|
||||
.view_type = .@"2d",
|
||||
@@ -143,6 +164,24 @@ pub fn main() !void {
|
||||
}, null);
|
||||
}
|
||||
|
||||
// for (chain.items(.fence)) |*fence| {
|
||||
// fence.* = try vkd.createFence(dev, &.{ .flags = .{ .signaled_bit = true } }, null);
|
||||
// }
|
||||
//
|
||||
// for (chain.items(.image_available)) |*sem| {
|
||||
// sem.* = try vkd.createSemaphore(dev, &.{}, null);
|
||||
// }
|
||||
//
|
||||
// for (chain.items(.render_finished)) |*sem| {
|
||||
// sem.* = try vkd.createSemaphore(dev, &.{}, null);
|
||||
// }
|
||||
|
||||
try vkd.allocateCommandBuffers(dev, &.{
|
||||
.command_buffer_count = @intCast(chain.len),
|
||||
.command_pool = pool,
|
||||
.level = .primary,
|
||||
}, chain.items(.cmdbuf).ptr);
|
||||
|
||||
const pipeline_layout = try vkd.createPipelineLayout(dev, &.{
|
||||
.flags = .{},
|
||||
.set_layout_count = 0,
|
||||
@@ -155,11 +194,6 @@ pub fn main() !void {
|
||||
const pipeline = try createPipeline(dev, pipeline_layout, format, vkd);
|
||||
defer vkd.destroyPipeline(dev, pipeline, null);
|
||||
|
||||
const pool = try vkd.createCommandPool(dev, &.{
|
||||
.queue_family_index = family,
|
||||
}, null);
|
||||
defer vkd.destroyCommandPool(dev, pool, null);
|
||||
|
||||
const vertex_buffer = try vkd.createBuffer(dev, &.{
|
||||
.size = @sizeOf(@TypeOf(vertices)),
|
||||
.usage = .{ .transfer_dst_bit = true, .vertex_buffer_bit = true },
|
||||
@@ -186,16 +220,11 @@ pub fn main() !void {
|
||||
|
||||
try gfx.uploadData(Index, pdev, vki, dev, vkd, queue, pool, index_buffer, &indices);
|
||||
|
||||
// var cmdbufs = try createCommandBuffers(
|
||||
// &gc,
|
||||
// pool,
|
||||
// ally,
|
||||
// vertex_buffer,
|
||||
// index_buffer,
|
||||
// pipeline,
|
||||
// swapchain,
|
||||
// );
|
||||
// defer destroyCommandBuffers(&gc, pool, ally, cmdbufs);
|
||||
for (chain.items(.image), chain.items(.view), chain.items(.cmdbuf)) |image, view, cmdbuf| {
|
||||
try record_cmdbuf(cmdbuf, vkd, image, view, extent, pipeline, vertex_buffer, index_buffer);
|
||||
}
|
||||
|
||||
// var index: u32 = 0;
|
||||
|
||||
while (c.glfwWindowShouldClose(window) == c.GLFW_FALSE) {
|
||||
var w: c_int = undefined;
|
||||
@@ -208,6 +237,37 @@ pub fn main() !void {
|
||||
continue;
|
||||
}
|
||||
|
||||
_ = try vkd.waitForFences(dev, 1, @ptrCast(&frame_fence), vk.TRUE, std.math.maxInt(u64));
|
||||
try vkd.resetFences(dev, 1, @ptrCast(&frame_fence));
|
||||
|
||||
// const frame: ChainImage = chain.get();
|
||||
|
||||
// var index: u32 = undefined;
|
||||
// try vkd.acquireNextImageKHR(dev, swapchain, std.math.maxInt(u64), frame., fence);
|
||||
const result = try vkd.acquireNextImageKHR(dev, swapchain, std.math.maxInt(u64), image_available, .null_handle);
|
||||
|
||||
// std.log.debug("frame {d}", .{result.image_index});
|
||||
const frame = chain.get(result.image_index);
|
||||
|
||||
try vkd.queueSubmit(queue, 1, @ptrCast(&vk.SubmitInfo{
|
||||
.wait_semaphore_count = 1,
|
||||
.p_wait_semaphores = @ptrCast(&image_available),
|
||||
.p_wait_dst_stage_mask = @ptrCast(&vk.PipelineStageFlags{ .color_attachment_output_bit = true }),
|
||||
.command_buffer_count = 1,
|
||||
.p_command_buffers = @ptrCast(&frame.cmdbuf),
|
||||
.signal_semaphore_count = 1,
|
||||
.p_signal_semaphores = @ptrCast(&render_finished),
|
||||
}), frame_fence);
|
||||
|
||||
_ = try vkd.queuePresentKHR(queue, &.{
|
||||
.wait_semaphore_count = 1,
|
||||
.p_wait_semaphores = @ptrCast(&render_finished),
|
||||
.swapchain_count = 1,
|
||||
.p_swapchains = @ptrCast(&swapchain),
|
||||
.p_image_indices = @ptrCast(&result.image_index),
|
||||
.p_results = null,
|
||||
});
|
||||
|
||||
// const cmdbuf = cmdbufs[swapchain.image_index];
|
||||
|
||||
// const state = swapchain.present(cmdbuf) catch |err| switch (err) {
|
||||
@@ -240,28 +300,16 @@ pub fn main() !void {
|
||||
try vkd.deviceWaitIdle(dev);
|
||||
}
|
||||
|
||||
fn createCommandBuffers(
|
||||
views: []const vk.Image,
|
||||
images: []const vk.ImageView,
|
||||
dev: vk.Device,
|
||||
fn record_cmdbuf(
|
||||
cmdbuf: vk.CommandBuffer,
|
||||
vkd: gfx.DeviceDispatch,
|
||||
pool: vk.CommandPool,
|
||||
allocator: Allocator,
|
||||
image: vk.Image,
|
||||
view: vk.ImageView,
|
||||
extent: vk.Extent2D,
|
||||
pipeline: vk.Pipeline,
|
||||
vertex_buffer: vk.Buffer,
|
||||
index_buffer: vk.Buffer,
|
||||
pipeline: vk.Pipeline,
|
||||
extent: vk.Extent2D,
|
||||
) ![]vk.CommandBuffer {
|
||||
const cmdbufs = try allocator.alloc(vk.CommandBuffer, images.len);
|
||||
errdefer allocator.free(cmdbufs);
|
||||
|
||||
try vkd.allocateCommandBuffers(dev, &.{
|
||||
.command_pool = pool,
|
||||
.level = .primary,
|
||||
.command_buffer_count = @as(u32, @truncate(cmdbufs.len)),
|
||||
}, cmdbufs.ptr);
|
||||
errdefer vkd.freeCommandBuffers(dev, pool, @truncate(cmdbufs.len), cmdbufs.ptr);
|
||||
|
||||
) !void {
|
||||
const clear = vk.ClearValue{
|
||||
.color = .{ .float_32 = .{ 0, 0, 0, 1 } },
|
||||
};
|
||||
@@ -269,8 +317,8 @@ fn createCommandBuffers(
|
||||
const viewport = vk.Viewport{
|
||||
.x = 0,
|
||||
.y = 0,
|
||||
.width = @as(f32, @floatFromInt(extent.width)),
|
||||
.height = @as(f32, @floatFromInt(extent.height)),
|
||||
.width = @floatFromInt(extent.width),
|
||||
.height = @floatFromInt(extent.height),
|
||||
.min_depth = 0,
|
||||
.max_depth = 1,
|
||||
};
|
||||
@@ -280,114 +328,99 @@ fn createCommandBuffers(
|
||||
.extent = extent,
|
||||
};
|
||||
|
||||
for (cmdbufs, images, views) |cmdbuf, image, view| {
|
||||
try vkd.beginCommandBuffer(cmdbuf, &.{});
|
||||
try vkd.beginCommandBuffer(cmdbuf, &.{});
|
||||
|
||||
vkd.cmdPipelineBarrier(
|
||||
cmdbuf,
|
||||
.{ .top_of_pipe_bit = true },
|
||||
.{ .color_attachment_output_bit = true },
|
||||
.{},
|
||||
0,
|
||||
null,
|
||||
0,
|
||||
null,
|
||||
1,
|
||||
@ptrCast(&vk.ImageMemoryBarrier{
|
||||
.src_access_mask = .{},
|
||||
.dst_access_mask = .{ .color_attachment_write_bit = true },
|
||||
.old_layout = .undefined,
|
||||
.new_layout = .color_attachment_optimal,
|
||||
.src_queue_family_index = 0,
|
||||
.dst_queue_family_index = 0,
|
||||
.image = image,
|
||||
.subresource_range = .{
|
||||
.aspect_mask = .{ .color_bit = true },
|
||||
.base_mip_level = 0,
|
||||
.level_count = 1,
|
||||
.base_array_layer = 0,
|
||||
.layer_count = 1,
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
vkd.cmdSetViewport(cmdbuf, 0, 1, @ptrCast(&viewport));
|
||||
vkd.cmdSetScissor(cmdbuf, 0, 1, @ptrCast(&scissor));
|
||||
|
||||
const color_attachments = [_]vk.RenderingAttachmentInfoKHR{
|
||||
.{
|
||||
.image_view = view,
|
||||
.image_layout = .color_attachment_optimal,
|
||||
.resolve_mode = .{},
|
||||
.resolve_image_view = .null_handle,
|
||||
.resolve_image_layout = .undefined,
|
||||
.load_op = .clear,
|
||||
.store_op = .store,
|
||||
.clear_value = clear,
|
||||
vkd.cmdPipelineBarrier(
|
||||
cmdbuf,
|
||||
.{ .top_of_pipe_bit = true },
|
||||
.{ .color_attachment_output_bit = true },
|
||||
.{},
|
||||
0,
|
||||
null,
|
||||
0,
|
||||
null,
|
||||
1,
|
||||
@ptrCast(&vk.ImageMemoryBarrier{
|
||||
.src_access_mask = .{},
|
||||
.dst_access_mask = .{ .color_attachment_write_bit = true },
|
||||
.old_layout = .undefined,
|
||||
.new_layout = .color_attachment_optimal,
|
||||
.src_queue_family_index = 0,
|
||||
.dst_queue_family_index = 0,
|
||||
.image = image,
|
||||
.subresource_range = .{
|
||||
.aspect_mask = .{ .color_bit = true },
|
||||
.base_mip_level = 0,
|
||||
.level_count = 1,
|
||||
.base_array_layer = 0,
|
||||
.layer_count = 1,
|
||||
},
|
||||
};
|
||||
}),
|
||||
);
|
||||
|
||||
const render_info = vk.RenderingInfoKHR{
|
||||
.render_area = scissor, // since we always do full-frame changes
|
||||
.layer_count = 1,
|
||||
.view_mask = 0,
|
||||
.color_attachment_count = color_attachments.len,
|
||||
.p_color_attachments = &color_attachments,
|
||||
};
|
||||
vkd.cmdSetViewport(cmdbuf, 0, 1, @ptrCast(&viewport));
|
||||
vkd.cmdSetScissor(cmdbuf, 0, 1, @ptrCast(&scissor));
|
||||
|
||||
vkd.cmdBeginRenderingKHR(cmdbuf, &render_info);
|
||||
const color_attachments = [_]vk.RenderingAttachmentInfoKHR{
|
||||
.{
|
||||
.image_view = view,
|
||||
.image_layout = .color_attachment_optimal,
|
||||
.resolve_mode = .{},
|
||||
.resolve_image_view = .null_handle,
|
||||
.resolve_image_layout = .undefined,
|
||||
.load_op = .clear,
|
||||
.store_op = .store,
|
||||
.clear_value = clear,
|
||||
},
|
||||
};
|
||||
|
||||
vkd.cmdBindPipeline(cmdbuf, .graphics, pipeline);
|
||||
const offset = [_]vk.DeviceSize{0};
|
||||
vkd.cmdBindVertexBuffers(cmdbuf, 0, 1, @ptrCast(&vertex_buffer), &offset);
|
||||
vkd.cmdBindIndexBuffer(cmdbuf, index_buffer, 0, .uint16);
|
||||
vkd.cmdDrawIndexed(cmdbuf, indices.len, 1, 0, 0, 0);
|
||||
const render_info = vk.RenderingInfoKHR{
|
||||
.render_area = scissor, // since we always do full-frame changes
|
||||
.layer_count = 1,
|
||||
.view_mask = 0,
|
||||
.color_attachment_count = color_attachments.len,
|
||||
.p_color_attachments = &color_attachments,
|
||||
};
|
||||
|
||||
vkd.cmdEndRenderingKHR(cmdbuf);
|
||||
vkd.cmdBeginRenderingKHR(cmdbuf, &render_info);
|
||||
|
||||
vkd.cmdPipelineBarrier(
|
||||
cmdbuf,
|
||||
.{ .color_attachment_output_bit = true },
|
||||
.{ .bottom_of_pipe_bit = true },
|
||||
.{},
|
||||
0,
|
||||
null,
|
||||
0,
|
||||
null,
|
||||
1,
|
||||
@ptrCast(&vk.ImageMemoryBarrier{
|
||||
.src_access_mask = .{ .color_attachment_write_bit = true },
|
||||
.dst_access_mask = .{},
|
||||
.old_layout = .color_attachment_optimal,
|
||||
.new_layout = .present_src_khr,
|
||||
.src_queue_family_index = 0,
|
||||
.dst_queue_family_index = 0,
|
||||
.image = image,
|
||||
.subresource_range = .{
|
||||
.aspect_mask = .{ .color_bit = true },
|
||||
.base_mip_level = 0,
|
||||
.level_count = 1,
|
||||
.base_array_layer = 0,
|
||||
.layer_count = 1,
|
||||
},
|
||||
}),
|
||||
);
|
||||
vkd.cmdBindPipeline(cmdbuf, .graphics, pipeline);
|
||||
const offset = [_]vk.DeviceSize{0};
|
||||
vkd.cmdBindVertexBuffers(cmdbuf, 0, 1, @ptrCast(&vertex_buffer), &offset);
|
||||
vkd.cmdBindIndexBuffer(cmdbuf, index_buffer, 0, .uint16);
|
||||
vkd.cmdDrawIndexed(cmdbuf, indices.len, 1, 0, 0, 0);
|
||||
|
||||
try vkd.endCommandBuffer(cmdbuf);
|
||||
}
|
||||
vkd.cmdEndRenderingKHR(cmdbuf);
|
||||
|
||||
return cmdbufs;
|
||||
}
|
||||
vkd.cmdPipelineBarrier(
|
||||
cmdbuf,
|
||||
.{ .color_attachment_output_bit = true },
|
||||
.{ .bottom_of_pipe_bit = true },
|
||||
.{},
|
||||
0,
|
||||
null,
|
||||
0,
|
||||
null,
|
||||
1,
|
||||
@ptrCast(&vk.ImageMemoryBarrier{
|
||||
.src_access_mask = .{ .color_attachment_write_bit = true },
|
||||
.dst_access_mask = .{},
|
||||
.old_layout = .color_attachment_optimal,
|
||||
.new_layout = .present_src_khr,
|
||||
.src_queue_family_index = 0,
|
||||
.dst_queue_family_index = 0,
|
||||
.image = image,
|
||||
.subresource_range = .{
|
||||
.aspect_mask = .{ .color_bit = true },
|
||||
.base_mip_level = 0,
|
||||
.level_count = 1,
|
||||
.base_array_layer = 0,
|
||||
.layer_count = 1,
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
fn destroyCommandBuffers(
|
||||
dev: vk.Device,
|
||||
vkd: gfx.DeviceDispatch,
|
||||
pool: vk.CommandPool,
|
||||
allocator: Allocator,
|
||||
cmdbufs: []vk.CommandBuffer,
|
||||
) void {
|
||||
vkd.freeCommandBuffers(dev, pool, @truncate(cmdbufs.len), cmdbufs.ptr);
|
||||
allocator.free(cmdbufs);
|
||||
try vkd.endCommandBuffer(cmdbuf);
|
||||
}
|
||||
|
||||
fn createPipeline(dev: vk.Device, layout: vk.PipelineLayout, format: vk.SurfaceFormatKHR, vkd: gfx.DeviceDispatch) !vk.Pipeline {
|
||||
|
Reference in New Issue
Block a user