DraVee 3 months ago
committed by Caio Oliveira
parent
commit
991e37a8ca
  1. 564
      src/eden_libretro/libretro_core.cpp
  2. 10
      src/video_core/gpu.cpp
  3. 5
      src/video_core/gpu_thread.cpp

564
src/eden_libretro/libretro_core.cpp

@ -107,6 +107,202 @@ void LibretroLog(retro_log_level level, const char* fmt, ...) {
log_cb(level, "%s", buffer);
}
// Helper to get core option value
static const char* GetCoreOptionValue(const char* key) {
if (!environ_cb) return nullptr;
struct retro_variable var = { key, nullptr };
if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) {
return var.value;
}
return nullptr;
}
// Read and apply core options to Settings
void ApplyCoreOptions() {
LOG_INFO(Frontend, "Libretro: Reading core options");
// Resolution Scale
if (const char* value = GetCoreOptionValue("eden_resolution_scale")) {
int scale = 1;
if (sscanf(value, "%dx", &scale) == 1) {
Settings::ResolutionSetup setup = Settings::ResolutionSetup::Res1X;
switch (scale) {
case 1: setup = Settings::ResolutionSetup::Res1X; break;
case 2: setup = Settings::ResolutionSetup::Res2X; break;
case 3: setup = Settings::ResolutionSetup::Res3X; break;
case 4: setup = Settings::ResolutionSetup::Res4X; break;
case 5: setup = Settings::ResolutionSetup::Res5X; break;
case 6: setup = Settings::ResolutionSetup::Res6X; break;
}
Settings::values.resolution_setup.SetValue(setup);
LOG_INFO(Frontend, "Resolution Scale: {}x", scale);
}
}
// GPU Accuracy
if (const char* value = GetCoreOptionValue("eden_gpu_accuracy")) {
Settings::GpuAccuracy accuracy = Settings::GpuAccuracy::Medium;
if (strcmp(value, "Low") == 0) accuracy = Settings::GpuAccuracy::Low;
else if (strcmp(value, "Medium") == 0) accuracy = Settings::GpuAccuracy::Medium;
else if (strcmp(value, "High") == 0) accuracy = Settings::GpuAccuracy::High;
Settings::values.gpu_accuracy.SetValue(accuracy);
LOG_INFO(Frontend, "GPU Accuracy: {}", value);
}
// Scaling Filter
if (const char* value = GetCoreOptionValue("eden_scaling_filter")) {
Settings::ScalingFilter filter = Settings::ScalingFilter::Bilinear;
if (strcmp(value, "NearestNeighbor") == 0) filter = Settings::ScalingFilter::NearestNeighbor;
else if (strcmp(value, "Bilinear") == 0) filter = Settings::ScalingFilter::Bilinear;
else if (strcmp(value, "Bicubic") == 0) filter = Settings::ScalingFilter::Bicubic;
else if (strcmp(value, "Gaussian") == 0) filter = Settings::ScalingFilter::Gaussian;
else if (strcmp(value, "ScaleForce") == 0) filter = Settings::ScalingFilter::ScaleForce;
else if (strcmp(value, "Fsr") == 0) filter = Settings::ScalingFilter::Fsr;
Settings::values.scaling_filter.SetValue(filter);
LOG_INFO(Frontend, "Scaling Filter: {}", value);
}
// Anti-Aliasing
if (const char* value = GetCoreOptionValue("eden_anti_aliasing")) {
Settings::AntiAliasing aa = Settings::AntiAliasing::None;
if (strcmp(value, "None") == 0) aa = Settings::AntiAliasing::None;
else if (strcmp(value, "Fxaa") == 0) aa = Settings::AntiAliasing::Fxaa;
else if (strcmp(value, "Smaa") == 0) aa = Settings::AntiAliasing::Smaa;
Settings::values.anti_aliasing.SetValue(aa);
LOG_INFO(Frontend, "Anti-Aliasing: {}", value);
}
// Anisotropic Filtering
if (const char* value = GetCoreOptionValue("eden_anisotropic_filtering")) {
Settings::AnisotropyMode aniso = Settings::AnisotropyMode::Automatic;
if (strcmp(value, "Automatic") == 0) aniso = Settings::AnisotropyMode::Automatic;
else if (strcmp(value, "Default") == 0) aniso = Settings::AnisotropyMode::Default;
else if (strcmp(value, "X2") == 0) aniso = Settings::AnisotropyMode::X2;
else if (strcmp(value, "X4") == 0) aniso = Settings::AnisotropyMode::X4;
else if (strcmp(value, "X8") == 0) aniso = Settings::AnisotropyMode::X8;
else if (strcmp(value, "X16") == 0) aniso = Settings::AnisotropyMode::X16;
Settings::values.max_anisotropy.SetValue(aniso);
LOG_INFO(Frontend, "Anisotropic Filtering: {}", value);
}
// ASTC Decode
if (const char* value = GetCoreOptionValue("eden_astc_decode")) {
Settings::AstcDecodeMode decode = Settings::AstcDecodeMode::Gpu;
if (strcmp(value, "Cpu") == 0) decode = Settings::AstcDecodeMode::Cpu;
else if (strcmp(value, "Gpu") == 0) decode = Settings::AstcDecodeMode::Gpu;
else if (strcmp(value, "CpuAsynchronous") == 0) decode = Settings::AstcDecodeMode::CpuAsynchronous;
Settings::values.accelerate_astc.SetValue(decode);
LOG_INFO(Frontend, "ASTC Decode: {}", value);
}
// Shader Backend
if (const char* value = GetCoreOptionValue("eden_shader_backend")) {
Settings::ShaderBackend backend = Settings::ShaderBackend::SpirV;
if (strcmp(value, "Glsl") == 0) backend = Settings::ShaderBackend::Glsl;
else if (strcmp(value, "Glasm") == 0) backend = Settings::ShaderBackend::Glasm;
else if (strcmp(value, "SpirV") == 0) backend = Settings::ShaderBackend::SpirV;
Settings::values.shader_backend.SetValue(backend);
LOG_INFO(Frontend, "Shader Backend: {}", value);
}
// Docked Mode
if (const char* value = GetCoreOptionValue("eden_docked_mode")) {
Settings::ConsoleMode mode = Settings::ConsoleMode::Docked;
if (strcmp(value, "Docked") == 0) mode = Settings::ConsoleMode::Docked;
else if (strcmp(value, "Handheld") == 0) mode = Settings::ConsoleMode::Handheld;
Settings::values.use_docked_mode.SetValue(mode);
LOG_INFO(Frontend, "Console Mode: {}", value);
}
// Language
if (const char* value = GetCoreOptionValue("eden_language")) {
Settings::Language lang = Settings::Language::EnglishAmerican;
if (strcmp(value, "Japanese") == 0) lang = Settings::Language::Japanese;
else if (strcmp(value, "EnglishAmerican") == 0) lang = Settings::Language::EnglishAmerican;
else if (strcmp(value, "French") == 0) lang = Settings::Language::French;
else if (strcmp(value, "German") == 0) lang = Settings::Language::German;
else if (strcmp(value, "Italian") == 0) lang = Settings::Language::Italian;
else if (strcmp(value, "Spanish") == 0) lang = Settings::Language::Spanish;
else if (strcmp(value, "Chinese") == 0) lang = Settings::Language::Chinese;
else if (strcmp(value, "Korean") == 0) lang = Settings::Language::Korean;
else if (strcmp(value, "Dutch") == 0) lang = Settings::Language::Dutch;
else if (strcmp(value, "Portuguese") == 0) lang = Settings::Language::Portuguese;
else if (strcmp(value, "Russian") == 0) lang = Settings::Language::Russian;
else if (strcmp(value, "EnglishBritish") == 0) lang = Settings::Language::EnglishBritish;
Settings::values.language_index.SetValue(lang);
LOG_INFO(Frontend, "Language: {}", value);
}
// Region
if (const char* value = GetCoreOptionValue("eden_region")) {
Settings::Region region = Settings::Region::Usa;
if (strcmp(value, "Japan") == 0) region = Settings::Region::Japan;
else if (strcmp(value, "Usa") == 0) region = Settings::Region::Usa;
else if (strcmp(value, "Europe") == 0) region = Settings::Region::Europe;
else if (strcmp(value, "Australia") == 0) region = Settings::Region::Australia;
else if (strcmp(value, "China") == 0) region = Settings::Region::China;
else if (strcmp(value, "Korea") == 0) region = Settings::Region::Korea;
else if (strcmp(value, "Taiwan") == 0) region = Settings::Region::Taiwan;
Settings::values.region_index.SetValue(region);
LOG_INFO(Frontend, "Region: {}", value);
}
// Multicore CPU
if (const char* value = GetCoreOptionValue("eden_use_multicore")) {
bool multicore = (strcmp(value, "enabled") == 0);
Settings::values.use_multi_core.SetValue(multicore);
LOG_INFO(Frontend, "Multicore CPU: {}", multicore);
}
// CPU Accuracy
if (const char* value = GetCoreOptionValue("eden_cpu_accuracy")) {
Settings::CpuAccuracy accuracy = Settings::CpuAccuracy::Auto;
if (strcmp(value, "Auto") == 0) accuracy = Settings::CpuAccuracy::Auto;
else if (strcmp(value, "Accurate") == 0) accuracy = Settings::CpuAccuracy::Accurate;
else if (strcmp(value, "Unsafe") == 0) accuracy = Settings::CpuAccuracy::Unsafe;
else if (strcmp(value, "Paranoid") == 0) accuracy = Settings::CpuAccuracy::Paranoid;
Settings::values.cpu_accuracy.SetValue(accuracy);
LOG_INFO(Frontend, "CPU Accuracy: {}", value);
}
// Async GPU (force off for libretro, but read in case user changes)
if (const char* value = GetCoreOptionValue("eden_use_async_gpu")) {
bool async_gpu = (strcmp(value, "enabled") == 0);
// Always force to false for libretro
Settings::values.use_asynchronous_gpu_emulation.SetValue(false);
if (async_gpu) {
LOG_WARNING(Frontend, "Async GPU requested but FORCED OFF for libretro compatibility");
}
}
// Disk Shader Cache
if (const char* value = GetCoreOptionValue("eden_disk_shader_cache")) {
bool cache = (strcmp(value, "enabled") == 0);
Settings::values.use_disk_shader_cache.SetValue(cache);
LOG_INFO(Frontend, "Disk Shader Cache: {}", cache);
}
// Reactive Flushing
if (const char* value = GetCoreOptionValue("eden_reactive_flushing")) {
bool flushing = (strcmp(value, "enabled") == 0);
Settings::values.use_reactive_flushing.SetValue(flushing);
LOG_INFO(Frontend, "Reactive Flushing: {}", flushing);
}
// ASTC Recompression
if (const char* value = GetCoreOptionValue("eden_astc_recompression")) {
Settings::AstcRecompression recomp = Settings::AstcRecompression::Uncompressed;
if (strcmp(value, "Uncompressed") == 0) recomp = Settings::AstcRecompression::Uncompressed;
else if (strcmp(value, "Bc1") == 0) recomp = Settings::AstcRecompression::Bc1;
else if (strcmp(value, "Bc3") == 0) recomp = Settings::AstcRecompression::Bc3;
Settings::values.astc_recompression.SetValue(recomp);
LOG_INFO(Frontend, "ASTC Recompression: {}", value);
}
LOG_INFO(Frontend, "Libretro: Core options applied");
}
// Context reset callback - called when OpenGL context is ready
void ContextReset() {
try {
@ -351,16 +547,315 @@ void retro_set_environment(retro_environment_t cb) {
bool need_fullpath = true;
environ_cb(RETRO_ENVIRONMENT_SET_SUPPORT_NO_GAME, &need_fullpath);
// Set core options
// Try v2 core options with categories first
static struct retro_core_option_v2_category option_cats[] = {
{ "graphics", "Graphics", "Configure graphics rendering settings." },
{ "system", "System", "Configure system and emulation settings." },
{ "cpu", "CPU", "Configure CPU emulation settings." },
{ "advanced", "Advanced", "Advanced performance and optimization settings." },
{ nullptr, nullptr, nullptr }
};
static struct retro_core_option_v2_definition option_defs[] = {
// Graphics Category
{
"eden_resolution_scale",
"Internal Resolution",
"Internal Resolution",
"Rendering resolution multiplier. Higher values improve visual quality but reduce performance.",
"Rendering resolution multiplier.",
"graphics",
{
{ "1x", "1x (1280x720)" },
{ "2x", "2x (2560x1440)" },
{ "3x", "3x (3840x2160)" },
{ "4x", "4x (5120x2880)" },
{ "5x", "5x (6400x3600)" },
{ "6x", "6x (7680x4320)" },
{ nullptr, nullptr }
},
"1x"
},
{
"eden_gpu_accuracy",
"GPU Accuracy",
"GPU Accuracy",
"Graphics emulation accuracy. Higher accuracy improves compatibility but reduces performance.",
"Graphics emulation accuracy.",
"graphics",
{
{ "Low", "Low" },
{ "Medium", "Medium" },
{ "High", "High" },
{ nullptr, nullptr }
},
"Medium"
},
{
"eden_scaling_filter",
"Scaling Filter",
"Scaling Filter",
"Upscaling filter applied when internal resolution is higher than native. FSR provides good quality.",
"Upscaling filter method.",
"graphics",
{
{ "Bilinear", "Bilinear" },
{ "Bicubic", "Bicubic" },
{ "Gaussian", "Gaussian" },
{ "ScaleForce", "ScaleForce" },
{ "Fsr", "FSR (AMD FidelityFX)" },
{ "NearestNeighbor", "Nearest Neighbor" },
{ nullptr, nullptr }
},
"Bilinear"
},
{
"eden_anti_aliasing",
"Anti-Aliasing",
"Anti-Aliasing",
"Post-process anti-aliasing. FXAA is faster, SMAA has better quality.",
"Post-process anti-aliasing.",
"graphics",
{
{ "None", "None" },
{ "Fxaa", "FXAA" },
{ "Smaa", "SMAA" },
{ nullptr, nullptr }
},
"None"
},
{
"eden_anisotropic_filtering",
"Anisotropic Filtering",
"Anisotropic Filtering",
"Texture filtering quality. Higher values improve texture sharpness at angles.",
"Texture filtering quality.",
"graphics",
{
{ "Automatic", "Automatic" },
{ "Default", "Default" },
{ "X2", "2x" },
{ "X4", "4x" },
{ "X8", "8x" },
{ "X16", "16x" },
{ nullptr, nullptr }
},
"Automatic"
},
{
"eden_astc_decode",
"ASTC Texture Decode",
"ASTC Texture Decode",
"Method for decoding ASTC textures. GPU is fastest. CPU Async balances quality and performance.",
"ASTC texture decoding method.",
"graphics",
{
{ "Gpu", "GPU" },
{ "Cpu", "CPU" },
{ "CpuAsynchronous", "CPU Asynchronous" },
{ nullptr, nullptr }
},
"Gpu"
},
{
"eden_shader_backend",
"Shader Backend",
"Shader Backend",
"Shader compilation backend. SPIRV is recommended for better compatibility.",
"Shader compilation backend.",
"graphics",
{
{ "SpirV", "SPIRV" },
{ "Glsl", "GLSL" },
{ "Glasm", "GLASM" },
{ nullptr, nullptr }
},
"SpirV"
},
// System Category
{
"eden_docked_mode",
"Console Mode",
"Console Mode",
"Docked mode runs at higher resolution/performance. Handheld mode saves power.",
"Switch console operating mode.",
"system",
{
{ "Docked", "Docked" },
{ "Handheld", "Handheld" },
{ nullptr, nullptr }
},
"Docked"
},
{
"eden_language",
"System Language",
"System Language",
"In-game language. Some games may not support all languages.",
"System language setting.",
"system",
{
{ "EnglishAmerican", "English (US)" },
{ "EnglishBritish", "English (UK)" },
{ "Japanese", "Japanese" },
{ "French", "French" },
{ "German", "German" },
{ "Italian", "Italian" },
{ "Spanish", "Spanish" },
{ "Chinese", "Chinese" },
{ "Korean", "Korean" },
{ "Dutch", "Dutch" },
{ "Portuguese", "Portuguese" },
{ "Russian", "Russian" },
{ nullptr, nullptr }
},
"EnglishAmerican"
},
{
"eden_region",
"System Region",
"System Region",
"System region setting. Affects regional game content.",
"System region.",
"system",
{
{ "Usa", "USA" },
{ "Europe", "Europe" },
{ "Japan", "Japan" },
{ "Australia", "Australia" },
{ "China", "China" },
{ "Korea", "Korea" },
{ "Taiwan", "Taiwan" },
{ nullptr, nullptr }
},
"Usa"
},
// CPU Category
{
"eden_use_multicore",
"Multicore CPU Emulation",
"Multicore CPU Emulation",
"Enable multi-threaded CPU emulation. Improves performance on multi-core systems.",
"Multi-threaded CPU emulation.",
"cpu",
{
{ "enabled", "Enabled" },
{ "disabled", "Disabled" },
{ nullptr, nullptr }
},
"enabled"
},
{
"eden_cpu_accuracy",
"CPU Accuracy",
"CPU Accuracy",
"CPU emulation accuracy. Auto is recommended. Unsafe improves performance but may cause issues.",
"CPU emulation accuracy level.",
"cpu",
{
{ "Auto", "Auto" },
{ "Accurate", "Accurate" },
{ "Unsafe", "Unsafe" },
{ "Paranoid", "Paranoid" },
{ nullptr, nullptr }
},
"Auto"
},
// Advanced Category
{
"eden_use_async_gpu",
"Async GPU Emulation",
"Async GPU Emulation",
"MUST be disabled for libretro. Separate GPU thread incompatible with RetroArch.",
"Async GPU (libretro incompatible).",
"advanced",
{
{ "disabled", "Disabled (Required)" },
{ "enabled", "Enabled (Broken)" },
{ nullptr, nullptr }
},
"disabled"
},
{
"eden_disk_shader_cache",
"Disk Shader Cache",
"Disk Shader Cache",
"Cache compiled shaders to disk. Reduces stuttering on subsequent runs.",
"Disk shader caching.",
"advanced",
{
{ "enabled", "Enabled" },
{ "disabled", "Disabled" },
{ nullptr, nullptr }
},
"enabled"
},
{
"eden_reactive_flushing",
"Reactive Memory Flushing",
"Reactive Memory Flushing",
"Memory synchronization optimization. Improves performance.",
"Reactive memory flushing.",
"advanced",
{
{ "enabled", "Enabled" },
{ "disabled", "Disabled" },
{ nullptr, nullptr }
},
"enabled"
},
{
"eden_astc_recompression",
"ASTC Recompression",
"ASTC Recompression",
"Recompress ASTC textures to save VRAM. BC1 for opaque, BC3 for transparent.",
"ASTC texture recompression.",
"advanced",
{
{ "Uncompressed", "Uncompressed" },
{ "Bc1", "BC1" },
{ "Bc3", "BC3" },
{ nullptr, nullptr }
},
"Uncompressed"
},
{ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, {{ nullptr, nullptr }}, nullptr }
};
struct retro_core_options_v2 options_v2 = {
option_cats,
option_defs
};
// Try v2 first, fall back to v1 if not supported
unsigned version = 0;
if (environ_cb(RETRO_ENVIRONMENT_GET_CORE_OPTIONS_VERSION, &version) && version >= 2) {
environ_cb(RETRO_ENVIRONMENT_SET_CORE_OPTIONS_V2, &options_v2);
LibretroLog(RETRO_LOG_INFO, "Eden: Using v2 core options\n");
} else {
// v1 fallback for older RetroArch
static const struct retro_variable variables[] = {
{ "eden_resolution_scale", "Resolution Scale; 1x|2x|3x|4x" },
{ "eden_use_vsync", "VSync; On|Off" },
{ "eden_use_async_gpu", "Async GPU; On|Off" },
{ "eden_use_multicore", "Multicore CPU; On|Off" },
{ "eden_shader_backend", "Shader Backend; GLSL|SPIRV" },
{ "eden_resolution_scale", "Internal Resolution; 1x|2x|3x|4x|5x|6x" },
{ "eden_gpu_accuracy", "GPU Accuracy; Medium|Low|High" },
{ "eden_scaling_filter", "Scaling Filter; Bilinear|Bicubic|Gaussian|ScaleForce|Fsr|NearestNeighbor" },
{ "eden_anti_aliasing", "Anti-Aliasing; None|Fxaa|Smaa" },
{ "eden_anisotropic_filtering", "Anisotropic Filtering; Automatic|Default|X2|X4|X8|X16" },
{ "eden_astc_decode", "ASTC Texture Decode; Gpu|Cpu|CpuAsynchronous" },
{ "eden_shader_backend", "Shader Backend; SpirV|Glsl|Glasm" },
{ "eden_docked_mode", "Console Mode; Docked|Handheld" },
{ "eden_language", "System Language; EnglishAmerican|EnglishBritish|Japanese|French|German|Italian|Spanish|Chinese|Korean|Dutch|Portuguese|Russian" },
{ "eden_region", "System Region; Usa|Europe|Japan|Australia|China|Korea|Taiwan" },
{ "eden_use_multicore", "Multicore CPU Emulation; enabled|disabled" },
{ "eden_cpu_accuracy", "CPU Accuracy; Auto|Accurate|Unsafe|Paranoid" },
{ "eden_use_async_gpu", "Async GPU Emulation; disabled|enabled" },
{ "eden_disk_shader_cache", "Disk Shader Cache; enabled|disabled" },
{ "eden_reactive_flushing", "Reactive Memory Flushing; enabled|disabled" },
{ "eden_astc_recompression", "ASTC Recompression; Uncompressed|Bc1|Bc3" },
{ nullptr, nullptr }
};
environ_cb(RETRO_ENVIRONMENT_SET_VARIABLES, (void*)variables);
LibretroLog(RETRO_LOG_INFO, "Eden: Using v1 core options\n");
}
// Set input descriptors
static const struct retro_input_descriptor input_desc[] = {
@ -461,44 +956,48 @@ void retro_init(void) {
}
void retro_deinit(void) {
try {
LOG_INFO(Frontend, "Libretro: retro_deinit called");
LibretroLog(RETRO_LOG_INFO, "Eden: Deinitializing (frame_count: %llu)\n", frame_count.load());
is_initialized = false;
// Mark as not running first to stop any processing
is_running = false;
is_initialized = false;
hw_context_ready = false;
// Shutdown system if still active (may have been shut down by retro_unload_game)
if (emu_system) {
LOG_INFO(Frontend, "Shutting down emulation system");
try {
// Notify GPU of shutdown first
if (emu_system->IsPoweredOn()) {
emu_system->GPU().NotifyShutdown();
}
emu_system->ShutdownMainProcess();
} catch (...) {
// Ignore errors during shutdown
}
emu_system.reset();
LOG_INFO(Frontend, "System shutdown complete");
}
// Reset window after system
emu_window.reset();
// Shutdown input
if (input_subsystem) {
try {
input_subsystem->Shutdown();
} catch (...) {}
input_subsystem.reset();
}
// Wait for detached tasks
if (detached_tasks) {
try {
detached_tasks->WaitForAllTasks();
} catch (...) {}
detached_tasks.reset();
}
LibretroLog(RETRO_LOG_INFO, "Eden: Deinitialized\n");
} catch (const std::exception& e) {
LOG_CRITICAL(Frontend, "EXCEPTION in retro_deinit: {}", e.what());
if (log_cb) {
log_cb(RETRO_LOG_ERROR, "Eden: Exception in deinit: %s\n", e.what());
}
} catch (...) {
LOG_CRITICAL(Frontend, "UNKNOWN EXCEPTION in retro_deinit");
if (log_cb) {
log_cb(RETRO_LOG_ERROR, "Eden: Unknown exception in deinit\n");
}
}
}
unsigned retro_api_version(void) {
@ -666,8 +1165,8 @@ bool retro_load_game(const struct retro_game_info* game) {
// CRITICAL: Use sync GPU mode for libretro - OpenGL context is only valid on main thread
Settings::values.use_asynchronous_gpu_emulation.SetValue(false);
// Apply settings
emu_system->ApplySettings();
// Read core options from RetroArch
ApplyCoreOptions();
// Set up filesystem
emu_system->SetContentProvider(std::make_unique<FileSys::ContentProviderUnion>());
@ -694,16 +1193,33 @@ bool retro_load_game_special(unsigned game_type, const struct retro_game_info* i
void retro_unload_game(void) {
LOG_INFO(Frontend, "Libretro: Unloading game");
// Stop running first
is_running = false;
game_loaded = false;
hw_context_ready = false;
if (emu_system) {
try {
// Pause first
emu_system->Pause();
// Notify GPU shutdown before main shutdown
if (emu_system->IsPoweredOn()) {
emu_system->GPU().NotifyShutdown();
// Give GPU time to process shutdown
std::this_thread::sleep_for(std::chrono::milliseconds(50));
}
emu_system->ShutdownMainProcess();
} catch (...) {
// Ignore errors during shutdown
}
emu_system.reset();
}
emu_window.reset();
// Don't reset emu_window here - let retro_deinit handle it
// This avoids double-free issues
game_path.clear();
LibretroLog(RETRO_LOG_INFO, "Eden: Game unloaded\n");

10
src/video_core/gpu.cpp

@ -127,7 +127,6 @@ struct GPU::Impl {
void WaitForSyncOperation(const u64 fence) {
// In deferred mode, process sync operations immediately since we're on main thread
if (gpu_thread.IsDeferredMode()) {
LOG_DEBUG(HW_GPU, "WaitForSyncOperation: deferred mode, calling TickWork");
TickWork();
return;
}
@ -138,10 +137,6 @@ struct GPU::Impl {
/// Tick pending requests within the GPU.
void TickWork() {
std::unique_lock lck{sync_request_mutex};
size_t request_count = sync_requests.size();
if (request_count > 0) {
LOG_DEBUG(HW_GPU, "TickWork: processing {} sync requests", request_count);
}
while (!sync_requests.empty()) {
auto request = std::move(sync_requests.front());
sync_requests.pop_front();
@ -300,14 +295,10 @@ struct GPU::Impl {
void RequestComposite(std::vector<Tegra::FramebufferConfig>&& layers,
std::vector<Service::Nvidia::NvFence>&& fences) {
LOG_INFO(HW_GPU, "RequestComposite called with {} layers, {} fences, deferred_mode={}",
layers.size(), fences.size(), gpu_thread.IsDeferredMode());
// In deferred mode, queue composite for main thread execution
if (gpu_thread.IsDeferredMode()) {
std::lock_guard lk(pending_composites_mutex);
pending_composites.push_back(std::move(layers));
LOG_INFO(HW_GPU, "Deferred mode: queued composite, {} pending", pending_composites.size());
return;
}
@ -569,7 +560,6 @@ void GPU::ProcessPendingComposites() {
}
for (auto& layers : composites_to_process) {
LOG_INFO(HW_GPU, "Processing queued composite with {} layers", layers.size());
impl->renderer->Composite(layers);
}
}

5
src/video_core/gpu_thread.cpp

@ -71,7 +71,6 @@ void ThreadManager::StartThread(VideoCore::RendererBase& renderer,
// In deferred mode, don't start the GPU thread - commands will be processed on main thread
if (deferred_mode) {
LOG_INFO(HW_GPU, "GPU deferred mode enabled - thread not started");
return;
}
@ -146,10 +145,6 @@ void ThreadManager::ProcessPendingCommands() {
deferred_commands.clear();
}
if (!commands_to_process.empty()) {
LOG_DEBUG(HW_GPU, "ProcessPendingCommands: processing {} commands", commands_to_process.size());
}
for (auto& cmd : commands_to_process) {
if (auto* submit_list = std::get_if<SubmitListCommand>(&cmd.data)) {
scheduler_ptr->Push(submit_list->channel, std::move(submit_list->entries));

Loading…
Cancel
Save