summaryrefslogtreecommitdiffstats
path: root/drivers/vulkan/vulkan_context.cpp
diff options
context:
space:
mode:
authorJuan Linietsky <reduzio@gmail.com>2019-06-24 16:13:06 -0300
committerJuan Linietsky <reduzio@gmail.com>2020-02-11 11:53:27 +0100
commit1b4281b895f3046ea972256182b18696a25f8316 (patch)
tree5f6b9c1600a4354f17b29e430a447d08f93ecf25 /drivers/vulkan/vulkan_context.cpp
parent42b44f43ee52eb664d3610d0fdae0eff14c00f0a (diff)
downloadredot-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.cpp504
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, &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();
- } 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 = &current_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;
}