summaryrefslogtreecommitdiff
path: root/src/video_core/renderer_opengl
diff options
context:
space:
mode:
authorGravatar James Rowe2020-03-24 20:58:49 -0600
committerGravatar James Rowe2020-03-24 21:03:42 -0600
commit282adfc70b5d7d958d564bfda0227bb3fbd8d110 (patch)
tree2a98e3bedec2e7fdb33478814a73be664661aecc /src/video_core/renderer_opengl
parentUse the correct directory for Qt Plugins (diff)
downloadyuzu-282adfc70b5d7d958d564bfda0227bb3fbd8d110.tar.gz
yuzu-282adfc70b5d7d958d564bfda0227bb3fbd8d110.tar.xz
yuzu-282adfc70b5d7d958d564bfda0227bb3fbd8d110.zip
Frontend/GPU: Refactor context management
Changes the GraphicsContext to be managed by the GPU core. This eliminates the need for the frontends to fool around with tricky MakeCurrent/DoneCurrent calls that are dependent on the settings (such as async gpu option). This also refactors out the need to use QWidget::fromWindowContainer as that caused issues with focus and input handling. Now we use a regular QWidget and just access the native windowHandle() directly. Another change is removing the debug tool setting in FrameMailbox. Instead of trying to block the frontend until a new frame is ready, the core will now take over presentation and draw directly to the window if the renderer detects that its hooked by NSight or RenderDoc Lastly, since it was in the way, I removed ScopeAcquireWindowContext and replaced it with a simple subclass in GraphicsContext that achieves the same result
Diffstat (limited to 'src/video_core/renderer_opengl')
-rw-r--r--src/video_core/renderer_opengl/gl_shader_cache.cpp5
-rw-r--r--src/video_core/renderer_opengl/renderer_opengl.cpp69
-rw-r--r--src/video_core/renderer_opengl/renderer_opengl.h10
3 files changed, 36 insertions, 48 deletions
diff --git a/src/video_core/renderer_opengl/gl_shader_cache.cpp b/src/video_core/renderer_opengl/gl_shader_cache.cpp
index e3d31c3eb..8f59e0442 100644
--- a/src/video_core/renderer_opengl/gl_shader_cache.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_cache.cpp
@@ -305,7 +305,6 @@ void ShaderCacheOpenGL::LoadDiskCache(const std::atomic_bool& stop_loading,
305 } 305 }
306 306
307 const std::vector gl_cache = disk_cache.LoadPrecompiled(); 307 const std::vector gl_cache = disk_cache.LoadPrecompiled();
308 const auto supported_formats = GetSupportedFormats();
309 308
310 // Track if precompiled cache was altered during loading to know if we have to 309 // Track if precompiled cache was altered during loading to know if we have to
311 // serialize the virtual precompiled cache file back to the hard drive 310 // serialize the virtual precompiled cache file back to the hard drive
@@ -327,8 +326,8 @@ void ShaderCacheOpenGL::LoadDiskCache(const std::atomic_bool& stop_loading,
327 326
328 const auto worker = [&](Core::Frontend::GraphicsContext* context, std::size_t begin, 327 const auto worker = [&](Core::Frontend::GraphicsContext* context, std::size_t begin,
329 std::size_t end) { 328 std::size_t end) {
330 context->MakeCurrent(); 329 const auto scope = context->Acquire();
331 SCOPE_EXIT({ return context->DoneCurrent(); }); 330 const auto supported_formats = GetSupportedFormats();
332 331
333 for (std::size_t i = begin; i < end; ++i) { 332 for (std::size_t i = begin; i < end; ++i) {
334 if (stop_loading) { 333 if (stop_loading) {
diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp
index fca5e3ec0..6f08803c1 100644
--- a/src/video_core/renderer_opengl/renderer_opengl.cpp
+++ b/src/video_core/renderer_opengl/renderer_opengl.cpp
@@ -7,9 +7,7 @@
7#include <cstdlib> 7#include <cstdlib>
8#include <cstring> 8#include <cstring>
9#include <memory> 9#include <memory>
10
11#include <glad/glad.h> 10#include <glad/glad.h>
12
13#include "common/assert.h" 11#include "common/assert.h"
14#include "common/logging/log.h" 12#include "common/logging/log.h"
15#include "common/microprofile.h" 13#include "common/microprofile.h"
@@ -30,8 +28,6 @@ namespace OpenGL {
30 28
31namespace { 29namespace {
32 30
33// If the size of this is too small, it ends up creating a soft cap on FPS as the renderer will have
34// to wait on available presentation frames.
35constexpr std::size_t SWAP_CHAIN_SIZE = 3; 31constexpr std::size_t SWAP_CHAIN_SIZE = 3;
36 32
37struct Frame { 33struct Frame {
@@ -214,7 +210,7 @@ public:
214 std::deque<Frame*> present_queue; 210 std::deque<Frame*> present_queue;
215 Frame* previous_frame{}; 211 Frame* previous_frame{};
216 212
217 FrameMailbox() : has_debug_tool{HasDebugTool()} { 213 FrameMailbox() {
218 for (auto& frame : swap_chain) { 214 for (auto& frame : swap_chain) {
219 free_queue.push(&frame); 215 free_queue.push(&frame);
220 } 216 }
@@ -285,13 +281,9 @@ public:
285 std::unique_lock lock{swap_chain_lock}; 281 std::unique_lock lock{swap_chain_lock};
286 present_queue.push_front(frame); 282 present_queue.push_front(frame);
287 present_cv.notify_one(); 283 present_cv.notify_one();
288
289 DebugNotifyNextFrame();
290 } 284 }
291 285
292 Frame* TryGetPresentFrame(int timeout_ms) { 286 Frame* TryGetPresentFrame(int timeout_ms) {
293 DebugWaitForNextFrame();
294
295 std::unique_lock lock{swap_chain_lock}; 287 std::unique_lock lock{swap_chain_lock};
296 // wait for new entries in the present_queue 288 // wait for new entries in the present_queue
297 present_cv.wait_for(lock, std::chrono::milliseconds(timeout_ms), 289 present_cv.wait_for(lock, std::chrono::milliseconds(timeout_ms),
@@ -317,38 +309,12 @@ public:
317 previous_frame = frame; 309 previous_frame = frame;
318 return frame; 310 return frame;
319 } 311 }
320
321private:
322 std::mutex debug_synch_mutex;
323 std::condition_variable debug_synch_condition;
324 std::atomic_int frame_for_debug{};
325 const bool has_debug_tool; // When true, using a GPU debugger, so keep frames in lock-step
326
327 /// Signal that a new frame is available (called from GPU thread)
328 void DebugNotifyNextFrame() {
329 if (!has_debug_tool) {
330 return;
331 }
332 frame_for_debug++;
333 std::lock_guard lock{debug_synch_mutex};
334 debug_synch_condition.notify_one();
335 }
336
337 /// Wait for a new frame to be available (called from presentation thread)
338 void DebugWaitForNextFrame() {
339 if (!has_debug_tool) {
340 return;
341 }
342 const int last_frame = frame_for_debug;
343 std::unique_lock lock{debug_synch_mutex};
344 debug_synch_condition.wait(lock,
345 [this, last_frame] { return frame_for_debug > last_frame; });
346 }
347}; 312};
348 313
349RendererOpenGL::RendererOpenGL(Core::Frontend::EmuWindow& emu_window, Core::System& system) 314RendererOpenGL::RendererOpenGL(Core::Frontend::EmuWindow& emu_window, Core::System& system,
350 : VideoCore::RendererBase{emu_window}, emu_window{emu_window}, system{system}, 315 Core::Frontend::GraphicsContext& context)
351 frame_mailbox{std::make_unique<FrameMailbox>()} {} 316 : VideoCore::RendererBase{emu_window}, emu_window{emu_window}, system{system}, frame_mailbox{},
317 has_debug_tool{HasDebugTool()}, context{context} {}
352 318
353RendererOpenGL::~RendererOpenGL() = default; 319RendererOpenGL::~RendererOpenGL() = default;
354 320
@@ -356,8 +322,6 @@ MICROPROFILE_DEFINE(OpenGL_RenderFrame, "OpenGL", "Render Frame", MP_RGB(128, 12
356MICROPROFILE_DEFINE(OpenGL_WaitPresent, "OpenGL", "Wait For Present", MP_RGB(128, 128, 128)); 322MICROPROFILE_DEFINE(OpenGL_WaitPresent, "OpenGL", "Wait For Present", MP_RGB(128, 128, 128));
357 323
358void RendererOpenGL::SwapBuffers(const Tegra::FramebufferConfig* framebuffer) { 324void RendererOpenGL::SwapBuffers(const Tegra::FramebufferConfig* framebuffer) {
359 render_window.PollEvents();
360
361 if (!framebuffer) { 325 if (!framebuffer) {
362 return; 326 return;
363 } 327 }
@@ -413,6 +377,13 @@ void RendererOpenGL::SwapBuffers(const Tegra::FramebufferConfig* framebuffer) {
413 m_current_frame++; 377 m_current_frame++;
414 rasterizer->TickFrame(); 378 rasterizer->TickFrame();
415 } 379 }
380
381 render_window.PollEvents();
382 if (has_debug_tool) {
383 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
384 Present(0);
385 context.SwapBuffers();
386 }
416} 387}
417 388
418void RendererOpenGL::PrepareRendertarget(const Tegra::FramebufferConfig* framebuffer) { 389void RendererOpenGL::PrepareRendertarget(const Tegra::FramebufferConfig* framebuffer) {
@@ -480,6 +451,8 @@ void RendererOpenGL::LoadColorToActiveGLTexture(u8 color_r, u8 color_g, u8 color
480} 451}
481 452
482void RendererOpenGL::InitOpenGLObjects() { 453void RendererOpenGL::InitOpenGLObjects() {
454 frame_mailbox = std::make_unique<FrameMailbox>();
455
483 glClearColor(Settings::values.bg_red, Settings::values.bg_green, Settings::values.bg_blue, 456 glClearColor(Settings::values.bg_red, Settings::values.bg_green, Settings::values.bg_blue,
484 0.0f); 457 0.0f);
485 458
@@ -692,12 +665,21 @@ void RendererOpenGL::DrawScreen(const Layout::FramebufferLayout& layout) {
692 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); 665 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
693} 666}
694 667
695void RendererOpenGL::TryPresent(int timeout_ms) { 668bool RendererOpenGL::TryPresent(int timeout_ms) {
669 if (has_debug_tool) {
670 LOG_DEBUG(Render_OpenGL,
671 "Skipping presentation because we are presenting on the main context");
672 return false;
673 }
674 return Present(timeout_ms);
675}
676
677bool RendererOpenGL::Present(int timeout_ms) {
696 const auto& layout = render_window.GetFramebufferLayout(); 678 const auto& layout = render_window.GetFramebufferLayout();
697 auto frame = frame_mailbox->TryGetPresentFrame(timeout_ms); 679 auto frame = frame_mailbox->TryGetPresentFrame(timeout_ms);
698 if (!frame) { 680 if (!frame) {
699 LOG_DEBUG(Render_OpenGL, "TryGetPresentFrame returned no frame to present"); 681 LOG_DEBUG(Render_OpenGL, "TryGetPresentFrame returned no frame to present");
700 return; 682 return false;
701 } 683 }
702 684
703 // Clearing before a full overwrite of a fbo can signal to drivers that they can avoid a 685 // Clearing before a full overwrite of a fbo can signal to drivers that they can avoid a
@@ -725,6 +707,7 @@ void RendererOpenGL::TryPresent(int timeout_ms) {
725 glFlush(); 707 glFlush();
726 708
727 glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); 709 glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
710 return true;
728} 711}
729 712
730void RendererOpenGL::RenderScreenshot() { 713void RendererOpenGL::RenderScreenshot() {
diff --git a/src/video_core/renderer_opengl/renderer_opengl.h b/src/video_core/renderer_opengl/renderer_opengl.h
index 33073ce5b..50b647661 100644
--- a/src/video_core/renderer_opengl/renderer_opengl.h
+++ b/src/video_core/renderer_opengl/renderer_opengl.h
@@ -55,13 +55,14 @@ class FrameMailbox;
55 55
56class RendererOpenGL final : public VideoCore::RendererBase { 56class RendererOpenGL final : public VideoCore::RendererBase {
57public: 57public:
58 explicit RendererOpenGL(Core::Frontend::EmuWindow& emu_window, Core::System& system); 58 explicit RendererOpenGL(Core::Frontend::EmuWindow& emu_window, Core::System& system,
59 Core::Frontend::GraphicsContext& context);
59 ~RendererOpenGL() override; 60 ~RendererOpenGL() override;
60 61
61 bool Init() override; 62 bool Init() override;
62 void ShutDown() override; 63 void ShutDown() override;
63 void SwapBuffers(const Tegra::FramebufferConfig* framebuffer) override; 64 void SwapBuffers(const Tegra::FramebufferConfig* framebuffer) override;
64 void TryPresent(int timeout_ms) override; 65 bool TryPresent(int timeout_ms) override;
65 66
66private: 67private:
67 /// Initializes the OpenGL state and creates persistent objects. 68 /// Initializes the OpenGL state and creates persistent objects.
@@ -89,8 +90,11 @@ private:
89 90
90 void PrepareRendertarget(const Tegra::FramebufferConfig* framebuffer); 91 void PrepareRendertarget(const Tegra::FramebufferConfig* framebuffer);
91 92
93 bool Present(int timeout_ms);
94
92 Core::Frontend::EmuWindow& emu_window; 95 Core::Frontend::EmuWindow& emu_window;
93 Core::System& system; 96 Core::System& system;
97 Core::Frontend::GraphicsContext& context;
94 98
95 StateTracker state_tracker{system}; 99 StateTracker state_tracker{system};
96 100
@@ -115,6 +119,8 @@ private:
115 119
116 /// Frame presentation mailbox 120 /// Frame presentation mailbox
117 std::unique_ptr<FrameMailbox> frame_mailbox; 121 std::unique_ptr<FrameMailbox> frame_mailbox;
122
123 bool has_debug_tool = false;
118}; 124};
119 125
120} // namespace OpenGL 126} // namespace OpenGL