@ -65,6 +65,8 @@ VKSwapchain::VKSwapchain(VkSurfaceKHR surface_, const Device& device_, VKSchedul
VKSwapchain : : ~ VKSwapchain ( ) = default ;
VKSwapchain : : ~ VKSwapchain ( ) = default ;
void VKSwapchain : : Create ( u32 width , u32 height , bool srgb ) {
void VKSwapchain : : Create ( u32 width , u32 height , bool srgb ) {
needs_recreate = false ;
const auto physical_device = device . GetPhysical ( ) ;
const auto physical_device = device . GetPhysical ( ) ;
const auto capabilities { physical_device . GetSurfaceCapabilitiesKHR ( surface ) } ;
const auto capabilities { physical_device . GetSurfaceCapabilitiesKHR ( surface ) } ;
if ( capabilities . maxImageExtent . width = = 0 | | capabilities . maxImageExtent . height = = 0 ) {
if ( capabilities . maxImageExtent . width = = 0 | | capabilities . maxImageExtent . height = = 0 ) {
@ -82,21 +84,20 @@ void VKSwapchain::Create(u32 width, u32 height, bool srgb) {
resource_ticks . resize ( image_count ) ;
resource_ticks . resize ( image_count ) ;
}
}
bool VKSwapchain : : AcquireNextImage ( ) {
void VKSwapchain : : AcquireNextImage ( ) {
const VkResult result =
const VkResult result =
device . GetLogical ( ) . AcquireNextImageKHR ( * swapchain , std : : numeric_limits < u64 > : : max ( ) ,
device . GetLogical ( ) . AcquireNextImageKHR ( * swapchain , std : : numeric_limits < u64 > : : max ( ) ,
* present_semaphores [ frame_index ] , { } , & image_index ) ;
* present_semaphores [ frame_index ] , { } , & image_index ) ;
needs_recreate | = result ! = VK_SUCCESS & & result ! = VK_SUBOPTIMAL_KHR ;
scheduler . Wait ( resource_ticks [ image_index ] ) ;
scheduler . Wait ( resource_ticks [ image_index ] ) ;
return result = = VK_SUCCESS | | result = = VK_SUBOPTIMAL_KHR ;
resource_ticks [ image_index ] = scheduler . CurrentTick ( ) ;
}
}
bool VKSwapchain : : Present ( VkSemaphore render_semaphore ) {
void VKSwapchain : : Present ( VkSemaphore render_semaphore ) {
const VkSemaphore present_semaphore { * present_semaphores [ frame_index ] } ;
const VkSemaphore present_semaphore { * present_semaphores [ frame_index ] } ;
const std : : array < VkSemaphore , 2 > semaphores { present_semaphore , render_semaphore } ;
const std : : array < VkSemaphore , 2 > semaphores { present_semaphore , render_semaphore } ;
const auto present_queue { device . GetPresentQueue ( ) } ;
const auto present_queue { device . GetPresentQueue ( ) } ;
bool recreated = false ;
const VkPresentInfoKHR present_info {
const VkPresentInfoKHR present_info {
. sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR ,
. sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR ,
. pNext = nullptr ,
. pNext = nullptr ,
@ -107,7 +108,6 @@ bool VKSwapchain::Present(VkSemaphore render_semaphore) {
. pImageIndices = & image_index ,
. pImageIndices = & image_index ,
. pResults = nullptr ,
. pResults = nullptr ,
} ;
} ;
switch ( const VkResult result = present_queue . Present ( present_info ) ) {
switch ( const VkResult result = present_queue . Present ( present_info ) ) {
case VK_SUCCESS :
case VK_SUCCESS :
break ;
break ;
@ -115,24 +115,16 @@ bool VKSwapchain::Present(VkSemaphore render_semaphore) {
LOG_DEBUG ( Render_Vulkan , " Suboptimal swapchain " ) ;
LOG_DEBUG ( Render_Vulkan , " Suboptimal swapchain " ) ;
break ;
break ;
case VK_ERROR_OUT_OF_DATE_KHR :
case VK_ERROR_OUT_OF_DATE_KHR :
if ( current_width > 0 & & current_height > 0 ) {
Create ( current_width , current_height , current_srgb ) ;
recreated = true ;
}
needs_recreate = true ;
break ;
break ;
default :
default :
LOG_CRITICAL ( Render_Vulkan , " Failed to present with error {} " , vk : : ToString ( result ) ) ;
LOG_CRITICAL ( Render_Vulkan , " Failed to present with error {} " , vk : : ToString ( result ) ) ;
break ;
break ;
}
}
resource_ticks [ image_index ] = scheduler . CurrentTick ( ) ;
frame_index = ( frame_index + 1 ) % static_cast < u32 > ( image_count ) ;
return recreated ;
}
bool VKSwapchain : : HasFramebufferChanged ( const Layout : : FramebufferLayout & framebuffer ) const {
// TODO(Rodrigo): Handle framebuffer pixel format changes
return framebuffer . width ! = current_width | | framebuffer . height ! = current_height ;
+ + frame_index ;
if ( frame_index > = image_count ) {
frame_index = 0 ;
}
}
}
void VKSwapchain : : CreateSwapchain ( const VkSurfaceCapabilitiesKHR & capabilities , u32 width ,
void VKSwapchain : : CreateSwapchain ( const VkSurfaceCapabilitiesKHR & capabilities , u32 width ,
@ -148,7 +140,6 @@ void VKSwapchain::CreateSwapchain(const VkSurfaceCapabilitiesKHR& capabilities,
if ( capabilities . maxImageCount > 0 & & requested_image_count > capabilities . maxImageCount ) {
if ( capabilities . maxImageCount > 0 & & requested_image_count > capabilities . maxImageCount ) {
requested_image_count = capabilities . maxImageCount ;
requested_image_count = capabilities . maxImageCount ;
}
}
VkSwapchainCreateInfoKHR swapchain_ci {
VkSwapchainCreateInfoKHR swapchain_ci {
. sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR ,
. sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR ,
. pNext = nullptr ,
. pNext = nullptr ,
@ -169,7 +160,6 @@ void VKSwapchain::CreateSwapchain(const VkSurfaceCapabilitiesKHR& capabilities,
. clipped = VK_FALSE ,
. clipped = VK_FALSE ,
. oldSwapchain = nullptr ,
. oldSwapchain = nullptr ,
} ;
} ;
const u32 graphics_family { device . GetGraphicsFamily ( ) } ;
const u32 graphics_family { device . GetGraphicsFamily ( ) } ;
const u32 present_family { device . GetPresentFamily ( ) } ;
const u32 present_family { device . GetPresentFamily ( ) } ;
const std : : array < u32 , 2 > queue_indices { graphics_family , present_family } ;
const std : : array < u32 , 2 > queue_indices { graphics_family , present_family } ;
@ -178,7 +168,6 @@ void VKSwapchain::CreateSwapchain(const VkSurfaceCapabilitiesKHR& capabilities,
swapchain_ci . queueFamilyIndexCount = static_cast < u32 > ( queue_indices . size ( ) ) ;
swapchain_ci . queueFamilyIndexCount = static_cast < u32 > ( queue_indices . size ( ) ) ;
swapchain_ci . pQueueFamilyIndices = queue_indices . data ( ) ;
swapchain_ci . pQueueFamilyIndices = queue_indices . data ( ) ;
}
}
// Request the size again to reduce the possibility of a TOCTOU race condition.
// Request the size again to reduce the possibility of a TOCTOU race condition.
const auto updated_capabilities = physical_device . GetSurfaceCapabilitiesKHR ( surface ) ;
const auto updated_capabilities = physical_device . GetSurfaceCapabilitiesKHR ( surface ) ;
swapchain_ci . imageExtent = ChooseSwapExtent ( updated_capabilities , width , height ) ;
swapchain_ci . imageExtent = ChooseSwapExtent ( updated_capabilities , width , height ) ;
@ -186,8 +175,6 @@ void VKSwapchain::CreateSwapchain(const VkSurfaceCapabilitiesKHR& capabilities,
swapchain = device . GetLogical ( ) . CreateSwapchainKHR ( swapchain_ci ) ;
swapchain = device . GetLogical ( ) . CreateSwapchainKHR ( swapchain_ci ) ;
extent = swapchain_ci . imageExtent ;
extent = swapchain_ci . imageExtent ;
current_width = extent . width ;
current_height = extent . height ;
current_srgb = srgb ;
current_srgb = srgb ;
images = swapchain . GetImages ( ) ;
images = swapchain . GetImages ( ) ;
@ -197,8 +184,8 @@ void VKSwapchain::CreateSwapchain(const VkSurfaceCapabilitiesKHR& capabilities,
void VKSwapchain : : CreateSemaphores ( ) {
void VKSwapchain : : CreateSemaphores ( ) {
present_semaphores . resize ( image_count ) ;
present_semaphores . resize ( image_count ) ;
std : : generate ( present_semaphores . begin ( ) , present_semaphores . end ( ) ,
[ this ] { return device . GetLogical ( ) . CreateSemaphore ( ) ; } ) ;
std : : ranges : : generate ( present_semaphores ,
[ this ] { return device . GetLogical ( ) . CreateSemaphore ( ) ; } ) ;
}
}
void VKSwapchain : : CreateImageViews ( ) {
void VKSwapchain : : CreateImageViews ( ) {