@@ -2705,6 +2705,7 @@ VK_IMPORT_DEVICE
27052705 m_indexBuffers[_blitter.m_ib ->handle .idx ].update (m_commandBuffer, 0 , _numIndices*2 , _blitter.m_ib ->data );
27062706 m_vertexBuffers[_blitter.m_vb ->handle .idx ].update (m_commandBuffer, 0 , numVertices*_blitter.m_layout .m_stride , _blitter.m_vb ->data , true );
27072707
2708+
27082709 VkRenderPassBeginInfo rpbi;
27092710 rpbi.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
27102711 rpbi.pNext = NULL ;
@@ -2799,27 +2800,26 @@ VK_IMPORT_DEVICE
27992800 return suspended;
28002801 }
28012802
2803+ // BX_TRACE("updateResolution(%d, %d) m_resolution=(%d, %d)"
2804+ // , _resolution.width
2805+ // , _resolution.height
2806+ // , m_resolution.width
2807+ // , m_resolution.height
2808+ // );
2809+
28022810 uint32_t flags = _resolution.reset & ~(0
28032811 | BGFX_RESET_SUSPEND
28042812 | BGFX_RESET_MAXANISOTROPY
28052813 | BGFX_RESET_DEPTH_CLAMP
28062814 );
28072815
2808- // Note: m_needToRefreshSwapchain is deliberately ignored when deciding whether to
2809- // recreate the swapchain because it can happen several frames before submit is called
2810- // with the new resolution.
2811- //
2812- // Instead, vkAcquireNextImageKHR and all draws to the backbuffer are skipped until
2813- // the window size is updated. That also fixes a related issue where VK_ERROR_OUT_OF_DATE_KHR
2814- // is returned from vkQueuePresentKHR when the window doesn't exist anymore, and
2815- // vkGetPhysicalDeviceSurfaceCapabilitiesKHR fails with VK_ERROR_SURFACE_LOST_KHR.
2816-
28172816 if (false
28182817 || m_resolution.format != _resolution.format
28192818 || m_resolution.width != _resolution.width
28202819 || m_resolution.height != _resolution.height
28212820 || m_resolution.reset != flags
2822- || m_backBuffer.m_swapChain .m_needToRecreateSurface )
2821+ || m_backBuffer.m_swapChain .m_needToRecreateSurface
2822+ || m_backBuffer.m_swapChain .m_needToRecreateSwapchain )
28232823 {
28242824 flags &= ~BGFX_RESET_INTERNAL_FORCE;
28252825
@@ -2837,6 +2837,10 @@ VK_IMPORT_DEVICE
28372837 preReset ();
28382838
28392839 m_backBuffer.update (m_commandBuffer, m_resolution);
2840+ // Update the resolution again here, as the actual width and height
2841+ // is now final (as it was potentially clamped by the Vulkan driver).
2842+ m_resolution.width = m_backBuffer.m_width ;
2843+ m_resolution.height = m_backBuffer.m_height ;
28402844
28412845 postReset ();
28422846 }
@@ -6849,6 +6853,7 @@ VK_DESTROY
68496853 ;
68506854
68516855 const bool recreateSwapchain = false
6856+ || m_needToRecreateSwapchain
68526857 || m_resolution.format != _resolution.format
68536858 || m_resolution.width != _resolution.width
68546859 || m_resolution.height != _resolution.height
@@ -6962,6 +6967,7 @@ VK_DESTROY
69626967 && NULL != vkCreateWaylandSurfaceKHR
69636968 )
69646969 {
6970+ BX_TRACE (" Attempting Wayland surface creation." );
69656971 VkWaylandSurfaceCreateInfoKHR sci;
69666972 sci.sType = VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR;
69676973 sci.pNext = NULL ;
@@ -6977,6 +6983,7 @@ VK_DESTROY
69776983 && NULL != vkCreateXlibSurfaceKHR
69786984 )
69796985 {
6986+ BX_TRACE (" Attempting Xlib surface creation." );
69806987 VkXlibSurfaceCreateInfoKHR sci;
69816988 sci.sType = VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR;
69826989 sci.pNext = NULL ;
@@ -6996,6 +7003,7 @@ VK_DESTROY
69967003
69977004 if (NULL != xcbdll)
69987005 {
7006+ BX_TRACE (" Attempting XCB surface creation." );
69997007 typedef xcb_connection_t * (*PFN_XGETXCBCONNECTION)(Display*);
70007008 PFN_XGETXCBCONNECTION XGetXCBConnection = (PFN_XGETXCBCONNECTION)bx::dlsym (xcbdll, " XGetXCBConnection" );
70017009
@@ -7108,8 +7116,9 @@ VK_DESTROY
71087116 const VkAllocationCallbacks* allocatorCb = s_renderVK->m_allocatorCb ;
71097117
71107118 // Waiting for the device to be idle seems to get rid of VK_DEVICE_LOST
7111- // upon resizing the window quickly. (See https://github.com/mpv-player/mpv/issues/8360
7112- // and https://github.com/bkaradzic/bgfx/issues/3227).
7119+ // upon resizing the window quickly. See:
7120+ // - https://github.com/mpv-player/mpv/issues/8360
7121+ // - https://github.com/bkaradzic/bgfx/issues/3227
71137122 result = vkDeviceWaitIdle (device);
71147123 BX_WARN (VK_SUCCESS == result, " Create swapchain error: vkDeviceWaitIdle() failed: %d: %s" , result, getName (result));
71157124
@@ -7166,6 +7175,15 @@ VK_DESTROY
71667175 , surfaceCapabilities.minImageExtent .height
71677176 , surfaceCapabilities.maxImageExtent .height
71687177 );
7178+ if (width != m_resolution.width || height != m_resolution.height )
7179+ {
7180+ BX_TRACE (" Clamped swapchain resolution from %dx%d to %dx%d"
7181+ , m_resolution.width
7182+ , m_resolution.height
7183+ , width
7184+ , height
7185+ );
7186+ }
71697187
71707188 VkCompositeAlphaFlagBitsKHR compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
71717189
@@ -7292,6 +7310,8 @@ VK_DESTROY
72927310 m_backBufferColorImageLayout[ii] = VK_IMAGE_LAYOUT_UNDEFINED;
72937311 }
72947312
7313+ BX_TRACE (" Succesfully created swapchain (%dx%d) with %d images." , width, height, m_numSwapChainImages);
7314+
72957315 VkSemaphoreCreateInfo sci;
72967316 sci.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
72977317 sci.pNext = NULL ;
@@ -7314,7 +7334,7 @@ VK_DESTROY
73147334 m_currentSemaphore = 0 ;
73157335
73167336 m_needPresent = false ;
7317- m_needToRefreshSwapchain = false ;
7337+ m_needToRecreateSwapchain = false ;
73187338
73197339 return result;
73207340 }
@@ -7626,7 +7646,7 @@ VK_DESTROY
76267646 {
76277647 BGFX_PROFILER_SCOPE (" SwapChainVK::acquire" , kColorFrame );
76287648 if (VK_NULL_HANDLE == m_swapChain
7629- || m_needToRefreshSwapchain )
7649+ || m_needToRecreateSwapchain )
76307650 {
76317651 return false ;
76327652 }
@@ -7652,18 +7672,25 @@ VK_DESTROY
76527672 );
76537673 }
76547674
7675+
7676+ if (result != VK_SUCCESS)
7677+ {
7678+ BX_TRACE (" vkAcquireNextImageKHR(...): result = %s" , getName (result));
7679+ }
7680+
76557681 switch (result)
76567682 {
76577683 case VK_SUCCESS:
76587684 break ;
76597685
76607686 case VK_ERROR_SURFACE_LOST_KHR:
76617687 m_needToRecreateSurface = true ;
7662- [[fallthrough]];
7688+ m_needToRecreateSwapchain = true ;
7689+ return false ;
76637690
76647691 case VK_ERROR_OUT_OF_DATE_KHR:
76657692 case VK_SUBOPTIMAL_KHR:
7666- m_needToRefreshSwapchain = true ;
7693+ m_needToRecreateSwapchain = true ;
76677694 return false ;
76687695
76697696 default :
@@ -7712,15 +7739,21 @@ VK_DESTROY
77127739 result = vkQueuePresentKHR (m_queue, &pi);
77137740 }
77147741
7742+ if (result != VK_SUCCESS)
7743+ {
7744+ BX_TRACE (" vkQueuePresentKHR(...): result = %s" , getName (result));
7745+ }
7746+
77157747 switch (result)
77167748 {
77177749 case VK_ERROR_SURFACE_LOST_KHR:
77187750 m_needToRecreateSurface = true ;
7719- [[fallthrough]];
7751+ m_needToRecreateSwapchain = true ;
7752+ break ;
77207753
77217754 case VK_ERROR_OUT_OF_DATE_KHR:
77227755 case VK_SUBOPTIMAL_KHR:
7723- m_needToRefreshSwapchain = true ;
7756+ m_needToRecreateSwapchain = true ;
77247757 break ;
77257758
77267759 default :
@@ -7883,8 +7916,10 @@ VK_DESTROY
78837916 BGFX_PROFILER_SCOPE (" FrameBufferVK::update" , kColorResource );
78847917 m_swapChain.update (_commandBuffer, m_nwh, _resolution);
78857918 VK_CHECK (s_renderVK->getRenderPass (m_swapChain, &m_renderPass) );
7886- m_width = _resolution.width ;
7887- m_height = _resolution.height ;
7919+ // Don't believe the passed Resolution, as the Vulkan driver might have
7920+ // specified another resolution, which we had to obey.
7921+ m_width = m_swapChain.m_sci .imageExtent .width ;
7922+ m_height = m_swapChain.m_sci .imageExtent .height ;
78887923 m_sampler = m_swapChain.m_sampler ;
78897924 }
78907925
@@ -8563,12 +8598,26 @@ VK_DESTROY
85638598 if (isFrameBufferValid)
85648599 {
85658600 viewState.m_rect = _render->m_view [view].m_rect ;
8566- const Rect& rect = _render->m_view [view].m_rect ;
8567- const Rect& scissorRect = _render->m_view [view].m_scissor ;
8601+ Rect rect = _render->m_view [view].m_rect ;
8602+ Rect scissorRect = _render->m_view [view].m_scissor ;
85688603 viewHasScissor = !scissorRect.isZero ();
85698604 viewScissorRect = viewHasScissor ? scissorRect : rect;
85708605 restoreScissor = false ;
85718606
8607+ // Clamp the rect to what's valid according to Vulkan.
8608+ rect.m_width = bx::min (rect.m_width , fb.m_width - rect.m_x );
8609+ rect.m_height = bx::min (rect.m_height , fb.m_height - rect.m_y );
8610+ if (_render->m_view [view].m_rect .m_width != rect.m_width
8611+ || _render->m_view [view].m_rect .m_height != rect.m_height )
8612+ {
8613+ BX_TRACE (" Clamp render pass from %dx%d to %dx%d"
8614+ , _render->m_view [view].m_rect .m_width
8615+ , _render->m_view [view].m_rect .m_height
8616+ , rect.m_width
8617+ , rect.m_height
8618+ );
8619+ }
8620+
85728621 rpbi.framebuffer = fb.m_currentFramebuffer ;
85738622 rpbi.renderPass = fb.m_renderPass ;
85748623 rpbi.renderArea .offset .x = rect.m_x ;
0 commit comments