Refactor Vulkan setup stage 2
This commit is contained in:
parent
3883827f94
commit
6e18542b2b
558
src/main.zig
558
src/main.zig
@ -18,6 +18,38 @@ const VulkanContext = struct {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const LogicalDeviceContext = struct {
|
||||||
|
physical_device: vk.PhysicalDevice,
|
||||||
|
graphics_queue_family_index: u32,
|
||||||
|
device: vk.Device,
|
||||||
|
vkd: vk.DeviceWrapper,
|
||||||
|
graphics_queue: vk.Queue,
|
||||||
|
|
||||||
|
fn destroy(self: *const LogicalDeviceContext) void {
|
||||||
|
self.vkd.destroyDevice(self.device, null);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const SwapchainContext = struct {
|
||||||
|
swapchain: vk.SwapchainKHR,
|
||||||
|
images: []vk.Image,
|
||||||
|
image_views: []vk.ImageView,
|
||||||
|
format: vk.SurfaceFormatKHR,
|
||||||
|
present_mode: vk.PresentModeKHR,
|
||||||
|
extent: vk.Extent2D,
|
||||||
|
image_count: u32,
|
||||||
|
allocator: std.mem.Allocator,
|
||||||
|
|
||||||
|
fn destroy(self: *const SwapchainContext, ldc: *const LogicalDeviceContext) void {
|
||||||
|
for (self.image_views) |image_view| {
|
||||||
|
ldc.vkd.destroyImageView(ldc.device, image_view, null);
|
||||||
|
}
|
||||||
|
self.allocator.free(self.image_views);
|
||||||
|
self.allocator.free(self.images);
|
||||||
|
ldc.vkd.destroySwapchainKHR(ldc.device, self.swapchain, null);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
pub fn main() !void {
|
pub fn main() !void {
|
||||||
std.debug.print("zig-chess bootstrap\n", .{});
|
std.debug.print("zig-chess bootstrap\n", .{});
|
||||||
std.debug.print("vertex shader bytes: {}\n", .{square_vert_spv.len});
|
std.debug.print("vertex shader bytes: {}\n", .{square_vert_spv.len});
|
||||||
@ -79,230 +111,15 @@ pub fn main() !void {
|
|||||||
|
|
||||||
// ---------------------------------------------------------------------
|
// ---------------------------------------------------------------------
|
||||||
// Logical device and queue
|
// Logical device and queue
|
||||||
//
|
|
||||||
// The logical device enables VK_KHR_swapchain so we can present rendered
|
|
||||||
// images. We request one queue from the selected queue family.
|
|
||||||
//
|
|
||||||
// Refactor direction: createLogicalDevice() should return the device,
|
|
||||||
// DeviceWrapper, and graphics/present queue handles or indices.
|
|
||||||
// ---------------------------------------------------------------------
|
// ---------------------------------------------------------------------
|
||||||
const queue_priority: f32 = 1.0;
|
const ldc = try initLogicalDevice(vc, selected_physical_device, graphics_queue_family_index);
|
||||||
|
defer ldc.destroy();
|
||||||
const queue_create_info = vk.DeviceQueueCreateInfo{
|
|
||||||
.queue_family_index = graphics_queue_family_index,
|
|
||||||
.queue_count = 1,
|
|
||||||
.p_queue_priorities = @ptrCast(&queue_priority),
|
|
||||||
};
|
|
||||||
|
|
||||||
const device_extensions = [_][*:0]const u8{
|
|
||||||
"VK_KHR_swapchain",
|
|
||||||
};
|
|
||||||
|
|
||||||
const device_create_info = vk.DeviceCreateInfo{
|
|
||||||
.queue_create_info_count = 1,
|
|
||||||
.p_queue_create_infos = @ptrCast(&queue_create_info),
|
|
||||||
.enabled_extension_count = device_extensions.len,
|
|
||||||
.pp_enabled_extension_names = &device_extensions,
|
|
||||||
};
|
|
||||||
|
|
||||||
const device = try vc.vki.createDevice(selected_physical_device, &device_create_info, null);
|
|
||||||
std.debug.print("created logical device\n", .{});
|
|
||||||
|
|
||||||
const vkd = vk.DeviceWrapper.load(device, vc.vki.dispatch.vkGetDeviceProcAddr.?);
|
|
||||||
defer vkd.destroyDevice(device, null);
|
|
||||||
|
|
||||||
const graphics_queue = vkd.getDeviceQueue(device, graphics_queue_family_index, 0);
|
|
||||||
|
|
||||||
std.debug.print("retrieved graphics queue\n", .{});
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------
|
// ---------------------------------------------------------------------
|
||||||
// Swapchain support query and choice of format/present mode/extent
|
// Swapchain setup
|
||||||
//
|
|
||||||
// These values describe how the surface can be presented to. FIFO is the
|
|
||||||
// safe baseline because Vulkan requires it to be supported.
|
|
||||||
//
|
|
||||||
// Refactor direction: create a chooseSwapchainSettings() helper returning
|
|
||||||
// the chosen format, present mode, extent, and image count.
|
|
||||||
// ---------------------------------------------------------------------
|
// ---------------------------------------------------------------------
|
||||||
const surface_caps = try vc.vki.getPhysicalDeviceSurfaceCapabilitiesKHR(
|
const swapchain_context = try initSwapchain(vc, ldc, surface, window, std.heap.page_allocator);
|
||||||
selected_physical_device,
|
defer swapchain_context.destroy(&ldc);
|
||||||
surface,
|
|
||||||
);
|
|
||||||
|
|
||||||
std.debug.print(
|
|
||||||
"surface current extent: {}x{}\n",
|
|
||||||
.{
|
|
||||||
surface_caps.current_extent.width,
|
|
||||||
surface_caps.current_extent.height,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
std.debug.print(
|
|
||||||
"surface min/max image count: {}/{}\n",
|
|
||||||
.{
|
|
||||||
surface_caps.min_image_count,
|
|
||||||
surface_caps.max_image_count,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
const surface_formats = try vc.vki.getPhysicalDeviceSurfaceFormatsAllocKHR(
|
|
||||||
selected_physical_device,
|
|
||||||
surface,
|
|
||||||
std.heap.page_allocator,
|
|
||||||
);
|
|
||||||
defer std.heap.page_allocator.free(surface_formats);
|
|
||||||
|
|
||||||
std.debug.print("surface formats: {}\n", .{surface_formats.len});
|
|
||||||
for (surface_formats, 0..) |format, i| {
|
|
||||||
std.debug.print(
|
|
||||||
" format {}: format={any}, color_space={any}\n",
|
|
||||||
.{ i, format.format, format.color_space },
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const present_modes = try vc.vki.getPhysicalDeviceSurfacePresentModesAllocKHR(
|
|
||||||
selected_physical_device,
|
|
||||||
surface,
|
|
||||||
std.heap.page_allocator,
|
|
||||||
);
|
|
||||||
defer std.heap.page_allocator.free(present_modes);
|
|
||||||
|
|
||||||
std.debug.print("present modes: {}\n", .{present_modes.len});
|
|
||||||
for (present_modes, 0..) |mode, i| {
|
|
||||||
std.debug.print(" present mode {}: {any}\n", .{ i, mode });
|
|
||||||
}
|
|
||||||
|
|
||||||
var chosen_surface_format = surface_formats[0];
|
|
||||||
for (surface_formats) |format| {
|
|
||||||
if (format.format == .b8g8r8a8_srgb and
|
|
||||||
format.color_space == .srgb_nonlinear_khr)
|
|
||||||
{
|
|
||||||
chosen_surface_format = format;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var chosen_present_mode: vk.PresentModeKHR = .fifo_khr;
|
|
||||||
for (present_modes) |mode| {
|
|
||||||
if (mode == .fifo_khr) {
|
|
||||||
chosen_present_mode = mode;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const framebuffer_size = window.getFramebufferSize();
|
|
||||||
|
|
||||||
const chosen_extent = if (surface_caps.current_extent.width != std.math.maxInt(u32))
|
|
||||||
surface_caps.current_extent
|
|
||||||
else
|
|
||||||
vk.Extent2D{
|
|
||||||
.width = @intCast(framebuffer_size[0]),
|
|
||||||
.height = @intCast(framebuffer_size[1]),
|
|
||||||
};
|
|
||||||
|
|
||||||
var chosen_image_count = surface_caps.min_image_count + 1;
|
|
||||||
if (surface_caps.max_image_count != 0 and chosen_image_count > surface_caps.max_image_count) {
|
|
||||||
chosen_image_count = surface_caps.max_image_count;
|
|
||||||
}
|
|
||||||
|
|
||||||
std.debug.print(
|
|
||||||
"chosen swapchain format={any}, color_space={any}\n",
|
|
||||||
.{ chosen_surface_format.format, chosen_surface_format.color_space },
|
|
||||||
);
|
|
||||||
std.debug.print("chosen present mode={any}\n", .{chosen_present_mode});
|
|
||||||
std.debug.print(
|
|
||||||
"chosen extent={}x{}\n",
|
|
||||||
.{ chosen_extent.width, chosen_extent.height },
|
|
||||||
);
|
|
||||||
std.debug.print("chosen image count={}\n", .{chosen_image_count});
|
|
||||||
|
|
||||||
const swapchain_create_info = vk.SwapchainCreateInfoKHR{
|
|
||||||
.surface = surface,
|
|
||||||
.min_image_count = chosen_image_count,
|
|
||||||
.image_format = chosen_surface_format.format,
|
|
||||||
.image_color_space = chosen_surface_format.color_space,
|
|
||||||
.image_extent = chosen_extent,
|
|
||||||
.image_array_layers = 1,
|
|
||||||
.image_usage = .{
|
|
||||||
.color_attachment_bit = true,
|
|
||||||
},
|
|
||||||
.image_sharing_mode = .exclusive,
|
|
||||||
.pre_transform = surface_caps.current_transform,
|
|
||||||
.composite_alpha = .{
|
|
||||||
.opaque_bit_khr = true,
|
|
||||||
},
|
|
||||||
.present_mode = chosen_present_mode,
|
|
||||||
.clipped = .true,
|
|
||||||
};
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------
|
|
||||||
// Swapchain creation
|
|
||||||
//
|
|
||||||
// The swapchain owns the presentable images. Anything tied to its image
|
|
||||||
// format or extent must be recreated when the window is resized or Vulkan
|
|
||||||
// reports the swapchain is out of date/suboptimal.
|
|
||||||
//
|
|
||||||
// Refactor direction: group swapchain, images, image views, framebuffers,
|
|
||||||
// format, and extent into a SwapchainResources struct.
|
|
||||||
// ---------------------------------------------------------------------
|
|
||||||
const swapchain = try vkd.createSwapchainKHR(device, &swapchain_create_info, null);
|
|
||||||
defer vkd.destroySwapchainKHR(device, swapchain, null);
|
|
||||||
|
|
||||||
std.debug.print("created swapchain\n", .{});
|
|
||||||
|
|
||||||
const swapchain_images = try vkd.getSwapchainImagesAllocKHR(
|
|
||||||
device,
|
|
||||||
swapchain,
|
|
||||||
std.heap.page_allocator,
|
|
||||||
);
|
|
||||||
defer std.heap.page_allocator.free(swapchain_images);
|
|
||||||
|
|
||||||
std.debug.print("swapchain images: {}\n", .{swapchain_images.len});
|
|
||||||
|
|
||||||
// Each swapchain image needs an image view so it can be used as a render
|
|
||||||
// pass attachment.
|
|
||||||
const swapchain_image_views = try std.heap.page_allocator.alloc(
|
|
||||||
vk.ImageView,
|
|
||||||
swapchain_images.len,
|
|
||||||
);
|
|
||||||
defer std.heap.page_allocator.free(swapchain_image_views);
|
|
||||||
|
|
||||||
for (swapchain_images, 0..) |image, i| {
|
|
||||||
const image_view_create_info = vk.ImageViewCreateInfo{
|
|
||||||
.image = image,
|
|
||||||
.view_type = .@"2d",
|
|
||||||
.format = chosen_surface_format.format,
|
|
||||||
.components = .{
|
|
||||||
.r = .identity,
|
|
||||||
.g = .identity,
|
|
||||||
.b = .identity,
|
|
||||||
.a = .identity,
|
|
||||||
},
|
|
||||||
.subresource_range = .{
|
|
||||||
.aspect_mask = .{
|
|
||||||
.color_bit = true,
|
|
||||||
},
|
|
||||||
.base_mip_level = 0,
|
|
||||||
.level_count = 1,
|
|
||||||
.base_array_layer = 0,
|
|
||||||
.layer_count = 1,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
swapchain_image_views[i] = try vkd.createImageView(
|
|
||||||
device,
|
|
||||||
&image_view_create_info,
|
|
||||||
null,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
defer {
|
|
||||||
for (swapchain_image_views) |image_view| {
|
|
||||||
vkd.destroyImageView(device, image_view, null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std.debug.print("created swapchain image views: {}\n", .{swapchain_image_views.len});
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------
|
// ---------------------------------------------------------------------
|
||||||
// Render pass
|
// Render pass
|
||||||
@ -316,7 +133,7 @@ pub fn main() !void {
|
|||||||
// if we move to dynamic rendering.
|
// if we move to dynamic rendering.
|
||||||
// ---------------------------------------------------------------------
|
// ---------------------------------------------------------------------
|
||||||
const color_attachment = vk.AttachmentDescription{
|
const color_attachment = vk.AttachmentDescription{
|
||||||
.format = chosen_surface_format.format,
|
.format = swapchain_context.format.format,
|
||||||
.samples = .{ .@"1_bit" = true },
|
.samples = .{ .@"1_bit" = true },
|
||||||
.load_op = .clear,
|
.load_op = .clear,
|
||||||
.store_op = .store,
|
.store_op = .store,
|
||||||
@ -361,8 +178,8 @@ pub fn main() !void {
|
|||||||
.p_dependencies = @ptrCast(&subpass_dependency),
|
.p_dependencies = @ptrCast(&subpass_dependency),
|
||||||
};
|
};
|
||||||
|
|
||||||
const render_pass = try vkd.createRenderPass(device, &render_pass_create_info, null);
|
const render_pass = try ldc.vkd.createRenderPass(ldc.device, &render_pass_create_info, null);
|
||||||
defer vkd.destroyRenderPass(device, render_pass, null);
|
defer ldc.vkd.destroyRenderPass(ldc.device, render_pass, null);
|
||||||
|
|
||||||
std.debug.print("created render pass\n", .{});
|
std.debug.print("created render pass\n", .{});
|
||||||
|
|
||||||
@ -374,24 +191,24 @@ pub fn main() !void {
|
|||||||
// ---------------------------------------------------------------------
|
// ---------------------------------------------------------------------
|
||||||
const framebuffers = try std.heap.page_allocator.alloc(
|
const framebuffers = try std.heap.page_allocator.alloc(
|
||||||
vk.Framebuffer,
|
vk.Framebuffer,
|
||||||
swapchain_image_views.len,
|
swapchain_context.image_views.len,
|
||||||
);
|
);
|
||||||
defer std.heap.page_allocator.free(framebuffers);
|
defer std.heap.page_allocator.free(framebuffers);
|
||||||
|
|
||||||
for (swapchain_image_views, 0..) |image_view, i| {
|
for (swapchain_context.image_views, 0..) |image_view, i| {
|
||||||
const attachments = [_]vk.ImageView{image_view};
|
const attachments = [_]vk.ImageView{image_view};
|
||||||
|
|
||||||
const framebuffer_create_info = vk.FramebufferCreateInfo{
|
const framebuffer_create_info = vk.FramebufferCreateInfo{
|
||||||
.render_pass = render_pass,
|
.render_pass = render_pass,
|
||||||
.attachment_count = attachments.len,
|
.attachment_count = attachments.len,
|
||||||
.p_attachments = &attachments,
|
.p_attachments = &attachments,
|
||||||
.width = chosen_extent.width,
|
.width = swapchain_context.extent.width,
|
||||||
.height = chosen_extent.height,
|
.height = swapchain_context.extent.height,
|
||||||
.layers = 1,
|
.layers = 1,
|
||||||
};
|
};
|
||||||
|
|
||||||
framebuffers[i] = try vkd.createFramebuffer(
|
framebuffers[i] = try ldc.vkd.createFramebuffer(
|
||||||
device,
|
ldc.device,
|
||||||
&framebuffer_create_info,
|
&framebuffer_create_info,
|
||||||
null,
|
null,
|
||||||
);
|
);
|
||||||
@ -399,7 +216,7 @@ pub fn main() !void {
|
|||||||
|
|
||||||
defer {
|
defer {
|
||||||
for (framebuffers) |framebuffer| {
|
for (framebuffers) |framebuffer| {
|
||||||
vkd.destroyFramebuffer(device, framebuffer, null);
|
ldc.vkd.destroyFramebuffer(ldc.device, framebuffer, null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -419,15 +236,15 @@ pub fn main() !void {
|
|||||||
.flags = .{
|
.flags = .{
|
||||||
.reset_command_buffer_bit = true,
|
.reset_command_buffer_bit = true,
|
||||||
},
|
},
|
||||||
.queue_family_index = graphics_queue_family_index,
|
.queue_family_index = ldc.graphics_queue_family_index,
|
||||||
};
|
};
|
||||||
|
|
||||||
const command_pool = try vkd.createCommandPool(
|
const command_pool = try ldc.vkd.createCommandPool(
|
||||||
device,
|
ldc.device,
|
||||||
&command_pool_create_info,
|
&command_pool_create_info,
|
||||||
null,
|
null,
|
||||||
);
|
);
|
||||||
defer vkd.destroyCommandPool(device, command_pool, null);
|
defer ldc.vkd.destroyCommandPool(ldc.device, command_pool, null);
|
||||||
|
|
||||||
std.debug.print("created command pool\n", .{});
|
std.debug.print("created command pool\n", .{});
|
||||||
|
|
||||||
@ -443,8 +260,8 @@ pub fn main() !void {
|
|||||||
.command_buffer_count = @intCast(command_buffers.len),
|
.command_buffer_count = @intCast(command_buffers.len),
|
||||||
};
|
};
|
||||||
|
|
||||||
try vkd.allocateCommandBuffers(
|
try ldc.vkd.allocateCommandBuffers(
|
||||||
device,
|
ldc.device,
|
||||||
&command_buffer_allocate_info,
|
&command_buffer_allocate_info,
|
||||||
command_buffers.ptr,
|
command_buffers.ptr,
|
||||||
);
|
);
|
||||||
@ -454,7 +271,7 @@ pub fn main() !void {
|
|||||||
for (command_buffers, 0..) |command_buffer, i| {
|
for (command_buffers, 0..) |command_buffer, i| {
|
||||||
const begin_info = vk.CommandBufferBeginInfo{};
|
const begin_info = vk.CommandBufferBeginInfo{};
|
||||||
|
|
||||||
try vkd.beginCommandBuffer(command_buffer, &begin_info);
|
try ldc.vkd.beginCommandBuffer(command_buffer, &begin_info);
|
||||||
|
|
||||||
// This is the only "drawing" currently happening: begin a render pass
|
// This is the only "drawing" currently happening: begin a render pass
|
||||||
// and clear the swapchain image. The embedded shaders are not used yet.
|
// and clear the swapchain image. The embedded shaders are not used yet.
|
||||||
@ -469,21 +286,21 @@ pub fn main() !void {
|
|||||||
.framebuffer = framebuffers[i],
|
.framebuffer = framebuffers[i],
|
||||||
.render_area = .{
|
.render_area = .{
|
||||||
.offset = .{ .x = 0, .y = 0 },
|
.offset = .{ .x = 0, .y = 0 },
|
||||||
.extent = chosen_extent,
|
.extent = swapchain_context.extent,
|
||||||
},
|
},
|
||||||
.clear_value_count = 1,
|
.clear_value_count = 1,
|
||||||
.p_clear_values = @ptrCast(&clear_color),
|
.p_clear_values = @ptrCast(&clear_color),
|
||||||
};
|
};
|
||||||
|
|
||||||
vkd.cmdBeginRenderPass(
|
ldc.vkd.cmdBeginRenderPass(
|
||||||
command_buffer,
|
command_buffer,
|
||||||
&render_pass_begin_info,
|
&render_pass_begin_info,
|
||||||
.@"inline",
|
.@"inline",
|
||||||
);
|
);
|
||||||
|
|
||||||
vkd.cmdEndRenderPass(command_buffer);
|
ldc.vkd.cmdEndRenderPass(command_buffer);
|
||||||
|
|
||||||
try vkd.endCommandBuffer(command_buffer);
|
try ldc.vkd.endCommandBuffer(command_buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
std.debug.print("recorded command buffers\n", .{});
|
std.debug.print("recorded command buffers\n", .{});
|
||||||
@ -501,19 +318,19 @@ pub fn main() !void {
|
|||||||
// ---------------------------------------------------------------------
|
// ---------------------------------------------------------------------
|
||||||
const semaphore_create_info = vk.SemaphoreCreateInfo{};
|
const semaphore_create_info = vk.SemaphoreCreateInfo{};
|
||||||
|
|
||||||
const image_available_semaphore = try vkd.createSemaphore(
|
const image_available_semaphore = try ldc.vkd.createSemaphore(
|
||||||
device,
|
ldc.device,
|
||||||
&semaphore_create_info,
|
&semaphore_create_info,
|
||||||
null,
|
null,
|
||||||
);
|
);
|
||||||
defer vkd.destroySemaphore(device, image_available_semaphore, null);
|
defer ldc.vkd.destroySemaphore(ldc.device, image_available_semaphore, null);
|
||||||
|
|
||||||
const render_finished_semaphore = try vkd.createSemaphore(
|
const render_finished_semaphore = try ldc.vkd.createSemaphore(
|
||||||
device,
|
ldc.device,
|
||||||
&semaphore_create_info,
|
&semaphore_create_info,
|
||||||
null,
|
null,
|
||||||
);
|
);
|
||||||
defer vkd.destroySemaphore(device, render_finished_semaphore, null);
|
defer ldc.vkd.destroySemaphore(ldc.device, render_finished_semaphore, null);
|
||||||
|
|
||||||
const fence_create_info = vk.FenceCreateInfo{
|
const fence_create_info = vk.FenceCreateInfo{
|
||||||
.flags = .{
|
.flags = .{
|
||||||
@ -521,12 +338,12 @@ pub fn main() !void {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const in_flight_fence = try vkd.createFence(
|
const in_flight_fence = try ldc.vkd.createFence(
|
||||||
device,
|
ldc.device,
|
||||||
&fence_create_info,
|
&fence_create_info,
|
||||||
null,
|
null,
|
||||||
);
|
);
|
||||||
defer vkd.destroyFence(device, in_flight_fence, null);
|
defer ldc.vkd.destroyFence(ldc.device, in_flight_fence, null);
|
||||||
|
|
||||||
std.debug.print("created synchronization objects\n", .{});
|
std.debug.print("created synchronization objects\n", .{});
|
||||||
|
|
||||||
@ -547,12 +364,12 @@ pub fn main() !void {
|
|||||||
// recreateSwapchainResources().
|
// recreateSwapchainResources().
|
||||||
// ---------------------------------------------------------------------
|
// ---------------------------------------------------------------------
|
||||||
const wait_fences = [_]vk.Fence{in_flight_fence};
|
const wait_fences = [_]vk.Fence{in_flight_fence};
|
||||||
_ = try vkd.waitForFences(device, &wait_fences, .true, std.math.maxInt(u64));
|
_ = try ldc.vkd.waitForFences(ldc.device, &wait_fences, .true, std.math.maxInt(u64));
|
||||||
try vkd.resetFences(device, &wait_fences);
|
try ldc.vkd.resetFences(ldc.device, &wait_fences);
|
||||||
|
|
||||||
const acquire_result = try vkd.acquireNextImageKHR(
|
const acquire_result = try ldc.vkd.acquireNextImageKHR(
|
||||||
device,
|
ldc.device,
|
||||||
swapchain,
|
swapchain_context.swapchain,
|
||||||
std.math.maxInt(u64),
|
std.math.maxInt(u64),
|
||||||
image_available_semaphore,
|
image_available_semaphore,
|
||||||
.null_handle,
|
.null_handle,
|
||||||
@ -582,9 +399,9 @@ pub fn main() !void {
|
|||||||
.p_signal_semaphores = &signal_semaphores,
|
.p_signal_semaphores = &signal_semaphores,
|
||||||
};
|
};
|
||||||
|
|
||||||
try vkd.queueSubmit(graphics_queue, &[_]vk.SubmitInfo{submit_info}, in_flight_fence);
|
try ldc.vkd.queueSubmit(ldc.graphics_queue, &[_]vk.SubmitInfo{submit_info}, in_flight_fence);
|
||||||
|
|
||||||
const present_swapchains = [_]vk.SwapchainKHR{swapchain};
|
const present_swapchains = [_]vk.SwapchainKHR{swapchain_context.swapchain};
|
||||||
const present_image_indices = [_]u32{image_index};
|
const present_image_indices = [_]u32{image_index};
|
||||||
|
|
||||||
const present_info = vk.PresentInfoKHR{
|
const present_info = vk.PresentInfoKHR{
|
||||||
@ -595,7 +412,7 @@ pub fn main() !void {
|
|||||||
.p_image_indices = &present_image_indices,
|
.p_image_indices = &present_image_indices,
|
||||||
};
|
};
|
||||||
|
|
||||||
_ = try vkd.queuePresentKHR(graphics_queue, &present_info);
|
_ = try ldc.vkd.queuePresentKHR(ldc.graphics_queue, &present_info);
|
||||||
|
|
||||||
std.debug.print("presented one frame\n", .{});
|
std.debug.print("presented one frame\n", .{});
|
||||||
|
|
||||||
@ -672,6 +489,231 @@ fn initInstance(name: [:0]const u8) !VulkanContext {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn initLogicalDevice(
|
||||||
|
vc: VulkanContext,
|
||||||
|
physical_device: vk.PhysicalDevice,
|
||||||
|
graphics_queue_family_index: u32,
|
||||||
|
) !LogicalDeviceContext {
|
||||||
|
const queue_priority: f32 = 1.0;
|
||||||
|
|
||||||
|
const queue_create_info = vk.DeviceQueueCreateInfo{
|
||||||
|
.queue_family_index = graphics_queue_family_index,
|
||||||
|
.queue_count = 1,
|
||||||
|
.p_queue_priorities = @ptrCast(&queue_priority),
|
||||||
|
};
|
||||||
|
|
||||||
|
const device_extensions = [_][*:0]const u8{
|
||||||
|
"VK_KHR_swapchain",
|
||||||
|
};
|
||||||
|
|
||||||
|
const device_create_info = vk.DeviceCreateInfo{
|
||||||
|
.queue_create_info_count = 1,
|
||||||
|
.p_queue_create_infos = @ptrCast(&queue_create_info),
|
||||||
|
.enabled_extension_count = device_extensions.len,
|
||||||
|
.pp_enabled_extension_names = &device_extensions,
|
||||||
|
};
|
||||||
|
|
||||||
|
const device = try vc.vki.createDevice(physical_device, &device_create_info, null);
|
||||||
|
errdefer vc.vki.destroyDevice(device, null);
|
||||||
|
std.debug.print("created logical device\n", .{});
|
||||||
|
|
||||||
|
const vkd = vk.DeviceWrapper.load(device, vc.vki.dispatch.vkGetDeviceProcAddr.?);
|
||||||
|
const graphics_queue = vkd.getDeviceQueue(device, graphics_queue_family_index, 0);
|
||||||
|
std.debug.print("retrieved graphics queue\n", .{});
|
||||||
|
|
||||||
|
return .{
|
||||||
|
.physical_device = physical_device,
|
||||||
|
.graphics_queue_family_index = graphics_queue_family_index,
|
||||||
|
.device = device,
|
||||||
|
.vkd = vkd,
|
||||||
|
.graphics_queue = graphics_queue,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
fn initSwapchain(
|
||||||
|
vc: VulkanContext,
|
||||||
|
ldc: LogicalDeviceContext,
|
||||||
|
surface: vk.SurfaceKHR,
|
||||||
|
window: *glfw.Window,
|
||||||
|
allocator: std.mem.Allocator,
|
||||||
|
) !SwapchainContext {
|
||||||
|
const surface_caps = try vc.vki.getPhysicalDeviceSurfaceCapabilitiesKHR(
|
||||||
|
ldc.physical_device,
|
||||||
|
surface,
|
||||||
|
);
|
||||||
|
|
||||||
|
std.debug.print(
|
||||||
|
"surface current extent: {}x{}\n",
|
||||||
|
.{
|
||||||
|
surface_caps.current_extent.width,
|
||||||
|
surface_caps.current_extent.height,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
std.debug.print(
|
||||||
|
"surface min/max image count: {}/{}\n",
|
||||||
|
.{
|
||||||
|
surface_caps.min_image_count,
|
||||||
|
surface_caps.max_image_count,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
const surface_formats = try vc.vki.getPhysicalDeviceSurfaceFormatsAllocKHR(
|
||||||
|
ldc.physical_device,
|
||||||
|
surface,
|
||||||
|
allocator,
|
||||||
|
);
|
||||||
|
defer allocator.free(surface_formats);
|
||||||
|
|
||||||
|
std.debug.print("surface formats: {}\n", .{surface_formats.len});
|
||||||
|
for (surface_formats, 0..) |format, i| {
|
||||||
|
std.debug.print(
|
||||||
|
" format {}: format={any}, color_space={any}\n",
|
||||||
|
.{ i, format.format, format.color_space },
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const present_modes = try vc.vki.getPhysicalDeviceSurfacePresentModesAllocKHR(
|
||||||
|
ldc.physical_device,
|
||||||
|
surface,
|
||||||
|
allocator,
|
||||||
|
);
|
||||||
|
defer allocator.free(present_modes);
|
||||||
|
|
||||||
|
std.debug.print("present modes: {}\n", .{present_modes.len});
|
||||||
|
for (present_modes, 0..) |mode, i| {
|
||||||
|
std.debug.print(" present mode {}: {any}\n", .{ i, mode });
|
||||||
|
}
|
||||||
|
|
||||||
|
var chosen_surface_format = surface_formats[0];
|
||||||
|
for (surface_formats) |format| {
|
||||||
|
if (format.format == .b8g8r8a8_srgb and
|
||||||
|
format.color_space == .srgb_nonlinear_khr)
|
||||||
|
{
|
||||||
|
chosen_surface_format = format;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var chosen_present_mode: vk.PresentModeKHR = .fifo_khr;
|
||||||
|
for (present_modes) |mode| {
|
||||||
|
if (mode == .fifo_khr) {
|
||||||
|
chosen_present_mode = mode;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const framebuffer_size = window.getFramebufferSize();
|
||||||
|
|
||||||
|
const chosen_extent = if (surface_caps.current_extent.width != std.math.maxInt(u32))
|
||||||
|
surface_caps.current_extent
|
||||||
|
else
|
||||||
|
vk.Extent2D{
|
||||||
|
.width = @intCast(framebuffer_size[0]),
|
||||||
|
.height = @intCast(framebuffer_size[1]),
|
||||||
|
};
|
||||||
|
|
||||||
|
var chosen_image_count = surface_caps.min_image_count + 1;
|
||||||
|
if (surface_caps.max_image_count != 0 and chosen_image_count > surface_caps.max_image_count) {
|
||||||
|
chosen_image_count = surface_caps.max_image_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
std.debug.print(
|
||||||
|
"chosen swapchain format={any}, color_space={any}\n",
|
||||||
|
.{ chosen_surface_format.format, chosen_surface_format.color_space },
|
||||||
|
);
|
||||||
|
std.debug.print("chosen present mode={any}\n", .{chosen_present_mode});
|
||||||
|
std.debug.print(
|
||||||
|
"chosen extent={}x{}\n",
|
||||||
|
.{ chosen_extent.width, chosen_extent.height },
|
||||||
|
);
|
||||||
|
std.debug.print("chosen image count={}\n", .{chosen_image_count});
|
||||||
|
|
||||||
|
const swapchain_create_info = vk.SwapchainCreateInfoKHR{
|
||||||
|
.surface = surface,
|
||||||
|
.min_image_count = chosen_image_count,
|
||||||
|
.image_format = chosen_surface_format.format,
|
||||||
|
.image_color_space = chosen_surface_format.color_space,
|
||||||
|
.image_extent = chosen_extent,
|
||||||
|
.image_array_layers = 1,
|
||||||
|
.image_usage = .{
|
||||||
|
.color_attachment_bit = true,
|
||||||
|
},
|
||||||
|
.image_sharing_mode = .exclusive,
|
||||||
|
.pre_transform = surface_caps.current_transform,
|
||||||
|
.composite_alpha = .{
|
||||||
|
.opaque_bit_khr = true,
|
||||||
|
},
|
||||||
|
.present_mode = chosen_present_mode,
|
||||||
|
.clipped = .true,
|
||||||
|
};
|
||||||
|
|
||||||
|
const swapchain = try ldc.vkd.createSwapchainKHR(ldc.device, &swapchain_create_info, null);
|
||||||
|
errdefer ldc.vkd.destroySwapchainKHR(ldc.device, swapchain, null);
|
||||||
|
std.debug.print("created swapchain\n", .{});
|
||||||
|
|
||||||
|
const swapchain_images = try ldc.vkd.getSwapchainImagesAllocKHR(
|
||||||
|
ldc.device,
|
||||||
|
swapchain,
|
||||||
|
allocator,
|
||||||
|
);
|
||||||
|
errdefer allocator.free(swapchain_images);
|
||||||
|
std.debug.print("swapchain images: {}\n", .{swapchain_images.len});
|
||||||
|
|
||||||
|
const swapchain_image_views = try allocator.alloc(vk.ImageView, swapchain_images.len);
|
||||||
|
errdefer allocator.free(swapchain_image_views);
|
||||||
|
|
||||||
|
var created_image_view_count: usize = 0;
|
||||||
|
errdefer {
|
||||||
|
for (swapchain_image_views[0..created_image_view_count]) |image_view| {
|
||||||
|
ldc.vkd.destroyImageView(ldc.device, image_view, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (swapchain_images, 0..) |image, i| {
|
||||||
|
const image_view_create_info = vk.ImageViewCreateInfo{
|
||||||
|
.image = image,
|
||||||
|
.view_type = .@"2d",
|
||||||
|
.format = chosen_surface_format.format,
|
||||||
|
.components = .{
|
||||||
|
.r = .identity,
|
||||||
|
.g = .identity,
|
||||||
|
.b = .identity,
|
||||||
|
.a = .identity,
|
||||||
|
},
|
||||||
|
.subresource_range = .{
|
||||||
|
.aspect_mask = .{
|
||||||
|
.color_bit = true,
|
||||||
|
},
|
||||||
|
.base_mip_level = 0,
|
||||||
|
.level_count = 1,
|
||||||
|
.base_array_layer = 0,
|
||||||
|
.layer_count = 1,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
swapchain_image_views[i] = try ldc.vkd.createImageView(
|
||||||
|
ldc.device,
|
||||||
|
&image_view_create_info,
|
||||||
|
null,
|
||||||
|
);
|
||||||
|
created_image_view_count += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
std.debug.print("created swapchain image views: {}\n", .{swapchain_image_views.len});
|
||||||
|
|
||||||
|
return .{
|
||||||
|
.swapchain = swapchain,
|
||||||
|
.images = swapchain_images,
|
||||||
|
.image_views = swapchain_image_views,
|
||||||
|
.format = chosen_surface_format,
|
||||||
|
.present_mode = chosen_present_mode,
|
||||||
|
.extent = chosen_extent,
|
||||||
|
.image_count = chosen_image_count,
|
||||||
|
.allocator = allocator,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
fn debugPhysicalGPUs(vc: VulkanContext, physical_devices: []vk.PhysicalDevice, surface: vk.SurfaceKHR) !void {
|
fn debugPhysicalGPUs(vc: VulkanContext, physical_devices: []vk.PhysicalDevice, surface: vk.SurfaceKHR) !void {
|
||||||
std.debug.print("physical devices: {}\n", .{physical_devices.len});
|
std.debug.print("physical devices: {}\n", .{physical_devices.len});
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user