Merge pull request #20898 from hrydgard/vulkan-init-refactor

Small Vulkan init refactor
This commit is contained in:
Henrik Rydgård authored and GitHub committed 2025-10-20 17:11:20 +02:00
commit 65fa765409
10 files changed
+73 -67

No files matched your search

+22 -8
View File
@@ -197,11 +197,6 @@ VkResult VulkanContext::CreateInstance(const CreateInfo &info) {
if (EnableInstanceExtension(VK_EXT_SWAPCHAIN_COLOR_SPACE_EXTENSION_NAME, 0)) {
extensionsLookup_.EXT_swapchain_colorspace = true;
}
#if PPSSPP_PLATFORM(IOS_APP_STORE)
if (EnableInstanceExtension(VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME, 0)) {
}
#endif
// Validate that all the instance extensions we ask for are actually available.
for (auto ext : instance_extensions_enabled_) {
@@ -397,6 +392,8 @@ void VulkanContext::DestroySurface() {
if (surface_ != VK_NULL_HANDLE) {
vkDestroySurfaceKHR(instance_, surface_, nullptr);
surface_ = VK_NULL_HANDLE;
// NOTE: We do not reset winSysData1 and 2, it's useful for debugging to compare them.
}
}
@@ -935,6 +932,12 @@ void VulkanContext::SetDebugNameImpl(uint64_t handle, VkObjectType type, const c
VkResult VulkanContext::InitSurface(WindowSystem winsys, void *data1, void *data2) {
winsys_ = winsys;
if (winsysData1_ != data1) {
WARN_LOG(Log::G3D, "winsysData1 changed from %p to %p", winsysData1_, data1);
}
if (winsysData2_ != data2) {
WARN_LOG(Log::G3D, "winsysData2 changed from %p to %p", winsysData2_, data2);
}
winsysData1_ = data1;
winsysData2_ = data2;
return ReinitSurface();
@@ -1337,13 +1340,17 @@ static std::string surface_transforms_to_string(VkSurfaceTransformFlagsKHR trans
return str;
}
bool VulkanContext::InitSwapchain() {
bool VulkanContext::InitSwapchain(VkPresentModeKHR desiredPresentMode) {
_assert_(physical_device_ >= 0 && physical_device_ < (int)physical_devices_.size());
if (!surface_) {
ERROR_LOG(Log::G3D, "VK: No surface, can't create swapchain");
return false;
}
if (swapchain_) {
INFO_LOG(Log::G3D, "Swapchain already exists, recreating...");
}
VkResult res = vkGetPhysicalDeviceSurfaceCapabilitiesKHR(physical_devices_[physical_device_], surface_, &surfCapabilities_);
if (res == VK_ERROR_SURFACE_LOST_KHR) {
// Not much to do.
@@ -1406,7 +1413,7 @@ bool VulkanContext::InitSwapchain() {
// Kind of silly logic now, but at least it performs a final sanity check of the chosen value.
for (size_t i = 0; i < presentModeCount; i++) {
bool match = presentModes[i] == createInfo_.presentMode;
bool match = presentModes[i] == desiredPresentMode;
// Default to the first present mode from the list.
if (match || swapchainPresentMode == VK_PRESENT_MODE_MAX_ENUM_KHR) {
swapchainPresentMode = presentModes[i];
@@ -1496,6 +1503,8 @@ bool VulkanContext::InitSwapchain() {
}
}
VkSwapchainKHR oldSwapchain = swapchain_;
VkSwapchainCreateInfoKHR swap_chain_info{ VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR };
swap_chain_info.surface = surface_;
swap_chain_info.minImageCount = desiredNumberOfSwapChainImages;
@@ -1506,7 +1515,7 @@ bool VulkanContext::InitSwapchain() {
swap_chain_info.preTransform = preTransform;
swap_chain_info.imageArrayLayers = 1;
swap_chain_info.presentMode = swapchainPresentMode;
swap_chain_info.oldSwapchain = VK_NULL_HANDLE;
swap_chain_info.oldSwapchain = swapchain_;
swap_chain_info.clipped = true;
swap_chain_info.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
@@ -1535,6 +1544,11 @@ bool VulkanContext::InitSwapchain() {
}
INFO_LOG(Log::G3D, "Created swapchain: %dx%d %s", swap_chain_info.imageExtent.width, swap_chain_info.imageExtent.height, (surfCapabilities_.supportedUsageFlags & VK_IMAGE_USAGE_TRANSFER_SRC_BIT) ? "(TRANSFER_SRC_BIT supported)" : "");
swapchainInited_ = true;
if (oldSwapchain != VK_NULL_HANDLE) {
vkDestroySwapchainKHR(device_, oldSwapchain, nullptr);
INFO_LOG(Log::G3D, "Destroyed old swapchain.");
}
return true;
}
+4 -3
View File
@@ -52,6 +52,7 @@ template<class R, class T> inline void ChainStruct(R &root, T *newStruct) {
// Not all will be usable on all platforms, of course...
enum WindowSystem {
WINDOWSYSTEM_UNINITIALIZED,
#ifdef _WIN32
WINDOWSYSTEM_WIN32,
#endif
@@ -181,7 +182,6 @@ public:
int app_ver;
VulkanInitFlags flags;
std::string customDriver;
VkPresentModeKHR presentMode;
};
VkResult CreateInstance(const CreateInfo &info);
@@ -217,7 +217,8 @@ public:
VkResult InitSurface(WindowSystem winsys, void *data1, void *data2);
VkResult ReinitSurface();
bool InitSwapchain();
// If the present mode is not available, will fall back to the first available (which is almost always FIFO).
bool InitSwapchain(VkPresentModeKHR desiredPresentMode);
void SetCbGetDrawSize(std::function<VkExtent2D()>);
void DestroySwapchain();
@@ -450,7 +451,7 @@ private:
bool CheckLayers(const std::vector<LayerProperties> &layer_props, const std::vector<const char *> &layer_names) const;
WindowSystem winsys_{};
WindowSystem winsys_ = WINDOWSYSTEM_UNINITIALIZED;
// Don't use the real types here to avoid having to include platform-specific stuff
// that we really don't want in everything that uses VulkanContext.
+2 -3
View File
@@ -174,7 +174,6 @@ bool VulkanQueueRunner::InitDepthStencilBuffer(VkCommandBuffer cmd, VulkanBarrie
return true;
}
void VulkanQueueRunner::DestroyBackBuffers() {
if (depth_.view) {
vulkan_->Delete().QueueDeleteImageView(depth_.view);
@@ -551,10 +550,10 @@ void VulkanQueueRunner::ApplyMGSHack(std::vector<VKRStep *> &steps) {
if (rc.offset.y < minScissorY) {
minScissorY = rc.offset.y;
}
if (rc.offset.x + rc.extent.width > maxScissorX) {
if (rc.offset.x + (int)rc.extent.width > maxScissorX) {
maxScissorX = rc.offset.x + rc.extent.width;
}
if (rc.offset.y + rc.extent.height > maxScissorY) {
if (rc.offset.y + (int)rc.extent.height > maxScissorY) {
maxScissorY = rc.offset.y + rc.extent.height;
}
break;
+2 -2
View File
@@ -36,7 +36,8 @@ const VkComponentMapping VULKAN_1555_SWIZZLE = { VK_COMPONENT_SWIZZLE_B, VK_COMP
const VkComponentMapping VULKAN_565_SWIZZLE = { VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_IDENTITY };
const VkComponentMapping VULKAN_8888_SWIZZLE = { VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY };
VkPresentModeKHR ConfigPresentModeToVulkan(PresentMode presentMode) {
VkPresentModeKHR ConfigPresentModeToVulkan() {
PresentMode presentMode = (PresentMode)g_Config.iVulkanPresentationMode;
switch (presentMode) {
case PresentMode::Immediate:
return VK_PRESENT_MODE_IMMEDIATE_KHR;
@@ -70,7 +71,6 @@ void InitVulkanCreateInfoFromConfig(VulkanContext::CreateInfo *info) {
info->app_ver = gitVer.ToInteger();
info->flags = VulkanInitFlagsFromConfig();
info->customDriver = g_Config.sCustomDriver;
info->presentMode = ConfigPresentModeToVulkan((PresentMode)g_Config.iVulkanPresentationMode);
}
VkShaderModule CompileShaderModule(VulkanContext *vulkan, VkShaderStageFlagBits stage, const char *code, std::string *error) {
+1 -1
View File
@@ -89,5 +89,5 @@ private:
VkShaderModule CompileShaderModule(VulkanContext *vulkan, VkShaderStageFlagBits stage, const char *code, std::string *error);
VkPresentModeKHR ConfigPresentModeToVulkan(PresentMode presentMode);
VkPresentModeKHR ConfigPresentModeToVulkan();
void InitVulkanCreateInfoFromConfig(VulkanContext::CreateInfo *info);
+6 -5
View File
@@ -128,7 +128,8 @@ bool SDLVulkanGraphicsContext::Init(SDL_Window *&window, int x, int y, int w, in
break;
}
if (!vulkan_->InitSwapchain()) {
VkPresentModeKHR presentMode = ConfigPresentModeToVulkan();
if (!vulkan_->InitSwapchain(presentMode)) {
*error_message = vulkan_->InitError();
Shutdown();
return false;
@@ -166,11 +167,11 @@ void SDLVulkanGraphicsContext::Shutdown() {
void SDLVulkanGraphicsContext::Resize() {
draw_->HandleEvent(Draw::Event::LOST_BACKBUFFER, vulkan_->GetBackbufferWidth(), vulkan_->GetBackbufferHeight());
// NOTE: Removing DestroySwapchain here causes a double re-create on MacOS with MoltenVK, for some reason.
// It's like passing on oldSwapchain doesn't really work as expected.
vulkan_->DestroySwapchain();
VulkanContext::CreateInfo info{};
InitVulkanCreateInfoFromConfig(&info);
vulkan_->UpdateCreateInfo(info);
vulkan_->InitSwapchain();
VkPresentModeKHR presentMode = ConfigPresentModeToVulkan();
vulkan_->InitSwapchain(presentMode);
draw_->HandleEvent(Draw::Event::GOT_BACKBUFFER, vulkan_->GetBackbufferWidth(), vulkan_->GetBackbufferHeight());
}
+5 -5
View File
@@ -116,7 +116,9 @@ bool WindowsVulkanContext::Init(HINSTANCE hInst, HWND hWnd, std::string *error_m
}
vulkan_->InitSurface(WINDOWSYSTEM_WIN32, (void *)hInst, (void *)hWnd);
if (!vulkan_->InitSwapchain()) {
VkPresentModeKHR presentMode = ConfigPresentModeToVulkan();
if (!vulkan_->InitSwapchain(presentMode)) {
*error_message = vulkan_->InitError();
Shutdown();
return false;
@@ -164,10 +166,8 @@ void WindowsVulkanContext::Shutdown() {
void WindowsVulkanContext::Resize() {
draw_->HandleEvent(Draw::Event::LOST_BACKBUFFER, vulkan_->GetBackbufferWidth(), vulkan_->GetBackbufferHeight());
vulkan_->DestroySwapchain();
VulkanContext::CreateInfo info{};
InitVulkanCreateInfoFromConfig(&info);
vulkan_->InitSwapchain();
VkPresentModeKHR presentMode = ConfigPresentModeToVulkan();
vulkan_->InitSwapchain(presentMode);
draw_->HandleEvent(Draw::Event::GOT_BACKBUFFER, vulkan_->GetBackbufferWidth(), vulkan_->GetBackbufferHeight());
}
+7 -8
View File
@@ -70,8 +70,9 @@ bool AndroidVulkanContext::InitFromRenderThread(ANativeWindow *wnd, int desiredB
return false;
}
VkPresentModeKHR presentMode = ConfigPresentModeToVulkan();
bool success = false;
if (g_Vulkan->InitSwapchain()) {
if (g_Vulkan->InitSwapchain(presentMode)) {
bool useMultiThreading = g_Config.bRenderMultiThreading;
if (g_Config.iInflightFrames == 1) {
useMultiThreading = false;
@@ -120,17 +121,15 @@ void AndroidVulkanContext::Shutdown() {
void AndroidVulkanContext::Resize() {
INFO_LOG(Log::G3D, "AndroidVulkanContext::Resize begin (oldsize: %dx%d)", g_Vulkan->GetBackbufferWidth(), g_Vulkan->GetBackbufferHeight());
draw_->HandleEvent(Draw::Event::LOST_BACKBUFFER, g_Vulkan->GetBackbufferWidth(), g_Vulkan->GetBackbufferHeight());
g_Vulkan->DestroySwapchain();
// TODO: We should only destroy the surface here if the window changed. We can track this inside g_Vulkan.
g_Vulkan->DestroySurface();
VulkanContext::CreateInfo info{};
InitVulkanCreateInfoFromConfig(&info);
g_Vulkan->UpdateCreateInfo(info);
g_Vulkan->ReinitSurface();
g_Vulkan->InitSwapchain();
VkPresentModeKHR presentMode = ConfigPresentModeToVulkan();
g_Vulkan->InitSwapchain(presentMode);
draw_->HandleEvent(Draw::Event::GOT_BACKBUFFER, g_Vulkan->GetBackbufferWidth(), g_Vulkan->GetBackbufferHeight());
INFO_LOG(Log::G3D, "AndroidVulkanContext::Resize end (final size: %dx%d)", g_Vulkan->GetBackbufferWidth(), g_Vulkan->GetBackbufferHeight());
}
+22 -31
View File
@@ -41,7 +41,7 @@ enum class GraphicsContextState {
class IOSVulkanContext : public GraphicsContext {
public:
IOSVulkanContext();
IOSVulkanContext() {}
~IOSVulkanContext() {
delete g_Vulkan;
g_Vulkan = nullptr;
@@ -64,8 +64,6 @@ private:
GraphicsContextState state_ = GraphicsContextState::PENDING;
};
IOSVulkanContext::IOSVulkanContext() {}
bool IOSVulkanContext::InitFromRenderThread(CAMetalLayer *layer, int desiredBackbufferSizeX, int desiredBackbufferSizeY) {
INFO_LOG(Log::G3D, "IOSVulkanContext::InitFromRenderThread: desiredwidth=%d desiredheight=%d", desiredBackbufferSizeX, desiredBackbufferSizeY);
if (!g_Vulkan) {
@@ -79,33 +77,30 @@ bool IOSVulkanContext::InitFromRenderThread(CAMetalLayer *layer, int desiredBack
return false;
}
bool success = true;
if (g_Vulkan->InitSwapchain()) {
bool useMultiThreading = g_Config.bRenderMultiThreading;
if (g_Config.iInflightFrames == 1) {
useMultiThreading = false;
}
draw_ = Draw::T3DCreateVulkanContext(g_Vulkan, useMultiThreading);
SetGPUBackend(GPUBackend::VULKAN);
success = draw_->CreatePresets(); // Doesn't fail, we ship the compiler.
_assert_msg_(success, "Failed to compile preset shaders");
draw_->HandleEvent(Draw::Event::GOT_BACKBUFFER, g_Vulkan->GetBackbufferWidth(), g_Vulkan->GetBackbufferHeight());
VulkanRenderManager *renderManager = (VulkanRenderManager *)draw_->GetNativeObject(Draw::NativeObject::RENDER_MANAGER);
renderManager->SetInflightFrames(g_Config.iInflightFrames);
success = renderManager->HasBackbuffers();
} else {
success = false;
}
INFO_LOG(Log::G3D, "IOSVulkanContext::Init completed, %s", success ? "successfully" : "but failed");
if (!success) {
VkPresentModeKHR presentMode = ConfigPresentModeToVulkan();
if (!g_Vulkan->InitSwapchain(presentMode)) {
ERROR_LOG(Log::G3D, "InitSwapchain failed");
g_Vulkan->DestroySwapchain();
g_Vulkan->DestroySurface();
g_Vulkan->DestroyDevice();
g_Vulkan->DestroyInstance();
return false;
}
return success;
bool useMultiThreading = g_Config.bRenderMultiThreading;
if (g_Config.iInflightFrames == 1) {
useMultiThreading = false;
}
draw_ = Draw::T3DCreateVulkanContext(g_Vulkan, useMultiThreading);
SetGPUBackend(GPUBackend::VULKAN);
bool shaderSuccess = draw_->CreatePresets(); // Doesn't fail, we ship the compiler.
_assert_msg_(shaderSuccess, "Failed to compile preset shaders");
draw_->HandleEvent(Draw::Event::GOT_BACKBUFFER, g_Vulkan->GetBackbufferWidth(), g_Vulkan->GetBackbufferHeight());
VulkanRenderManager *renderManager = (VulkanRenderManager *)draw_->GetNativeObject(Draw::NativeObject::RENDER_MANAGER);
renderManager->SetInflightFrames(g_Config.iInflightFrames);
return true;
}
void IOSVulkanContext::ShutdownFromRenderThread() {
@@ -135,13 +130,9 @@ void IOSVulkanContext::Resize() {
draw_->HandleEvent(Draw::Event::LOST_BACKBUFFER, g_Vulkan->GetBackbufferWidth(), g_Vulkan->GetBackbufferHeight());
g_Vulkan->DestroySwapchain();
g_Vulkan->DestroySurface();
VulkanContext::CreateInfo info{};
InitVulkanCreateInfoFromConfig(&info);
g_Vulkan->UpdateCreateInfo(info);
g_Vulkan->ReinitSurface();
g_Vulkan->InitSwapchain();
VkPresentModeKHR presentMode = ConfigPresentModeToVulkan();
g_Vulkan->InitSwapchain(presentMode);
draw_->HandleEvent(Draw::Event::GOT_BACKBUFFER, g_Vulkan->GetBackbufferWidth(), g_Vulkan->GetBackbufferHeight());
INFO_LOG(Log::G3D, "IOSVulkanContext::Resize end (final size: %dx%d)", g_Vulkan->GetBackbufferWidth(), g_Vulkan->GetBackbufferHeight());
}
+2 -1
View File
@@ -129,7 +129,8 @@ void LibretroVulkanContext::ContextDestroy() {
void LibretroVulkanContext::CreateDrawContext() {
vk->ReinitSurface();
if (!vk->InitSwapchain()) {
// TODO: Integrate properly with libretro vulkan context. We currently use a wacky wrapper (libretro_vulkan.cpp)
if (!vk->InitSwapchain(VK_PRESENT_MODE_FIFO_KHR)) {
return;
}