fix xlib differences in vulkan, properly handle swapchain recreations

This commit is contained in:
Matthew 2025-12-04 11:47:13 +11:00
parent 6bd4718063
commit b05d055383

View File

@ -387,7 +387,6 @@ struct Vulkan
u32 semaphore_index; u32 semaphore_index;
PlatformHandles platform_handles; PlatformHandles platform_handles;
u32 window_h, window_w;
VkDebugUtilsMessengerEXT dbg_msg; VkDebugUtilsMessengerEXT dbg_msg;
VkInstance instance; VkInstance instance;
@ -400,6 +399,8 @@ struct Vulkan
VkSurfaceFormatKHR surface_format; VkSurfaceFormatKHR surface_format;
VkPresentModeKHR present_mode; VkPresentModeKHR present_mode;
VkExtent3D swapchain_extent; VkExtent3D swapchain_extent;
f32[2] res;
bool recreate_swapchain;
VkRenderPass render_pass; VkRenderPass render_pass;
VkFramebuffer framebuffer; VkFramebuffer framebuffer;
@ -666,15 +667,27 @@ BeginFrame(Vulkan* vk)
result = vkResetFences(vk.device, 1, vk.render_fences.ptr + vk.frame_index); result = vkResetFences(vk.device, 1, vk.render_fences.ptr + vk.frame_index);
VkCheckA("BeginFrame failure: vkResetFences error", result); VkCheckA("BeginFrame failure: vkResetFences error", result);
result = vkAcquireNextImageKHR(vk.device, vk.swapchain, 1000000000, vk.acquire_sems[vk.frame_index], null, &vk.image_index); for(u64 i = 0; i < 3; i += 1)
if(result == VK_ERROR_OUT_OF_DATE_KHR) {
{ result = vkAcquireNextImageKHR(vk.device, vk.swapchain, 1000000000, vk.acquire_sems[vk.frame_index], null, &vk.image_index);
RecreateSwapchain(vk); if(result == VK_ERROR_OUT_OF_DATE_KHR || vk.recreate_swapchain)
} {
else if(result != VK_SUBOPTIMAL_KHR) RecreateSwapchain(vk);
{
VkCheckA("BeginFrame failure: vkAcquireNextImageKHR error", result); VkSemaphoreCreateInfo sem_info = { sType: VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO };
} vkDestroySemaphore(vk.device, vk.acquire_sems[vk.frame_index], null);
VkResult sem_res = vkCreateSemaphore(vk.device, &sem_info, null, &vk.acquire_sems[vk.frame_index]);
VkCheckA("Recreating swapchain sem reset failure", sem_res);
continue;
}
else if(result != VK_SUBOPTIMAL_KHR)
{
VkCheckA("BeginFrame failure: vkAcquireNextImageKHR error", result);
}
break;
}
result = vkResetCommandBuffer(vk.cmds[vk.frame_index], 0); result = vkResetCommandBuffer(vk.cmds[vk.frame_index], 0);
VkCheckA("BeginFrame failure: vkResetCommandBuffer failure", result); VkCheckA("BeginFrame failure: vkResetCommandBuffer failure", result);
@ -830,7 +843,7 @@ SubmitAndPresent(Vulkan* vk)
}; };
result = vkQueuePresentKHR(vk.queues.gfx_queue, &present_info); result = vkQueuePresentKHR(vk.queues.gfx_queue, &present_info);
if(result == VK_ERROR_OUT_OF_DATE_KHR || result == VK_SUBOPTIMAL_KHR) if(result == VK_ERROR_OUT_OF_DATE_KHR || result == VK_SUBOPTIMAL_KHR || vk.recreate_swapchain)
{ {
RecreateSwapchain(vk); RecreateSwapchain(vk);
} }
@ -1507,6 +1520,13 @@ Bind(Vulkan* vk, Pipeline pipeline_handle, DescSet set, bool compute = false)
); );
} }
void
SetExtent(Vulkan* vk, u32 x, u32 y)
{
vk.recreate_swapchain = true;
vk.res = [x, y];
}
pragma(inline): void pragma(inline): void
BindPipeline(Vulkan* vk, VkCommandBuffer cmd, PipelineHandles* pipeline) BindPipeline(Vulkan* vk, VkCommandBuffer cmd, PipelineHandles* pipeline)
{ {
@ -1538,20 +1558,20 @@ pragma(inline): void
Transition(VkCommandBuffer cmd, VkImage image, VkImageLayout current_layout, VkImageLayout new_layout) Transition(VkCommandBuffer cmd, VkImage image, VkImageLayout current_layout, VkImageLayout new_layout)
{ {
VkImageMemoryBarrier2 barrier = { VkImageMemoryBarrier2 barrier = {
sType: VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2, sType: VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2,
srcStageMask: VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT, srcStageMask: VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
srcAccessMask: VK_ACCESS_2_MEMORY_WRITE_BIT, srcAccessMask: VK_ACCESS_2_MEMORY_WRITE_BIT,
dstStageMask: VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT, dstStageMask: VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
dstAccessMask: VK_ACCESS_2_MEMORY_WRITE_BIT | VK_ACCESS_2_MEMORY_READ_BIT, dstAccessMask: VK_ACCESS_2_MEMORY_WRITE_BIT | VK_ACCESS_2_MEMORY_READ_BIT,
oldLayout: current_layout, oldLayout: current_layout,
newLayout: new_layout, newLayout: new_layout,
image: image, image: image,
subresourceRange: { subresourceRange: {
aspectMask: new_layout == VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL ? VK_IMAGE_ASPECT_DEPTH_BIT : VK_IMAGE_ASPECT_COLOR_BIT, aspectMask: new_layout == VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL ? VK_IMAGE_ASPECT_DEPTH_BIT : VK_IMAGE_ASPECT_COLOR_BIT,
baseMipLevel: 0, baseMipLevel: 0,
levelCount: VK_REMAINING_MIP_LEVELS, levelCount: VK_REMAINING_MIP_LEVELS,
baseArrayLayer: 0, baseArrayLayer: 0,
layerCount: VK_REMAINING_ARRAY_LAYERS, layerCount: VK_REMAINING_ARRAY_LAYERS,
}, },
}; };
@ -2198,20 +2218,6 @@ SelectSwapchainFormats(Vulkan* vk)
vk.present_mode = present_mode; vk.present_mode = present_mode;
} }
void
CheckAndRecreateSwapchain(Vulkan* vk)
{
VkResult result = vkGetSwapchainStatusKHR(vk.device, vk.swapchain);
if(result == VK_ERROR_OUT_OF_DATE_KHR)
{
RecreateSwapchain(vk);
}
else if(result != VK_SUBOPTIMAL_KHR)
{
VkCheckA("BeginFrame failure: vkAcquireNextImageKHR error", result);
}
}
Descriptor Descriptor
CreateSampler(Vulkan* vk, MipmapMode mode, u32 binding) CreateSampler(Vulkan* vk, MipmapMode mode, u32 binding)
{ {
@ -2275,6 +2281,9 @@ CreateSwapchain(Vulkan* vk)
SelectSwapchainFormats(vk); SelectSwapchainFormats(vk);
} }
u32 w = clamp(cast(u32)vk.res[0], cap.minImageExtent.width, cap.maxImageExtent.width);
u32 h = clamp(cast(u32)vk.res[1], cap.minImageExtent.height, cap.maxImageExtent.height);
VkSwapchainCreateInfoKHR info = { VkSwapchainCreateInfoKHR info = {
sType: VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR, sType: VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR,
imageArrayLayers: 1, imageArrayLayers: 1,
@ -2287,8 +2296,8 @@ CreateSwapchain(Vulkan* vk)
imageFormat: vk.surface_format.format, imageFormat: vk.surface_format.format,
imageColorSpace: vk.surface_format.colorSpace, imageColorSpace: vk.surface_format.colorSpace,
imageExtent: { imageExtent: {
width: clamp(cast(u32)vk.window_w, cap.minImageExtent.width, cap.maxImageExtent.width), width: w,
height: clamp(cast(u32)vk.window_h, cap.minImageExtent.height, cap.maxImageExtent.height), height: h,
}, },
preTransform: cap.currentTransform, preTransform: cap.currentTransform,
presentMode: vk.present_mode, presentMode: vk.present_mode,
@ -2338,9 +2347,11 @@ CreateSwapchain(Vulkan* vk)
success = VkCheck("vkCreateImageView failure", result); success = VkCheck("vkCreateImageView failure", result);
} }
vk.swapchain_extent.width = info.imageExtent.width; vk.swapchain_extent.width = w;
vk.swapchain_extent.height = info.imageExtent.height; vk.swapchain_extent.height = h;
vk.swapchain_extent.depth = 1; vk.swapchain_extent.depth = 1;
Logf("resized swapchain to %s %s", w, h);
if(!initialized && success) if(!initialized && success)
{ {
@ -2364,6 +2375,8 @@ RecreateSwapchain(Vulkan* vk)
CreateDrawImages(vk); CreateDrawImages(vk);
Write(vk, vk.global_set, &vk.draw_image); Write(vk, vk.global_set, &vk.draw_image);
CreateFramebuffer(vk); CreateFramebuffer(vk);
vk.recreate_swapchain = false;
} }
void void
@ -3211,3 +3224,4 @@ unittest
PlatformHandles handles; PlatformHandles handles;
Vulkan vk = Init(handles, 10*1000*1000, 10*1000*1000); Vulkan vk = Init(handles, 10*1000*1000, 10*1000*1000);
} }