aboutsummaryrefslogtreecommitdiff
path: root/src/video_core
diff options
context:
space:
mode:
authorBriar <205427297+icy-briar@users.noreply.github.com>2025-05-02 18:42:58 +0000
committerCamilleLaVey <camillelavey@noreply.localhost>2025-05-02 18:42:58 +0000
commit559eb0a488b651397802066878aebdbd65b42baf (patch)
tree49a8295dabe49f0419bc2508fcff6a622f1f30cb /src/video_core
parentcb8f449dca521a5625d012d5e8ec4ea5b2138f83 (diff)
renderer_vulkan: Use raw surface handles and improve release logic (#75)
Should fix or at least lessen the crashes when leaving runtime emulation on both Android / PC Also, may have improved the time required to leave the game Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/75 Co-authored-by: Briar <205427297+icy-briar@users.noreply.github.com> Co-committed-by: Briar <205427297+icy-briar@users.noreply.github.com>
Diffstat (limited to 'src/video_core')
-rw-r--r--src/video_core/renderer_vulkan/renderer_vulkan.cpp15
-rw-r--r--src/video_core/renderer_vulkan/vk_present_manager.cpp16
-rw-r--r--src/video_core/renderer_vulkan/vk_present_manager.h6
-rw-r--r--src/video_core/renderer_vulkan/vk_swapchain.cpp20
-rw-r--r--src/video_core/renderer_vulkan/vk_swapchain.h8
-rw-r--r--src/video_core/vulkan_common/vulkan_wrapper.h18
6 files changed, 57 insertions, 26 deletions
diff --git a/src/video_core/renderer_vulkan/renderer_vulkan.cpp b/src/video_core/renderer_vulkan/renderer_vulkan.cpp
index ebc50290a9..32a207bc26 100644
--- a/src/video_core/renderer_vulkan/renderer_vulkan.cpp
+++ b/src/video_core/renderer_vulkan/renderer_vulkan.cpp
@@ -120,12 +120,13 @@ RendererVulkan::RendererVulkan(Core::Frontend::EmuWindow& emu_window,
// Create surface
surface(CreateSurface(instance, render_window.GetWindowInfo())),
managed_surface(MakeManagedSurface(surface, instance, dld)),
- device(CreateDevice(instance, dld, *surface)), memory_allocator(device), state_tracker(),
+ device(CreateDevice(instance, dld, *surface)),
+ memory_allocator(device), state_tracker(),
scheduler(device, state_tracker),
swapchain(*surface, device, scheduler, render_window.GetFramebufferLayout().width,
render_window.GetFramebufferLayout().height),
present_manager(instance, render_window, device, memory_allocator, scheduler, swapchain,
- surface),
+ *surface),
blit_swapchain(device_memory, device, memory_allocator, present_manager, scheduler,
PresentFiltersForDisplay),
blit_capture(device_memory, device, memory_allocator, present_manager, scheduler,
@@ -136,11 +137,19 @@ RendererVulkan::RendererVulkan(Core::Frontend::EmuWindow& emu_window,
scheduler),
hybrid_memory(std::make_unique<HybridMemory>(device, memory_allocator)),
applet_frame() {
- if (Settings::values.renderer_force_max_clock.GetValue() && device.ShouldBoostClocks()) {
+
+ if (Settings::values.renderer_force_max_clock.GetValue() && device.ShouldBoostClocks()) {
turbo_mode.emplace(instance, dld);
scheduler.RegisterOnSubmit([this] { turbo_mode->QueueSubmitted(); });
}
+ // Release ownership from the old instance and surface
+ instance.release();
+ surface.release();
+ if (Settings::values.renderer_debug) {
+ debug_messenger.release();
+ }
+
// Initialize HybridMemory system
if (Settings::values.use_gpu_memory_manager.GetValue()) {
#if defined(__linux__) || defined(__ANDROID__) || defined(_WIN32)
diff --git a/src/video_core/renderer_vulkan/vk_present_manager.cpp b/src/video_core/renderer_vulkan/vk_present_manager.cpp
index 5e7518d968..8f5edeae24 100644
--- a/src/video_core/renderer_vulkan/vk_present_manager.cpp
+++ b/src/video_core/renderer_vulkan/vk_present_manager.cpp
@@ -10,6 +10,7 @@
#include "video_core/renderer_vulkan/vk_swapchain.h"
#include "video_core/vulkan_common/vulkan_device.h"
#include "video_core/vulkan_common/vulkan_surface.h"
+#include "video_core/vulkan_common/vulkan_wrapper.h"
namespace Vulkan {
@@ -94,14 +95,14 @@ bool CanBlitToSwapchain(const vk::PhysicalDevice& physical_device, VkFormat form
} // Anonymous namespace
-PresentManager::PresentManager(const vk::Instance& instance_,
- Core::Frontend::EmuWindow& render_window_, const Device& device_,
- MemoryAllocator& memory_allocator_, Scheduler& scheduler_,
- Swapchain& swapchain_, vk::SurfaceKHR& surface_)
+PresentManager::PresentManager(const vk::Instance& instance_, Core::Frontend::EmuWindow& render_window_,
+ const Device& device_, MemoryAllocator& memory_allocator_, Scheduler& scheduler_,
+ Swapchain& swapchain_, VkSurfaceKHR_T* surface_handle_)
: instance{instance_}, render_window{render_window_}, device{device_},
memory_allocator{memory_allocator_}, scheduler{scheduler_}, swapchain{swapchain_},
- surface{surface_}, blit_supported{CanBlitToSwapchain(device.GetPhysical(),
- swapchain.GetImageViewFormat())},
+ surface_handle{surface_handle_},
+ blit_supported{CanBlitToSwapchain(device.GetPhysical(),
+ swapchain.GetImageViewFormat())},
use_present_thread{Settings::values.async_presentation.GetValue()} {
SetImageCount();
@@ -288,7 +289,7 @@ void PresentManager::PresentThread(std::stop_token token) {
}
void PresentManager::RecreateSwapchain(Frame* frame) {
- swapchain.Create(*surface, frame->width, frame->height);
+ swapchain.Create(surface_handle, frame->width, frame->height); // Pass raw pointer
SetImageCount();
}
@@ -306,7 +307,6 @@ void PresentManager::CopyToSwapchain(Frame* frame) {
try {
// Recreate surface and swapchain if needed.
if (requires_recreation) {
- surface = CreateSurface(instance, render_window.GetWindowInfo());
RecreateSwapchain(frame);
}
diff --git a/src/video_core/renderer_vulkan/vk_present_manager.h b/src/video_core/renderer_vulkan/vk_present_manager.h
index 23ee61c8c5..96850ed56f 100644
--- a/src/video_core/renderer_vulkan/vk_present_manager.h
+++ b/src/video_core/renderer_vulkan/vk_present_manager.h
@@ -12,6 +12,8 @@
#include "video_core/vulkan_common/vulkan_memory_allocator.h"
#include "video_core/vulkan_common/vulkan_wrapper.h"
+struct VkSurfaceKHR_T;
+
namespace Core::Frontend {
class EmuWindow;
} // namespace Core::Frontend
@@ -37,7 +39,7 @@ class PresentManager {
public:
PresentManager(const vk::Instance& instance, Core::Frontend::EmuWindow& render_window,
const Device& device, MemoryAllocator& memory_allocator, Scheduler& scheduler,
- Swapchain& swapchain, vk::SurfaceKHR& surface);
+ Swapchain& swapchain, VkSurfaceKHR_T* surface_handle);
~PresentManager();
/// Returns the last used presentation frame
@@ -71,7 +73,7 @@ private:
MemoryAllocator& memory_allocator;
Scheduler& scheduler;
Swapchain& swapchain;
- vk::SurfaceKHR& surface;
+ VkSurfaceKHR_T* surface_handle;
vk::CommandPool cmdpool;
std::vector<Frame> frames;
std::queue<Frame*> present_queue;
diff --git a/src/video_core/renderer_vulkan/vk_swapchain.cpp b/src/video_core/renderer_vulkan/vk_swapchain.cpp
index 4f1d3b4e3f..ec96b75036 100644
--- a/src/video_core/renderer_vulkan/vk_swapchain.cpp
+++ b/src/video_core/renderer_vulkan/vk_swapchain.cpp
@@ -105,23 +105,23 @@ VkCompositeAlphaFlagBitsKHR ChooseAlphaFlags(const VkSurfaceCapabilitiesKHR& cap
} // Anonymous namespace
-Swapchain::Swapchain(VkSurfaceKHR surface_, const Device& device_, Scheduler& scheduler_,
+Swapchain::Swapchain(VkSurfaceKHR_T* surface_handle_, const Device& device_, Scheduler& scheduler_,
u32 width_, u32 height_)
- : surface{surface_}, device{device_}, scheduler{scheduler_} {
- Create(surface_, width_, height_);
+ : surface_handle{surface_handle_}, device{device_}, scheduler{scheduler_} {
+ Create(surface_handle, width_, height_);
}
Swapchain::~Swapchain() = default;
-void Swapchain::Create(VkSurfaceKHR surface_, u32 width_, u32 height_) {
+void Swapchain::Create(VkSurfaceKHR_T* surface_handle_, u32 width_, u32 height_) {
is_outdated = false;
is_suboptimal = false;
width = width_;
height = height_;
- surface = surface_;
+ surface_handle = surface_handle_;
const auto physical_device = device.GetPhysical();
- const auto capabilities{physical_device.GetSurfaceCapabilitiesKHR(surface)};
+ const auto capabilities{physical_device.GetSurfaceCapabilitiesKHR(surface_handle)};
if (capabilities.maxImageExtent.width == 0 || capabilities.maxImageExtent.height == 0) {
return;
}
@@ -199,8 +199,8 @@ void Swapchain::Present(VkSemaphore render_semaphore) {
void Swapchain::CreateSwapchain(const VkSurfaceCapabilitiesKHR& capabilities) {
const auto physical_device{device.GetPhysical()};
- const auto formats{physical_device.GetSurfaceFormatsKHR(surface)};
- const auto present_modes = physical_device.GetSurfacePresentModesKHR(surface);
+ const auto formats{physical_device.GetSurfaceFormatsKHR(surface_handle)};
+ const auto present_modes = physical_device.GetSurfacePresentModesKHR(surface_handle);
has_mailbox = std::find(present_modes.begin(), present_modes.end(),
VK_PRESENT_MODE_MAILBOX_KHR) != present_modes.end();
has_imm = std::find(present_modes.begin(), present_modes.end(),
@@ -228,7 +228,7 @@ void Swapchain::CreateSwapchain(const VkSurfaceCapabilitiesKHR& capabilities) {
.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR,
.pNext = nullptr,
.flags = 0,
- .surface = surface,
+ .surface = surface_handle,
.minImageCount = requested_image_count,
.imageFormat = surface_format.format,
.imageColorSpace = surface_format.colorSpace,
@@ -269,7 +269,7 @@ void Swapchain::CreateSwapchain(const VkSurfaceCapabilitiesKHR& capabilities) {
swapchain_ci.flags |= VK_SWAPCHAIN_CREATE_MUTABLE_FORMAT_BIT_KHR;
}
// Request the size again to reduce the possibility of a TOCTOU race condition.
- const auto updated_capabilities = physical_device.GetSurfaceCapabilitiesKHR(surface);
+ const auto updated_capabilities = physical_device.GetSurfaceCapabilitiesKHR(surface_handle);
swapchain_ci.imageExtent = ChooseSwapExtent(updated_capabilities, width, height);
// Don't add code within this and the swapchain creation.
swapchain = device.GetLogical().CreateSwapchainKHR(swapchain_ci);
diff --git a/src/video_core/renderer_vulkan/vk_swapchain.h b/src/video_core/renderer_vulkan/vk_swapchain.h
index d264f06e41..f5090c27f4 100644
--- a/src/video_core/renderer_vulkan/vk_swapchain.h
+++ b/src/video_core/renderer_vulkan/vk_swapchain.h
@@ -8,6 +8,8 @@
#include "common/common_types.h"
#include "video_core/vulkan_common/vulkan_wrapper.h"
+struct VkSurfaceKHR_T;
+
namespace Layout {
struct FramebufferLayout;
}
@@ -19,12 +21,12 @@ class Scheduler;
class Swapchain {
public:
- explicit Swapchain(VkSurfaceKHR surface, const Device& device, Scheduler& scheduler, u32 width,
+ explicit Swapchain(VkSurfaceKHR_T* surface_handle, const Device& device, Scheduler& scheduler, u32 width,
u32 height);
~Swapchain();
/// Creates (or recreates) the swapchain with a given size.
- void Create(VkSurfaceKHR surface, u32 width, u32 height);
+ void Create(VkSurfaceKHR_T* surface_handle, u32 width, u32 height);
/// Acquires the next image in the swapchain, waits as needed.
bool AcquireNextImage();
@@ -108,7 +110,7 @@ private:
bool NeedsPresentModeUpdate() const;
- VkSurfaceKHR surface;
+ VkSurfaceKHR_T* surface_handle;
const Device& device;
Scheduler& scheduler;
diff --git a/src/video_core/vulkan_common/vulkan_wrapper.h b/src/video_core/vulkan_common/vulkan_wrapper.h
index 1bb8a47bdf..aa9fb8e17b 100644
--- a/src/video_core/vulkan_common/vulkan_wrapper.h
+++ b/src/video_core/vulkan_common/vulkan_wrapper.h
@@ -430,6 +430,15 @@ public:
return handle != nullptr;
}
+ /**
+ * Releases ownership of the managed handle.
+ * The caller is responsible for managing the lifetime of the returned handle.
+ * The Handle object becomes invalid after this call.
+ */
+ Type release() noexcept {
+ return std::exchange(handle, nullptr);
+ }
+
protected:
Type handle = nullptr;
OwnerType owner = nullptr;
@@ -501,6 +510,15 @@ public:
return handle != nullptr;
}
+ /**
+ * Releases ownership of the managed handle.
+ * The caller is responsible for managing the lifetime of the returned handle.
+ * The Handle object becomes invalid after this call.
+ */
+ Type release() noexcept {
+ return std::exchange(handle, nullptr);
+ }
+
protected:
Type handle = nullptr;
const Dispatch* dld = nullptr;