mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-31 13:50:03 +00:00 
			
		
		
		
	Frontend PR fixes (#6378)
* citra_qt: Check if renderer is null * core: Fix dynarmic use-after-free error * bootmanager: Add current context check in DoneCurrent * Loading a save state would destroy the frame dumper class, which contains a shared context. That context would call DoneCurrent without checking if it was actually bound or not, resulting in crashes when calling opengl functions * externals: Correct glad readme * common: Log renderer debug setting * citra: Make lambda lower case * Consistency with review comments on the PR * video_core: Kill more global state * GetResolutionScaleFactor would be called somewhere in the renderer constructor chain but it relies on the yet unitialized g_renderer, resulting in crashes when the resolution scale is set to auto. Rather than adding a workaround, let's kill this global state to fix this for good
This commit is contained in:
		
							parent
							
								
									5346ca27b5
								
							
						
					
					
						commit
						ffc95eb59b
					
				
					 17 changed files with 102 additions and 93 deletions
				
			
		|  | @ -9,6 +9,7 @@ | |||
| #include "common/microprofile.h" | ||||
| #include "video_core/pica_state.h" | ||||
| #include "video_core/rasterizer_cache/rasterizer_cache.h" | ||||
| #include "video_core/renderer_base.h" | ||||
| #include "video_core/renderer_opengl/gl_format_reinterpreter.h" | ||||
| #include "video_core/renderer_opengl/texture_downloader_es.h" | ||||
| #include "video_core/renderer_opengl/texture_filters/texture_filterer.h" | ||||
|  | @ -239,8 +240,9 @@ static Surface FindMatch(const SurfaceCache& surface_cache, const SurfaceParams& | |||
|     return match_surface; | ||||
| } | ||||
| 
 | ||||
| RasterizerCacheOpenGL::RasterizerCacheOpenGL() { | ||||
|     resolution_scale_factor = VideoCore::GetResolutionScaleFactor(); | ||||
| RasterizerCacheOpenGL::RasterizerCacheOpenGL(VideoCore::RendererBase& renderer_) | ||||
|     : renderer{renderer_} { | ||||
|     resolution_scale_factor = renderer.GetResolutionScaleFactor(); | ||||
|     texture_filterer = std::make_unique<TextureFilterer>( | ||||
|         Settings::values.texture_filter_name.GetValue(), resolution_scale_factor); | ||||
|     format_reinterpreter = std::make_unique<FormatReinterpreterOpenGL>(); | ||||
|  | @ -588,15 +590,14 @@ SurfaceSurfaceRect_Tuple RasterizerCacheOpenGL::GetFramebufferSurfaces( | |||
|     const auto& config = regs.framebuffer.framebuffer; | ||||
| 
 | ||||
|     // Update resolution_scale_factor and reset cache if changed
 | ||||
|     const bool resolution_scale_changed = | ||||
|         resolution_scale_factor != VideoCore::GetResolutionScaleFactor(); | ||||
|     const u32 scale_factor = renderer.GetResolutionScaleFactor(); | ||||
|     const bool resolution_scale_changed = resolution_scale_factor != scale_factor; | ||||
|     const bool texture_filter_changed = | ||||
|         VideoCore::g_texture_filter_update_requested.exchange(false) && | ||||
|         texture_filterer->Reset(Settings::values.texture_filter_name.GetValue(), | ||||
|                                 VideoCore::GetResolutionScaleFactor()); | ||||
|         renderer.Settings().texture_filter_update_requested.exchange(false) && | ||||
|         texture_filterer->Reset(Settings::values.texture_filter_name.GetValue(), scale_factor); | ||||
| 
 | ||||
|     if (resolution_scale_changed || texture_filter_changed) { | ||||
|         resolution_scale_factor = VideoCore::GetResolutionScaleFactor(); | ||||
|         resolution_scale_factor = scale_factor; | ||||
|         FlushAll(); | ||||
|         while (!surface_cache.empty()) | ||||
|             UnregisterSurface(*surface_cache.begin()->second.begin()); | ||||
|  |  | |||
|  | @ -9,6 +9,10 @@ | |||
| #include "video_core/rasterizer_cache/surface_params.h" | ||||
| #include "video_core/texture/texture_decode.h" | ||||
| 
 | ||||
| namespace VideoCore { | ||||
| class RendererBase; | ||||
| } | ||||
| 
 | ||||
| namespace OpenGL { | ||||
| 
 | ||||
| enum class ScaleMatch { | ||||
|  | @ -23,7 +27,7 @@ class FormatReinterpreterOpenGL; | |||
| 
 | ||||
| class RasterizerCacheOpenGL : NonCopyable { | ||||
| public: | ||||
|     RasterizerCacheOpenGL(); | ||||
|     RasterizerCacheOpenGL(VideoCore::RendererBase& renderer); | ||||
|     ~RasterizerCacheOpenGL(); | ||||
| 
 | ||||
|     /// Blit one surface's texture to another
 | ||||
|  | @ -108,6 +112,7 @@ private: | |||
|     /// Increase/decrease the number of surface in pages touching the specified region
 | ||||
|     void UpdatePagesCachedCount(PAddr addr, u32 size, int delta); | ||||
| 
 | ||||
|     VideoCore::RendererBase& renderer; | ||||
|     TextureRuntime runtime; | ||||
|     SurfaceCache surface_cache; | ||||
|     PageMap cached_pages; | ||||
|  |  | |||
|  | @ -16,6 +16,18 @@ RendererBase::RendererBase(Core::System& system_, Frontend::EmuWindow& window, | |||
| 
 | ||||
| RendererBase::~RendererBase() = default; | ||||
| 
 | ||||
| u32 RendererBase::GetResolutionScaleFactor() { | ||||
|     const auto graphics_api = Settings::values.graphics_api.GetValue(); | ||||
|     if (graphics_api == Settings::GraphicsAPI::Software) { | ||||
|         // Software renderer always render at native resolution
 | ||||
|         return 1; | ||||
|     } | ||||
| 
 | ||||
|     const u32 scale_factor = Settings::values.resolution_factor.GetValue(); | ||||
|     return scale_factor != 0 ? scale_factor | ||||
|                              : render_window.GetFramebufferLayout().GetScalingRatio(); | ||||
| } | ||||
| 
 | ||||
| void RendererBase::UpdateCurrentFramebufferLayout(bool is_portrait_mode) { | ||||
|     const auto update_layout = [is_portrait_mode](Frontend::EmuWindow& window) { | ||||
|         const Layout::FramebufferLayout& layout = window.GetFramebufferLayout(); | ||||
|  | @ -43,19 +55,19 @@ void RendererBase::EndFrame() { | |||
| } | ||||
| 
 | ||||
| bool RendererBase::IsScreenshotPending() const { | ||||
|     return renderer_settings.screenshot_requested; | ||||
|     return settings.screenshot_requested; | ||||
| } | ||||
| 
 | ||||
| void RendererBase::RequestScreenshot(void* data, std::function<void()> callback, | ||||
|                                      const Layout::FramebufferLayout& layout) { | ||||
|     if (renderer_settings.screenshot_requested) { | ||||
|     if (settings.screenshot_requested) { | ||||
|         LOG_ERROR(Render, "A screenshot is already requested or in progress, ignoring the request"); | ||||
|         return; | ||||
|     } | ||||
|     renderer_settings.screenshot_bits = data; | ||||
|     renderer_settings.screenshot_complete_callback = callback; | ||||
|     renderer_settings.screenshot_framebuffer_layout = layout; | ||||
|     renderer_settings.screenshot_requested = true; | ||||
|     settings.screenshot_bits = data; | ||||
|     settings.screenshot_complete_callback = callback; | ||||
|     settings.screenshot_framebuffer_layout = layout; | ||||
|     settings.screenshot_requested = true; | ||||
| } | ||||
| 
 | ||||
| } // namespace VideoCore
 | ||||
|  |  | |||
|  | @ -24,6 +24,11 @@ struct RendererSettings { | |||
|     void* screenshot_bits{}; | ||||
|     std::function<void()> screenshot_complete_callback; | ||||
|     Layout::FramebufferLayout screenshot_framebuffer_layout; | ||||
|     // Renderer
 | ||||
|     std::atomic_bool texture_filter_update_requested{false}; | ||||
|     std::atomic_bool bg_color_update_requested{false}; | ||||
|     std::atomic_bool sampler_update_requested{false}; | ||||
|     std::atomic_bool shader_update_requested{false}; | ||||
| }; | ||||
| 
 | ||||
| class RendererBase : NonCopyable { | ||||
|  | @ -54,6 +59,9 @@ public: | |||
|     /// Synchronizes fixed function renderer state
 | ||||
|     virtual void Sync() {} | ||||
| 
 | ||||
|     /// Returns the resolution scale factor relative to the native 3DS screen resolution
 | ||||
|     u32 GetResolutionScaleFactor(); | ||||
| 
 | ||||
|     /// Updates the framebuffer layout of the contained render window handle.
 | ||||
|     void UpdateCurrentFramebufferLayout(bool is_portrait_mode = {}); | ||||
| 
 | ||||
|  | @ -80,11 +88,11 @@ public: | |||
|     } | ||||
| 
 | ||||
|     [[nodiscard]] RendererSettings& Settings() { | ||||
|         return renderer_settings; | ||||
|         return settings; | ||||
|     } | ||||
| 
 | ||||
|     [[nodiscard]] const RendererSettings& Settings() const { | ||||
|         return renderer_settings; | ||||
|         return settings; | ||||
|     } | ||||
| 
 | ||||
|     /// Returns true if a screenshot is being processed
 | ||||
|  | @ -96,7 +104,7 @@ public: | |||
| 
 | ||||
| protected: | ||||
|     Core::System& system; | ||||
|     RendererSettings renderer_settings; | ||||
|     RendererSettings settings; | ||||
|     Frontend::EmuWindow& render_window;    ///< Reference to the render window handle.
 | ||||
|     Frontend::EmuWindow* secondary_window; ///< Reference to the secondary render window handle.
 | ||||
|     f32 current_fps = 0.0f;                ///< Current framerate, should be set by the renderer
 | ||||
|  |  | |||
|  | @ -64,11 +64,10 @@ GLenum MakeAttributeType(Pica::PipelineRegs::VertexAttributeFormat format) { | |||
| 
 | ||||
| } // Anonymous namespace
 | ||||
| 
 | ||||
| RasterizerOpenGL::RasterizerOpenGL(Memory::MemorySystem& memory, Frontend::EmuWindow& emu_window, | ||||
| RasterizerOpenGL::RasterizerOpenGL(Memory::MemorySystem& memory, VideoCore::RendererBase& renderer, | ||||
|                                    Driver& driver_) | ||||
|     : VideoCore::RasterizerAccelerated{memory}, driver{driver_}, vertex_buffer{driver, | ||||
|                                                                                GL_ARRAY_BUFFER, | ||||
|                                                                                VERTEX_BUFFER_SIZE}, | ||||
|     : VideoCore::RasterizerAccelerated{memory}, driver{driver_}, res_cache{renderer}, | ||||
|       vertex_buffer{driver, GL_ARRAY_BUFFER, VERTEX_BUFFER_SIZE}, | ||||
|       uniform_buffer{driver, GL_UNIFORM_BUFFER, UNIFORM_BUFFER_SIZE}, | ||||
|       index_buffer{driver, GL_ELEMENT_ARRAY_BUFFER, INDEX_BUFFER_SIZE}, | ||||
|       texture_buffer{driver, GL_TEXTURE_BUFFER, TEXTURE_BUFFER_SIZE}, texture_lf_buffer{ | ||||
|  | @ -167,12 +166,14 @@ RasterizerOpenGL::RasterizerOpenGL(Memory::MemorySystem& memory, Frontend::EmuWi | |||
| #ifdef __APPLE__ | ||||
|     if (driver.GetVendor() == Vendor::Intel) { | ||||
|         shader_program_manager = std::make_unique<ShaderProgramManager>( | ||||
|             emu_window, driver, VideoCore::g_separable_shader_enabled); | ||||
|             renderer.GetRenderWindow(), driver, VideoCore::g_separable_shader_enabled); | ||||
|     } else { | ||||
|         shader_program_manager = std::make_unique<ShaderProgramManager>(emu_window, driver, true); | ||||
|         shader_program_manager = | ||||
|             std::make_unique<ShaderProgramManager>(renderer.GetRenderWindow(), driver, true); | ||||
|     } | ||||
| #else | ||||
|     shader_program_manager = std::make_unique<ShaderProgramManager>(emu_window, driver, !GLES); | ||||
|     shader_program_manager = | ||||
|         std::make_unique<ShaderProgramManager>(renderer.GetRenderWindow(), driver, !GLES); | ||||
| #endif | ||||
| 
 | ||||
|     glEnable(GL_BLEND); | ||||
|  |  | |||
|  | @ -14,8 +14,8 @@ | |||
| #include "video_core/renderer_opengl/gl_stream_buffer.h" | ||||
| #include "video_core/shader/shader.h" | ||||
| 
 | ||||
| namespace Frontend { | ||||
| class EmuWindow; | ||||
| namespace VideoCore { | ||||
| class RendererBase; | ||||
| } | ||||
| 
 | ||||
| namespace OpenGL { | ||||
|  | @ -25,7 +25,7 @@ class ShaderProgramManager; | |||
| 
 | ||||
| class RasterizerOpenGL : public VideoCore::RasterizerAccelerated { | ||||
| public: | ||||
|     explicit RasterizerOpenGL(Memory::MemorySystem& memory, Frontend::EmuWindow& emu_window, | ||||
|     explicit RasterizerOpenGL(Memory::MemorySystem& memory, VideoCore::RendererBase& renderer, | ||||
|                               Driver& driver); | ||||
|     ~RasterizerOpenGL() override; | ||||
| 
 | ||||
|  |  | |||
|  | @ -360,7 +360,7 @@ RendererOpenGL::RendererOpenGL(Core::System& system, Frontend::EmuWindow& window | |||
|     } | ||||
|     frame_dumper.mailbox = std::make_unique<OGLVideoDumpingMailbox>(); | ||||
|     InitOpenGLObjects(); | ||||
|     rasterizer = std::make_unique<RasterizerOpenGL>(system.Memory(), render_window, driver); | ||||
|     rasterizer = std::make_unique<RasterizerOpenGL>(system.Memory(), *this, driver); | ||||
| } | ||||
| 
 | ||||
| RendererOpenGL::~RendererOpenGL() = default; | ||||
|  | @ -401,7 +401,7 @@ void RendererOpenGL::SwapBuffers() { | |||
| } | ||||
| 
 | ||||
| void RendererOpenGL::RenderScreenshot() { | ||||
|     if (renderer_settings.screenshot_requested.exchange(false)) { | ||||
|     if (settings.screenshot_requested.exchange(false)) { | ||||
|         // Draw this frame to the screenshot framebuffer
 | ||||
|         screenshot_framebuffer.Create(); | ||||
|         GLuint old_read_fb = state.draw.read_framebuffer; | ||||
|  | @ -409,7 +409,7 @@ void RendererOpenGL::RenderScreenshot() { | |||
|         state.draw.read_framebuffer = state.draw.draw_framebuffer = screenshot_framebuffer.handle; | ||||
|         state.Apply(); | ||||
| 
 | ||||
|         const auto layout{renderer_settings.screenshot_framebuffer_layout}; | ||||
|         const Layout::FramebufferLayout layout{settings.screenshot_framebuffer_layout}; | ||||
| 
 | ||||
|         GLuint renderbuffer; | ||||
|         glGenRenderbuffers(1, &renderbuffer); | ||||
|  | @ -421,7 +421,7 @@ void RendererOpenGL::RenderScreenshot() { | |||
|         DrawScreens(layout, false); | ||||
| 
 | ||||
|         glReadPixels(0, 0, layout.width, layout.height, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, | ||||
|                      renderer_settings.screenshot_bits); | ||||
|                      settings.screenshot_bits); | ||||
| 
 | ||||
|         screenshot_framebuffer.Release(); | ||||
|         state.draw.read_framebuffer = old_read_fb; | ||||
|  | @ -429,7 +429,7 @@ void RendererOpenGL::RenderScreenshot() { | |||
|         state.Apply(); | ||||
|         glDeleteRenderbuffers(1, &renderbuffer); | ||||
| 
 | ||||
|         renderer_settings.screenshot_complete_callback(); | ||||
|         settings.screenshot_complete_callback(); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
|  | @ -808,7 +808,7 @@ void RendererOpenGL::DrawSingleScreenRotated(const ScreenInfo& screen_info, floa | |||
|     // As this is the "DrawSingleScreenRotated" function, the output resolution dimensions have been
 | ||||
|     // swapped. If a non-rotated draw-screen function were to be added for book-mode games, those
 | ||||
|     // should probably be set to the standard (w, h, 1.0 / w, 1.0 / h) ordering.
 | ||||
|     const u16 scale_factor = VideoCore::GetResolutionScaleFactor(); | ||||
|     const u32 scale_factor = GetResolutionScaleFactor(); | ||||
|     glUniform4f(uniform_i_resolution, static_cast<float>(screen_info.texture.width * scale_factor), | ||||
|                 static_cast<float>(screen_info.texture.height * scale_factor), | ||||
|                 1.0f / static_cast<float>(screen_info.texture.width * scale_factor), | ||||
|  | @ -837,7 +837,7 @@ void RendererOpenGL::DrawSingleScreen(const ScreenInfo& screen_info, float x, fl | |||
|         ScreenRectVertex(x + w, y + h, texcoords.top, texcoords.left), | ||||
|     }}; | ||||
| 
 | ||||
|     const u16 scale_factor = VideoCore::GetResolutionScaleFactor(); | ||||
|     const u32 scale_factor = GetResolutionScaleFactor(); | ||||
|     glUniform4f(uniform_i_resolution, static_cast<float>(screen_info.texture.width * scale_factor), | ||||
|                 static_cast<float>(screen_info.texture.height * scale_factor), | ||||
|                 1.0f / static_cast<float>(screen_info.texture.width * scale_factor), | ||||
|  | @ -871,7 +871,7 @@ void RendererOpenGL::DrawSingleScreenStereoRotated(const ScreenInfo& screen_info | |||
|         ScreenRectVertex(x + w, y + h, texcoords.top, texcoords.right), | ||||
|     }}; | ||||
| 
 | ||||
|     const u16 scale_factor = VideoCore::GetResolutionScaleFactor(); | ||||
|     const u32 scale_factor = GetResolutionScaleFactor(); | ||||
|     glUniform4f(uniform_i_resolution, | ||||
|                 static_cast<float>(screen_info_l.texture.width * scale_factor), | ||||
|                 static_cast<float>(screen_info_l.texture.height * scale_factor), | ||||
|  | @ -906,7 +906,7 @@ void RendererOpenGL::DrawSingleScreenStereo(const ScreenInfo& screen_info_l, | |||
|         ScreenRectVertex(x + w, y + h, texcoords.top, texcoords.left), | ||||
|     }}; | ||||
| 
 | ||||
|     const u16 scale_factor = VideoCore::GetResolutionScaleFactor(); | ||||
|     const u32 scale_factor = GetResolutionScaleFactor(); | ||||
|     glUniform4f(uniform_i_resolution, | ||||
|                 static_cast<float>(screen_info_l.texture.width * scale_factor), | ||||
|                 static_cast<float>(screen_info_l.texture.height * scale_factor), | ||||
|  | @ -933,18 +933,18 @@ void RendererOpenGL::DrawSingleScreenStereo(const ScreenInfo& screen_info_l, | |||
|  * Draws the emulated screens to the emulator window. | ||||
|  */ | ||||
| void RendererOpenGL::DrawScreens(const Layout::FramebufferLayout& layout, bool flipped) { | ||||
|     if (VideoCore::g_renderer_bg_color_update_requested.exchange(false)) { | ||||
|     if (settings.bg_color_update_requested.exchange(false)) { | ||||
|         // Update background color before drawing
 | ||||
|         glClearColor(Settings::values.bg_red.GetValue(), Settings::values.bg_green.GetValue(), | ||||
|                      Settings::values.bg_blue.GetValue(), 0.0f); | ||||
|     } | ||||
| 
 | ||||
|     if (VideoCore::g_renderer_sampler_update_requested.exchange(false)) { | ||||
|     if (settings.sampler_update_requested.exchange(false)) { | ||||
|         // Set the new filtering mode for the sampler
 | ||||
|         ReloadSampler(); | ||||
|     } | ||||
| 
 | ||||
|     if (VideoCore::g_renderer_shader_update_requested.exchange(false)) { | ||||
|     if (settings.shader_update_requested.exchange(false)) { | ||||
|         // Update fragment shader before drawing
 | ||||
|         shader.Release(); | ||||
|         // Link shaders and get variable locations
 | ||||
|  |  | |||
|  | @ -26,11 +26,6 @@ std::atomic<bool> g_shader_jit_enabled; | |||
| std::atomic<bool> g_hw_shader_enabled; | ||||
| std::atomic<bool> g_separable_shader_enabled; | ||||
| std::atomic<bool> g_hw_shader_accurate_mul; | ||||
| std::atomic<bool> g_use_disk_shader_cache; | ||||
| std::atomic<bool> g_renderer_bg_color_update_requested; | ||||
| std::atomic<bool> g_renderer_sampler_update_requested; | ||||
| std::atomic<bool> g_renderer_shader_update_requested; | ||||
| std::atomic<bool> g_texture_filter_update_requested; | ||||
| 
 | ||||
| Memory::MemorySystem* g_memory; | ||||
| 
 | ||||
|  | @ -64,18 +59,6 @@ void Shutdown() { | |||
|     LOG_DEBUG(Render, "shutdown OK"); | ||||
| } | ||||
| 
 | ||||
| u16 GetResolutionScaleFactor() { | ||||
|     const auto graphics_api = Settings::values.graphics_api.GetValue(); | ||||
|     if (graphics_api == Settings::GraphicsAPI::Software) { | ||||
|         // Software renderer always render at native resolution
 | ||||
|         return 1; | ||||
|     } | ||||
| 
 | ||||
|     return Settings::values.resolution_factor.GetValue() | ||||
|                ? Settings::values.resolution_factor.GetValue() | ||||
|                : g_renderer->GetRenderWindow().GetFramebufferLayout().GetScalingRatio(); | ||||
| } | ||||
| 
 | ||||
| template <class Archive> | ||||
| void serialize(Archive& ar, const unsigned int) { | ||||
|     ar& Pica::g_state; | ||||
|  |  | |||
|  | @ -37,11 +37,6 @@ extern std::atomic<bool> g_shader_jit_enabled; | |||
| extern std::atomic<bool> g_hw_shader_enabled; | ||||
| extern std::atomic<bool> g_separable_shader_enabled; | ||||
| extern std::atomic<bool> g_hw_shader_accurate_mul; | ||||
| extern std::atomic<bool> g_use_disk_shader_cache; | ||||
| extern std::atomic<bool> g_renderer_bg_color_update_requested; | ||||
| extern std::atomic<bool> g_renderer_sampler_update_requested; | ||||
| extern std::atomic<bool> g_renderer_shader_update_requested; | ||||
| extern std::atomic<bool> g_texture_filter_update_requested; | ||||
| 
 | ||||
| extern Memory::MemorySystem* g_memory; | ||||
| 
 | ||||
|  | @ -52,8 +47,6 @@ void Init(Frontend::EmuWindow& emu_window, Frontend::EmuWindow* secondary_window | |||
| /// Shutdown the video core
 | ||||
| void Shutdown(); | ||||
| 
 | ||||
| u16 GetResolutionScaleFactor(); | ||||
| 
 | ||||
| template <class Archive> | ||||
| void serialize(Archive& ar, const unsigned int file_version); | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue