Vulkan: Detect swapchain init failure.

This seems to be a driver bug, and occurs on NVIDIA when OpenGL has
previously been inited.  Or we're not cleaning something up properly...
but there's a driver error logged to debug output.
This commit is contained in:
Unknown W. Brackets 2017-04-15 16:26:26 -07:00
parent 627c280031
commit bf02f7d98b
3 changed files with 36 additions and 18 deletions

View file

@ -341,7 +341,7 @@ void VulkanBeginCommandBuffer(VkCommandBuffer cmd) {
assert(res == VK_SUCCESS); assert(res == VK_SUCCESS);
} }
void VulkanContext::InitObjects(bool depthPresent) { bool VulkanContext::InitObjects(bool depthPresent) {
InitQueue(); InitQueue();
InitCommandPool(); InitCommandPool();
@ -364,13 +364,17 @@ void VulkanContext::InitObjects(bool depthPresent) {
frame_[1].fence = CreateFence(true); frame_[1].fence = CreateFence(true);
VkCommandBuffer cmd = GetInitCommandBuffer(); VkCommandBuffer cmd = GetInitCommandBuffer();
InitSwapchain(cmd); if (!InitSwapchain(cmd)) {
return false;
}
InitDepthStencilBuffer(cmd); InitDepthStencilBuffer(cmd);
InitSurfaceRenderPass(depthPresent, true); InitSurfaceRenderPass(depthPresent, true);
InitFramebuffers(depthPresent); InitFramebuffers(depthPresent);
// The init command buffer will be executed as part of the first frame. // The init command buffer will be executed as part of the first frame.
return true;
} }
void VulkanContext::DestroyObjects() { void VulkanContext::DestroyObjects() {
@ -948,7 +952,7 @@ void VulkanContext::InitQueue() {
assert(res == VK_SUCCESS); assert(res == VK_SUCCESS);
} }
void VulkanContext::InitSwapchain(VkCommandBuffer cmd) { bool VulkanContext::InitSwapchain(VkCommandBuffer cmd) {
VkResult U_ASSERT_ONLY res; VkResult U_ASSERT_ONLY res;
VkSurfaceCapabilitiesKHR surfCapabilities; VkSurfaceCapabilitiesKHR surfCapabilities;
@ -1051,6 +1055,9 @@ void VulkanContext::InitSwapchain(VkCommandBuffer cmd) {
res = vkCreateSwapchainKHR(device_, &swap_chain_info, NULL, &swap_chain_); res = vkCreateSwapchainKHR(device_, &swap_chain_info, NULL, &swap_chain_);
assert(res == VK_SUCCESS); assert(res == VK_SUCCESS);
if (res != VK_SUCCESS) {
return false;
}
res = vkGetSwapchainImagesKHR(device_, swap_chain_, res = vkGetSwapchainImagesKHR(device_, swap_chain_,
&swapchainImageCount, NULL); &swapchainImageCount, NULL);
@ -1097,6 +1104,8 @@ void VulkanContext::InitSwapchain(VkCommandBuffer cmd) {
free(swapchainImages); free(swapchainImages);
current_buffer = 0; current_buffer = 0;
return true;
} }
void VulkanContext::InitSurfaceRenderPass(bool include_depth, bool clear) { void VulkanContext::InitSurfaceRenderPass(bool include_depth, bool clear) {
@ -1206,13 +1215,17 @@ void VulkanContext::WaitAndResetFence(VkFence fence) {
} }
void VulkanContext::DestroyCommandPool() { void VulkanContext::DestroyCommandPool() {
if (cmd_pool_ != VK_NULL_HANDLE)
vkDestroyCommandPool(device_, cmd_pool_, NULL); vkDestroyCommandPool(device_, cmd_pool_, NULL);
cmd_pool_ = VK_NULL_HANDLE; cmd_pool_ = VK_NULL_HANDLE;
} }
void VulkanContext::DestroyDepthStencilBuffer() { void VulkanContext::DestroyDepthStencilBuffer() {
if (depth.view != VK_NULL_HANDLE)
vkDestroyImageView(device_, depth.view, NULL); vkDestroyImageView(device_, depth.view, NULL);
if (depth.image != VK_NULL_HANDLE)
vkDestroyImage(device_, depth.image, NULL); vkDestroyImage(device_, depth.image, NULL);
if (depth.mem != VK_NULL_HANDLE)
vkFreeMemory(device_, depth.mem, NULL); vkFreeMemory(device_, depth.mem, NULL);
depth.view = VK_NULL_HANDLE; depth.view = VK_NULL_HANDLE;
@ -1224,6 +1237,7 @@ void VulkanContext::DestroySwapChain() {
for (uint32_t i = 0; i < swapchainImageCount; i++) { for (uint32_t i = 0; i < swapchainImageCount; i++) {
vkDestroyImageView(device_, swapChainBuffers[i].view, NULL); vkDestroyImageView(device_, swapChainBuffers[i].view, NULL);
} }
if (swap_chain_ != VK_NULL_HANDLE)
vkDestroySwapchainKHR(device_, swap_chain_, NULL); vkDestroySwapchainKHR(device_, swap_chain_, NULL);
swap_chain_ = VK_NULL_HANDLE; swap_chain_ = VK_NULL_HANDLE;
swapChainBuffers.clear(); swapChainBuffers.clear();
@ -1238,6 +1252,7 @@ void VulkanContext::DestroyFramebuffers() {
} }
void VulkanContext::DestroySurfaceRenderPass() { void VulkanContext::DestroySurfaceRenderPass() {
if (surface_render_pass_ != VK_NULL_HANDLE)
vkDestroyRenderPass(device_, surface_render_pass_, NULL); vkDestroyRenderPass(device_, surface_render_pass_, NULL);
surface_render_pass_ = VK_NULL_HANDLE; surface_render_pass_ = VK_NULL_HANDLE;
} }

View file

@ -206,8 +206,8 @@ public:
void ReinitSurfaceAndroid(int width, int height); void ReinitSurfaceAndroid(int width, int height);
#endif #endif
void InitQueue(); void InitQueue();
void InitObjects(bool depthPresent); bool InitObjects(bool depthPresent);
void InitSwapchain(VkCommandBuffer cmd); bool InitSwapchain(VkCommandBuffer cmd);
void InitSurfaceRenderPass(bool include_depth, bool clear); void InitSurfaceRenderPass(bool include_depth, bool clear);
void InitFramebuffers(bool include_depth); void InitFramebuffers(bool include_depth);
void InitDepthStencilBuffer(VkCommandBuffer cmd); void InitDepthStencilBuffer(VkCommandBuffer cmd);
@ -365,14 +365,14 @@ private:
struct { struct {
VkFormat format; VkFormat format;
VkImage image; VkImage image = VK_NULL_HANDLE;
VkDeviceMemory mem; VkDeviceMemory mem = VK_NULL_HANDLE;
VkImageView view; VkImageView view = VK_NULL_HANDLE;
} depth; } depth;
VkRenderPass surface_render_pass_; VkRenderPass surface_render_pass_ = VK_NULL_HANDLE;
uint32_t current_buffer; uint32_t current_buffer = 0;
uint32_t queue_count; uint32_t queue_count = 0;
VkPhysicalDeviceFeatures featuresAvailable_; VkPhysicalDeviceFeatures featuresAvailable_;
VkPhysicalDeviceFeatures featuresEnabled_; VkPhysicalDeviceFeatures featuresEnabled_;

View file

@ -191,7 +191,10 @@ bool WindowsVulkanContext::Init(HINSTANCE hInst, HWND hWnd, std::string *error_m
g_Vulkan->InitDebugMsgCallback(&Vulkan_Dbg, bits, &g_LogOptions); g_Vulkan->InitDebugMsgCallback(&Vulkan_Dbg, bits, &g_LogOptions);
} }
g_Vulkan->InitSurfaceWin32(hInst, hWnd); g_Vulkan->InitSurfaceWin32(hInst, hWnd);
g_Vulkan->InitObjects(true); if (!g_Vulkan->InitObjects(true)) {
Shutdown();
return false;
}
draw_ = Draw::T3DCreateVulkanContext(g_Vulkan); draw_ = Draw::T3DCreateVulkanContext(g_Vulkan);