diff options
| author | Zephyron <zephyron@citron-emu.org> | 2025-04-10 20:22:00 +1000 |
|---|---|---|
| committer | MrPurple666 <antoniosacramento666usa@gmail.com> | 2025-04-12 23:41:26 -0300 |
| commit | 9615e910f90ea0af0c616eed5329b176d4700d7f (patch) | |
| tree | 3b60c22c61941eae8ed2cb76764c5e4a49529dd1 /src/video_core/renderer_vulkan/renderer_vulkan.cpp | |
| parent | 0c5659a198816ef09b554308c12cea0b5d6220e9 (diff) | |
feat(video_core): Implement HybridMemory for advanced Vulkan memory management
Adds a new cross-platform memory management system with enhanced capabilities:
- Fault-managed memory allocation for Linux/Android platforms
- Memory snapshot and differential snapshot support
- Predictive memory reuse tracking for optimized access patterns
- Vulkan compute buffer integration
- User-configurable settings for enabling features
The system integrates with the existing Vulkan renderer to provide more
efficient memory handling, especially for compute-intensive workloads.
Co-authored-by: boss.sfc <boss.sfc@citron-emu.org>
Co-committed-by: boss.sfc <boss.sfc@citron-emu.org>
Signed-off-by: Zephyron <zephyron@citron-emu.org>
Diffstat (limited to 'src/video_core/renderer_vulkan/renderer_vulkan.cpp')
| -rw-r--r-- | src/video_core/renderer_vulkan/renderer_vulkan.cpp | 70 |
1 files changed, 70 insertions, 0 deletions
diff --git a/src/video_core/renderer_vulkan/renderer_vulkan.cpp b/src/video_core/renderer_vulkan/renderer_vulkan.cpp index e301dd7aef..c9f6f0836c 100644 --- a/src/video_core/renderer_vulkan/renderer_vulkan.cpp +++ b/src/video_core/renderer_vulkan/renderer_vulkan.cpp @@ -34,6 +34,7 @@ #include "video_core/vulkan_common/vulkan_instance.h" #include "video_core/vulkan_common/vulkan_library.h" #include "video_core/vulkan_common/vulkan_memory_allocator.h" +#include "video_core/vulkan_common/hybrid_memory.h" #include "video_core/vulkan_common/vulkan_surface.h" #include "video_core/vulkan_common/vulkan_wrapper.h" #ifdef __ANDROID__ @@ -123,6 +124,7 @@ RendererVulkan::RendererVulkan(Core::Frontend::EmuWindow& emu_window, PresentFiltersForAppletCapture), rasterizer(render_window, gpu, device_memory, device, memory_allocator, state_tracker, scheduler), + hybrid_memory(std::make_unique<HybridMemory>(device, memory_allocator)), texture_manager(device, memory_allocator), shader_manager(device), applet_frame() { @@ -131,6 +133,28 @@ RendererVulkan::RendererVulkan(Core::Frontend::EmuWindow& emu_window, scheduler.RegisterOnSubmit([this] { turbo_mode->QueueSubmitted(); }); } + // Initialize HybridMemory system + if (Settings::values.use_gpu_memory_manager.GetValue()) { +#if defined(__linux__) || defined(__ANDROID__) + try { + void* guest_memory_base = std::aligned_alloc(4096, 64 * 1024 * 1024); + if (guest_memory_base) { + try { + hybrid_memory->InitializeGuestMemory(guest_memory_base, 64 * 1024 * 1024); + LOG_INFO(Render_Vulkan, "HybridMemory initialized with {} MB of fault-managed memory", 64); + } catch (const std::exception& e) { + std::free(guest_memory_base); + throw; + } + } + } catch (const std::exception& e) { + LOG_ERROR(Render_Vulkan, "Failed to initialize HybridMemory: {}", e.what()); + } +#else + LOG_INFO(Render_Vulkan, "Fault-managed memory not supported on this platform"); +#endif + } + // Initialize enhanced shader compilation system shader_manager.SetScheduler(&scheduler); LOG_INFO(Render_Vulkan, "Enhanced shader compilation system initialized"); @@ -389,6 +413,35 @@ void RendererVulkan::RenderScreenshot(std::span<const Tegra::FramebufferConfig> return; } + // If memory snapshots are enabled, take a snapshot with the screenshot + if (Settings::values.enable_memory_snapshots.GetValue() && hybrid_memory) { + try { + const auto now = std::chrono::system_clock::now(); + const auto now_time_t = std::chrono::system_clock::to_time_t(now); + std::tm local_tm; +#ifdef _WIN32 + localtime_s(&local_tm, &now_time_t); +#else + localtime_r(&now_time_t, &local_tm); +#endif + char time_str[128]; + std::strftime(time_str, sizeof(time_str), "%Y%m%d_%H%M%S", &local_tm); + + std::string snapshot_path = fmt::format("snapshots/memory_snapshot_{}.bin", time_str); + hybrid_memory->SaveSnapshot(snapshot_path); + + // Also save a differential snapshot if there's been a previous snapshot + if (Settings::values.use_gpu_memory_manager.GetValue()) { + std::string diff_path = fmt::format("snapshots/diff_snapshot_{}.bin", time_str); + hybrid_memory->SaveDifferentialSnapshot(diff_path); + hybrid_memory->ResetDirtyTracking(); + LOG_INFO(Render_Vulkan, "Memory snapshots saved with screenshot"); + } + } catch (const std::exception& e) { + LOG_ERROR(Render_Vulkan, "Failed to save memory snapshot: {}", e.what()); + } + } + const auto& layout{renderer_settings.screenshot_framebuffer_layout}; const auto dst_buffer = RenderToBuffer(framebuffers, layout, VK_FORMAT_B8G8R8A8_UNORM, layout.width * layout.height * 4); @@ -498,6 +551,23 @@ void RendererVulkan::InitializePlatformSpecific() { #else LOG_INFO(Render_Vulkan, "Platform-specific Vulkan initialization not implemented for this platform"); #endif + + // Create a compute buffer using the HybridMemory system if enabled + if (Settings::values.use_gpu_memory_manager.GetValue()) { + try { + // Create a small compute buffer for testing + const VkDeviceSize buffer_size = 1 * 1024 * 1024; // 1 MB + ComputeBuffer compute_buffer = hybrid_memory->CreateComputeBuffer( + buffer_size, + VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT | + VK_BUFFER_USAGE_TRANSFER_DST_BIT, + MemoryUsage::DeviceLocal); + + LOG_INFO(Render_Vulkan, "Successfully created compute buffer using HybridMemory"); + } catch (const std::exception& e) { + LOG_ERROR(Render_Vulkan, "Failed to create compute buffer: {}", e.what()); + } + } } } // namespace Vulkan |
