Recreate swap chain on window resize.
This commit is contained in:
parent
a97fa36512
commit
ca5902c111
|
@ -115,6 +115,17 @@ void VulkanContext::BeginSwap() {
|
|||
auto provider = static_cast<VulkanProvider*>(provider_);
|
||||
auto device = provider->device();
|
||||
|
||||
// If we have a window see if it's been resized since we last swapped.
|
||||
// If it has been, we'll need to reinitialize the swap chain before we
|
||||
// start touching it.
|
||||
if (target_window_) {
|
||||
if (target_window_->width() != swap_chain_->surface_width() ||
|
||||
target_window_->height() != swap_chain_->surface_height()) {
|
||||
// Resized!
|
||||
swap_chain_->Reinitialize();
|
||||
}
|
||||
}
|
||||
|
||||
// Acquire the next image and set it up for use.
|
||||
swap_chain_->Begin();
|
||||
|
||||
|
|
|
@ -32,31 +32,7 @@ namespace vulkan {
|
|||
VulkanSwapChain::VulkanSwapChain(VulkanInstance* instance, VulkanDevice* device)
|
||||
: instance_(instance), device_(device) {}
|
||||
|
||||
VulkanSwapChain::~VulkanSwapChain() {
|
||||
for (auto& buffer : buffers_) {
|
||||
DestroyBuffer(&buffer);
|
||||
}
|
||||
if (image_available_semaphore_) {
|
||||
vkDestroySemaphore(*device_, image_available_semaphore_, nullptr);
|
||||
}
|
||||
if (render_pass_) {
|
||||
vkDestroyRenderPass(*device_, render_pass_, nullptr);
|
||||
}
|
||||
if (render_cmd_buffer_) {
|
||||
vkFreeCommandBuffers(*device_, cmd_pool_, 1, &render_cmd_buffer_);
|
||||
}
|
||||
if (cmd_pool_) {
|
||||
vkDestroyCommandPool(*device_, cmd_pool_, nullptr);
|
||||
}
|
||||
// images_ doesn't need to be cleaned up as the swapchain does it implicitly.
|
||||
if (handle) {
|
||||
vkDestroySwapchainKHR(*device_, handle, nullptr);
|
||||
handle = nullptr;
|
||||
}
|
||||
if (surface_) {
|
||||
vkDestroySurfaceKHR(*instance_, surface_, nullptr);
|
||||
}
|
||||
}
|
||||
VulkanSwapChain::~VulkanSwapChain() { Shutdown(); }
|
||||
|
||||
bool VulkanSwapChain::Initialize(VkSurfaceKHR surface) {
|
||||
surface_ = surface;
|
||||
|
@ -338,6 +314,47 @@ void VulkanSwapChain::DestroyBuffer(Buffer* buffer) {
|
|||
buffer->image = nullptr;
|
||||
}
|
||||
|
||||
bool VulkanSwapChain::Reinitialize() {
|
||||
// Hacky, but stash the surface so we can reuse it.
|
||||
auto surface = surface_;
|
||||
surface_ = nullptr;
|
||||
Shutdown();
|
||||
return Initialize(surface);
|
||||
}
|
||||
|
||||
void VulkanSwapChain::Shutdown() {
|
||||
// TODO(benvanik): properly wait for a clean state.
|
||||
for (auto& buffer : buffers_) {
|
||||
DestroyBuffer(&buffer);
|
||||
}
|
||||
buffers_.clear();
|
||||
if (image_available_semaphore_) {
|
||||
vkDestroySemaphore(*device_, image_available_semaphore_, nullptr);
|
||||
image_available_semaphore_ = nullptr;
|
||||
}
|
||||
if (render_pass_) {
|
||||
vkDestroyRenderPass(*device_, render_pass_, nullptr);
|
||||
render_pass_ = nullptr;
|
||||
}
|
||||
if (render_cmd_buffer_) {
|
||||
vkFreeCommandBuffers(*device_, cmd_pool_, 1, &render_cmd_buffer_);
|
||||
render_cmd_buffer_ = nullptr;
|
||||
}
|
||||
if (cmd_pool_) {
|
||||
vkDestroyCommandPool(*device_, cmd_pool_, nullptr);
|
||||
cmd_pool_ = nullptr;
|
||||
}
|
||||
// images_ doesn't need to be cleaned up as the swapchain does it implicitly.
|
||||
if (handle) {
|
||||
vkDestroySwapchainKHR(*device_, handle, nullptr);
|
||||
handle = nullptr;
|
||||
}
|
||||
if (surface_) {
|
||||
vkDestroySurfaceKHR(*instance_, surface_, nullptr);
|
||||
surface_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
bool VulkanSwapChain::Begin() {
|
||||
// Get the index of the next available swapchain image.
|
||||
auto err =
|
||||
|
|
|
@ -41,7 +41,12 @@ class VulkanSwapChain {
|
|||
// Render command buffer, active inside the render pass from Begin to End.
|
||||
VkCommandBuffer render_cmd_buffer() const { return render_cmd_buffer_; }
|
||||
|
||||
// Initializes the swap chain with the given WSI surface.
|
||||
bool Initialize(VkSurfaceKHR surface);
|
||||
// Reinitializes the swap chain with the initial surface.
|
||||
// The surface will be retained but all other swap chain resources will be
|
||||
// torn down and recreated with the new surface properties (size/etc).
|
||||
bool Reinitialize();
|
||||
|
||||
// Begins the swap operation, preparing state for rendering.
|
||||
bool Begin();
|
||||
|
@ -58,6 +63,9 @@ class VulkanSwapChain {
|
|||
bool InitializeBuffer(Buffer* buffer, VkImage target_image);
|
||||
void DestroyBuffer(Buffer* buffer);
|
||||
|
||||
// Safely releases all swap chain resources.
|
||||
void Shutdown();
|
||||
|
||||
VulkanInstance* instance_ = nullptr;
|
||||
VulkanDevice* device_ = nullptr;
|
||||
|
||||
|
|
Loading…
Reference in New Issue