Added optional dispatch table usage to swapchain.

This commit is contained in:
Cody Goodson 2021-06-07 00:05:59 -05:00 committed by Charles Giessen
parent 87a63e942c
commit f5d3061043
3 changed files with 52 additions and 7 deletions

View File

@ -1619,8 +1619,9 @@ VkExtent2D find_extent(VkSurfaceCapabilitiesKHR const& capabilities, uint32_t de
void destroy_swapchain(Swapchain const& swapchain) {
if (swapchain.device != VK_NULL_HANDLE && swapchain.swapchain != VK_NULL_HANDLE) {
detail::vulkan_functions().fp_vkDestroySwapchainKHR(
swapchain.device, swapchain.swapchain, swapchain.allocation_callbacks);
/*detail::vulkan_functions().fp_vkDestroySwapchainKHR(
swapchain.device, swapchain.swapchain, swapchain.allocation_callbacks);*/
swapchain.internal_table.fp_vkDestroySwapchainKHR(swapchain.device, swapchain.swapchain, swapchain.allocation_callbacks);
}
}
@ -1737,14 +1738,31 @@ detail::Result<Swapchain> SwapchainBuilder::build() const {
swapchain_create_info.clipped = info.clipped;
swapchain_create_info.oldSwapchain = info.old_swapchain;
Swapchain swapchain{};
VkResult res = detail::vulkan_functions().fp_vkCreateSwapchainKHR(
VkResult res;
if(info.dispatch_table != nullptr) {
assert(info.dispatch_table->device == info.device);
res = info.dispatch_table->createSwapchainKHR(&swapchain_create_info, info.allocation_callbacks, &swapchain.swapchain);
} else {
res = detail::vulkan_functions().fp_vkCreateSwapchainKHR(
info.device, &swapchain_create_info, info.allocation_callbacks, &swapchain.swapchain);
}
if (res != VK_SUCCESS) {
return detail::Error{ SwapchainError::failed_create_swapchain, res };
}
swapchain.device = info.device;
swapchain.image_format = surface_format.format;
swapchain.extent = extent;
if(info.dispatch_table != nullptr) {
swapchain.internal_table.fp_vkGetSwapchainImagesKHR = info.dispatch_table->fp_vkGetSwapchainImagesKHR;
swapchain.internal_table.fp_vkCreateImageView = info.dispatch_table->fp_vkCreateImageView;
swapchain.internal_table.fp_vkDestroyImageView = info.dispatch_table->fp_vkDestroyImageView;
swapchain.internal_table.fp_vkDestroySwapchainKHR = info.dispatch_table->fp_vkDestroySwapchainKHR;
} else {
swapchain.internal_table.fp_vkGetSwapchainImagesKHR = detail::vulkan_functions().fp_vkGetSwapchainImagesKHR;
swapchain.internal_table.fp_vkCreateImageView = detail::vulkan_functions().fp_vkCreateImageView;
swapchain.internal_table.fp_vkDestroyImageView = detail::vulkan_functions().fp_vkDestroyImageView;
swapchain.internal_table.fp_vkDestroySwapchainKHR = detail::vulkan_functions().fp_vkDestroySwapchainKHR;
}
auto images = swapchain.get_images();
if (!images) {
return detail::Error{ SwapchainError::failed_get_swapchain_images };
@ -1787,8 +1805,9 @@ detail::Result<std::vector<VkImageView>> Swapchain::get_image_views() {
createInfo.subresourceRange.baseArrayLayer = 0;
createInfo.subresourceRange.layerCount = 1;
VkResult res = detail::vulkan_functions().fp_vkCreateImageView(
device, &createInfo, allocation_callbacks, &views[i]);
/*VkResult res = detail::vulkan_functions().fp_vkCreateImageView(
device, &createInfo, allocation_callbacks, &views[i]);*/
VkResult res = internal_table.fp_vkCreateImageView(device, &createInfo, allocation_callbacks, &views[i]);
if (res != VK_SUCCESS)
return detail::Error{ SwapchainError::failed_create_swapchain_image_views, res };
}
@ -1796,7 +1815,7 @@ detail::Result<std::vector<VkImageView>> Swapchain::get_image_views() {
}
void Swapchain::destroy_image_views(std::vector<VkImageView> const& image_views) {
for (auto& image_view : image_views) {
detail::vulkan_functions().fp_vkDestroyImageView(device, image_view, allocation_callbacks);
internal_table.fp_vkDestroyImageView(device, image_view, allocation_callbacks);
}
}
SwapchainBuilder& SwapchainBuilder::set_old_swapchain(VkSwapchainKHR old_swapchain) {
@ -1843,6 +1862,10 @@ SwapchainBuilder& SwapchainBuilder::set_allocation_callbacks(VkAllocationCallbac
info.allocation_callbacks = callbacks;
return *this;
}
SwapchainBuilder& SwapchainBuilder::use_dispatch_table(DispatchTable& dispatch_table) {
info.dispatch_table = &dispatch_table;
return *this;
}
SwapchainBuilder& SwapchainBuilder::set_image_usage_flags(VkImageUsageFlags usage_flags) {
info.image_usage_flags = usage_flags;
return *this;

View File

@ -615,6 +615,15 @@ struct Swapchain {
// VkImageViews must be destroyed.
detail::Result<std::vector<VkImageView>> get_image_views();
void destroy_image_views(std::vector<VkImageView> const& image_views);
private:
struct {
PFN_vkGetSwapchainImagesKHR fp_vkGetSwapchainImagesKHR = nullptr;
PFN_vkCreateImageView fp_vkCreateImageView = nullptr;
PFN_vkDestroyImageView fp_vkDestroyImageView = nullptr;
PFN_vkDestroySwapchainKHR fp_vkDestroySwapchainKHR = nullptr;
} internal_table;
friend class SwapchainBuilder;
friend void destroy_swapchain(Swapchain const& swapchain);
};
void destroy_swapchain(Swapchain const& swapchain);
@ -705,6 +714,9 @@ class SwapchainBuilder {
// Provide custom allocation callbacks.
SwapchainBuilder& set_allocation_callbacks(VkAllocationCallbacks* callbacks);
// Provide an optional dispatch table for the builder to use for device pfn's
SwapchainBuilder& use_dispatch_table(DispatchTable& dispatch_table);
private:
void add_desired_formats(std::vector<VkSurfaceFormatKHR>& formats) const;
void add_desired_present_modes(std::vector<VkPresentModeKHR>& modes) const;
@ -729,6 +741,7 @@ class SwapchainBuilder {
bool clipped = true;
VkSwapchainKHR old_swapchain = VK_NULL_HANDLE;
VkAllocationCallbacks* allocation_callbacks = VK_NULL_HANDLE;
DispatchTable* dispatch_table = nullptr;
} info;
};

View File

@ -322,6 +322,15 @@ TEST_CASE("Swapchain", "[VkBootstrap.bootstrap]") {
vkb::destroy_swapchain(recreated_swapchain_ret.value());
}
AND_THEN("Swapchain can be created with a dispatch table") {
vkb::DispatchTable dispatch_table = device.make_table();
vkb::SwapchainBuilder swapchain_builder(
device.physical_device.physical_device, device.device, surface);
auto swapchain_ret = swapchain_builder.use_dispatch_table(dispatch_table).build();
REQUIRE(swapchain_ret.has_value());
vkb::destroy_swapchain(swapchain_ret.value());
}
vkb::destroy_device(device_ret.value());
vkb::destroy_surface(instance_ret.value(), surface);