From 34693001aa6e86bb543e5b8b18b3c9dc919ddde7 Mon Sep 17 00:00:00 2001 From: Zephyron Date: Sat, 12 Apr 2025 16:15:51 +1000 Subject: Add Windows support to Hybrid Memory Manager This commit adds Windows-specific implementation of the fault-managed memory system, providing similar functionality to the existing Linux/Android implementation. Key changes: - Added Windows-specific memory management using VirtualAlloc/VirtualFree - Implemented Windows vectored exception handler for page fault handling - Added proper memory protection and page fault handling on Windows - Updated memory snapshot functionality to work on Windows - Added proper cleanup of Windows-specific resources - Fixed type conversion issues in memory management code - Added proper error handling for Windows memory operations - Fixed VRAM Memory Layout Mode to allow up to 12Gb The implementation uses Windows-specific APIs: - VirtualAlloc/VirtualFree for memory management - AddVectoredExceptionHandler for page fault handling - VirtualProtect for memory protection management This change maintains feature parity with the Linux/Android implementation while using Windows-native APIs for better performance and reliability. Signed-off-by: Zephyron --- src/video_core/renderer_vulkan/renderer_vulkan.cpp | 50 ++++++++++++++++------ 1 file changed, 37 insertions(+), 13 deletions(-) (limited to 'src/video_core/renderer_vulkan/renderer_vulkan.cpp') diff --git a/src/video_core/renderer_vulkan/renderer_vulkan.cpp b/src/video_core/renderer_vulkan/renderer_vulkan.cpp index c9f6f0836c..041fb9e054 100644 --- a/src/video_core/renderer_vulkan/renderer_vulkan.cpp +++ b/src/video_core/renderer_vulkan/renderer_vulkan.cpp @@ -9,6 +9,8 @@ #include #include #include +#include +#include #include @@ -135,15 +137,37 @@ RendererVulkan::RendererVulkan(Core::Frontend::EmuWindow& emu_window, // Initialize HybridMemory system if (Settings::values.use_gpu_memory_manager.GetValue()) { -#if defined(__linux__) || defined(__ANDROID__) +#if defined(__linux__) || defined(__ANDROID__) || defined(_WIN32) try { - void* guest_memory_base = std::aligned_alloc(4096, 64 * 1024 * 1024); - if (guest_memory_base) { + // Define memory size with explicit types to avoid conversion warnings + constexpr size_t memory_size_mb = 64; + constexpr size_t memory_size_bytes = memory_size_mb * 1024 * 1024; + + void* guest_memory_base = nullptr; +#if defined(_WIN32) + // On Windows, use VirtualAlloc to reserve (but not commit) memory + const SIZE_T win_size = static_cast(memory_size_bytes); + LPVOID result = VirtualAlloc(nullptr, win_size, MEM_RESERVE, PAGE_NOACCESS); + if (result != nullptr) { + guest_memory_base = result; + } +#else + // On Linux/Android, use aligned_alloc + guest_memory_base = std::aligned_alloc(4096, memory_size_bytes); +#endif + if (guest_memory_base != nullptr) { 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) { + hybrid_memory->InitializeGuestMemory(guest_memory_base, memory_size_bytes); + LOG_INFO(Render_Vulkan, "HybridMemory initialized with {} MB of fault-managed memory", memory_size_mb); + } catch (const std::exception&) { +#if defined(_WIN32) + if (guest_memory_base != nullptr) { + const LPVOID win_ptr = static_cast(guest_memory_base); + VirtualFree(win_ptr, 0, MEM_RELEASE); + } +#else std::free(guest_memory_base); +#endif throw; } } @@ -167,10 +191,10 @@ RendererVulkan::RendererVulkan(Core::Frontend::EmuWindow& emu_window, // Add paths to common shaders that should be preloaded // These will be compiled in parallel for faster startup - if (std::filesystem::exists(shader_dir)) { - try { + try { + if (std::filesystem::exists(shader_dir)) { for (const auto& entry : std::filesystem::directory_iterator(shader_dir)) { - if (entry.path().extension() == ".spv") { + if (entry.is_regular_file() && entry.path().extension() == ".spv") { common_shaders.push_back(entry.path().string()); } } @@ -179,11 +203,11 @@ RendererVulkan::RendererVulkan(Core::Frontend::EmuWindow& emu_window, LOG_INFO(Render_Vulkan, "Preloading {} common shaders", common_shaders.size()); shader_manager.PreloadShaders(common_shaders); } - } catch (const std::exception& e) { - LOG_ERROR(Render_Vulkan, "Error during shader preloading: {}", e.what()); + } else { + LOG_INFO(Render_Vulkan, "Shader directory not found at {}", shader_dir); } - } else { - LOG_INFO(Render_Vulkan, "Shader directory not found at {}", shader_dir); + } catch (const std::exception& e) { + LOG_ERROR(Render_Vulkan, "Error during shader preloading: {}", e.what()); } } -- cgit v1.2.3