mirror of
https://github.com/charles-lunarg/vk-bootstrap.git
synced 2024-11-22 15:24:34 +00:00
Polished SwapchainBuilder. Redid swapchain recreation.
To recreate a swapchain now requires making a new SwapchainBuilder or keeping the old one around. Removed the recreate function since its purpose was unclear. Introduced set_old_swapchain to allow recyling the old swapchain. Updated documentation and getting started guide.
This commit is contained in:
parent
e2c65e7ec1
commit
8a053cadc3
@ -219,6 +219,29 @@ for (uint32_t i = 0; i < static_cast<uint32_t>(queue_families.size ()); i++) {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
## Swapchain
|
## Swapchain
|
||||||
// TODO
|
|
||||||
|
|
||||||
|
Creating a swapchain follows the same form outlined by `vkb::InstanceBuilder` and `vkb::DeviceBuilder`. Create the `vkb::SwapchainBuilder`, provide `vkb::Device`, call the appropriate builder functions, and call `build()`.
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
vkb::SwapchainBuilder swapchain_builder{ device };
|
||||||
|
auto swap_ret = swapchain_builder.build ();
|
||||||
|
if !(swap_ret){
|
||||||
|
|
||||||
|
}
|
||||||
|
vkb::swapchain swapchain = swap_ret.value();
|
||||||
|
```
|
||||||
|
|
||||||
|
By default, the swapchain will use the VK_FORMAT_B8G8R8A8_SRGB or VK_FORMAT_R8G8B8A8_SRGB image format with the color space VK_COLOR_SPACE_SRGB_NONLINEAR_KHR. The present mode will default to VK_PRESENT_MODE_MAILBOX_KHR if available and fallback to VK_PRESENT_MODE_FIFO_KHR. The image usage default flag is VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT.
|
||||||
|
|
||||||
|
Recreating the swapchain is equivalent to creating a new swapchain but providing the old swapchain as a source. Be sure to not use the same `VkSwapchainKHR` again as it expires when it is recycled after trying to create a new swapchain.
|
||||||
|
```cpp
|
||||||
|
vkb::SwapchainBuilder swapchain_builder{ device };
|
||||||
|
auto swap_ret = swapchain_builder.set_old_swapchain (vkb_swapchain)
|
||||||
|
.build ();
|
||||||
|
if !(swap_ret){
|
||||||
|
// If it failed to create a swapchain, the old swapchain handle is invalid.
|
||||||
|
vkb_swapchain.swapchain = VK_NULL_HANDLE;
|
||||||
|
}
|
||||||
|
// Note that this is the same vkb::Swapchain which was fed into vkb::SwapchainBuilder
|
||||||
|
vkb_swapchain = swap_ret.value();
|
||||||
|
```
|
||||||
|
@ -39,7 +39,7 @@ struct RenderData {
|
|||||||
};
|
};
|
||||||
|
|
||||||
int device_initialization (Init& init) {
|
int device_initialization (Init& init) {
|
||||||
init.window = create_window_glfw ("Vulkan Triangle", false);
|
init.window = create_window_glfw ("Vulkan Triangle", true);
|
||||||
|
|
||||||
vkb::InstanceBuilder instance_builder;
|
vkb::InstanceBuilder instance_builder;
|
||||||
auto instance_ret = instance_builder.use_default_debug_messenger ().request_validation_layers ().build ();
|
auto instance_ret = instance_builder.use_default_debug_messenger ().request_validation_layers ().build ();
|
||||||
@ -67,17 +67,24 @@ int device_initialization (Init& init) {
|
|||||||
}
|
}
|
||||||
init.device = device_ret.value ();
|
init.device = device_ret.value ();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int create_swapchain (Init& init) {
|
||||||
vkb::SwapchainBuilder swapchain_builder{ init.device };
|
vkb::SwapchainBuilder swapchain_builder{ init.device };
|
||||||
auto swap_ret =
|
auto swap_ret = swapchain_builder.use_default_format_selection ()
|
||||||
swapchain_builder.use_default_format_selection ().use_default_present_mode_selection ().build ();
|
.use_default_present_mode_selection ()
|
||||||
|
.set_old_swapchain (init.swapchain)
|
||||||
|
.build ();
|
||||||
if (!swap_ret) {
|
if (!swap_ret) {
|
||||||
std::cout << swap_ret.error ().message () << "\n";
|
std::cout << swap_ret.error ().message () << " " << swap_ret.vk_result () << "\n";
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
init.swapchain = swap_ret.value ();
|
init.swapchain = swap_ret.value ();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int get_queues (Init& init, RenderData& data) {
|
int get_queues (Init& init, RenderData& data) {
|
||||||
auto gq = init.device.get_queue (vkb::QueueType::graphics);
|
auto gq = init.device.get_queue (vkb::QueueType::graphics);
|
||||||
if (!gq.has_value ()) {
|
if (!gq.has_value ()) {
|
||||||
@ -267,23 +274,31 @@ int create_graphics_pipeline (Init& init, RenderData& data) {
|
|||||||
return -1; // failed to create pipeline layout
|
return -1; // failed to create pipeline layout
|
||||||
}
|
}
|
||||||
|
|
||||||
VkGraphicsPipelineCreateInfo pipelineInfo = {};
|
std::vector<VkDynamicState> dynamic_states = { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR };
|
||||||
pipelineInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
|
|
||||||
pipelineInfo.stageCount = 2;
|
VkPipelineDynamicStateCreateInfo dynamic_info = {};
|
||||||
pipelineInfo.pStages = shader_stages;
|
dynamic_info.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
|
||||||
pipelineInfo.pVertexInputState = &vertex_input_info;
|
dynamic_info.dynamicStateCount = static_cast<uint32_t> (dynamic_states.size ());
|
||||||
pipelineInfo.pInputAssemblyState = &input_assembly;
|
dynamic_info.pDynamicStates = dynamic_states.data ();
|
||||||
pipelineInfo.pViewportState = &viewport_state;
|
|
||||||
pipelineInfo.pRasterizationState = &rasterizer;
|
VkGraphicsPipelineCreateInfo pipeline_info = {};
|
||||||
pipelineInfo.pMultisampleState = &multisampling;
|
pipeline_info.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
|
||||||
pipelineInfo.pColorBlendState = &color_blending;
|
pipeline_info.stageCount = 2;
|
||||||
pipelineInfo.layout = data.pipeline_layout;
|
pipeline_info.pStages = shader_stages;
|
||||||
pipelineInfo.renderPass = data.render_pass;
|
pipeline_info.pVertexInputState = &vertex_input_info;
|
||||||
pipelineInfo.subpass = 0;
|
pipeline_info.pInputAssemblyState = &input_assembly;
|
||||||
pipelineInfo.basePipelineHandle = VK_NULL_HANDLE;
|
pipeline_info.pViewportState = &viewport_state;
|
||||||
|
pipeline_info.pRasterizationState = &rasterizer;
|
||||||
|
pipeline_info.pMultisampleState = &multisampling;
|
||||||
|
pipeline_info.pColorBlendState = &color_blending;
|
||||||
|
pipeline_info.pDynamicState = &dynamic_info;
|
||||||
|
pipeline_info.layout = data.pipeline_layout;
|
||||||
|
pipeline_info.renderPass = data.render_pass;
|
||||||
|
pipeline_info.subpass = 0;
|
||||||
|
pipeline_info.basePipelineHandle = VK_NULL_HANDLE;
|
||||||
|
|
||||||
if (vkCreateGraphicsPipelines (
|
if (vkCreateGraphicsPipelines (
|
||||||
init.device.device, VK_NULL_HANDLE, 1, &pipelineInfo, nullptr, &data.graphics_pipeline) != VK_SUCCESS) {
|
init.device.device, VK_NULL_HANDLE, 1, &pipeline_info, nullptr, &data.graphics_pipeline) != VK_SUCCESS) {
|
||||||
std::cout << "failed to create pipline\n";
|
std::cout << "failed to create pipline\n";
|
||||||
return -1; // failed to create graphics pipeline
|
return -1; // failed to create graphics pipeline
|
||||||
}
|
}
|
||||||
@ -361,6 +376,21 @@ int create_command_buffers (Init& init, RenderData& data) {
|
|||||||
render_pass_info.clearValueCount = 1;
|
render_pass_info.clearValueCount = 1;
|
||||||
render_pass_info.pClearValues = &clearColor;
|
render_pass_info.pClearValues = &clearColor;
|
||||||
|
|
||||||
|
VkViewport viewport = {};
|
||||||
|
viewport.x = 0.0f;
|
||||||
|
viewport.y = 0.0f;
|
||||||
|
viewport.width = (float)init.swapchain.extent.width;
|
||||||
|
viewport.height = (float)init.swapchain.extent.height;
|
||||||
|
viewport.minDepth = 0.0f;
|
||||||
|
viewport.maxDepth = 1.0f;
|
||||||
|
|
||||||
|
VkRect2D scissor = {};
|
||||||
|
scissor.offset = { 0, 0 };
|
||||||
|
scissor.extent = init.swapchain.extent;
|
||||||
|
|
||||||
|
vkCmdSetViewport (data.command_buffers[i], 0, 1, &viewport);
|
||||||
|
vkCmdSetScissor (data.command_buffers[i], 0, 1, &scissor);
|
||||||
|
|
||||||
vkCmdBeginRenderPass (data.command_buffers[i], &render_pass_info, VK_SUBPASS_CONTENTS_INLINE);
|
vkCmdBeginRenderPass (data.command_buffers[i], &render_pass_info, VK_SUBPASS_CONTENTS_INLINE);
|
||||||
|
|
||||||
vkCmdBindPipeline (data.command_buffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, data.graphics_pipeline);
|
vkCmdBindPipeline (data.command_buffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, data.graphics_pipeline);
|
||||||
@ -401,17 +431,47 @@ int create_sync_objects (Init& init, RenderData& data) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int recreate_swapchain (Init& init, RenderData& data) {
|
||||||
|
vkDeviceWaitIdle (init.device.device);
|
||||||
|
|
||||||
|
vkDestroyCommandPool (init.device.device, data.command_pool, nullptr);
|
||||||
|
|
||||||
|
for (auto framebuffer : data.framebuffers) {
|
||||||
|
vkDestroyFramebuffer (init.device.device, framebuffer, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
init.swapchain.destroy_image_views (data.swapchain_image_views);
|
||||||
|
|
||||||
|
int created_swapchain = create_swapchain (init);
|
||||||
|
while (created_swapchain != 0) {
|
||||||
|
init.swapchain.swapchain = VK_NULL_HANDLE;
|
||||||
|
created_swapchain = create_swapchain (init);
|
||||||
|
}
|
||||||
|
if (0 != create_framebuffers (init, data)) return -1;
|
||||||
|
if (0 != create_command_pool (init, data)) return -1;
|
||||||
|
if (0 != create_command_buffers (init, data)) return -1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int draw_frame (Init& init, RenderData& data) {
|
int draw_frame (Init& init, RenderData& data) {
|
||||||
vkWaitForFences (init.device.device, 1, &data.in_flight_fences[data.current_frame], VK_TRUE, UINT64_MAX);
|
vkWaitForFences (init.device.device, 1, &data.in_flight_fences[data.current_frame], VK_TRUE, UINT64_MAX);
|
||||||
|
|
||||||
uint32_t image_index = 0;
|
uint32_t image_index = 0;
|
||||||
vkAcquireNextImageKHR (init.device.device,
|
VkResult result = vkAcquireNextImageKHR (init.device.device,
|
||||||
init.swapchain.swapchain,
|
init.swapchain.swapchain,
|
||||||
UINT64_MAX,
|
UINT64_MAX,
|
||||||
data.available_semaphores[data.current_frame],
|
data.available_semaphores[data.current_frame],
|
||||||
VK_NULL_HANDLE,
|
VK_NULL_HANDLE,
|
||||||
&image_index);
|
&image_index);
|
||||||
|
|
||||||
|
if (result == VK_ERROR_OUT_OF_DATE_KHR) {
|
||||||
|
return recreate_swapchain (init, data);
|
||||||
|
return 0;
|
||||||
|
} else if (result != VK_SUCCESS && result != VK_SUBOPTIMAL_KHR) {
|
||||||
|
std::cout << "failed to recreate swapchain. Error " << result << "\n";
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
if (data.image_in_flight[image_index] != VK_NULL_HANDLE) {
|
if (data.image_in_flight[image_index] != VK_NULL_HANDLE) {
|
||||||
vkWaitForFences (init.device.device, 1, &data.image_in_flight[image_index], VK_TRUE, UINT64_MAX);
|
vkWaitForFences (init.device.device, 1, &data.image_in_flight[image_index], VK_TRUE, UINT64_MAX);
|
||||||
}
|
}
|
||||||
@ -452,7 +512,14 @@ int draw_frame (Init& init, RenderData& data) {
|
|||||||
|
|
||||||
present_info.pImageIndices = &image_index;
|
present_info.pImageIndices = &image_index;
|
||||||
|
|
||||||
vkQueuePresentKHR (data.present_queue, &present_info);
|
result = vkQueuePresentKHR (data.present_queue, &present_info);
|
||||||
|
if (result == VK_ERROR_OUT_OF_DATE_KHR || result == VK_SUBOPTIMAL_KHR) {
|
||||||
|
return recreate_swapchain (init, data);
|
||||||
|
return 0;
|
||||||
|
} else if (result != VK_SUCCESS) {
|
||||||
|
std::cout << "failed to present swapchain image\n";
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
data.current_frame = (data.current_frame + 1) % MAX_FRAMES_IN_FLIGHT;
|
data.current_frame = (data.current_frame + 1) % MAX_FRAMES_IN_FLIGHT;
|
||||||
return 0;
|
return 0;
|
||||||
@ -475,9 +542,7 @@ void cleanup (Init& init, RenderData& data) {
|
|||||||
vkDestroyPipelineLayout (init.device.device, data.pipeline_layout, nullptr);
|
vkDestroyPipelineLayout (init.device.device, data.pipeline_layout, nullptr);
|
||||||
vkDestroyRenderPass (init.device.device, data.render_pass, nullptr);
|
vkDestroyRenderPass (init.device.device, data.render_pass, nullptr);
|
||||||
|
|
||||||
for (auto imageView : data.swapchain_image_views) {
|
init.swapchain.destroy_image_views (data.swapchain_image_views);
|
||||||
vkDestroyImageView (init.device.device, imageView, nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
vkb::destroy_swapchain (init.swapchain);
|
vkb::destroy_swapchain (init.swapchain);
|
||||||
vkb::destroy_device (init.device);
|
vkb::destroy_device (init.device);
|
||||||
@ -491,6 +556,7 @@ int main () {
|
|||||||
RenderData render_data;
|
RenderData render_data;
|
||||||
|
|
||||||
if (0 != device_initialization (init)) return -1;
|
if (0 != device_initialization (init)) return -1;
|
||||||
|
if (0 != create_swapchain (init)) return -1;
|
||||||
if (0 != get_queues (init, render_data)) return -1;
|
if (0 != get_queues (init, render_data)) return -1;
|
||||||
if (0 != create_render_pass (init, render_data)) return -1;
|
if (0 != create_render_pass (init, render_data)) return -1;
|
||||||
if (0 != create_graphics_pipeline (init, render_data)) return -1;
|
if (0 != create_graphics_pipeline (init, render_data)) return -1;
|
||||||
|
@ -1240,6 +1240,7 @@ Result<SurfaceSupportDetails> query_surface_support_details (VkPhysicalDevice ph
|
|||||||
present_modes, vkGetPhysicalDeviceSurfacePresentModesKHR, phys_device, surface);
|
present_modes, vkGetPhysicalDeviceSurfacePresentModesKHR, phys_device, surface);
|
||||||
if (present_modes_ret != VK_SUCCESS)
|
if (present_modes_ret != VK_SUCCESS)
|
||||||
return { make_error_code (SurfaceSupportError::failed_enumerate_present_modes), present_modes_ret };
|
return { make_error_code (SurfaceSupportError::failed_enumerate_present_modes), present_modes_ret };
|
||||||
|
|
||||||
return SurfaceSupportDetails{ capabilities, formats, present_modes };
|
return SurfaceSupportDetails{ capabilities, formats, present_modes };
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1291,6 +1292,11 @@ VkExtent2D find_extent (
|
|||||||
}
|
}
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
|
|
||||||
|
void destroy_swapchain (Swapchain const& swapchain) {
|
||||||
|
if (swapchain.device != VK_NULL_HANDLE && swapchain.swapchain != VK_NULL_HANDLE)
|
||||||
|
vkDestroySwapchainKHR (swapchain.device, swapchain.swapchain, swapchain.allocation_callbacks);
|
||||||
|
}
|
||||||
|
|
||||||
SwapchainBuilder::SwapchainBuilder (Device const& device) {
|
SwapchainBuilder::SwapchainBuilder (Device const& device) {
|
||||||
info.device = device.device;
|
info.device = device.device;
|
||||||
info.physical_device = device.physical_device.physical_device;
|
info.physical_device = device.physical_device.physical_device;
|
||||||
@ -1314,8 +1320,7 @@ SwapchainBuilder::SwapchainBuilder (Device const& device, VkSurfaceKHR const sur
|
|||||||
info.present_queue_index = graphics.value ();
|
info.present_queue_index = graphics.value ();
|
||||||
}
|
}
|
||||||
|
|
||||||
detail::Result<Swapchain> SwapchainBuilder::build () const { return build (VK_NULL_HANDLE); }
|
detail::Result<Swapchain> SwapchainBuilder::build () const {
|
||||||
detail::Result<Swapchain> SwapchainBuilder::build (VkSwapchainKHR old_swapchain) const {
|
|
||||||
if (info.surface == VK_NULL_HANDLE) {
|
if (info.surface == VK_NULL_HANDLE) {
|
||||||
return detail::Error{ SwapchainError::surface_handle_not_provided };
|
return detail::Error{ SwapchainError::surface_handle_not_provided };
|
||||||
}
|
}
|
||||||
@ -1325,36 +1330,48 @@ detail::Result<Swapchain> SwapchainBuilder::build (VkSwapchainKHR old_swapchain)
|
|||||||
auto desired_present_modes = info.desired_present_modes;
|
auto desired_present_modes = info.desired_present_modes;
|
||||||
if (desired_present_modes.size () == 0) add_desired_present_modes (desired_present_modes);
|
if (desired_present_modes.size () == 0) add_desired_present_modes (desired_present_modes);
|
||||||
|
|
||||||
auto surface_support = detail::query_surface_support_details (info.physical_device, info.surface);
|
auto surface_support_ret = detail::query_surface_support_details (info.physical_device, info.surface);
|
||||||
if (!surface_support.has_value ())
|
if (!surface_support_ret.has_value ())
|
||||||
return detail::Error{ SwapchainError::failed_query_surface_support_details,
|
return detail::Error{ SwapchainError::failed_query_surface_support_details,
|
||||||
surface_support.vk_result () };
|
surface_support_ret.vk_result () };
|
||||||
VkSurfaceFormatKHR surface_format =
|
auto surface_support = surface_support_ret.value ();
|
||||||
detail::find_surface_format (surface_support.value ().formats, desired_formats);
|
|
||||||
VkPresentModeKHR present_mode =
|
|
||||||
detail::find_present_mode (surface_support.value ().present_modes, desired_present_modes);
|
|
||||||
VkExtent2D extent = detail::find_extent (
|
|
||||||
surface_support.value ().capabilities, info.desired_width, info.desired_height);
|
|
||||||
|
|
||||||
uint32_t imageCount = surface_support.value ().capabilities.minImageCount + 1;
|
uint32_t image_count = surface_support.capabilities.minImageCount + 1;
|
||||||
if (surface_support.value ().capabilities.maxImageCount > 0 &&
|
if (surface_support.capabilities.maxImageCount > 0 && image_count > surface_support.capabilities.maxImageCount) {
|
||||||
imageCount > surface_support.value ().capabilities.maxImageCount) {
|
image_count = surface_support.capabilities.maxImageCount;
|
||||||
imageCount = surface_support.value ().capabilities.maxImageCount;
|
|
||||||
}
|
}
|
||||||
|
VkSurfaceFormatKHR surface_format = detail::find_surface_format (surface_support.formats, desired_formats);
|
||||||
|
|
||||||
|
VkExtent2D extent =
|
||||||
|
detail::find_extent (surface_support.capabilities, info.desired_width, info.desired_height);
|
||||||
|
|
||||||
|
uint32_t image_array_layers = info.array_layer_count;
|
||||||
|
if (surface_support.capabilities.maxImageArrayLayers < info.array_layer_count)
|
||||||
|
image_array_layers = surface_support.capabilities.maxImageArrayLayers;
|
||||||
|
if (info.array_layer_count == 0) image_array_layers = 1;
|
||||||
|
|
||||||
|
uint32_t queue_family_indices[] = { info.graphics_queue_index, info.present_queue_index };
|
||||||
|
|
||||||
|
|
||||||
|
VkPresentModeKHR present_mode =
|
||||||
|
detail::find_present_mode (surface_support.present_modes, desired_present_modes);
|
||||||
|
|
||||||
|
VkSurfaceTransformFlagBitsKHR pre_transform = info.pre_transform;
|
||||||
|
if (info.pre_transform == static_cast<VkSurfaceTransformFlagBitsKHR> (0))
|
||||||
|
pre_transform = surface_support.capabilities.currentTransform;
|
||||||
|
|
||||||
VkSwapchainCreateInfoKHR swapchain_create_info = {};
|
VkSwapchainCreateInfoKHR swapchain_create_info = {};
|
||||||
swapchain_create_info.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
|
swapchain_create_info.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
|
||||||
detail::setup_pNext_chain (swapchain_create_info, info.pNext_elements);
|
detail::setup_pNext_chain (swapchain_create_info, info.pNext_chain);
|
||||||
|
swapchain_create_info.flags = info.create_flags;
|
||||||
swapchain_create_info.surface = info.surface;
|
swapchain_create_info.surface = info.surface;
|
||||||
swapchain_create_info.minImageCount = imageCount;
|
swapchain_create_info.minImageCount = image_count;
|
||||||
swapchain_create_info.imageFormat = surface_format.format;
|
swapchain_create_info.imageFormat = surface_format.format;
|
||||||
swapchain_create_info.imageColorSpace = surface_format.colorSpace;
|
swapchain_create_info.imageColorSpace = surface_format.colorSpace;
|
||||||
swapchain_create_info.imageExtent = extent;
|
swapchain_create_info.imageExtent = extent;
|
||||||
swapchain_create_info.imageArrayLayers = info.array_layer_count;
|
swapchain_create_info.imageArrayLayers = image_array_layers;
|
||||||
swapchain_create_info.imageUsage = info.image_usage_flags;
|
swapchain_create_info.imageUsage = info.image_usage_flags;
|
||||||
|
|
||||||
uint32_t queue_family_indices[] = { info.graphics_queue_index, info.present_queue_index };
|
|
||||||
|
|
||||||
if (info.graphics_queue_index != info.present_queue_index) {
|
if (info.graphics_queue_index != info.present_queue_index) {
|
||||||
swapchain_create_info.imageSharingMode = VK_SHARING_MODE_CONCURRENT;
|
swapchain_create_info.imageSharingMode = VK_SHARING_MODE_CONCURRENT;
|
||||||
swapchain_create_info.queueFamilyIndexCount = 2;
|
swapchain_create_info.queueFamilyIndexCount = 2;
|
||||||
@ -1363,11 +1380,11 @@ detail::Result<Swapchain> SwapchainBuilder::build (VkSwapchainKHR old_swapchain)
|
|||||||
swapchain_create_info.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
swapchain_create_info.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
||||||
}
|
}
|
||||||
|
|
||||||
swapchain_create_info.preTransform = surface_support.value ().capabilities.currentTransform;
|
swapchain_create_info.preTransform = pre_transform;
|
||||||
swapchain_create_info.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
|
swapchain_create_info.compositeAlpha = info.composite_alpha;
|
||||||
swapchain_create_info.presentMode = present_mode;
|
swapchain_create_info.presentMode = present_mode;
|
||||||
swapchain_create_info.clipped = info.clipped;
|
swapchain_create_info.clipped = info.clipped;
|
||||||
swapchain_create_info.oldSwapchain = old_swapchain;
|
swapchain_create_info.oldSwapchain = info.old_swapchain;
|
||||||
Swapchain swapchain{};
|
Swapchain swapchain{};
|
||||||
VkResult res = vkCreateSwapchainKHR (
|
VkResult res = vkCreateSwapchainKHR (
|
||||||
info.device, &swapchain_create_info, info.allocation_callbacks, &swapchain.swapchain);
|
info.device, &swapchain_create_info, info.allocation_callbacks, &swapchain.swapchain);
|
||||||
@ -1385,9 +1402,6 @@ detail::Result<Swapchain> SwapchainBuilder::build (VkSwapchainKHR old_swapchain)
|
|||||||
swapchain.allocation_callbacks = info.allocation_callbacks;
|
swapchain.allocation_callbacks = info.allocation_callbacks;
|
||||||
return swapchain;
|
return swapchain;
|
||||||
}
|
}
|
||||||
detail::Result<Swapchain> SwapchainBuilder::recreate (Swapchain const& swapchain) const {
|
|
||||||
return build (swapchain.swapchain);
|
|
||||||
}
|
|
||||||
detail::Result<std::vector<VkImage>> Swapchain::get_images () {
|
detail::Result<std::vector<VkImage>> Swapchain::get_images () {
|
||||||
std::vector<VkImage> swapchain_images;
|
std::vector<VkImage> swapchain_images;
|
||||||
|
|
||||||
@ -1433,9 +1447,13 @@ void Swapchain::destroy_image_views (std::vector<VkImageView> const& image_views
|
|||||||
vkDestroyImageView (device, image_view, allocation_callbacks);
|
vkDestroyImageView (device, image_view, allocation_callbacks);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void destroy_swapchain (Swapchain const& swapchain) {
|
SwapchainBuilder& SwapchainBuilder::set_old_swapchain (VkSwapchainKHR old_swapchain) {
|
||||||
if (swapchain.device != VK_NULL_HANDLE && swapchain.swapchain != VK_NULL_HANDLE)
|
info.old_swapchain = old_swapchain;
|
||||||
vkDestroySwapchainKHR (swapchain.device, swapchain.swapchain, swapchain.allocation_callbacks);
|
return *this;
|
||||||
|
}
|
||||||
|
SwapchainBuilder& SwapchainBuilder::set_old_swapchain (Swapchain const& swapchain) {
|
||||||
|
info.old_swapchain = swapchain.swapchain;
|
||||||
|
return *this;
|
||||||
}
|
}
|
||||||
SwapchainBuilder& SwapchainBuilder::set_desired_extent (uint32_t width, uint32_t height) {
|
SwapchainBuilder& SwapchainBuilder::set_desired_extent (uint32_t width, uint32_t height) {
|
||||||
info.desired_width = width;
|
info.desired_width = width;
|
||||||
@ -1451,6 +1469,7 @@ SwapchainBuilder& SwapchainBuilder::add_fallback_format (VkSurfaceFormatKHR form
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
SwapchainBuilder& SwapchainBuilder::use_default_format_selection () {
|
SwapchainBuilder& SwapchainBuilder::use_default_format_selection () {
|
||||||
|
info.desired_formats.clear ();
|
||||||
add_desired_formats (info.desired_formats);
|
add_desired_formats (info.desired_formats);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
@ -1464,6 +1483,7 @@ SwapchainBuilder& SwapchainBuilder::add_fallback_present_mode (VkPresentModeKHR
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
SwapchainBuilder& SwapchainBuilder::use_default_present_mode_selection () {
|
SwapchainBuilder& SwapchainBuilder::use_default_present_mode_selection () {
|
||||||
|
info.desired_present_modes.clear ();
|
||||||
add_desired_present_modes (info.desired_present_modes);
|
add_desired_present_modes (info.desired_present_modes);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
@ -1491,6 +1511,18 @@ SwapchainBuilder& SwapchainBuilder::set_clipped (bool clipped) {
|
|||||||
info.clipped = clipped;
|
info.clipped = clipped;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
SwapchainBuilder& SwapchainBuilder::set_create_flags (VkSwapchainCreateFlagBitsKHR create_flags) {
|
||||||
|
info.create_flags = create_flags;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
SwapchainBuilder& SwapchainBuilder::set_pre_transform_flags (VkSurfaceTransformFlagBitsKHR pre_transform_flags) {
|
||||||
|
info.pre_transform = pre_transform_flags;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
SwapchainBuilder& SwapchainBuilder::set_composite_alpha_flags (VkCompositeAlphaFlagBitsKHR composite_alpha_flags) {
|
||||||
|
info.composite_alpha = composite_alpha_flags;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
void SwapchainBuilder::add_desired_formats (std::vector<VkSurfaceFormatKHR>& formats) const {
|
void SwapchainBuilder::add_desired_formats (std::vector<VkSurfaceFormatKHR>& formats) const {
|
||||||
formats.push_back ({ VK_FORMAT_B8G8R8A8_SRGB, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR });
|
formats.push_back ({ VK_FORMAT_B8G8R8A8_SRGB, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR });
|
||||||
|
@ -107,7 +107,7 @@ enum class InstanceError {
|
|||||||
failed_create_debug_messenger,
|
failed_create_debug_messenger,
|
||||||
requested_layers_not_present,
|
requested_layers_not_present,
|
||||||
requested_extensions_not_present,
|
requested_extensions_not_present,
|
||||||
windowing_extensions_not_present,
|
windowing_extensions_not_present,
|
||||||
};
|
};
|
||||||
enum class PhysicalDeviceError {
|
enum class PhysicalDeviceError {
|
||||||
no_surface_provided,
|
no_surface_provided,
|
||||||
@ -519,11 +519,11 @@ struct Swapchain {
|
|||||||
VkExtent2D extent = { 0, 0 };
|
VkExtent2D extent = { 0, 0 };
|
||||||
VkAllocationCallbacks* allocation_callbacks = VK_NULL_HANDLE;
|
VkAllocationCallbacks* allocation_callbacks = VK_NULL_HANDLE;
|
||||||
|
|
||||||
// Returns a vector of VkImage handles to the swapchain
|
// Returns a vector of VkImage handles to the swapchain.
|
||||||
detail::Result<std::vector<VkImage>> get_images ();
|
detail::Result<std::vector<VkImage>> get_images ();
|
||||||
|
|
||||||
// Returns a vector of VkImageView's to the VkImage's of the swapchain
|
// Returns a vector of VkImageView's to the VkImage's of the swapchain.
|
||||||
// VkImageViews must be destroyed
|
// VkImageViews must be destroyed.
|
||||||
detail::Result<std::vector<VkImageView>> get_image_views ();
|
detail::Result<std::vector<VkImageView>> get_image_views ();
|
||||||
void destroy_image_views (std::vector<VkImageView> const& image_views);
|
void destroy_image_views (std::vector<VkImageView> const& image_views);
|
||||||
};
|
};
|
||||||
@ -536,25 +536,62 @@ class SwapchainBuilder {
|
|||||||
SwapchainBuilder (Device const& device, VkSurfaceKHR const surface);
|
SwapchainBuilder (Device const& device, VkSurfaceKHR const surface);
|
||||||
|
|
||||||
detail::Result<Swapchain> build () const;
|
detail::Result<Swapchain> build () const;
|
||||||
detail::Result<Swapchain> recreate (Swapchain const& swapchain) const;
|
|
||||||
|
|
||||||
|
// Set the oldSwapchain member of VkSwapchainCreateInfoKHR.
|
||||||
|
// For use in rebuilding a swapchain.
|
||||||
|
SwapchainBuilder& set_old_swapchain (VkSwapchainKHR old_swapchain);
|
||||||
|
SwapchainBuilder& set_old_swapchain (Swapchain const& swapchain);
|
||||||
|
|
||||||
|
|
||||||
|
// Desired size of the swapchain. By default, the swapchain will use the size
|
||||||
|
// of the window being drawn to.
|
||||||
SwapchainBuilder& set_desired_extent (uint32_t width, uint32_t height);
|
SwapchainBuilder& set_desired_extent (uint32_t width, uint32_t height);
|
||||||
|
|
||||||
|
// When determining the surface format, make this the first to be used if supported.
|
||||||
SwapchainBuilder& set_desired_format (VkSurfaceFormatKHR format);
|
SwapchainBuilder& set_desired_format (VkSurfaceFormatKHR format);
|
||||||
|
// Add this swapchain format to the end of the list of formats selected from.
|
||||||
SwapchainBuilder& add_fallback_format (VkSurfaceFormatKHR format);
|
SwapchainBuilder& add_fallback_format (VkSurfaceFormatKHR format);
|
||||||
|
// Use the default swapchain formats. This is done if no formats are provided.
|
||||||
SwapchainBuilder& use_default_format_selection ();
|
SwapchainBuilder& use_default_format_selection ();
|
||||||
|
|
||||||
|
// When determining the present mode, make this the first to be used if supported.
|
||||||
SwapchainBuilder& set_desired_present_mode (VkPresentModeKHR present_mode);
|
SwapchainBuilder& set_desired_present_mode (VkPresentModeKHR present_mode);
|
||||||
|
// Add this present mode to the end of the list of present modes selected from.
|
||||||
SwapchainBuilder& add_fallback_present_mode (VkPresentModeKHR present_mode);
|
SwapchainBuilder& add_fallback_present_mode (VkPresentModeKHR present_mode);
|
||||||
|
// Use the default presentation mode. This is done if no present modes are provided.
|
||||||
SwapchainBuilder& use_default_present_mode_selection ();
|
SwapchainBuilder& use_default_present_mode_selection ();
|
||||||
|
|
||||||
SwapchainBuilder& set_image_usage_flags(VkImageUsageFlags usage_flags);
|
// Set the bitmask of the image usage for acquired swapchain images.
|
||||||
SwapchainBuilder& add_image_usage_flags(VkImageUsageFlags usage_flags);
|
SwapchainBuilder& set_image_usage_flags (VkImageUsageFlags usage_flags);
|
||||||
SwapchainBuilder& use_default_image_usage_flags();
|
// Add a image usage to the bitmask for acquired swapchain images.
|
||||||
|
SwapchainBuilder& add_image_usage_flags (VkImageUsageFlags usage_flags);
|
||||||
|
// Use the default image usage bitmask values. This is the default if no image usages
|
||||||
|
// are provided. The default is VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT
|
||||||
|
SwapchainBuilder& use_default_image_usage_flags ();
|
||||||
|
|
||||||
SwapchainBuilder& set_image_array_layer_count(uint32_t array_layer_count = 1);
|
// Set the number of views in for multiview/stereo surface
|
||||||
|
SwapchainBuilder& set_image_array_layer_count (uint32_t array_layer_count);
|
||||||
|
|
||||||
SwapchainBuilder& set_clipped(bool clipped = true);
|
// Set whether the Vulkan implementation is allowed to discard rendering operations that
|
||||||
|
// affect regions of the surface that are not visible. Default is true.
|
||||||
|
// Note: Applications should use the default of true if they do not expect to read back the content
|
||||||
|
// of presentable images before presenting them or after reacquiring them, and if their fragment
|
||||||
|
// shaders do not have any side effects that require them to run for all pixels in the presentable image.
|
||||||
|
SwapchainBuilder& set_clipped (bool clipped = true);
|
||||||
|
|
||||||
|
// Set the VkSwapchainCreateFlagBitsKHR.
|
||||||
|
SwapchainBuilder& set_create_flags (VkSwapchainCreateFlagBitsKHR create_flags);
|
||||||
|
// Set the transform to be applied, like a 90 degree rotation. Default is the current transform.
|
||||||
|
SwapchainBuilder& set_pre_transform_flags (VkSurfaceTransformFlagBitsKHR pre_transform_flags);
|
||||||
|
// Set the alpha channel to be used with other windows in on the system. Default is VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR.
|
||||||
|
SwapchainBuilder& set_composite_alpha_flags (VkCompositeAlphaFlagBitsKHR composite_alpha_flags);
|
||||||
|
|
||||||
|
// Add a structure to the pNext chain of VkSwapchainCreateInfoKHR.
|
||||||
|
// The structure must be valid when SwapchainBuilder::build() is called.
|
||||||
|
template <typename T> SwapchainBuilder& add_pNext (T* structure) {
|
||||||
|
info.pNext_chain.push_back (reinterpret_cast<VkBaseOutStructure*> (structure));
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
// Provide custom allocation callbacks.
|
// Provide custom allocation callbacks.
|
||||||
SwapchainBuilder& set_allocation_callbacks (VkAllocationCallbacks* callbacks);
|
SwapchainBuilder& set_allocation_callbacks (VkAllocationCallbacks* callbacks);
|
||||||
@ -562,24 +599,25 @@ class SwapchainBuilder {
|
|||||||
private:
|
private:
|
||||||
void add_desired_formats (std::vector<VkSurfaceFormatKHR>& formats) const;
|
void add_desired_formats (std::vector<VkSurfaceFormatKHR>& formats) const;
|
||||||
void add_desired_present_modes (std::vector<VkPresentModeKHR>& modes) const;
|
void add_desired_present_modes (std::vector<VkPresentModeKHR>& modes) const;
|
||||||
// for use in swapchain recreation
|
|
||||||
detail::Result<Swapchain> build (VkSwapchainKHR old_swapchain) const;
|
|
||||||
|
|
||||||
struct SwapchainInfo {
|
struct SwapchainInfo {
|
||||||
VkPhysicalDevice physical_device = VK_NULL_HANDLE;
|
VkPhysicalDevice physical_device = VK_NULL_HANDLE;
|
||||||
VkDevice device = VK_NULL_HANDLE;
|
VkDevice device = VK_NULL_HANDLE;
|
||||||
|
std::vector<VkBaseOutStructure*> pNext_chain;
|
||||||
|
VkSwapchainCreateFlagBitsKHR create_flags = static_cast<VkSwapchainCreateFlagBitsKHR> (0);
|
||||||
VkSurfaceKHR surface = VK_NULL_HANDLE;
|
VkSurfaceKHR surface = VK_NULL_HANDLE;
|
||||||
VkSwapchainKHR old_swapchain = VK_NULL_HANDLE;
|
|
||||||
std::vector<VkSurfaceFormatKHR> desired_formats;
|
std::vector<VkSurfaceFormatKHR> desired_formats;
|
||||||
std::vector<VkPresentModeKHR> desired_present_modes;
|
|
||||||
uint32_t desired_width = 256;
|
uint32_t desired_width = 256;
|
||||||
uint32_t desired_height = 256;
|
uint32_t desired_height = 256;
|
||||||
VkImageUsageFlags image_usage_flags = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
|
uint32_t array_layer_count = 1;
|
||||||
uint32_t array_layer_count = 1;
|
VkImageUsageFlags image_usage_flags = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
|
||||||
bool clipped = true;
|
|
||||||
uint32_t graphics_queue_index = 0;
|
uint32_t graphics_queue_index = 0;
|
||||||
uint32_t present_queue_index = 0;
|
uint32_t present_queue_index = 0;
|
||||||
std::vector<VkBaseOutStructure*> pNext_elements;
|
VkSurfaceTransformFlagBitsKHR pre_transform = static_cast<VkSurfaceTransformFlagBitsKHR> (0);
|
||||||
|
VkCompositeAlphaFlagBitsKHR composite_alpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
|
||||||
|
std::vector<VkPresentModeKHR> desired_present_modes;
|
||||||
|
bool clipped = true;
|
||||||
|
VkSwapchainKHR old_swapchain = VK_NULL_HANDLE;
|
||||||
VkAllocationCallbacks* allocation_callbacks = VK_NULL_HANDLE;
|
VkAllocationCallbacks* allocation_callbacks = VK_NULL_HANDLE;
|
||||||
} info;
|
} info;
|
||||||
};
|
};
|
||||||
|
@ -225,6 +225,10 @@ TEST_CASE ("Swapchain", "[VkBootstrap.bootstrap]") {
|
|||||||
swapchain_builder.set_desired_extent (256, 256)
|
swapchain_builder.set_desired_extent (256, 256)
|
||||||
.set_desired_format ({ VK_FORMAT_R8G8B8A8_UNORM, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR })
|
.set_desired_format ({ VK_FORMAT_R8G8B8A8_UNORM, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR })
|
||||||
.set_desired_present_mode (VK_PRESENT_MODE_IMMEDIATE_KHR)
|
.set_desired_present_mode (VK_PRESENT_MODE_IMMEDIATE_KHR)
|
||||||
|
.set_pre_transform_flags (VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR)
|
||||||
|
.set_composite_alpha_flags (VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR)
|
||||||
|
.set_clipped (false)
|
||||||
|
.set_image_array_layer_count (1)
|
||||||
.build ();
|
.build ();
|
||||||
REQUIRE (swapchain_ret.has_value ());
|
REQUIRE (swapchain_ret.has_value ());
|
||||||
|
|
||||||
@ -234,6 +238,7 @@ TEST_CASE ("Swapchain", "[VkBootstrap.bootstrap]") {
|
|||||||
vkb::SwapchainBuilder swapchain_builder (device);
|
vkb::SwapchainBuilder swapchain_builder (device);
|
||||||
auto swapchain_ret = swapchain_builder.use_default_format_selection ()
|
auto swapchain_ret = swapchain_builder.use_default_format_selection ()
|
||||||
.use_default_present_mode_selection ()
|
.use_default_present_mode_selection ()
|
||||||
|
.use_default_image_usage_flags ()
|
||||||
.build ();
|
.build ();
|
||||||
REQUIRE (swapchain_ret.has_value ());
|
REQUIRE (swapchain_ret.has_value ());
|
||||||
|
|
||||||
@ -245,7 +250,8 @@ TEST_CASE ("Swapchain", "[VkBootstrap.bootstrap]") {
|
|||||||
REQUIRE (swapchain_ret.has_value ());
|
REQUIRE (swapchain_ret.has_value ());
|
||||||
|
|
||||||
auto swapchain = swapchain_ret.value ();
|
auto swapchain = swapchain_ret.value ();
|
||||||
auto recreated_swapchain_ret = swapchain_builder.recreate (swapchain);
|
|
||||||
|
auto recreated_swapchain_ret = swapchain_builder.set_old_swapchain (swapchain).build ();
|
||||||
REQUIRE (recreated_swapchain_ret.has_value ());
|
REQUIRE (recreated_swapchain_ret.has_value ());
|
||||||
|
|
||||||
vkb::destroy_swapchain (recreated_swapchain_ret.value ());
|
vkb::destroy_swapchain (recreated_swapchain_ret.value ());
|
||||||
|
Loading…
Reference in New Issue
Block a user