mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-30 21:30:04 +00:00 
			
		
		
		
	Prevent softlock on shutdown and various cleanup
This commit is contained in:
		
							parent
							
								
									9c32c0b98b
								
							
						
					
					
						commit
						26d828fb4c
					
				
					 6 changed files with 21 additions and 24 deletions
				
			
		|  | @ -227,7 +227,6 @@ void EmuWindow_SDL2::Present() { | ||||||
|     while (IsOpen()) { |     while (IsOpen()) { | ||||||
|         VideoCore::g_renderer->TryPresent(100); |         VideoCore::g_renderer->TryPresent(100); | ||||||
|         SDL_GL_SwapWindow(render_window); |         SDL_GL_SwapWindow(render_window); | ||||||
|         VideoCore::g_renderer->PresentComplete(); |  | ||||||
|     } |     } | ||||||
|     SDL_GL_MakeCurrent(render_window, nullptr); |     SDL_GL_MakeCurrent(render_window, nullptr); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -86,7 +86,6 @@ GRenderWindow::GRenderWindow(QWidget* parent, EmuThread* emu_thread) | ||||||
|     setWindowTitle(QStringLiteral("Citra %1 | %2-%3") |     setWindowTitle(QStringLiteral("Citra %1 | %2-%3") | ||||||
|                        .arg(Common::g_build_name, Common::g_scm_branch, Common::g_scm_desc)); |                        .arg(Common::g_build_name, Common::g_scm_branch, Common::g_scm_desc)); | ||||||
|     setAttribute(Qt::WA_AcceptTouchEvents); |     setAttribute(Qt::WA_AcceptTouchEvents); | ||||||
|     connect(this, &QOpenGLWidget::frameSwapped, this, &GRenderWindow::OnFrameSwapped); |  | ||||||
|     InputCommon::Init(); |     InputCommon::Init(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -104,10 +103,6 @@ void GRenderWindow::DoneCurrent() { | ||||||
| 
 | 
 | ||||||
| void GRenderWindow::PollEvents() {} | void GRenderWindow::PollEvents() {} | ||||||
| 
 | 
 | ||||||
| void OnFrameSwapped() { |  | ||||||
|     VideoCore::g_renderer->PresentComplete(); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // On Qt 5.0+, this correctly gets the size of the framebuffer (pixels).
 | // On Qt 5.0+, this correctly gets the size of the framebuffer (pixels).
 | ||||||
| //
 | //
 | ||||||
| // Older versions get the window size (density independent pixels),
 | // Older versions get the window size (density independent pixels),
 | ||||||
|  | @ -303,10 +298,6 @@ void GRenderWindow::paintGL() { | ||||||
|     update(); |     update(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void GRenderWindow::OnFrameSwapped() { |  | ||||||
|     VideoCore::g_renderer->PresentComplete(); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void GRenderWindow::showEvent(QShowEvent* event) { | void GRenderWindow::showEvent(QShowEvent* event) { | ||||||
|     QWidget::showEvent(event); |     QWidget::showEvent(event); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -164,7 +164,6 @@ public slots: | ||||||
|     void OnEmulationStarting(EmuThread* emu_thread); |     void OnEmulationStarting(EmuThread* emu_thread); | ||||||
|     void OnEmulationStopping(); |     void OnEmulationStopping(); | ||||||
|     void OnFramebufferSizeChanged(); |     void OnFramebufferSizeChanged(); | ||||||
|     void OnFrameSwapped(); |  | ||||||
| 
 | 
 | ||||||
| signals: | signals: | ||||||
|     /// Emitted when the window is closed
 |     /// Emitted when the window is closed
 | ||||||
|  |  | ||||||
|  | @ -35,9 +35,6 @@ public: | ||||||
|     /// specific implementation)
 |     /// specific implementation)
 | ||||||
|     virtual void TryPresent(int timeout_ms) = 0; |     virtual void TryPresent(int timeout_ms) = 0; | ||||||
| 
 | 
 | ||||||
|     /// Marks the presentation buffer as complete and swaps it back into the pool
 |  | ||||||
|     virtual void PresentComplete() = 0; |  | ||||||
| 
 |  | ||||||
|     /// Prepares for video dumping (e.g. create necessary buffers, etc)
 |     /// Prepares for video dumping (e.g. create necessary buffers, etc)
 | ||||||
|     virtual void PrepareVideoDumping() = 0; |     virtual void PrepareVideoDumping() = 0; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -50,8 +50,8 @@ namespace OpenGL { | ||||||
| 
 | 
 | ||||||
| // If the size of this is too small, it ends up creating a soft cap on FPS as the renderer will have
 | // If the size of this is too small, it ends up creating a soft cap on FPS as the renderer will have
 | ||||||
| // to wait on available presentation frames. There doesn't seem to be much of a downside to a larger
 | // to wait on available presentation frames. There doesn't seem to be much of a downside to a larger
 | ||||||
| // number but 8 seems to be a good trade off for now
 | // number but 9 swap textures at 60FPS presentation allows for 800% speed so thats probably fine
 | ||||||
| constexpr std::size_t SWAP_CHAIN_SIZE = 8; | constexpr std::size_t SWAP_CHAIN_SIZE = 9; | ||||||
| 
 | 
 | ||||||
| class OGLTextureMailbox : public Frontend::TextureMailbox { | class OGLTextureMailbox : public Frontend::TextureMailbox { | ||||||
| public: | public: | ||||||
|  | @ -72,6 +72,11 @@ public: | ||||||
|     ~OGLTextureMailbox() override { |     ~OGLTextureMailbox() override { | ||||||
|         // lock the mutex and clear out the present and free_queues and notify any people who are
 |         // lock the mutex and clear out the present and free_queues and notify any people who are
 | ||||||
|         // blocked to prevent deadlock on shutdown
 |         // blocked to prevent deadlock on shutdown
 | ||||||
|  |         std::scoped_lock lock(swap_chain_lock); | ||||||
|  |         free_queue.clear(); | ||||||
|  |         present_queue.clear(); | ||||||
|  |         free_cv.notify_all(); | ||||||
|  |         present_cv.notify_all(); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     void ReloadPresentFrame(Frontend::Frame* frame, u32 height, u32 width) override { |     void ReloadPresentFrame(Frontend::Frame* frame, u32 height, u32 width) override { | ||||||
|  | @ -120,7 +125,16 @@ public: | ||||||
|     Frontend::Frame* GetRenderFrame() override { |     Frontend::Frame* GetRenderFrame() override { | ||||||
|         std::unique_lock<std::mutex> lock(swap_chain_lock); |         std::unique_lock<std::mutex> lock(swap_chain_lock); | ||||||
|         // wait for new entries in the free_queue
 |         // wait for new entries in the free_queue
 | ||||||
|         free_cv.wait(lock, [&] { return !free_queue.empty(); }); |         // we want to break at some point to prevent a softlock on close if the presentation thread
 | ||||||
|  |         // stops consuming buffers
 | ||||||
|  |         free_cv.wait_for(lock, std::chrono::milliseconds(100), [&] { return !free_queue.empty(); }); | ||||||
|  | 
 | ||||||
|  |         // If theres no free frames, we will reuse the oldest render frame
 | ||||||
|  |         if (free_queue.empty()) { | ||||||
|  |             auto frame = present_queue.back(); | ||||||
|  |             present_queue.pop_back(); | ||||||
|  |             return frame; | ||||||
|  |         } | ||||||
| 
 | 
 | ||||||
|         Frontend::Frame* frame = free_queue.front(); |         Frontend::Frame* frame = free_queue.front(); | ||||||
|         free_queue.pop_front(); |         free_queue.pop_front(); | ||||||
|  | @ -396,7 +410,7 @@ void RendererOpenGL::SwapBuffers() { | ||||||
| 
 | 
 | ||||||
|     // Recreate the frame if the size of the window has changed
 |     // Recreate the frame if the size of the window has changed
 | ||||||
|     if (layout.width != frame->width || layout.height != frame->height) { |     if (layout.width != frame->width || layout.height != frame->height) { | ||||||
|         LOG_CRITICAL(Render_OpenGL, "Reloading render frame"); |         LOG_DEBUG(Render_OpenGL, "Reloading render frame"); | ||||||
|         render_window.mailbox->ReloadRenderFrame(frame, layout.width, layout.height); |         render_window.mailbox->ReloadRenderFrame(frame, layout.width, layout.height); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | @ -846,6 +860,8 @@ void RendererOpenGL::TryPresent(int timeout_ms) { | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     // Clearing before a full overwrite of a fbo can signal to drivers that they can avoid a
 | ||||||
|  |     // readback since we won't be doing any blending
 | ||||||
|     glClear(GL_COLOR_BUFFER_BIT); |     glClear(GL_COLOR_BUFFER_BIT); | ||||||
| 
 | 
 | ||||||
|     // Recreate the presentation FBO if the color attachment was changed
 |     // Recreate the presentation FBO if the color attachment was changed
 | ||||||
|  | @ -867,10 +883,8 @@ void RendererOpenGL::TryPresent(int timeout_ms) { | ||||||
|     /* insert fence for the main thread to block on */ |     /* insert fence for the main thread to block on */ | ||||||
|     frame->present_fence = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0); |     frame->present_fence = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0); | ||||||
|     glFlush(); |     glFlush(); | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| void RendererOpenGL::PresentComplete() { |     glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); | ||||||
|     //    render_window.mailbox->PresentationComplete();
 |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /// Updates the framerate
 | /// Updates the framerate
 | ||||||
|  |  | ||||||
|  | @ -60,9 +60,6 @@ public: | ||||||
|     /// context
 |     /// context
 | ||||||
|     void TryPresent(int timeout_ms) override; |     void TryPresent(int timeout_ms) override; | ||||||
| 
 | 
 | ||||||
|     /// Finializes the presentation and sets up the presentation frame to go back into the mailbox
 |  | ||||||
|     void PresentComplete() override; |  | ||||||
| 
 |  | ||||||
|     /// Prepares for video dumping (e.g. create necessary buffers, etc)
 |     /// Prepares for video dumping (e.g. create necessary buffers, etc)
 | ||||||
|     void PrepareVideoDumping() override; |     void PrepareVideoDumping() override; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue