diff options
author | Juan Linietsky <reduzio@gmail.com> | 2019-06-24 16:13:06 -0300 |
---|---|---|
committer | Juan Linietsky <reduzio@gmail.com> | 2020-02-11 11:53:27 +0100 |
commit | 1b4281b895f3046ea972256182b18696a25f8316 (patch) | |
tree | 5f6b9c1600a4354f17b29e430a447d08f93ecf25 /drivers/vulkan/vulkan_context.cpp | |
parent | 42b44f43ee52eb664d3610d0fdae0eff14c00f0a (diff) | |
download | redot-engine-1b4281b895f3046ea972256182b18696a25f8316.tar.gz |
basic 2D engine is more or less working with Vulkan, including editor.
Still a lot to do
Diffstat (limited to 'drivers/vulkan/vulkan_context.cpp')
-rw-r--r-- | drivers/vulkan/vulkan_context.cpp | 504 |
1 files changed, 292 insertions, 212 deletions
diff --git a/drivers/vulkan/vulkan_context.cpp b/drivers/vulkan/vulkan_context.cpp index 991429f963..37eb99db7a 100644 --- a/drivers/vulkan/vulkan_context.cpp +++ b/drivers/vulkan/vulkan_context.cpp @@ -471,10 +471,7 @@ Error VulkanContext::_create_device() { return OK; } -Error VulkanContext::_create_swap_chain() { - - VkResult err = _create_surface(&surface, inst); - ERR_FAIL_COND_V(err, ERR_CANT_CREATE); +Error VulkanContext::_initialize_queues(VkSurfaceKHR surface) { // Iterate over each queue to learn whether it supports presenting: VkBool32 *supportsPresent = (VkBool32 *)malloc(queue_family_count * sizeof(VkBool32)); @@ -551,7 +548,7 @@ Error VulkanContext::_create_swap_chain() { // Get the list of VkFormat's that are supported: uint32_t formatCount; - err = fpGetPhysicalDeviceSurfaceFormatsKHR(gpu, surface, &formatCount, NULL); + VkResult err = fpGetPhysicalDeviceSurfaceFormatsKHR(gpu, surface, &formatCount, NULL); ERR_FAIL_COND_V(err, ERR_CANT_CREATE); VkSurfaceFormatKHR *surfFormats = (VkSurfaceFormatKHR *)malloc(formatCount * sizeof(VkSurfaceFormatKHR)); err = fpGetPhysicalDeviceSurfaceFormatsKHR(gpu, surface, &formatCount, surfFormats); @@ -566,6 +563,13 @@ Error VulkanContext::_create_swap_chain() { format = surfFormats[0].format; } color_space = surfFormats[0].colorSpace; + + Error serr = _create_semaphores(); + if (serr) { + return serr; + } + + queues_initialized = true; return OK; } @@ -608,21 +612,111 @@ Error VulkanContext::_create_semaphores() { return OK; } -Error VulkanContext::_prepare_buffers() { +int VulkanContext::_window_create(VkSurfaceKHR p_surface, int p_width, int p_height) { + + if (!queues_initialized) { + // We use a single GPU, but we need a surface to initialize the + // queues, so this process must be deferred until a surface + // is created. + _initialize_queues(p_surface); + } + + Window window; + window.surface = p_surface; + window.width = p_width; + window.height = p_height; + Error err = _update_swap_chain(&window); + ERR_FAIL_COND_V(err != OK, -1); + + int id = last_window_id; + windows[id] = window; + last_window_id++; + return id; +} + +void VulkanContext::window_resize(int p_window, int p_width, int p_height) { + ERR_FAIL_COND(!windows.has(p_window)); + windows[p_window].width = p_width; + windows[p_window].height = p_height; + _update_swap_chain(&windows[p_window]); +} + +int VulkanContext::window_get_width(int p_window) { + ERR_FAIL_COND_V(!windows.has(p_window), -1); + return windows[p_window].width; +} + +int VulkanContext::window_get_height(int p_window) { + ERR_FAIL_COND_V(!windows.has(p_window), -1); + return windows[p_window].height; +} + +VkRenderPass VulkanContext::window_get_render_pass(int p_window) { + ERR_FAIL_COND_V(!windows.has(p_window), VK_NULL_HANDLE); + Window *w = &windows[p_window]; + //vulkan use of currentbuffer + return w->render_pass; +} + +VkFramebuffer VulkanContext::window_get_framebuffer(int p_window) { + ERR_FAIL_COND_V(!windows.has(p_window), VK_NULL_HANDLE); + ERR_FAIL_COND_V(!buffers_prepared, VK_NULL_HANDLE); + Window *w = &windows[p_window]; + //vulkan use of currentbuffer + return w->swapchain_image_resources[w->current_buffer].framebuffer; +} + +void VulkanContext::window_destroy(int p_window_id) { + ERR_FAIL_COND(!windows.has(p_window_id)); + _clean_up_swap_chain(&windows[p_window_id]); + vkDestroySurfaceKHR(inst, windows[p_window_id].surface, NULL); + windows.erase(p_window_id); +} + +Error VulkanContext::_clean_up_swap_chain(Window *window) { + + if (!window->swapchain) { + return OK; + } + vkDeviceWaitIdle(device); + + //this destroys images associated it seems + fpDestroySwapchainKHR(device, window->swapchain, NULL); + window->swapchain = VK_NULL_HANDLE; + vkDestroyRenderPass(device, window->render_pass, NULL); + if (window->swapchain_image_resources) { + for (uint32_t i = 0; i < swapchainImageCount; i++) { + vkDestroyImageView(device, window->swapchain_image_resources[i].view, NULL); + vkDestroyFramebuffer(device, window->swapchain_image_resources[i].framebuffer, NULL); + } + + free(window->swapchain_image_resources); + window->swapchain_image_resources = NULL; + } + if (separate_present_queue) { + vkDestroyCommandPool(device, window->present_cmd_pool, NULL); + } + return OK; +} + +Error VulkanContext::_update_swap_chain(Window *window) { VkResult err; - VkSwapchainKHR oldSwapchain = swapchain; + + if (window->swapchain) { + _clean_up_swap_chain(window); + } // Check the surface capabilities and formats VkSurfaceCapabilitiesKHR surfCapabilities; - err = fpGetPhysicalDeviceSurfaceCapabilitiesKHR(gpu, surface, &surfCapabilities); + err = fpGetPhysicalDeviceSurfaceCapabilitiesKHR(gpu, window->surface, &surfCapabilities); ERR_FAIL_COND_V(err, ERR_CANT_CREATE); uint32_t presentModeCount; - err = fpGetPhysicalDeviceSurfacePresentModesKHR(gpu, surface, &presentModeCount, NULL); + err = fpGetPhysicalDeviceSurfacePresentModesKHR(gpu, window->surface, &presentModeCount, NULL); ERR_FAIL_COND_V(err, ERR_CANT_CREATE); VkPresentModeKHR *presentModes = (VkPresentModeKHR *)malloc(presentModeCount * sizeof(VkPresentModeKHR)); ERR_FAIL_COND_V(!presentModes, ERR_CANT_CREATE); - err = fpGetPhysicalDeviceSurfacePresentModesKHR(gpu, surface, &presentModeCount, presentModes); + err = fpGetPhysicalDeviceSurfacePresentModesKHR(gpu, window->surface, &presentModeCount, presentModes); ERR_FAIL_COND_V(err, ERR_CANT_CREATE); VkExtent2D swapchainExtent; @@ -631,8 +725,8 @@ Error VulkanContext::_prepare_buffers() { // If the surface size is undefined, the size is set to the size // of the images requested, which must fit within the minimum and // maximum values. - swapchainExtent.width = width; - swapchainExtent.height = height; + swapchainExtent.width = window->width; + swapchainExtent.height = window->height; if (swapchainExtent.width < surfCapabilities.minImageExtent.width) { swapchainExtent.width = surfCapabilities.minImageExtent.width; @@ -648,17 +742,14 @@ Error VulkanContext::_prepare_buffers() { } else { // If the surface size is defined, the swap chain size must match swapchainExtent = surfCapabilities.currentExtent; - width = surfCapabilities.currentExtent.width; - height = surfCapabilities.currentExtent.height; + window->width = surfCapabilities.currentExtent.width; + window->height = surfCapabilities.currentExtent.height; } - if (width == 0 || height == 0) { - is_minimized = true; + if (window->width == 0 || window->height == 0) { + //likely window minimized, no swapchain created return OK; - } else { - is_minimized = false; } - // The FIFO present mode is guaranteed by the spec to be supported // and to have no tearing. It's a great default present mode to use. VkPresentModeKHR swapchainPresentMode = VK_PRESENT_MODE_FIFO_KHR; @@ -690,15 +781,15 @@ Error VulkanContext::_prepare_buffers() { // the application wants the late image to be immediately displayed, even // though that may mean some tearing. - if (presentMode != swapchainPresentMode) { + if (window->presentMode != swapchainPresentMode) { for (size_t i = 0; i < presentModeCount; ++i) { - if (presentModes[i] == presentMode) { - swapchainPresentMode = presentMode; + if (presentModes[i] == window->presentMode) { + swapchainPresentMode = window->presentMode; break; } } } - ERR_FAIL_COND_V_MSG(swapchainPresentMode != presentMode, ERR_CANT_CREATE, "Present mode specified is not supported\n"); + ERR_FAIL_COND_V_MSG(swapchainPresentMode != window->presentMode, ERR_CANT_CREATE, "Present mode specified is not supported\n"); // Determine the number of VkImages to use in the swap chain. // Application desires to acquire 3 images at a time for triple @@ -739,7 +830,7 @@ Error VulkanContext::_prepare_buffers() { VkSwapchainCreateInfoKHR swapchain_ci = { .sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR, .pNext = NULL, - .surface = surface, + .surface = window->surface, .minImageCount = desiredNumOfSwapchainImages, .imageFormat = format, .imageColorSpace = color_space, @@ -756,33 +847,33 @@ Error VulkanContext::_prepare_buffers() { .compositeAlpha = compositeAlpha, .presentMode = swapchainPresentMode, .clipped = true, - .oldSwapchain = oldSwapchain, + .oldSwapchain = NULL, }; - uint32_t i; - err = fpCreateSwapchainKHR(device, &swapchain_ci, NULL, &swapchain); - ERR_FAIL_COND_V(err, ERR_CANT_CREATE); - // If we just re-created an existing swapchain, we should destroy the old - // swapchain at this point. - // Note: destroying the swapchain also cleans up all its associated - // presentable images once the platform is done with them. - if (oldSwapchain != VK_NULL_HANDLE) { - fpDestroySwapchainKHR(device, oldSwapchain, NULL); - } + err = fpCreateSwapchainKHR(device, &swapchain_ci, NULL, &window->swapchain); + ERR_FAIL_COND_V(err, ERR_CANT_CREATE); - err = fpGetSwapchainImagesKHR(device, swapchain, &swapchainImageCount, NULL); + uint32_t sp_image_count; + err = fpGetSwapchainImagesKHR(device, window->swapchain, &sp_image_count, NULL); ERR_FAIL_COND_V(err, ERR_CANT_CREATE); + if (swapchainImageCount == 0) { + //assign here for the first time. + swapchainImageCount = sp_image_count; + } else { + ERR_FAIL_COND_V(swapchainImageCount != sp_image_count, ERR_BUG); + } + VkImage *swapchainImages = (VkImage *)malloc(swapchainImageCount * sizeof(VkImage)); ERR_FAIL_COND_V(!swapchainImages, ERR_CANT_CREATE); - err = fpGetSwapchainImagesKHR(device, swapchain, &swapchainImageCount, swapchainImages); + err = fpGetSwapchainImagesKHR(device, window->swapchain, &swapchainImageCount, swapchainImages); ERR_FAIL_COND_V(err, ERR_CANT_CREATE); - swapchain_image_resources = + window->swapchain_image_resources = (SwapchainImageResources *)malloc(sizeof(SwapchainImageResources) * swapchainImageCount); - ERR_FAIL_COND_V(!swapchain_image_resources, ERR_CANT_CREATE); + ERR_FAIL_COND_V(!window->swapchain_image_resources, ERR_CANT_CREATE); - for (i = 0; i < swapchainImageCount; i++) { + for (uint32_t i = 0; i < swapchainImageCount; i++) { VkImageViewCreateInfo color_image_view = { .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, .pNext = NULL, @@ -798,118 +889,84 @@ Error VulkanContext::_prepare_buffers() { .subresourceRange = { .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, .baseMipLevel = 0, .levelCount = 1, .baseArrayLayer = 0, .layerCount = 1 }, }; - swapchain_image_resources[i].image = swapchainImages[i]; + window->swapchain_image_resources[i].image = swapchainImages[i]; - color_image_view.image = swapchain_image_resources[i].image; + color_image_view.image = window->swapchain_image_resources[i].image; - err = vkCreateImageView(device, &color_image_view, NULL, &swapchain_image_resources[i].view); + err = vkCreateImageView(device, &color_image_view, NULL, &window->swapchain_image_resources[i].view); ERR_FAIL_COND_V(err, ERR_CANT_CREATE); } - if (VK_GOOGLE_display_timing_enabled) { - VkRefreshCycleDurationGOOGLE rc_dur; - err = fpGetRefreshCycleDurationGOOGLE(device, swapchain, &rc_dur); - ERR_FAIL_COND_V(err, ERR_CANT_CREATE); - refresh_duration = rc_dur.refreshDuration; - - syncd_with_actual_presents = false; - // Initially target 1X the refresh duration: - target_IPD = refresh_duration; - refresh_duration_multiplier = 1; - prev_desired_present_time = 0; - next_present_id = 1; - } - if (NULL != presentModes) { free(presentModes); } - return OK; -} - -Error VulkanContext::_prepare_framebuffers() { - - //for this, we only need color (no depth), since Godot does not render to the main - //render buffer - - const VkAttachmentDescription attachment = { - - .flags = 0, - .format = format, - .samples = VK_SAMPLE_COUNT_1_BIT, - .loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR, - .storeOp = VK_ATTACHMENT_STORE_OP_STORE, - .stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE, - .stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE, - .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED, - .finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, + /******** FRAMEBUFFER ************/ - }; - const VkAttachmentReference color_reference = { - .attachment = 0, - .layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, - }; + { + const VkAttachmentDescription attachment = { - const VkSubpassDescription subpass = { - .flags = 0, - .pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS, - .inputAttachmentCount = 0, - .pInputAttachments = NULL, - .colorAttachmentCount = 1, - .pColorAttachments = &color_reference, - .pResolveAttachments = NULL, - .pDepthStencilAttachment = NULL, - .preserveAttachmentCount = 0, - .pPreserveAttachments = NULL, - }; - const VkRenderPassCreateInfo rp_info = { - .sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, - .pNext = NULL, - .flags = 0, - .attachmentCount = 1, - .pAttachments = &attachment, - .subpassCount = 1, - .pSubpasses = &subpass, - .dependencyCount = 0, - .pDependencies = NULL, - }; - VkResult err; + .flags = 0, + .format = format, + .samples = VK_SAMPLE_COUNT_1_BIT, + .loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR, + .storeOp = VK_ATTACHMENT_STORE_OP_STORE, + .stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE, + .stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE, + .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED, + .finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, - err = vkCreateRenderPass(device, &rp_info, NULL, &render_pass); - ERR_FAIL_COND_V(err, ERR_CANT_CREATE); + }; + const VkAttachmentReference color_reference = { + .attachment = 0, + .layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, + }; - for (uint32_t i = 0; i < swapchainImageCount; i++) { - const VkFramebufferCreateInfo fb_info = { - .sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, + const VkSubpassDescription subpass = { + .flags = 0, + .pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS, + .inputAttachmentCount = 0, + .pInputAttachments = NULL, + .colorAttachmentCount = 1, + .pColorAttachments = &color_reference, + .pResolveAttachments = NULL, + .pDepthStencilAttachment = NULL, + .preserveAttachmentCount = 0, + .pPreserveAttachments = NULL, + }; + const VkRenderPassCreateInfo rp_info = { + .sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, .pNext = NULL, - .renderPass = render_pass, + .flags = 0, .attachmentCount = 1, - .pAttachments = &swapchain_image_resources[i].view, - .width = width, - .height = height, - .layers = 1, + .pAttachments = &attachment, + .subpassCount = 1, + .pSubpasses = &subpass, + .dependencyCount = 0, + .pDependencies = NULL, }; - err = vkCreateFramebuffer(device, &fb_info, NULL, &swapchain_image_resources[i].framebuffer); + err = vkCreateRenderPass(device, &rp_info, NULL, &window->render_pass); ERR_FAIL_COND_V(err, ERR_CANT_CREATE); - } - return OK; -} - -Error VulkanContext::_create_buffers() { - - Error error = _prepare_buffers(); - if (error != OK) { - return error; - } + for (uint32_t i = 0; i < swapchainImageCount; i++) { + const VkFramebufferCreateInfo fb_info = { + .sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, + .pNext = NULL, + .renderPass = window->render_pass, + .attachmentCount = 1, + .pAttachments = &window->swapchain_image_resources[i].view, + .width = (uint32_t)window->width, + .height = (uint32_t)window->height, + .layers = 1, + }; - if (minimized) { - prepared = false; - return OK; + err = vkCreateFramebuffer(device, &fb_info, NULL, &window->swapchain_image_resources[i].framebuffer); + ERR_FAIL_COND_V(err, ERR_CANT_CREATE); + } } - _prepare_framebuffers(); + /******** SEPARATE PRESENT QUEUE ************/ if (separate_present_queue) { const VkCommandPoolCreateInfo present_cmd_pool_info = { @@ -918,18 +975,18 @@ Error VulkanContext::_create_buffers() { .flags = 0, .queueFamilyIndex = present_queue_family_index, }; - VkResult err = vkCreateCommandPool(device, &present_cmd_pool_info, NULL, &present_cmd_pool); + err = vkCreateCommandPool(device, &present_cmd_pool_info, NULL, &window->present_cmd_pool); ERR_FAIL_COND_V(err, ERR_CANT_CREATE); const VkCommandBufferAllocateInfo present_cmd_info = { .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, .pNext = NULL, - .commandPool = present_cmd_pool, + .commandPool = window->present_cmd_pool, .level = VK_COMMAND_BUFFER_LEVEL_PRIMARY, .commandBufferCount = 1, }; for (uint32_t i = 0; i < swapchainImageCount; i++) { err = vkAllocateCommandBuffers(device, &present_cmd_info, - &swapchain_image_resources[i].graphics_to_present_cmd); + &window->swapchain_image_resources[i].graphics_to_present_cmd); ERR_FAIL_COND_V(err, ERR_CANT_CREATE); const VkCommandBufferBeginInfo cmd_buf_info = { @@ -938,7 +995,7 @@ Error VulkanContext::_create_buffers() { .flags = VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT, .pInheritanceInfo = NULL, }; - err = vkBeginCommandBuffer(swapchain_image_resources[i].graphics_to_present_cmd, &cmd_buf_info); + err = vkBeginCommandBuffer(window->swapchain_image_resources[i].graphics_to_present_cmd, &cmd_buf_info); ERR_FAIL_COND_V(err, ERR_CANT_CREATE); VkImageMemoryBarrier image_ownership_barrier = { .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, @@ -949,49 +1006,29 @@ Error VulkanContext::_create_buffers() { .newLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, .srcQueueFamilyIndex = graphics_queue_family_index, .dstQueueFamilyIndex = present_queue_family_index, - .image = swapchain_image_resources[i].image, + .image = window->swapchain_image_resources[i].image, .subresourceRange = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 } }; - vkCmdPipelineBarrier(swapchain_image_resources[i].graphics_to_present_cmd, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, + vkCmdPipelineBarrier(window->swapchain_image_resources[i].graphics_to_present_cmd, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0, 0, NULL, 0, NULL, 1, &image_ownership_barrier); - err = vkEndCommandBuffer(swapchain_image_resources[i].graphics_to_present_cmd); + err = vkEndCommandBuffer(window->swapchain_image_resources[i].graphics_to_present_cmd); ERR_FAIL_COND_V(err, ERR_CANT_CREATE); } } - current_buffer = 0; - prepared = true; + //reset current buffer + window->current_buffer = 0; return OK; } -Error VulkanContext::initialize(int p_width, int p_height, bool p_minimized) { - - screen_width = p_width; - screen_height = p_height; - minimized = p_minimized; +Error VulkanContext::initialize() { Error err = _create_physical_device(); if (err) { return err; } - - err = _create_swap_chain(); - if (err) { - return err; - } - - err = _create_semaphores(); - if (err) { - return err; - } - - err = _create_buffers(); - if (err) { - return err; - } - - print_line("Vulkan context creation success o_O"); + print_line("Vulkan physical device creation success o_O"); return OK; } @@ -1012,10 +1049,7 @@ void VulkanContext::append_command_buffer(const VkCommandBuffer &pCommandBuffer) void VulkanContext::flush(bool p_flush_setup, bool p_flush_pending) { // ensure everything else pending is executed - for (int i = 0; i < FRAME_LAG; i++) { - int to_fence = (frame_index + i) % FRAME_LAG; - vkWaitForFences(device, 1, &fences[to_fence], VK_TRUE, UINT64_MAX); - } + vkDeviceWaitIdle(device); //flush the pending setup buffer @@ -1038,7 +1072,7 @@ void VulkanContext::flush(bool p_flush_setup, bool p_flush_pending) { VkResult err = vkQueueSubmit(graphics_queue, 1, &submit_info, fences[frame_index]); command_buffer_queue.write[0] = NULL; ERR_FAIL_COND(err); - vkWaitForFences(device, 1, &fences[frame_index], VK_TRUE, UINT64_MAX); + vkDeviceWaitIdle(device); } if (p_flush_pending && command_buffer_count > 1) { @@ -1060,41 +1094,68 @@ void VulkanContext::flush(bool p_flush_setup, bool p_flush_pending) { VkResult err = vkQueueSubmit(graphics_queue, 1, &submit_info, fences[frame_index]); command_buffer_queue.write[0] = NULL; ERR_FAIL_COND(err); - vkWaitForFences(device, 1, &fences[frame_index], VK_TRUE, UINT64_MAX); + vkDeviceWaitIdle(device); command_buffer_count = 1; } } -Error VulkanContext::swap_buffers() { +Error VulkanContext::prepare_buffers() { + + if (!queues_initialized) { + return OK; + } - // print_line("swapbuffers?"); VkResult err; // Ensure no more than FRAME_LAG renderings are outstanding vkWaitForFences(device, 1, &fences[frame_index], VK_TRUE, UINT64_MAX); vkResetFences(device, 1, &fences[frame_index]); - do { - // Get the index of the next available swapchain image: - err = - fpAcquireNextImageKHR(device, swapchain, UINT64_MAX, - image_acquired_semaphores[frame_index], VK_NULL_HANDLE, ¤t_buffer); - - if (err == VK_ERROR_OUT_OF_DATE_KHR) { - // swapchain is out of date (e.g. the window was resized) and - // must be recreated: - print_line("early out of data"); - resize_notify(); - } else if (err == VK_SUBOPTIMAL_KHR) { - print_line("early suboptimal"); - // swapchain is not as optimal as it could be, but the platform's - // presentation engine will still present the image correctly. - break; - } else { - ERR_FAIL_COND_V(err, ERR_CANT_CREATE); + for (Map<int, Window>::Element *E = windows.front(); E; E = E->next()) { + + Window *w = &E->get(); + + if (w->swapchain == VK_NULL_HANDLE) { + continue; } - } while (err != VK_SUCCESS); + + do { + // Get the index of the next available swapchain image: + err = + fpAcquireNextImageKHR(device, w->swapchain, UINT64_MAX, + image_acquired_semaphores[frame_index], VK_NULL_HANDLE, &w->current_buffer); + + if (err == VK_ERROR_OUT_OF_DATE_KHR) { + // swapchain is out of date (e.g. the window was resized) and + // must be recreated: + print_line("early out of data"); + //resize_notify(); + _update_swap_chain(w); + } else if (err == VK_SUBOPTIMAL_KHR) { + print_line("early suboptimal"); + // swapchain is not as optimal as it could be, but the platform's + // presentation engine will still present the image correctly. + break; + } else { + ERR_FAIL_COND_V(err, ERR_CANT_CREATE); + } + } while (err != VK_SUCCESS); + } + + buffers_prepared = true; + + return OK; +} + +Error VulkanContext::swap_buffers() { + + if (!queues_initialized) { + return OK; + } + + // print_line("swapbuffers?"); + VkResult err; #if 0 if (VK_GOOGLE_display_timing_enabled) { @@ -1154,8 +1215,21 @@ Error VulkanContext::swap_buffers() { pipe_stage_flags = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; submit_info.waitSemaphoreCount = 1; submit_info.pWaitSemaphores = &draw_complete_semaphores[frame_index]; - submit_info.commandBufferCount = 1; - submit_info.pCommandBuffers = &swapchain_image_resources[current_buffer].graphics_to_present_cmd; + submit_info.commandBufferCount = 0; + + VkCommandBuffer *cmdbufptr = (VkCommandBuffer *)alloca(sizeof(VkCommandBuffer *) * windows.size()); + submit_info.pCommandBuffers = cmdbufptr; + + for (Map<int, Window>::Element *E = windows.front(); E; E = E->next()) { + Window *w = &E->get(); + + if (w->swapchain == VK_NULL_HANDLE) { + continue; + } + cmdbufptr[submit_info.commandBufferCount] = w->swapchain_image_resources[w->current_buffer].graphics_to_present_cmd; + submit_info.commandBufferCount++; + } + submit_info.signalSemaphoreCount = 1; submit_info.pSignalSemaphores = &image_ownership_semaphores[frame_index]; err = vkQueueSubmit(present_queue, 1, &submit_info, nullFence); @@ -1169,10 +1243,28 @@ Error VulkanContext::swap_buffers() { .pNext = NULL, .waitSemaphoreCount = 1, .pWaitSemaphores = (separate_present_queue) ? &image_ownership_semaphores[frame_index] : &draw_complete_semaphores[frame_index], - .swapchainCount = 1, - .pSwapchains = &swapchain, - .pImageIndices = ¤t_buffer, + .swapchainCount = 0, + .pSwapchains = NULL, + .pImageIndices = NULL, }; + + VkSwapchainKHR *pSwapchains = (VkSwapchainKHR *)alloca(sizeof(VkSwapchainKHR *) * windows.size()); + uint32_t *pImageIndices = (uint32_t *)alloca(sizeof(uint32_t *) * windows.size()); + + present.pSwapchains = pSwapchains; + present.pImageIndices = pImageIndices; + + for (Map<int, Window>::Element *E = windows.front(); E; E = E->next()) { + Window *w = &E->get(); + + if (w->swapchain == VK_NULL_HANDLE) { + continue; + } + pSwapchains[present.swapchainCount] = w->swapchain; + pImageIndices[present.swapchainCount] = w->current_buffer; + present.swapchainCount++; + } + #if 0 if (VK_KHR_incremental_present_enabled) { // If using VK_KHR_incremental_present, we provide a hint of the region @@ -1261,6 +1353,7 @@ Error VulkanContext::swap_buffers() { ERR_FAIL_COND_V(err, ERR_CANT_CREATE); } + buffers_prepared = false; return OK; } @@ -1274,47 +1367,34 @@ VkDevice VulkanContext::get_device() { VkPhysicalDevice VulkanContext::get_physical_device() { return gpu; } -int VulkanContext::get_frame_count() const { +int VulkanContext::get_swapchain_image_count() const { return swapchainImageCount; } uint32_t VulkanContext::get_graphics_queue() const { return graphics_queue_family_index; } -int VulkanContext::get_screen_width(int p_screen) { - return width; -} - -int VulkanContext::get_screen_height(int p_screen) { - return height; -} - -VkFramebuffer VulkanContext::get_frame_framebuffer(int p_frame) { - return swapchain_image_resources[p_frame].framebuffer; -} VkFormat VulkanContext::get_screen_format() const { return format; } -VkRenderPass VulkanContext::get_render_pass() { - return render_pass; -} - VkPhysicalDeviceLimits VulkanContext::get_device_limits() const { return gpu_props.limits; } VulkanContext::VulkanContext() { - presentMode = VK_PRESENT_MODE_FIFO_KHR; command_buffer_count = 0; instance_validation_layers = NULL; use_validation_layers = true; VK_KHR_incremental_present_enabled = true; VK_GOOGLE_display_timing_enabled = true; - swapchain = NULL; - prepared = false; command_buffer_queue.resize(1); //first one is the setup command always command_buffer_queue.write[0] = NULL; command_buffer_count = 1; + queues_initialized = false; + + buffers_prepared = false; + swapchainImageCount = 0; + last_window_id = 0; } |