mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-30 21:30:04 +00:00 
			
		
		
		
	renderer_vulkan: Address vulkan surface recreation issues (#198)
This commit is contained in:
		
							parent
							
								
									55748d7d1a
								
							
						
					
					
						commit
						959a66d839
					
				
					 9 changed files with 24 additions and 34 deletions
				
			
		|  | @ -29,7 +29,7 @@ android { | |||
|     namespace = "org.citra.citra_emu" | ||||
| 
 | ||||
|     compileSdkVersion = "android-34" | ||||
|     ndkVersion = "26.1.10909125" | ||||
|     ndkVersion = "26.3.11579264" | ||||
| 
 | ||||
|     compileOptions { | ||||
|         sourceCompatibility = JavaVersion.VERSION_17 | ||||
|  |  | |||
|  | @ -38,7 +38,6 @@ import org.citra.citra_emu.features.settings.model.view.InputBindingSetting | |||
| import org.citra.citra_emu.fragments.MessageDialogFragment | ||||
| import org.citra.citra_emu.utils.ControllerMappingHelper | ||||
| import org.citra.citra_emu.utils.FileBrowserHelper | ||||
| import org.citra.citra_emu.utils.ForegroundService | ||||
| import org.citra.citra_emu.utils.EmulationLifecycleUtil | ||||
| import org.citra.citra_emu.utils.EmulationMenuSettings | ||||
| import org.citra.citra_emu.utils.ThemeUtil | ||||
|  | @ -47,7 +46,6 @@ import org.citra.citra_emu.viewmodel.EmulationViewModel | |||
| class EmulationActivity : AppCompatActivity() { | ||||
|     private val preferences: SharedPreferences | ||||
|         get() = PreferenceManager.getDefaultSharedPreferences(CitraApplication.appContext) | ||||
|     private var foregroundService: Intent? = null | ||||
|     var isActivityRecreated = false | ||||
| 
 | ||||
|     private val settingsViewModel: SettingsViewModel by viewModels() | ||||
|  | @ -85,10 +83,6 @@ class EmulationActivity : AppCompatActivity() { | |||
|             windowManager.defaultDisplay.rotation | ||||
|         ) | ||||
| 
 | ||||
|         // Start a foreground service to prevent the app from getting killed in the background | ||||
|         foregroundService = Intent(this, ForegroundService::class.java) | ||||
|         startForegroundService(foregroundService) | ||||
| 
 | ||||
|         EmulationLifecycleUtil.addShutdownHook(hook = { this.finish() }) | ||||
|     } | ||||
| 
 | ||||
|  | @ -112,7 +106,6 @@ class EmulationActivity : AppCompatActivity() { | |||
| 
 | ||||
|     override fun onDestroy() { | ||||
|         EmulationLifecycleUtil.clear() | ||||
|         stopForegroundService(this) | ||||
|         super.onDestroy() | ||||
|     } | ||||
| 
 | ||||
|  | @ -452,12 +445,4 @@ class EmulationActivity : AppCompatActivity() { | |||
| 
 | ||||
|             OnFilePickerResult(result.toString()) | ||||
|         } | ||||
| 
 | ||||
|     companion object { | ||||
|         fun stopForegroundService(activity: Activity) { | ||||
|             val startIntent = Intent(activity, ForegroundService::class.java) | ||||
|             startIntent.action = ForegroundService.ACTION_STOP | ||||
|             activity.startForegroundService(startIntent) | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  |  | |||
|  | @ -156,9 +156,6 @@ class MainActivity : AppCompatActivity(), ThemeProvider { | |||
|             } | ||||
|         } | ||||
| 
 | ||||
|         // Dismiss previous notifications (should not happen unless a crash occurred) | ||||
|         EmulationActivity.stopForegroundService(this) | ||||
| 
 | ||||
|         setInsets() | ||||
|     } | ||||
| 
 | ||||
|  | @ -170,7 +167,6 @@ class MainActivity : AppCompatActivity(), ThemeProvider { | |||
|     } | ||||
| 
 | ||||
|     override fun onDestroy() { | ||||
|         EmulationActivity.stopForegroundService(this) | ||||
|         super.onDestroy() | ||||
|     } | ||||
| 
 | ||||
|  |  | |||
|  | @ -27,14 +27,18 @@ static void UpdateLandscapeScreenLayout() { | |||
|             IDCache::GetNativeLibraryClass(), IDCache::GetLandscapeScreenLayout())); | ||||
| } | ||||
| 
 | ||||
| void EmuWindow_Android::OnSurfaceChanged(ANativeWindow* surface) { | ||||
|     render_window = surface; | ||||
| bool EmuWindow_Android::OnSurfaceChanged(ANativeWindow* surface) { | ||||
|     if (render_window == surface) { | ||||
|         return false; | ||||
|     } | ||||
| 
 | ||||
|     render_window = surface; | ||||
|     window_info.type = Frontend::WindowSystemType::Android; | ||||
|     window_info.render_surface = surface; | ||||
| 
 | ||||
|     StopPresenting(); | ||||
|     OnFramebufferSizeChanged(); | ||||
|     return true; | ||||
| } | ||||
| 
 | ||||
| bool EmuWindow_Android::OnTouchEvent(int x, int y, bool pressed) { | ||||
|  |  | |||
|  | @ -17,7 +17,7 @@ public: | |||
|     ~EmuWindow_Android(); | ||||
| 
 | ||||
|     /// Called by the onSurfaceChanges() method to change the surface
 | ||||
|     void OnSurfaceChanged(ANativeWindow* surface); | ||||
|     bool OnSurfaceChanged(ANativeWindow* surface); | ||||
| 
 | ||||
|     /// Handles touch event that occur.(Touched or released)
 | ||||
|     bool OnTouchEvent(int x, int y, bool pressed); | ||||
|  |  | |||
|  | @ -294,12 +294,13 @@ void Java_org_citra_citra_1emu_NativeLibrary_surfaceChanged(JNIEnv* env, | |||
|                                                             jobject surf) { | ||||
|     s_surf = ANativeWindow_fromSurface(env, surf); | ||||
| 
 | ||||
|     bool notify = false; | ||||
|     if (window) { | ||||
|         window->OnSurfaceChanged(s_surf); | ||||
|         notify = window->OnSurfaceChanged(s_surf); | ||||
|     } | ||||
| 
 | ||||
|     auto& system = Core::System::GetInstance(); | ||||
|     if (system.IsPoweredOn()) { | ||||
|     if (notify && system.IsPoweredOn()) { | ||||
|         system.GPU().Renderer().NotifySurfaceChanged(); | ||||
|     } | ||||
| 
 | ||||
|  |  | |||
|  | @ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME | |||
| distributionPath=wrapper/dists | ||||
| zipStoreBase=GRADLE_USER_HOME | ||||
| zipStorePath=wrapper/dists | ||||
| distributionUrl=https\://services.gradle.org/distributions/gradle-8.2-bin.zip | ||||
| distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip | ||||
|  |  | |||
|  | @ -473,7 +473,7 @@ void PresentWindow::CopyToSwapchain(Frame* frame) { | |||
|         .pSignalSemaphores = &present_ready, | ||||
|     }; | ||||
| 
 | ||||
|     std::scoped_lock submit_lock{scheduler.submit_mutex}; | ||||
|     std::scoped_lock submit_lock{scheduler.submit_mutex, recreate_surface_mutex}; | ||||
| 
 | ||||
|     try { | ||||
|         graphics_queue.submit(submit_info, frame->present_done); | ||||
|  |  | |||
|  | @ -78,9 +78,13 @@ void Swapchain::Create(u32 width_, u32 height_, vk::SurfaceKHR surface_) { | |||
| } | ||||
| 
 | ||||
| bool Swapchain::AcquireNextImage() { | ||||
|     if (needs_recreation) { | ||||
|         return false; | ||||
|     } | ||||
| 
 | ||||
|     MICROPROFILE_SCOPE(Vulkan_Acquire); | ||||
|     vk::Device device = instance.GetDevice(); | ||||
|     vk::Result result = | ||||
|     const vk::Device device = instance.GetDevice(); | ||||
|     const vk::Result result = | ||||
|         device.acquireNextImageKHR(swapchain, std::numeric_limits<u64>::max(), | ||||
|                                    image_acquired[frame_index], VK_NULL_HANDLE, &image_index); | ||||
| 
 | ||||
|  | @ -102,10 +106,6 @@ bool Swapchain::AcquireNextImage() { | |||
| } | ||||
| 
 | ||||
| void Swapchain::Present() { | ||||
|     if (needs_recreation) { | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     const vk::PresentInfoKHR present_info = { | ||||
|         .waitSemaphoreCount = 1, | ||||
|         .pWaitSemaphores = &present_ready[image_index], | ||||
|  | @ -119,6 +119,10 @@ void Swapchain::Present() { | |||
|         [[maybe_unused]] vk::Result result = instance.GetPresentQueue().presentKHR(present_info); | ||||
|     } catch (vk::OutOfDateKHRError&) { | ||||
|         needs_recreation = true; | ||||
|         return; | ||||
|     } catch (vk::SurfaceLostKHRError&) { | ||||
|         needs_recreation = true; | ||||
|         return; | ||||
|     } catch (const vk::SystemError& err) { | ||||
|         LOG_CRITICAL(Render_Vulkan, "Swapchain presentation failed {}", err.what()); | ||||
|         UNREACHABLE(); | ||||
|  | @ -268,4 +272,4 @@ void Swapchain::SetupImages() { | |||
|     } | ||||
| } | ||||
| 
 | ||||
| } // namespace Vulkan
 | ||||
| } // namespace Vulkan
 | ||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue