mirror of
https://github.com/charles-lunarg/vk-bootstrap.git
synced 2024-11-22 07: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
|
||||
// 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) {
|
||||
init.window = create_window_glfw ("Vulkan Triangle", false);
|
||||
init.window = create_window_glfw ("Vulkan Triangle", true);
|
||||
|
||||
vkb::InstanceBuilder instance_builder;
|
||||
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 ();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int create_swapchain (Init& init) {
|
||||
vkb::SwapchainBuilder swapchain_builder{ init.device };
|
||||
auto swap_ret =
|
||||
swapchain_builder.use_default_format_selection ().use_default_present_mode_selection ().build ();
|
||||
auto swap_ret = swapchain_builder.use_default_format_selection ()
|
||||
.use_default_present_mode_selection ()
|
||||
.set_old_swapchain (init.swapchain)
|
||||
.build ();
|
||||
if (!swap_ret) {
|
||||
std::cout << swap_ret.error ().message () << "\n";
|
||||
std::cout << swap_ret.error ().message () << " " << swap_ret.vk_result () << "\n";
|
||||
return -1;
|
||||
}
|
||||
init.swapchain = swap_ret.value ();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int get_queues (Init& init, RenderData& data) {
|
||||
auto gq = init.device.get_queue (vkb::QueueType::graphics);
|
||||
if (!gq.has_value ()) {
|
||||
@ -267,23 +274,31 @@ int create_graphics_pipeline (Init& init, RenderData& data) {
|
||||
return -1; // failed to create pipeline layout
|
||||
}
|
||||
|
||||
VkGraphicsPipelineCreateInfo pipelineInfo = {};
|
||||
pipelineInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
|
||||
pipelineInfo.stageCount = 2;
|
||||
pipelineInfo.pStages = shader_stages;
|
||||
pipelineInfo.pVertexInputState = &vertex_input_info;
|
||||
pipelineInfo.pInputAssemblyState = &input_assembly;
|
||||
pipelineInfo.pViewportState = &viewport_state;
|
||||
pipelineInfo.pRasterizationState = &rasterizer;
|
||||
pipelineInfo.pMultisampleState = &multisampling;
|
||||
pipelineInfo.pColorBlendState = &color_blending;
|
||||
pipelineInfo.layout = data.pipeline_layout;
|
||||
pipelineInfo.renderPass = data.render_pass;
|
||||
pipelineInfo.subpass = 0;
|
||||
pipelineInfo.basePipelineHandle = VK_NULL_HANDLE;
|
||||
std::vector<VkDynamicState> dynamic_states = { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR };
|
||||
|
||||
VkPipelineDynamicStateCreateInfo dynamic_info = {};
|
||||
dynamic_info.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
|
||||
dynamic_info.dynamicStateCount = static_cast<uint32_t> (dynamic_states.size ());
|
||||
dynamic_info.pDynamicStates = dynamic_states.data ();
|
||||
|
||||
VkGraphicsPipelineCreateInfo pipeline_info = {};
|
||||
pipeline_info.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
|
||||
pipeline_info.stageCount = 2;
|
||||
pipeline_info.pStages = shader_stages;
|
||||
pipeline_info.pVertexInputState = &vertex_input_info;
|
||||
pipeline_info.pInputAssemblyState = &input_assembly;
|
||||
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 (
|
||||
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";
|
||||
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.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);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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) {
|
||||
vkWaitForFences (init.device.device, 1, &data.in_flight_fences[data.current_frame], VK_TRUE, UINT64_MAX);
|
||||
|
||||
uint32_t image_index = 0;
|
||||
vkAcquireNextImageKHR (init.device.device,
|
||||
VkResult result = vkAcquireNextImageKHR (init.device.device,
|
||||
init.swapchain.swapchain,
|
||||
UINT64_MAX,
|
||||
data.available_semaphores[data.current_frame],
|
||||
VK_NULL_HANDLE,
|
||||
&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) {
|
||||
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;
|
||||
|
||||
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;
|
||||
return 0;
|
||||
@ -475,9 +542,7 @@ void cleanup (Init& init, RenderData& data) {
|
||||
vkDestroyPipelineLayout (init.device.device, data.pipeline_layout, nullptr);
|
||||
vkDestroyRenderPass (init.device.device, data.render_pass, nullptr);
|
||||
|
||||
for (auto imageView : data.swapchain_image_views) {
|
||||
vkDestroyImageView (init.device.device, imageView, nullptr);
|
||||
}
|
||||
init.swapchain.destroy_image_views (data.swapchain_image_views);
|
||||
|
||||
vkb::destroy_swapchain (init.swapchain);
|
||||
vkb::destroy_device (init.device);
|
||||
@ -491,6 +556,7 @@ int main () {
|
||||
RenderData render_data;
|
||||
|
||||
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 != create_render_pass (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);
|
||||
if (present_modes_ret != VK_SUCCESS)
|
||||
return { make_error_code (SurfaceSupportError::failed_enumerate_present_modes), present_modes_ret };
|
||||
|
||||
return SurfaceSupportDetails{ capabilities, formats, present_modes };
|
||||
}
|
||||
|
||||
@ -1291,6 +1292,11 @@ VkExtent2D find_extent (
|
||||
}
|
||||
} // 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) {
|
||||
info.device = device.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 ();
|
||||
}
|
||||
|
||||
detail::Result<Swapchain> SwapchainBuilder::build () const { return build (VK_NULL_HANDLE); }
|
||||
detail::Result<Swapchain> SwapchainBuilder::build (VkSwapchainKHR old_swapchain) const {
|
||||
detail::Result<Swapchain> SwapchainBuilder::build () const {
|
||||
if (info.surface == VK_NULL_HANDLE) {
|
||||
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;
|
||||
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);
|
||||
if (!surface_support.has_value ())
|
||||
auto surface_support_ret = detail::query_surface_support_details (info.physical_device, info.surface);
|
||||
if (!surface_support_ret.has_value ())
|
||||
return detail::Error{ SwapchainError::failed_query_surface_support_details,
|
||||
surface_support.vk_result () };
|
||||
VkSurfaceFormatKHR surface_format =
|
||||
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);
|
||||
surface_support_ret.vk_result () };
|
||||
auto surface_support = surface_support_ret.value ();
|
||||
|
||||
uint32_t imageCount = surface_support.value ().capabilities.minImageCount + 1;
|
||||
if (surface_support.value ().capabilities.maxImageCount > 0 &&
|
||||
imageCount > surface_support.value ().capabilities.maxImageCount) {
|
||||
imageCount = surface_support.value ().capabilities.maxImageCount;
|
||||
uint32_t image_count = surface_support.capabilities.minImageCount + 1;
|
||||
if (surface_support.capabilities.maxImageCount > 0 && image_count > surface_support.capabilities.maxImageCount) {
|
||||
image_count = surface_support.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 = {};
|
||||
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.minImageCount = imageCount;
|
||||
swapchain_create_info.minImageCount = image_count;
|
||||
swapchain_create_info.imageFormat = surface_format.format;
|
||||
swapchain_create_info.imageColorSpace = surface_format.colorSpace;
|
||||
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;
|
||||
|
||||
uint32_t queue_family_indices[] = { 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.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.preTransform = surface_support.value ().capabilities.currentTransform;
|
||||
swapchain_create_info.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
|
||||
swapchain_create_info.preTransform = pre_transform;
|
||||
swapchain_create_info.compositeAlpha = info.composite_alpha;
|
||||
swapchain_create_info.presentMode = present_mode;
|
||||
swapchain_create_info.clipped = info.clipped;
|
||||
swapchain_create_info.oldSwapchain = old_swapchain;
|
||||
swapchain_create_info.oldSwapchain = info.old_swapchain;
|
||||
Swapchain swapchain{};
|
||||
VkResult res = vkCreateSwapchainKHR (
|
||||
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;
|
||||
return swapchain;
|
||||
}
|
||||
detail::Result<Swapchain> SwapchainBuilder::recreate (Swapchain const& swapchain) const {
|
||||
return build (swapchain.swapchain);
|
||||
}
|
||||
detail::Result<std::vector<VkImage>> Swapchain::get_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);
|
||||
}
|
||||
}
|
||||
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::set_old_swapchain (VkSwapchainKHR old_swapchain) {
|
||||
info.old_swapchain = old_swapchain;
|
||||
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) {
|
||||
info.desired_width = width;
|
||||
@ -1451,6 +1469,7 @@ SwapchainBuilder& SwapchainBuilder::add_fallback_format (VkSurfaceFormatKHR form
|
||||
return *this;
|
||||
}
|
||||
SwapchainBuilder& SwapchainBuilder::use_default_format_selection () {
|
||||
info.desired_formats.clear ();
|
||||
add_desired_formats (info.desired_formats);
|
||||
return *this;
|
||||
}
|
||||
@ -1464,6 +1483,7 @@ SwapchainBuilder& SwapchainBuilder::add_fallback_present_mode (VkPresentModeKHR
|
||||
return *this;
|
||||
}
|
||||
SwapchainBuilder& SwapchainBuilder::use_default_present_mode_selection () {
|
||||
info.desired_present_modes.clear ();
|
||||
add_desired_present_modes (info.desired_present_modes);
|
||||
return *this;
|
||||
}
|
||||
@ -1491,6 +1511,18 @@ SwapchainBuilder& SwapchainBuilder::set_clipped (bool clipped) {
|
||||
info.clipped = clipped;
|
||||
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 {
|
||||
formats.push_back ({ VK_FORMAT_B8G8R8A8_SRGB, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR });
|
||||
|
@ -107,7 +107,7 @@ enum class InstanceError {
|
||||
failed_create_debug_messenger,
|
||||
requested_layers_not_present,
|
||||
requested_extensions_not_present,
|
||||
windowing_extensions_not_present,
|
||||
windowing_extensions_not_present,
|
||||
};
|
||||
enum class PhysicalDeviceError {
|
||||
no_surface_provided,
|
||||
@ -519,11 +519,11 @@ struct Swapchain {
|
||||
VkExtent2D extent = { 0, 0 };
|
||||
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 ();
|
||||
|
||||
// Returns a vector of VkImageView's to the VkImage's of the swapchain
|
||||
// VkImageViews must be destroyed
|
||||
// Returns a vector of VkImageView's to the VkImage's of the swapchain.
|
||||
// VkImageViews must be destroyed.
|
||||
detail::Result<std::vector<VkImageView>> get_image_views ();
|
||||
void destroy_image_views (std::vector<VkImageView> const& image_views);
|
||||
};
|
||||
@ -534,27 +534,64 @@ class SwapchainBuilder {
|
||||
public:
|
||||
SwapchainBuilder (Device const& device);
|
||||
SwapchainBuilder (Device const& device, VkSurfaceKHR const surface);
|
||||
|
||||
detail::Result<Swapchain> build () const;
|
||||
detail::Result<Swapchain> recreate (Swapchain const& swapchain) const;
|
||||
|
||||
detail::Result<Swapchain> build () 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);
|
||||
|
||||
// When determining the surface format, make this the first to be used if supported.
|
||||
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);
|
||||
// Use the default swapchain formats. This is done if no formats are provided.
|
||||
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);
|
||||
// Add this present mode to the end of the list of present modes selected from.
|
||||
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& set_image_usage_flags(VkImageUsageFlags usage_flags);
|
||||
SwapchainBuilder& add_image_usage_flags(VkImageUsageFlags usage_flags);
|
||||
SwapchainBuilder& use_default_image_usage_flags();
|
||||
// Set the bitmask of the image usage for acquired swapchain images.
|
||||
SwapchainBuilder& set_image_usage_flags (VkImageUsageFlags 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.
|
||||
SwapchainBuilder& set_allocation_callbacks (VkAllocationCallbacks* callbacks);
|
||||
@ -562,24 +599,25 @@ class SwapchainBuilder {
|
||||
private:
|
||||
void add_desired_formats (std::vector<VkSurfaceFormatKHR>& formats) 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 {
|
||||
VkPhysicalDevice physical_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;
|
||||
VkSwapchainKHR old_swapchain = VK_NULL_HANDLE;
|
||||
std::vector<VkSurfaceFormatKHR> desired_formats;
|
||||
std::vector<VkPresentModeKHR> desired_present_modes;
|
||||
uint32_t desired_width = 256;
|
||||
uint32_t desired_height = 256;
|
||||
VkImageUsageFlags image_usage_flags = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
|
||||
uint32_t array_layer_count = 1;
|
||||
bool clipped = true;
|
||||
uint32_t array_layer_count = 1;
|
||||
VkImageUsageFlags image_usage_flags = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
|
||||
uint32_t graphics_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;
|
||||
} info;
|
||||
};
|
||||
|
@ -225,6 +225,10 @@ TEST_CASE ("Swapchain", "[VkBootstrap.bootstrap]") {
|
||||
swapchain_builder.set_desired_extent (256, 256)
|
||||
.set_desired_format ({ VK_FORMAT_R8G8B8A8_UNORM, VK_COLOR_SPACE_SRGB_NONLINEAR_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 ();
|
||||
REQUIRE (swapchain_ret.has_value ());
|
||||
|
||||
@ -234,6 +238,7 @@ TEST_CASE ("Swapchain", "[VkBootstrap.bootstrap]") {
|
||||
vkb::SwapchainBuilder swapchain_builder (device);
|
||||
auto swapchain_ret = swapchain_builder.use_default_format_selection ()
|
||||
.use_default_present_mode_selection ()
|
||||
.use_default_image_usage_flags ()
|
||||
.build ();
|
||||
REQUIRE (swapchain_ret.has_value ());
|
||||
|
||||
@ -245,7 +250,8 @@ TEST_CASE ("Swapchain", "[VkBootstrap.bootstrap]") {
|
||||
REQUIRE (swapchain_ret.has_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 ());
|
||||
|
||||
vkb::destroy_swapchain (recreated_swapchain_ret.value ());
|
||||
|
Loading…
Reference in New Issue
Block a user