summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJames Rowe <jroweboy@gmail.com>2020-03-25 05:57:36 +0100
committerJames Rowe <jroweboy@gmail.com>2020-03-26 06:32:42 +0100
commitcf9c94d4017120b618194a720942ef4e5c8289bd (patch)
tree30cbea0216626e3a1db1a68120b54e6bd53804f5
parentFrontend/GPU: Refactor context management (diff)
downloadyuzu-cf9c94d4017120b618194a720942ef4e5c8289bd.tar
yuzu-cf9c94d4017120b618194a720942ef4e5c8289bd.tar.gz
yuzu-cf9c94d4017120b618194a720942ef4e5c8289bd.tar.bz2
yuzu-cf9c94d4017120b618194a720942ef4e5c8289bd.tar.lz
yuzu-cf9c94d4017120b618194a720942ef4e5c8289bd.tar.xz
yuzu-cf9c94d4017120b618194a720942ef4e5c8289bd.tar.zst
yuzu-cf9c94d4017120b618194a720942ef4e5c8289bd.zip
-rw-r--r--src/core/core.cpp4
-rw-r--r--src/core/frontend/emu_window.h2
-rw-r--r--src/video_core/renderer_opengl/gl_shader_cache.cpp2
-rw-r--r--src/video_core/renderer_opengl/renderer_opengl.cpp6
-rw-r--r--src/video_core/video_core.cpp4
-rw-r--r--src/yuzu/bootmanager.cpp97
-rw-r--r--src/yuzu/bootmanager.h9
-rw-r--r--src/yuzu_cmd/yuzu.cpp4
-rw-r--r--src/yuzu_tester/emu_window/emu_window_sdl2_hide.cpp42
-rw-r--r--src/yuzu_tester/emu_window/emu_window_sdl2_hide.h9
-rw-r--r--src/yuzu_tester/yuzu.cpp6
11 files changed, 83 insertions, 102 deletions
diff --git a/src/core/core.cpp b/src/core/core.cpp
index 6cc4a0812..26a580cb7 100644
--- a/src/core/core.cpp
+++ b/src/core/core.cpp
@@ -169,6 +169,9 @@ struct System::Impl {
interrupt_manager = std::make_unique<Core::Hardware::InterruptManager>(system);
gpu_core = VideoCore::CreateGPU(emu_window, system);
+ if (!gpu_core) {
+ return ResultStatus::ErrorVideoCore;
+ }
gpu_core->Renderer().Rasterizer().SetupDirtyFlags();
is_powered_on = true;
@@ -181,7 +184,6 @@ struct System::Impl {
ResultStatus Load(System& system, Frontend::EmuWindow& emu_window,
const std::string& filepath) {
-
app_loader = Loader::GetLoader(GetGameFileFromPath(virtual_filesystem, filepath));
if (!app_loader) {
LOG_CRITICAL(Core, "Failed to obtain loader for {}!", filepath);
diff --git a/src/core/frontend/emu_window.h b/src/core/frontend/emu_window.h
index bb283d844..72294d4d8 100644
--- a/src/core/frontend/emu_window.h
+++ b/src/core/frontend/emu_window.h
@@ -30,7 +30,7 @@ public:
class Scoped {
public:
- Scoped(GraphicsContext& context_) : context(context_) {
+ explicit Scoped(GraphicsContext& context_) : context(context_) {
context.MakeCurrent();
}
~Scoped() {
diff --git a/src/video_core/renderer_opengl/gl_shader_cache.cpp b/src/video_core/renderer_opengl/gl_shader_cache.cpp
index 8f59e0442..046ee55a5 100644
--- a/src/video_core/renderer_opengl/gl_shader_cache.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_cache.cpp
@@ -305,6 +305,7 @@ void ShaderCacheOpenGL::LoadDiskCache(const std::atomic_bool& stop_loading,
}
const std::vector gl_cache = disk_cache.LoadPrecompiled();
+ const auto supported_formats = GetSupportedFormats();
// Track if precompiled cache was altered during loading to know if we have to
// serialize the virtual precompiled cache file back to the hard drive
@@ -327,7 +328,6 @@ void ShaderCacheOpenGL::LoadDiskCache(const std::atomic_bool& stop_loading,
const auto worker = [&](Core::Frontend::GraphicsContext* context, std::size_t begin,
std::size_t end) {
const auto scope = context->Acquire();
- const auto supported_formats = GetSupportedFormats();
for (std::size_t i = begin; i < end; ++i) {
if (stop_loading) {
diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp
index 6f08803c1..f1a28cc21 100644
--- a/src/video_core/renderer_opengl/renderer_opengl.cpp
+++ b/src/video_core/renderer_opengl/renderer_opengl.cpp
@@ -7,7 +7,9 @@
#include <cstdlib>
#include <cstring>
#include <memory>
+
#include <glad/glad.h>
+
#include "common/assert.h"
#include "common/logging/log.h"
#include "common/microprofile.h"
@@ -313,8 +315,8 @@ public:
RendererOpenGL::RendererOpenGL(Core::Frontend::EmuWindow& emu_window, Core::System& system,
Core::Frontend::GraphicsContext& context)
- : VideoCore::RendererBase{emu_window}, emu_window{emu_window}, system{system}, frame_mailbox{},
- has_debug_tool{HasDebugTool()}, context{context} {}
+ : VideoCore::RendererBase{emu_window}, emu_window{emu_window}, system{system},
+ frame_mailbox{}, context{context}, has_debug_tool{HasDebugTool()} {}
RendererOpenGL::~RendererOpenGL() = default;
diff --git a/src/video_core/video_core.cpp b/src/video_core/video_core.cpp
index fd9fec018..f60bdc60a 100644
--- a/src/video_core/video_core.cpp
+++ b/src/video_core/video_core.cpp
@@ -30,7 +30,7 @@ std::unique_ptr<VideoCore::RendererBase> CreateRenderer(Core::Frontend::EmuWindo
return nullptr;
}
}
-} // namespace
+} // Anonymous namespace
namespace VideoCore {
@@ -39,7 +39,7 @@ std::unique_ptr<Tegra::GPU> CreateGPU(Core::Frontend::EmuWindow& emu_window, Cor
const auto scope = context->Acquire();
auto renderer = CreateRenderer(emu_window, system, *context);
if (!renderer->Init()) {
- return {};
+ return nullptr;
}
if (Settings::values.use_asynchronous_gpu_emulation) {
diff --git a/src/yuzu/bootmanager.cpp b/src/yuzu/bootmanager.cpp
index d120ee818..4e9ced8ba 100644
--- a/src/yuzu/bootmanager.cpp
+++ b/src/yuzu/bootmanager.cpp
@@ -42,6 +42,10 @@ EmuThread::~EmuThread() = default;
void EmuThread::run() {
MicroProfileOnThreadCreate("EmuThread");
+ // Main process has been loaded. Make the context current to this thread and begin GPU and CPU
+ // execution.
+ Core::System::GetInstance().GPU().Start();
+
emit LoadProgress(VideoCore::LoadCallbackStage::Prepare, 0, 0);
Core::System::GetInstance().Renderer().Rasterizer().LoadDiskResources(
@@ -51,10 +55,6 @@ void EmuThread::run() {
emit LoadProgress(VideoCore::LoadCallbackStage::Complete, 0, 0);
- // Main process has been loaded. Make the context current to this thread and begin GPU and CPU
- // execution.
- Core::System::GetInstance().GPU().Start();
-
// Holds whether the cpu was running during the last iteration,
// so that the DebugModeLeft signal can be emitted before the
// next execution step
@@ -152,7 +152,7 @@ public:
if (is_current) {
return;
}
- context->makeCurrent(surface);
+ is_current = context->makeCurrent(surface);
}
void DoneCurrent() override {
@@ -160,7 +160,11 @@ public:
is_current = false;
}
- QOpenGLContext* GetShareContext() const {
+ QOpenGLContext* GetShareContext() {
+ return context.get();
+ }
+
+ const QOpenGLContext* GetShareContext() const {
return context.get();
}
@@ -177,13 +181,15 @@ class DummyContext : public Core::Frontend::GraphicsContext {};
class RenderWidget : public QWidget {
public:
- RenderWidget(GRenderWindow* parent) : QWidget(parent), render_window(parent) {
+ explicit RenderWidget(GRenderWindow* parent) : QWidget(parent), render_window(parent) {
setAttribute(Qt::WA_NativeWindow);
setAttribute(Qt::WA_PaintOnScreen);
}
virtual ~RenderWidget() = default;
+ /// Called on the UI thread when this Widget is ready to draw
+ /// Dervied classes can override this to draw the latest frame.
virtual void Present() {}
void paintEvent(QPaintEvent* event) override {
@@ -191,56 +197,6 @@ public:
update();
}
- void resizeEvent(QResizeEvent* ev) override {
- render_window->resize(ev->size());
- render_window->OnFramebufferSizeChanged();
- }
-
- void keyPressEvent(QKeyEvent* event) override {
- InputCommon::GetKeyboard()->PressKey(event->key());
- }
-
- void keyReleaseEvent(QKeyEvent* event) override {
- InputCommon::GetKeyboard()->ReleaseKey(event->key());
- }
-
- void mousePressEvent(QMouseEvent* event) override {
- if (event->source() == Qt::MouseEventSynthesizedBySystem)
- return; // touch input is handled in TouchBeginEvent
-
- const auto pos{event->pos()};
- if (event->button() == Qt::LeftButton) {
- const auto [x, y] = render_window->ScaleTouch(pos);
- render_window->TouchPressed(x, y);
- } else if (event->button() == Qt::RightButton) {
- InputCommon::GetMotionEmu()->BeginTilt(pos.x(), pos.y());
- }
- }
-
- void mouseMoveEvent(QMouseEvent* event) override {
- if (event->source() == Qt::MouseEventSynthesizedBySystem)
- return; // touch input is handled in TouchUpdateEvent
-
- const auto pos{event->pos()};
- const auto [x, y] = render_window->ScaleTouch(pos);
- render_window->TouchMoved(x, y);
- InputCommon::GetMotionEmu()->Tilt(pos.x(), pos.y());
- }
-
- void mouseReleaseEvent(QMouseEvent* event) override {
- if (event->source() == Qt::MouseEventSynthesizedBySystem)
- return; // touch input is handled in TouchEndEvent
-
- if (event->button() == Qt::LeftButton)
- render_window->TouchReleased();
- else if (event->button() == Qt::RightButton)
- InputCommon::GetMotionEmu()->EndTilt();
- }
-
- std::pair<unsigned, unsigned> GetSize() const {
- return std::make_pair(width(), height());
- }
-
QPaintEngine* paintEngine() const override {
return nullptr;
}
@@ -276,6 +232,7 @@ private:
std::unique_ptr<Core::Frontend::GraphicsContext> context{};
};
+#ifdef HAS_VULKAN
class VulkanRenderWidget : public RenderWidget {
public:
explicit VulkanRenderWidget(GRenderWindow* parent, QVulkanInstance* instance)
@@ -284,6 +241,7 @@ public:
windowHandle()->setVulkanInstance(instance);
}
};
+#endif
GRenderWindow::GRenderWindow(GMainWindow* parent_, EmuThread* emu_thread)
: QWidget(parent_), emu_thread(emu_thread) {
@@ -358,7 +316,7 @@ qreal GRenderWindow::windowPixelRatio() const {
return devicePixelRatio();
}
-std::pair<u32, u32> GRenderWindow::ScaleTouch(const QPointF pos) const {
+std::pair<u32, u32> GRenderWindow::ScaleTouch(const QPointF& pos) const {
const qreal pixel_ratio = windowPixelRatio();
return {static_cast<u32>(std::max(std::round(pos.x() * pixel_ratio), qreal{0.0})),
static_cast<u32>(std::max(std::round(pos.y() * pixel_ratio), qreal{0.0}))};
@@ -378,8 +336,10 @@ void GRenderWindow::keyReleaseEvent(QKeyEvent* event) {
}
void GRenderWindow::mousePressEvent(QMouseEvent* event) {
- if (event->source() == Qt::MouseEventSynthesizedBySystem)
- return; // touch input is handled in TouchBeginEvent
+ // touch input is handled in TouchBeginEvent
+ if (event->source() == Qt::MouseEventSynthesizedBySystem) {
+ return;
+ }
auto pos = event->pos();
if (event->button() == Qt::LeftButton) {
@@ -391,8 +351,10 @@ void GRenderWindow::mousePressEvent(QMouseEvent* event) {
}
void GRenderWindow::mouseMoveEvent(QMouseEvent* event) {
- if (event->source() == Qt::MouseEventSynthesizedBySystem)
- return; // touch input is handled in TouchUpdateEvent
+ // touch input is handled in TouchUpdateEvent
+ if (event->source() == Qt::MouseEventSynthesizedBySystem) {
+ return;
+ }
auto pos = event->pos();
const auto [x, y] = ScaleTouch(pos);
@@ -401,13 +363,16 @@ void GRenderWindow::mouseMoveEvent(QMouseEvent* event) {
}
void GRenderWindow::mouseReleaseEvent(QMouseEvent* event) {
- if (event->source() == Qt::MouseEventSynthesizedBySystem)
- return; // touch input is handled in TouchEndEvent
+ // touch input is handled in TouchEndEvent
+ if (event->source() == Qt::MouseEventSynthesizedBySystem) {
+ return;
+ }
- if (event->button() == Qt::LeftButton)
+ if (event->button() == Qt::LeftButton) {
this->TouchReleased();
- else if (event->button() == Qt::RightButton)
+ } else if (event->button() == Qt::RightButton) {
InputCommon::GetMotionEmu()->EndTilt();
+ }
}
void GRenderWindow::TouchBeginEvent(const QTouchEvent* event) {
diff --git a/src/yuzu/bootmanager.h b/src/yuzu/bootmanager.h
index 3739ec7ed..d69078df1 100644
--- a/src/yuzu/bootmanager.h
+++ b/src/yuzu/bootmanager.h
@@ -7,11 +7,12 @@
#include <atomic>
#include <condition_variable>
#include <mutex>
-#include <thread>
+
#include <QImage>
#include <QThread>
#include <QWidget>
#include <QWindow>
+
#include "common/thread.h"
#include "core/core.h"
#include "core/frontend/emu_window.h"
@@ -84,8 +85,8 @@ private:
bool exec_step = false;
bool running = false;
std::atomic_bool stop_run{false};
- std::mutex running_mutex = {};
- std::condition_variable running_cv = {};
+ std::mutex running_mutex;
+ std::condition_variable running_cv;
signals:
/**
@@ -154,7 +155,7 @@ public:
void CaptureScreenshot(u32 res_scale, const QString& screenshot_path);
- std::pair<u32, u32> ScaleTouch(const QPointF pos) const;
+ std::pair<u32, u32> ScaleTouch(const QPointF& pos) const;
public slots:
void OnEmulationStarting(EmuThread* emu_thread);
diff --git a/src/yuzu_cmd/yuzu.cpp b/src/yuzu_cmd/yuzu.cpp
index e5db7d819..4d2ea7e9e 100644
--- a/src/yuzu_cmd/yuzu.cpp
+++ b/src/yuzu_cmd/yuzu.cpp
@@ -230,11 +230,11 @@ int main(int argc, char** argv) {
system.TelemetrySession().AddField(Telemetry::FieldType::App, "Frontend", "SDL");
- system.Renderer().Rasterizer().LoadDiskResources();
-
// Core is loaded, start the GPU (makes the GPU contexts current to this thread)
system.GPU().Start();
+ system.Renderer().Rasterizer().LoadDiskResources();
+
std::thread render_thread([&emu_window] { emu_window->Present(); });
while (emu_window->IsOpen()) {
system.RunLoop();
diff --git a/src/yuzu_tester/emu_window/emu_window_sdl2_hide.cpp b/src/yuzu_tester/emu_window/emu_window_sdl2_hide.cpp
index a1bdb1a12..a837430cc 100644
--- a/src/yuzu_tester/emu_window/emu_window_sdl2_hide.cpp
+++ b/src/yuzu_tester/emu_window/emu_window_sdl2_hide.cpp
@@ -102,8 +102,6 @@ EmuWindow_SDL2_Hide::EmuWindow_SDL2_Hide() {
LOG_INFO(Frontend, "yuzu-tester Version: {} | {}-{}", Common::g_build_fullname,
Common::g_scm_branch, Common::g_scm_desc);
Settings::LogSettings();
-
- DoneCurrent();
}
EmuWindow_SDL2_Hide::~EmuWindow_SDL2_Hide() {
@@ -114,14 +112,6 @@ EmuWindow_SDL2_Hide::~EmuWindow_SDL2_Hide() {
void EmuWindow_SDL2_Hide::PollEvents() {}
-void EmuWindow_SDL2_Hide::MakeCurrent() {
- SDL_GL_MakeCurrent(render_window, gl_context);
-}
-
-void EmuWindow_SDL2_Hide::DoneCurrent() {
- SDL_GL_MakeCurrent(render_window, nullptr);
-}
-
bool EmuWindow_SDL2_Hide::IsShown() const {
return false;
}
@@ -129,3 +119,35 @@ bool EmuWindow_SDL2_Hide::IsShown() const {
void EmuWindow_SDL2_Hide::RetrieveVulkanHandlers(void*, void*, void*) const {
UNREACHABLE();
}
+
+class SDLGLContext : public Core::Frontend::GraphicsContext {
+public:
+ explicit SDLGLContext() {
+ // create a hidden window to make the shared context against
+ window = SDL_CreateWindow(NULL, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 0, 0,
+ SDL_WINDOW_HIDDEN | SDL_WINDOW_OPENGL);
+ context = SDL_GL_CreateContext(window);
+ }
+
+ ~SDLGLContext() {
+ DoneCurrent();
+ SDL_GL_DeleteContext(context);
+ SDL_DestroyWindow(window);
+ }
+
+ void MakeCurrent() override {
+ SDL_GL_MakeCurrent(window, context);
+ }
+
+ void DoneCurrent() override {
+ SDL_GL_MakeCurrent(window, nullptr);
+ }
+
+private:
+ SDL_Window* window;
+ SDL_GLContext context;
+};
+
+std::unique_ptr<Core::Frontend::GraphicsContext> EmuWindow_SDL2_Hide::CreateSharedContext() const {
+ return std::make_unique<SDLGLContext>();
+}
diff --git a/src/yuzu_tester/emu_window/emu_window_sdl2_hide.h b/src/yuzu_tester/emu_window/emu_window_sdl2_hide.h
index b13e15309..9f5d04fca 100644
--- a/src/yuzu_tester/emu_window/emu_window_sdl2_hide.h
+++ b/src/yuzu_tester/emu_window/emu_window_sdl2_hide.h
@@ -16,12 +16,6 @@ public:
/// Polls window events
void PollEvents() override;
- /// Makes the graphics context current for the caller thread
- void MakeCurrent() override;
-
- /// Releases the GL context from the caller thread
- void DoneCurrent() override;
-
/// Whether the screen is being shown or not.
bool IsShown() const override;
@@ -29,8 +23,7 @@ public:
void RetrieveVulkanHandlers(void* get_instance_proc_addr, void* instance,
void* surface) const override;
- /// Whether the window is still open, and a close request hasn't yet been sent
- bool IsOpen() const;
+ std::unique_ptr<Core::Frontend::GraphicsContext> CreateSharedContext() const override;
private:
/// Whether the GPU and driver supports the OpenGL extension required
diff --git a/src/yuzu_tester/yuzu.cpp b/src/yuzu_tester/yuzu.cpp
index 94ad50cb3..676e70ebd 100644
--- a/src/yuzu_tester/yuzu.cpp
+++ b/src/yuzu_tester/yuzu.cpp
@@ -164,11 +164,6 @@ int main(int argc, char** argv) {
std::unique_ptr<EmuWindow_SDL2_Hide> emu_window{std::make_unique<EmuWindow_SDL2_Hide>()};
- if (!Settings::values.use_multi_core) {
- // Single core mode must acquire OpenGL context for entire emulation session
- emu_window->MakeCurrent();
- }
-
bool finished = false;
int return_value = 0;
const auto callback = [&finished,
@@ -257,6 +252,7 @@ int main(int argc, char** argv) {
system.TelemetrySession().AddField(Telemetry::FieldType::App, "Frontend", "SDLHideTester");
+ system.GPU().Start();
system.Renderer().Rasterizer().LoadDiskResources();
while (!finished) {