Vulkan: Move swapchain related members from Renderer to SwapChain

This commit is contained in:
Stenzek 2019-01-27 12:59:57 +10:00
parent bd66db049a
commit e2cf238ec4
4 changed files with 85 additions and 94 deletions

View File

@ -76,35 +76,12 @@ bool Renderer::Initialize()
BindEFBToStateTracker(); BindEFBToStateTracker();
if (!CreateSemaphores())
{
PanicAlert("Failed to create semaphores.");
return false;
}
if (!CompileShaders()) if (!CompileShaders())
{ {
PanicAlert("Failed to compile shaders."); PanicAlert("Failed to compile shaders.");
return false; return false;
} }
// Swap chain render pass.
if (m_swap_chain)
{
m_swap_chain_render_pass =
g_object_cache->GetRenderPass(m_swap_chain->GetSurfaceFormat().format, VK_FORMAT_UNDEFINED,
1, VK_ATTACHMENT_LOAD_OP_LOAD);
m_swap_chain_clear_render_pass =
g_object_cache->GetRenderPass(m_swap_chain->GetSurfaceFormat().format, VK_FORMAT_UNDEFINED,
1, VK_ATTACHMENT_LOAD_OP_CLEAR);
if (m_swap_chain_render_pass == VK_NULL_HANDLE ||
m_swap_chain_clear_render_pass == VK_NULL_HANDLE)
{
PanicAlert("Failed to create swap chain render passes.");
return false;
}
}
m_bounding_box = std::make_unique<BoundingBox>(); m_bounding_box = std::make_unique<BoundingBox>();
if (!m_bounding_box->Initialize()) if (!m_bounding_box->Initialize())
{ {
@ -142,45 +119,6 @@ void Renderer::Shutdown()
::Renderer::Shutdown(); ::Renderer::Shutdown();
DestroyShaders(); DestroyShaders();
DestroySemaphores();
}
bool Renderer::CreateSemaphores()
{
// Create two semaphores, one that is triggered when the swapchain buffer is ready, another after
// submit and before present
VkSemaphoreCreateInfo semaphore_info = {
VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO, // VkStructureType sType
nullptr, // const void* pNext
0 // VkSemaphoreCreateFlags flags
};
VkResult res;
if ((res = vkCreateSemaphore(g_vulkan_context->GetDevice(), &semaphore_info, nullptr,
&m_image_available_semaphore)) != VK_SUCCESS ||
(res = vkCreateSemaphore(g_vulkan_context->GetDevice(), &semaphore_info, nullptr,
&m_rendering_finished_semaphore)) != VK_SUCCESS)
{
LOG_VULKAN_ERROR(res, "vkCreateSemaphore failed: ");
return false;
}
return true;
}
void Renderer::DestroySemaphores()
{
if (m_image_available_semaphore)
{
vkDestroySemaphore(g_vulkan_context->GetDevice(), m_image_available_semaphore, nullptr);
m_image_available_semaphore = VK_NULL_HANDLE;
}
if (m_rendering_finished_semaphore)
{
vkDestroySemaphore(g_vulkan_context->GetDevice(), m_rendering_finished_semaphore, nullptr);
m_rendering_finished_semaphore = VK_NULL_HANDLE;
}
} }
std::unique_ptr<AbstractTexture> Renderer::CreateTexture(const TextureConfig& config) std::unique_ptr<AbstractTexture> Renderer::CreateTexture(const TextureConfig& config)
@ -553,7 +491,7 @@ void Renderer::BindBackbuffer(const ClearColor& clear_color)
if (!g_command_buffer_mgr->CheckLastPresentFail()) if (!g_command_buffer_mgr->CheckLastPresentFail())
{ {
// Grab the next image from the swap chain in preparation for drawing the window. // Grab the next image from the swap chain in preparation for drawing the window.
res = m_swap_chain->AcquireNextImage(m_image_available_semaphore); res = m_swap_chain->AcquireNextImage();
} }
else else
{ {
@ -573,7 +511,7 @@ void Renderer::BindBackbuffer(const ClearColor& clear_color)
m_swap_chain->ResizeSwapChain(); m_swap_chain->ResizeSwapChain();
BeginFrame(); BeginFrame();
g_command_buffer_mgr->PrepareToSubmitCommandBuffer(); g_command_buffer_mgr->PrepareToSubmitCommandBuffer();
res = m_swap_chain->AcquireNextImage(m_image_available_semaphore); res = m_swap_chain->AcquireNextImage();
} }
if (res != VK_SUCCESS) if (res != VK_SUCCESS)
PanicAlert("Failed to grab image from swap chain"); PanicAlert("Failed to grab image from swap chain");
@ -591,8 +529,8 @@ void Renderer::BindBackbuffer(const ClearColor& clear_color)
// Draw to the backbuffer. // Draw to the backbuffer.
VkRect2D region = {{0, 0}, {backbuffer->GetWidth(), backbuffer->GetHeight()}}; VkRect2D region = {{0, 0}, {backbuffer->GetWidth(), backbuffer->GetHeight()}};
StateTracker::GetInstance()->SetRenderPass(m_swap_chain_render_pass, StateTracker::GetInstance()->SetRenderPass(m_swap_chain->GetLoadRenderPass(),
m_swap_chain_clear_render_pass); m_swap_chain->GetClearRenderPass());
StateTracker::GetInstance()->SetFramebuffer(m_swap_chain->GetCurrentFramebuffer(), region); StateTracker::GetInstance()->SetFramebuffer(m_swap_chain->GetCurrentFramebuffer(), region);
// Begin render pass for rendering to the swap chain. // Begin render pass for rendering to the swap chain.
@ -608,18 +546,17 @@ void Renderer::PresentBackbuffer()
// Transition the backbuffer to PRESENT_SRC to ensure all commands drawing // Transition the backbuffer to PRESENT_SRC to ensure all commands drawing
// to it have finished before present. // to it have finished before present.
Texture2D* backbuffer = m_swap_chain->GetCurrentTexture(); m_swap_chain->GetCurrentTexture()->TransitionToLayout(
backbuffer->TransitionToLayout(g_command_buffer_mgr->GetCurrentCommandBuffer(), g_command_buffer_mgr->GetCurrentCommandBuffer(), VK_IMAGE_LAYOUT_PRESENT_SRC_KHR);
VK_IMAGE_LAYOUT_PRESENT_SRC_KHR);
// Submit the current command buffer, signaling rendering finished semaphore when it's done // Submit the current command buffer, signaling rendering finished semaphore when it's done
// Because this final command buffer is rendering to the swap chain, we need to wait for // Because this final command buffer is rendering to the swap chain, we need to wait for
// the available semaphore to be signaled before executing the buffer. This final submission // the available semaphore to be signaled before executing the buffer. This final submission
// can happen off-thread in the background while we're preparing the next frame. // can happen off-thread in the background while we're preparing the next frame.
g_command_buffer_mgr->SubmitCommandBuffer( g_command_buffer_mgr->SubmitCommandBuffer(true, m_swap_chain->GetImageAvailableSemaphore(),
true, m_image_available_semaphore, m_rendering_finished_semaphore, m_swap_chain->GetRenderingFinishedSemaphore(),
m_swap_chain->GetSwapChain(), m_swap_chain->GetCurrentImageIndex()); m_swap_chain->GetSwapChain(),
m_swap_chain->GetCurrentImageIndex());
BeginFrame(); BeginFrame();
} }
@ -637,22 +574,22 @@ void Renderer::RenderXFBToScreen(const AbstractTexture* texture, const EFBRectan
post_processor->BlitFromTexture(left_rect, rc, post_processor->BlitFromTexture(left_rect, rc,
static_cast<const VKTexture*>(texture)->GetRawTexIdentifier(), static_cast<const VKTexture*>(texture)->GetRawTexIdentifier(),
0, m_swap_chain_render_pass); 0, m_swap_chain->GetLoadRenderPass());
post_processor->BlitFromTexture(right_rect, rc, post_processor->BlitFromTexture(right_rect, rc,
static_cast<const VKTexture*>(texture)->GetRawTexIdentifier(), static_cast<const VKTexture*>(texture)->GetRawTexIdentifier(),
1, m_swap_chain_render_pass); 1, m_swap_chain->GetLoadRenderPass());
} }
else if (g_ActiveConfig.stereo_mode == StereoMode::QuadBuffer) else if (g_ActiveConfig.stereo_mode == StereoMode::QuadBuffer)
{ {
post_processor->BlitFromTexture(target_rc, rc, post_processor->BlitFromTexture(target_rc, rc,
static_cast<const VKTexture*>(texture)->GetRawTexIdentifier(), static_cast<const VKTexture*>(texture)->GetRawTexIdentifier(),
-1, m_swap_chain_render_pass); -1, m_swap_chain->GetLoadRenderPass());
} }
else else
{ {
post_processor->BlitFromTexture(target_rc, rc, post_processor->BlitFromTexture(target_rc, rc,
static_cast<const VKTexture*>(texture)->GetRawTexIdentifier(), static_cast<const VKTexture*>(texture)->GetRawTexIdentifier(),
0, m_swap_chain_render_pass); 0, m_swap_chain->GetLoadRenderPass());
} }
// The post-processor uses the old-style Vulkan draws, which mess with the tracked state. // The post-processor uses the old-style Vulkan draws, which mess with the tracked state.

View File

@ -92,9 +92,6 @@ public:
void PresentBackbuffer() override; void PresentBackbuffer() override;
private: private:
bool CreateSemaphores();
void DestroySemaphores();
void BeginFrame(); void BeginFrame();
void CheckForSurfaceChange(); void CheckForSurfaceChange();
@ -111,11 +108,6 @@ private:
bool CompileShaders(); bool CompileShaders();
void DestroyShaders(); void DestroyShaders();
VkSemaphore m_image_available_semaphore = VK_NULL_HANDLE;
VkSemaphore m_rendering_finished_semaphore = VK_NULL_HANDLE;
VkRenderPass m_swap_chain_render_pass = VK_NULL_HANDLE;
VkRenderPass m_swap_chain_clear_render_pass = VK_NULL_HANDLE;
std::unique_ptr<SwapChain> m_swap_chain; std::unique_ptr<SwapChain> m_swap_chain;
std::unique_ptr<BoundingBox> m_bounding_box; std::unique_ptr<BoundingBox> m_bounding_box;

View File

@ -36,6 +36,7 @@ SwapChain::~SwapChain()
DestroySwapChainImages(); DestroySwapChainImages();
DestroySwapChain(); DestroySwapChain();
DestroySurface(); DestroySurface();
DestroySemaphores();
} }
VkSurfaceKHR SwapChain::CreateVulkanSurface(VkInstance instance, void* display_handle, void* hwnd) VkSurfaceKHR SwapChain::CreateVulkanSurface(VkInstance instance, void* display_handle, void* hwnd)
@ -142,12 +143,53 @@ std::unique_ptr<SwapChain> SwapChain::Create(void* display_handle, void* native_
std::unique_ptr<SwapChain> swap_chain = std::unique_ptr<SwapChain> swap_chain =
std::make_unique<SwapChain>(display_handle, native_handle, surface, vsync); std::make_unique<SwapChain>(display_handle, native_handle, surface, vsync);
if (!swap_chain->CreateSwapChain() || !swap_chain->SetupSwapChainImages()) if (!swap_chain->CreateSemaphores() || !swap_chain->CreateSwapChain() ||
!swap_chain->SetupSwapChainImages())
{
return nullptr; return nullptr;
}
return swap_chain; return swap_chain;
} }
bool SwapChain::CreateSemaphores()
{
// Create two semaphores, one that is triggered when the swapchain buffer is ready, another after
// submit and before present
VkSemaphoreCreateInfo semaphore_info = {
VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO, // VkStructureType sType
nullptr, // const void* pNext
0 // VkSemaphoreCreateFlags flags
};
VkResult res;
if ((res = vkCreateSemaphore(g_vulkan_context->GetDevice(), &semaphore_info, nullptr,
&m_image_available_semaphore)) != VK_SUCCESS ||
(res = vkCreateSemaphore(g_vulkan_context->GetDevice(), &semaphore_info, nullptr,
&m_rendering_finished_semaphore)) != VK_SUCCESS)
{
LOG_VULKAN_ERROR(res, "vkCreateSemaphore failed: ");
return false;
}
return true;
}
void SwapChain::DestroySemaphores()
{
if (m_image_available_semaphore)
{
vkDestroySemaphore(g_vulkan_context->GetDevice(), m_image_available_semaphore, nullptr);
m_image_available_semaphore = VK_NULL_HANDLE;
}
if (m_rendering_finished_semaphore)
{
vkDestroySemaphore(g_vulkan_context->GetDevice(), m_rendering_finished_semaphore, nullptr);
m_rendering_finished_semaphore = VK_NULL_HANDLE;
}
}
bool SwapChain::SelectSurfaceFormat() bool SwapChain::SelectSurfaceFormat()
{ {
u32 format_count; u32 format_count;
@ -370,8 +412,15 @@ bool SwapChain::SetupSwapChainImages()
images.data()); images.data());
ASSERT(res == VK_SUCCESS); ASSERT(res == VK_SUCCESS);
VkRenderPass render_pass = g_object_cache->GetRenderPass( m_render_pass = g_object_cache->GetRenderPass(m_surface_format.format, VK_FORMAT_UNDEFINED, 1,
m_surface_format.format, VK_FORMAT_UNDEFINED, 1, VK_ATTACHMENT_LOAD_OP_CLEAR); VK_ATTACHMENT_LOAD_OP_LOAD);
m_clear_render_pass = g_object_cache->GetRenderPass(m_surface_format.format, VK_FORMAT_UNDEFINED,
1, VK_ATTACHMENT_LOAD_OP_CLEAR);
if (m_render_pass == VK_NULL_HANDLE || m_clear_render_pass == VK_NULL_HANDLE)
{
PanicAlert("Failed to get swap chain render passes.");
return false;
}
m_swap_chain_images.reserve(image_count); m_swap_chain_images.reserve(image_count);
for (uint32_t i = 0; i < image_count; i++) for (uint32_t i = 0; i < image_count; i++)
@ -388,7 +437,7 @@ bool SwapChain::SetupSwapChainImages()
VkFramebufferCreateInfo framebuffer_info = {VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, VkFramebufferCreateInfo framebuffer_info = {VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
nullptr, nullptr,
0, 0,
render_pass, m_render_pass,
1, 1,
&view, &view,
m_width, m_width,
@ -428,11 +477,11 @@ void SwapChain::DestroySwapChain()
m_swap_chain = VK_NULL_HANDLE; m_swap_chain = VK_NULL_HANDLE;
} }
VkResult SwapChain::AcquireNextImage(VkSemaphore available_semaphore) VkResult SwapChain::AcquireNextImage()
{ {
VkResult res = VkResult res = vkAcquireNextImageKHR(g_vulkan_context->GetDevice(), m_swap_chain, UINT64_MAX,
vkAcquireNextImageKHR(g_vulkan_context->GetDevice(), m_swap_chain, UINT64_MAX, m_image_available_semaphore, VK_NULL_HANDLE,
available_semaphore, VK_NULL_HANDLE, &m_current_swap_chain_image_index); &m_current_swap_chain_image_index);
if (res != VK_SUCCESS && res != VK_ERROR_OUT_OF_DATE_KHR && res != VK_SUBOPTIMAL_KHR) if (res != VK_SUCCESS && res != VK_ERROR_OUT_OF_DATE_KHR && res != VK_SUBOPTIMAL_KHR)
LOG_VULKAN_ERROR(res, "vkAcquireNextImageKHR failed: "); LOG_VULKAN_ERROR(res, "vkAcquireNextImageKHR failed: ");

View File

@ -53,8 +53,12 @@ public:
{ {
return m_swap_chain_images[m_current_swap_chain_image_index].framebuffer; return m_swap_chain_images[m_current_swap_chain_image_index].framebuffer;
} }
VkRenderPass GetLoadRenderPass() const { return m_render_pass; }
VkRenderPass GetClearRenderPass() const { return m_clear_render_pass; }
VkSemaphore GetImageAvailableSemaphore() const { return m_image_available_semaphore; }
VkSemaphore GetRenderingFinishedSemaphore() const { return m_rendering_finished_semaphore; }
VkResult AcquireNextImage(VkSemaphore available_semaphore); VkResult AcquireNextImage();
bool RecreateSurface(void* native_handle); bool RecreateSurface(void* native_handle);
bool ResizeSwapChain(); bool ResizeSwapChain();
@ -64,6 +68,9 @@ public:
bool SetVSync(bool enabled); bool SetVSync(bool enabled);
private: private:
bool CreateSemaphores();
void DestroySemaphores();
bool SelectSurfaceFormat(); bool SelectSurfaceFormat();
bool SelectPresentMode(); bool SelectPresentMode();
@ -94,6 +101,12 @@ private:
std::vector<SwapChainImage> m_swap_chain_images; std::vector<SwapChainImage> m_swap_chain_images;
u32 m_current_swap_chain_image_index = 0; u32 m_current_swap_chain_image_index = 0;
VkSemaphore m_image_available_semaphore = VK_NULL_HANDLE;
VkSemaphore m_rendering_finished_semaphore = VK_NULL_HANDLE;
VkRenderPass m_render_pass = VK_NULL_HANDLE;
VkRenderPass m_clear_render_pass = VK_NULL_HANDLE;
u32 m_width = 0; u32 m_width = 0;
u32 m_height = 0; u32 m_height = 0;
u32 m_layers = 0; u32 m_layers = 0;