Skip to content

Commit 1706075

Browse files
Vulkan: Several swapchain fixes and refactors (#1132)
1 parent 4d609f0 commit 1706075

File tree

4 files changed

+99
-84
lines changed

4 files changed

+99
-84
lines changed

src/Cafe/HW/Latte/Renderer/Vulkan/SwapchainInfoVk.cpp

+41-50
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,34 @@
11
#include "SwapchainInfoVk.h"
22

33
#include "config/CemuConfig.h"
4+
#include "gui/guiWrapper.h"
45
#include "Cafe/HW/Latte/Core/Latte.h"
56
#include "Cafe/HW/Latte/Core/LatteTiming.h"
67
#include "Cafe/HW/Latte/Renderer/Vulkan/VulkanAPI.h"
8+
#include "Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.h"
79

8-
void SwapchainInfoVk::Create(VkPhysicalDevice physicalDevice, VkDevice logicalDevice)
10+
SwapchainInfoVk::SwapchainInfoVk(bool mainWindow, Vector2i size) : mainWindow(mainWindow), m_desiredExtent(size)
911
{
10-
m_physicalDevice = physicalDevice;
11-
m_logicalDevice = logicalDevice;
12-
const auto details = QuerySwapchainSupport(surface, physicalDevice);
12+
auto& windowHandleInfo = mainWindow ? gui_getWindowInfo().canvas_main : gui_getWindowInfo().canvas_pad;
13+
auto renderer = VulkanRenderer::GetInstance();
14+
m_instance = renderer->GetVkInstance();
15+
m_logicalDevice = renderer->GetLogicalDevice();
16+
m_physicalDevice = renderer->GetPhysicalDevice();
17+
18+
m_surface = renderer->CreateFramebufferSurface(m_instance, windowHandleInfo);
19+
}
20+
21+
22+
SwapchainInfoVk::~SwapchainInfoVk()
23+
{
24+
Cleanup();
25+
if(m_surface != VK_NULL_HANDLE)
26+
vkDestroySurfaceKHR(m_instance, m_surface, nullptr);
27+
}
28+
29+
void SwapchainInfoVk::Create()
30+
{
31+
const auto details = QuerySwapchainSupport(m_surface, m_physicalDevice);
1332
m_surfaceFormat = ChooseSurfaceFormat(details.formats);
1433
m_actualExtent = ChooseSwapExtent(details.capabilities);
1534

@@ -20,28 +39,28 @@ void SwapchainInfoVk::Create(VkPhysicalDevice physicalDevice, VkDevice logicalDe
2039
if(image_count < 2)
2140
cemuLog_log(LogType::Force, "Vulkan: Swapchain image count less than 2 may cause problems");
2241

23-
VkSwapchainCreateInfoKHR create_info = CreateSwapchainCreateInfo(surface, details, m_surfaceFormat, image_count, m_actualExtent);
42+
VkSwapchainCreateInfoKHR create_info = CreateSwapchainCreateInfo(m_surface, details, m_surfaceFormat, image_count, m_actualExtent);
2443
create_info.oldSwapchain = nullptr;
2544
create_info.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
2645

27-
VkResult result = vkCreateSwapchainKHR(logicalDevice, &create_info, nullptr, &swapchain);
46+
VkResult result = vkCreateSwapchainKHR(m_logicalDevice, &create_info, nullptr, &m_swapchain);
2847
if (result != VK_SUCCESS)
2948
UnrecoverableError("Error attempting to create a swapchain");
3049

31-
result = vkGetSwapchainImagesKHR(logicalDevice, swapchain, &image_count, nullptr);
50+
result = vkGetSwapchainImagesKHR(m_logicalDevice, m_swapchain, &image_count, nullptr);
3251
if (result != VK_SUCCESS)
3352
UnrecoverableError("Error attempting to retrieve the count of swapchain images");
3453

3554

3655
m_swapchainImages.resize(image_count);
37-
result = vkGetSwapchainImagesKHR(logicalDevice, swapchain, &image_count, m_swapchainImages.data());
56+
result = vkGetSwapchainImagesKHR(m_logicalDevice, m_swapchain, &image_count, m_swapchainImages.data());
3857
if (result != VK_SUCCESS)
3958
UnrecoverableError("Error attempting to retrieve swapchain images");
4059
// create default renderpass
4160
VkAttachmentDescription colorAttachment = {};
4261
colorAttachment.format = m_surfaceFormat.format;
4362
colorAttachment.samples = VK_SAMPLE_COUNT_1_BIT;
44-
colorAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
63+
colorAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
4564
colorAttachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
4665
colorAttachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
4766
colorAttachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
@@ -62,7 +81,7 @@ void SwapchainInfoVk::Create(VkPhysicalDevice physicalDevice, VkDevice logicalDe
6281
renderPassInfo.pAttachments = &colorAttachment;
6382
renderPassInfo.subpassCount = 1;
6483
renderPassInfo.pSubpasses = &subpass;
65-
result = vkCreateRenderPass(logicalDevice, &renderPassInfo, nullptr, &m_swapchainRenderPass);
84+
result = vkCreateRenderPass(m_logicalDevice, &renderPassInfo, nullptr, &m_swapchainRenderPass);
6685
if (result != VK_SUCCESS)
6786
UnrecoverableError("Failed to create renderpass for swapchain");
6887

@@ -84,7 +103,7 @@ void SwapchainInfoVk::Create(VkPhysicalDevice physicalDevice, VkDevice logicalDe
84103
createInfo.subresourceRange.levelCount = 1;
85104
createInfo.subresourceRange.baseArrayLayer = 0;
86105
createInfo.subresourceRange.layerCount = 1;
87-
result = vkCreateImageView(logicalDevice, &createInfo, nullptr, &m_swapchainImageViews[i]);
106+
result = vkCreateImageView(m_logicalDevice, &createInfo, nullptr, &m_swapchainImageViews[i]);
88107
if (result != VK_SUCCESS)
89108
UnrecoverableError("Failed to create imageviews for swapchain");
90109
}
@@ -104,7 +123,7 @@ void SwapchainInfoVk::Create(VkPhysicalDevice physicalDevice, VkDevice logicalDe
104123
framebufferInfo.width = m_actualExtent.width;
105124
framebufferInfo.height = m_actualExtent.height;
106125
framebufferInfo.layers = 1;
107-
result = vkCreateFramebuffer(logicalDevice, &framebufferInfo, nullptr, &m_swapchainFramebuffers[i]);
126+
result = vkCreateFramebuffer(m_logicalDevice, &framebufferInfo, nullptr, &m_swapchainFramebuffers[i]);
108127
if (result != VK_SUCCESS)
109128
UnrecoverableError("Failed to create framebuffer for swapchain");
110129
}
@@ -114,7 +133,7 @@ void SwapchainInfoVk::Create(VkPhysicalDevice physicalDevice, VkDevice logicalDe
114133
VkSemaphoreCreateInfo info = {};
115134
info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
116135
for (auto& semaphore : m_presentSemaphores){
117-
if (vkCreateSemaphore(logicalDevice, &info, nullptr, &semaphore) != VK_SUCCESS)
136+
if (vkCreateSemaphore(m_logicalDevice, &info, nullptr, &semaphore) != VK_SUCCESS)
118137
UnrecoverableError("Failed to create semaphore for swapchain present");
119138
}
120139

@@ -123,14 +142,14 @@ void SwapchainInfoVk::Create(VkPhysicalDevice physicalDevice, VkDevice logicalDe
123142
info = {};
124143
info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
125144
for (auto& semaphore : m_acquireSemaphores){
126-
if (vkCreateSemaphore(logicalDevice, &info, nullptr, &semaphore) != VK_SUCCESS)
145+
if (vkCreateSemaphore(m_logicalDevice, &info, nullptr, &semaphore) != VK_SUCCESS)
127146
UnrecoverableError("Failed to create semaphore for swapchain acquire");
128147
}
129148

130149
VkFenceCreateInfo fenceInfo = {};
131150
fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
132151
fenceInfo.flags = VK_FENCE_CREATE_SIGNALED_BIT;
133-
result = vkCreateFence(logicalDevice, &fenceInfo, nullptr, &m_imageAvailableFence);
152+
result = vkCreateFence(m_logicalDevice, &fenceInfo, nullptr, &m_imageAvailableFence);
134153
if (result != VK_SUCCESS)
135154
UnrecoverableError("Failed to create fence for swapchain");
136155

@@ -167,19 +186,20 @@ void SwapchainInfoVk::Cleanup()
167186

168187
if (m_imageAvailableFence)
169188
{
189+
WaitAvailableFence();
170190
vkDestroyFence(m_logicalDevice, m_imageAvailableFence, nullptr);
171191
m_imageAvailableFence = nullptr;
172192
}
173-
if (swapchain)
193+
if (m_swapchain)
174194
{
175-
vkDestroySwapchainKHR(m_logicalDevice, swapchain, nullptr);
176-
swapchain = VK_NULL_HANDLE;
195+
vkDestroySwapchainKHR(m_logicalDevice, m_swapchain, nullptr);
196+
m_swapchain = VK_NULL_HANDLE;
177197
}
178198
}
179199

180200
bool SwapchainInfoVk::IsValid() const
181201
{
182-
return swapchain && !m_acquireSemaphores.empty();
202+
return m_swapchain && !m_acquireSemaphores.empty();
183203
}
184204

185205
void SwapchainInfoVk::WaitAvailableFence()
@@ -207,7 +227,7 @@ bool SwapchainInfoVk::AcquireImage(uint64 timeout)
207227
ResetAvailableFence();
208228

209229
VkSemaphore acquireSemaphore = m_acquireSemaphores[m_acquireIndex];
210-
VkResult result = vkAcquireNextImageKHR(m_logicalDevice, swapchain, timeout, acquireSemaphore, m_imageAvailableFence, &swapchainImageIndex);
230+
VkResult result = vkAcquireNextImageKHR(m_logicalDevice, m_swapchain, timeout, acquireSemaphore, m_imageAvailableFence, &swapchainImageIndex);
211231
if (result == VK_ERROR_OUT_OF_DATE_KHR || result == VK_SUBOPTIMAL_KHR)
212232
m_shouldRecreate = true;
213233
if (result < 0)
@@ -231,35 +251,6 @@ void SwapchainInfoVk::UnrecoverableError(const char* errMsg)
231251
throw std::runtime_error(errMsg);
232252
}
233253

234-
SwapchainInfoVk::QueueFamilyIndices SwapchainInfoVk::FindQueueFamilies(VkSurfaceKHR surface, VkPhysicalDevice device)
235-
{
236-
uint32_t queueFamilyCount = 0;
237-
vkGetPhysicalDeviceQueueFamilyProperties(device, &queueFamilyCount, nullptr);
238-
239-
std::vector<VkQueueFamilyProperties> queueFamilies(queueFamilyCount);
240-
vkGetPhysicalDeviceQueueFamilyProperties(device, &queueFamilyCount, queueFamilies.data());
241-
242-
QueueFamilyIndices indices;
243-
for (int i = 0; i < (int)queueFamilies.size(); ++i)
244-
{
245-
const auto& queueFamily = queueFamilies[i];
246-
if (queueFamily.queueCount > 0 && queueFamily.queueFlags & VK_QUEUE_GRAPHICS_BIT)
247-
indices.graphicsFamily = i;
248-
249-
VkBool32 presentSupport = false;
250-
const VkResult result = vkGetPhysicalDeviceSurfaceSupportKHR(device, i, surface, &presentSupport);
251-
if (result != VK_SUCCESS)
252-
throw std::runtime_error(fmt::format("Error while attempting to check if a surface supports presentation: {}", result));
253-
254-
if (queueFamily.queueCount > 0 && presentSupport)
255-
indices.presentFamily = i;
256-
257-
if (indices.IsComplete())
258-
break;
259-
}
260-
261-
return indices;
262-
}
263254

264255
SwapchainInfoVk::SwapchainSupportDetails SwapchainInfoVk::QuerySwapchainSupport(VkSurfaceKHR surface, const VkPhysicalDevice& device)
265256
{
@@ -391,7 +382,7 @@ VkSwapchainCreateInfoKHR SwapchainInfoVk::CreateSwapchainCreateInfo(VkSurfaceKHR
391382
createInfo.imageArrayLayers = 1;
392383
createInfo.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
393384

394-
const QueueFamilyIndices indices = FindQueueFamilies(surface, m_physicalDevice);
385+
const VulkanRenderer::QueueFamilyIndices indices = VulkanRenderer::GetInstance()->FindQueueFamilies(surface, m_physicalDevice);
395386
m_swapchainQueueFamilyIndices = { (uint32)indices.graphicsFamily, (uint32)indices.presentFamily };
396387
if (indices.graphicsFamily != indices.presentFamily)
397388
{

src/Cafe/HW/Latte/Renderer/Vulkan/SwapchainInfoVk.h

+6-19
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,6 @@ struct SwapchainInfoVk
1414
SYNC_AND_LIMIT = 3, // synchronize emulated vsync events to monitor vsync. But skip events if rate higher than virtual vsync period
1515
};
1616

17-
struct QueueFamilyIndices
18-
{
19-
int32_t graphicsFamily = -1;
20-
int32_t presentFamily = -1;
21-
22-
bool IsComplete() const { return graphicsFamily >= 0 && presentFamily >= 0; }
23-
};
24-
2517
struct SwapchainSupportDetails
2618
{
2719
VkSurfaceCapabilitiesKHR capabilities;
@@ -30,7 +22,7 @@ struct SwapchainInfoVk
3022
};
3123

3224
void Cleanup();
33-
void Create(VkPhysicalDevice physicalDevice, VkDevice logicalDevice);
25+
void Create();
3426

3527
bool IsValid() const;
3628

@@ -45,8 +37,6 @@ struct SwapchainInfoVk
4537

4638
static void UnrecoverableError(const char* errMsg);
4739

48-
// todo: move this function somewhere more sensible. Not directly swapchain related
49-
static QueueFamilyIndices FindQueueFamilies(VkSurfaceKHR surface, VkPhysicalDevice device);
5040
static SwapchainSupportDetails QuerySwapchainSupport(VkSurfaceKHR surface, const VkPhysicalDevice& device);
5141

5242
VkPresentModeKHR ChoosePresentMode(const std::vector<VkPresentModeKHR>& modes);
@@ -61,14 +51,10 @@ struct SwapchainInfoVk
6151
return m_actualExtent;
6252
}
6353

64-
SwapchainInfoVk(VkSurfaceKHR surface, bool mainWindow)
65-
: surface(surface), mainWindow(mainWindow) {}
54+
SwapchainInfoVk(bool mainWindow, Vector2i size);
6655
SwapchainInfoVk(const SwapchainInfoVk&) = delete;
6756
SwapchainInfoVk(SwapchainInfoVk&&) noexcept = default;
68-
~SwapchainInfoVk()
69-
{
70-
Cleanup();
71-
}
57+
~SwapchainInfoVk();
7258

7359
bool mainWindow{};
7460

@@ -77,11 +63,12 @@ struct SwapchainInfoVk
7763
VSync m_vsyncState = VSync::Immediate;
7864
bool hasDefinedSwapchainImage{}; // indicates if the swapchain image is in a defined state
7965

66+
VkInstance m_instance{};
8067
VkPhysicalDevice m_physicalDevice{};
8168
VkDevice m_logicalDevice{};
82-
VkSurfaceKHR surface{};
69+
VkSurfaceKHR m_surface{};
8370
VkSurfaceFormatKHR m_surfaceFormat{};
84-
VkSwapchainKHR swapchain{};
71+
VkSwapchainKHR m_swapchain{};
8572
Vector2i m_desiredExtent{};
8673
uint32 swapchainImageIndex = (uint32)-1;
8774

src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.cpp

+40-14
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,7 @@ std::vector<VulkanRenderer::DeviceInfo> VulkanRenderer::GetDevices()
167167
result.emplace_back(physDeviceProps.properties.deviceName, physDeviceIDProps.deviceUUID);
168168
}
169169
}
170+
vkDestroySurfaceKHR(instance, surface, nullptr);
170171
}
171172
catch (...)
172173
{
@@ -441,7 +442,7 @@ VulkanRenderer::VulkanRenderer()
441442
}
442443

443444
// create logical device
444-
m_indices = SwapchainInfoVk::FindQueueFamilies(surface, m_physicalDevice);
445+
m_indices = FindQueueFamilies(surface, m_physicalDevice);
445446
std::set<int> uniqueQueueFamilies = { m_indices.graphicsFamily, m_indices.presentFamily };
446447
std::vector<VkDeviceQueueCreateInfo> queueCreateInfos = CreateQueueCreateInfos(uniqueQueueFamilies);
447448
VkPhysicalDeviceFeatures deviceFeatures = {};
@@ -510,7 +511,7 @@ VulkanRenderer::VulkanRenderer()
510511
PFN_vkCreateDebugUtilsMessengerEXT vkCreateDebugUtilsMessengerEXT = reinterpret_cast<PFN_vkCreateDebugUtilsMessengerEXT>(vkGetInstanceProcAddr(m_instance, "vkCreateDebugUtilsMessengerEXT"));
511512

512513
VkDebugUtilsMessengerCreateInfoEXT debugCallback{};
513-
debugCallback.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT;
514+
debugCallback.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT;
514515
debugCallback.pNext = nullptr;
515516
debugCallback.flags = 0;
516517
debugCallback.messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT;
@@ -673,24 +674,19 @@ VulkanRenderer* VulkanRenderer::GetInstance()
673674

674675
void VulkanRenderer::InitializeSurface(const Vector2i& size, bool mainWindow)
675676
{
676-
auto& windowHandleInfo = mainWindow ? gui_getWindowInfo().canvas_main : gui_getWindowInfo().canvas_pad;
677-
678-
const auto surface = CreateFramebufferSurface(m_instance, windowHandleInfo);
679677
if (mainWindow)
680678
{
681-
m_mainSwapchainInfo = std::make_unique<SwapchainInfoVk>(surface, mainWindow);
682-
m_mainSwapchainInfo->m_desiredExtent = size;
683-
m_mainSwapchainInfo->Create(m_physicalDevice, m_logicalDevice);
679+
m_mainSwapchainInfo = std::make_unique<SwapchainInfoVk>(mainWindow, size);
680+
m_mainSwapchainInfo->Create();
684681

685682
// aquire first command buffer
686683
InitFirstCommandBuffer();
687684
}
688685
else
689686
{
690-
m_padSwapchainInfo = std::make_unique<SwapchainInfoVk>(surface, mainWindow);
691-
m_padSwapchainInfo->m_desiredExtent = size;
687+
m_padSwapchainInfo = std::make_unique<SwapchainInfoVk>(mainWindow, size);
692688
// todo: figure out a way to exclusively create swapchain on main LatteThread
693-
m_padSwapchainInfo->Create(m_physicalDevice, m_logicalDevice);
689+
m_padSwapchainInfo->Create();
694690
}
695691
}
696692

@@ -1074,6 +1070,36 @@ RendererShader* VulkanRenderer::shader_create(RendererShader::ShaderType type, u
10741070
return new RendererShaderVk(type, baseHash, auxHash, isGameShader, isGfxPackShader, source);
10751071
}
10761072

1073+
VulkanRenderer::QueueFamilyIndices VulkanRenderer::FindQueueFamilies(VkSurfaceKHR surface, VkPhysicalDevice device)
1074+
{
1075+
uint32_t queueFamilyCount = 0;
1076+
vkGetPhysicalDeviceQueueFamilyProperties(device, &queueFamilyCount, nullptr);
1077+
1078+
std::vector<VkQueueFamilyProperties> queueFamilies(queueFamilyCount);
1079+
vkGetPhysicalDeviceQueueFamilyProperties(device, &queueFamilyCount, queueFamilies.data());
1080+
1081+
QueueFamilyIndices indices;
1082+
for (int i = 0; i < (int)queueFamilies.size(); ++i)
1083+
{
1084+
const auto& queueFamily = queueFamilies[i];
1085+
if (queueFamily.queueCount > 0 && queueFamily.queueFlags & VK_QUEUE_GRAPHICS_BIT)
1086+
indices.graphicsFamily = i;
1087+
1088+
VkBool32 presentSupport = false;
1089+
const VkResult result = vkGetPhysicalDeviceSurfaceSupportKHR(device, i, surface, &presentSupport);
1090+
if (result != VK_SUCCESS)
1091+
throw std::runtime_error(fmt::format("Error while attempting to check if a surface supports presentation: {}", result));
1092+
1093+
if (queueFamily.queueCount > 0 && presentSupport)
1094+
indices.presentFamily = i;
1095+
1096+
if (indices.IsComplete())
1097+
break;
1098+
}
1099+
1100+
return indices;
1101+
}
1102+
10771103
bool VulkanRenderer::CheckDeviceExtensionSupport(const VkPhysicalDevice device, FeatureControl& info)
10781104
{
10791105
std::vector<VkExtensionProperties> availableDeviceExtensions;
@@ -1215,7 +1241,7 @@ std::vector<const char*> VulkanRenderer::CheckInstanceExtensionSupport(FeatureCo
12151241

12161242
bool VulkanRenderer::IsDeviceSuitable(VkSurfaceKHR surface, const VkPhysicalDevice& device)
12171243
{
1218-
if (!SwapchainInfoVk::FindQueueFamilies(surface, device).IsComplete())
1244+
if (!FindQueueFamilies(surface, device).IsComplete())
12191245
return false;
12201246

12211247
// check API version (using Vulkan 1.0 way of querying properties)
@@ -2605,7 +2631,7 @@ void VulkanRenderer::RecreateSwapchain(bool mainWindow, bool skipCreate)
26052631
chainInfo.m_desiredExtent = size;
26062632
if(!skipCreate)
26072633
{
2608-
chainInfo.Create(m_physicalDevice, m_logicalDevice);
2634+
chainInfo.Create();
26092635
}
26102636

26112637
if (mainWindow)
@@ -2675,7 +2701,7 @@ void VulkanRenderer::SwapBuffer(bool mainWindow)
26752701
VkPresentInfoKHR presentInfo = {};
26762702
presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
26772703
presentInfo.swapchainCount = 1;
2678-
presentInfo.pSwapchains = &chainInfo.swapchain;
2704+
presentInfo.pSwapchains = &chainInfo.m_swapchain;
26792705
presentInfo.pImageIndices = &chainInfo.swapchainImageIndex;
26802706
// wait on command buffer semaphore
26812707
presentInfo.waitSemaphoreCount = 1;

0 commit comments

Comments
 (0)