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 provider = static_cast<VulkanProvider*>(provider_);
|
||||||
auto device = provider->device();
|
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.
|
// Acquire the next image and set it up for use.
|
||||||
swap_chain_->Begin();
|
swap_chain_->Begin();
|
||||||
|
|
||||||
|
|
|
@ -32,31 +32,7 @@ namespace vulkan {
|
||||||
VulkanSwapChain::VulkanSwapChain(VulkanInstance* instance, VulkanDevice* device)
|
VulkanSwapChain::VulkanSwapChain(VulkanInstance* instance, VulkanDevice* device)
|
||||||
: instance_(instance), device_(device) {}
|
: instance_(instance), device_(device) {}
|
||||||
|
|
||||||
VulkanSwapChain::~VulkanSwapChain() {
|
VulkanSwapChain::~VulkanSwapChain() { Shutdown(); }
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool VulkanSwapChain::Initialize(VkSurfaceKHR surface) {
|
bool VulkanSwapChain::Initialize(VkSurfaceKHR surface) {
|
||||||
surface_ = surface;
|
surface_ = surface;
|
||||||
|
@ -338,6 +314,47 @@ void VulkanSwapChain::DestroyBuffer(Buffer* buffer) {
|
||||||
buffer->image = nullptr;
|
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() {
|
bool VulkanSwapChain::Begin() {
|
||||||
// Get the index of the next available swapchain image.
|
// Get the index of the next available swapchain image.
|
||||||
auto err =
|
auto err =
|
||||||
|
|
|
@ -41,7 +41,12 @@ class VulkanSwapChain {
|
||||||
// Render command buffer, active inside the render pass from Begin to End.
|
// Render command buffer, active inside the render pass from Begin to End.
|
||||||
VkCommandBuffer render_cmd_buffer() const { return render_cmd_buffer_; }
|
VkCommandBuffer render_cmd_buffer() const { return render_cmd_buffer_; }
|
||||||
|
|
||||||
|
// Initializes the swap chain with the given WSI surface.
|
||||||
bool Initialize(VkSurfaceKHR 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.
|
// Begins the swap operation, preparing state for rendering.
|
||||||
bool Begin();
|
bool Begin();
|
||||||
|
@ -58,6 +63,9 @@ class VulkanSwapChain {
|
||||||
bool InitializeBuffer(Buffer* buffer, VkImage target_image);
|
bool InitializeBuffer(Buffer* buffer, VkImage target_image);
|
||||||
void DestroyBuffer(Buffer* buffer);
|
void DestroyBuffer(Buffer* buffer);
|
||||||
|
|
||||||
|
// Safely releases all swap chain resources.
|
||||||
|
void Shutdown();
|
||||||
|
|
||||||
VulkanInstance* instance_ = nullptr;
|
VulkanInstance* instance_ = nullptr;
|
||||||
VulkanDevice* device_ = nullptr;
|
VulkanDevice* device_ = nullptr;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue