summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar bunnei2020-02-17 21:29:12 -0500
committerGravatar bunnei2020-02-25 21:23:01 -0500
commite25297536f975db307f7117b3060e9919c44be52 (patch)
tree80e2f2b7e577fe3b16521b0f6f28e38a352b97b0
parentfrontend: qt: bootmanager: OpenGL: Implement separate presentation thread. (diff)
downloadyuzu-e25297536f975db307f7117b3060e9919c44be52.tar.gz
yuzu-e25297536f975db307f7117b3060e9919c44be52.tar.xz
yuzu-e25297536f975db307f7117b3060e9919c44be52.zip
frontend: qt: bootmanager: Vulkan: Restore support for VK backend.
-rw-r--r--src/video_core/renderer_vulkan/renderer_vulkan.cpp15
-rw-r--r--src/video_core/renderer_vulkan/renderer_vulkan.h8
-rw-r--r--src/yuzu/bootmanager.cpp205
-rw-r--r--src/yuzu/bootmanager.h26
-rw-r--r--src/yuzu_cmd/emu_window/emu_window_sdl2_vk.cpp4
5 files changed, 145 insertions, 113 deletions
diff --git a/src/video_core/renderer_vulkan/renderer_vulkan.cpp b/src/video_core/renderer_vulkan/renderer_vulkan.cpp
index d5032b432..ddc62bc97 100644
--- a/src/video_core/renderer_vulkan/renderer_vulkan.cpp
+++ b/src/video_core/renderer_vulkan/renderer_vulkan.cpp
@@ -106,8 +106,14 @@ RendererVulkan::~RendererVulkan() {
106} 106}
107 107
108void RendererVulkan::SwapBuffers(const Tegra::FramebufferConfig* framebuffer) { 108void RendererVulkan::SwapBuffers(const Tegra::FramebufferConfig* framebuffer) {
109 render_window.PollEvents();
110
111 if (!framebuffer) {
112 return;
113 }
114
109 const auto& layout = render_window.GetFramebufferLayout(); 115 const auto& layout = render_window.GetFramebufferLayout();
110 if (framebuffer && layout.width > 0 && layout.height > 0 && render_window.IsShown()) { 116 if (layout.width > 0 && layout.height > 0 && render_window.IsShown()) {
111 const VAddr framebuffer_addr = framebuffer->address + framebuffer->offset; 117 const VAddr framebuffer_addr = framebuffer->address + framebuffer->offset;
112 const bool use_accelerated = 118 const bool use_accelerated =
113 rasterizer->AccelerateDisplay(*framebuffer, framebuffer_addr, framebuffer->stride); 119 rasterizer->AccelerateDisplay(*framebuffer, framebuffer_addr, framebuffer->stride);
@@ -128,13 +134,16 @@ void RendererVulkan::SwapBuffers(const Tegra::FramebufferConfig* framebuffer) {
128 blit_screen->Recreate(); 134 blit_screen->Recreate();
129 } 135 }
130 136
131 render_window.SwapBuffers();
132 rasterizer->TickFrame(); 137 rasterizer->TickFrame();
133 } 138 }
134 139
135 render_window.PollEvents(); 140 render_window.PollEvents();
136} 141}
137 142
143void RendererVulkan::TryPresent(int /*timeout_ms*/) {
144 // TODO (bunnei): ImplementMe
145}
146
138bool RendererVulkan::Init() { 147bool RendererVulkan::Init() {
139 PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr{}; 148 PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr{};
140 render_window.RetrieveVulkanHandlers(&vkGetInstanceProcAddr, &instance, &surface); 149 render_window.RetrieveVulkanHandlers(&vkGetInstanceProcAddr, &instance, &surface);
@@ -262,4 +271,4 @@ void RendererVulkan::Report() const {
262 telemetry_session.AddField(field, "GPU_Vulkan_Extensions", extensions); 271 telemetry_session.AddField(field, "GPU_Vulkan_Extensions", extensions);
263} 272}
264 273
265} // namespace Vulkan \ No newline at end of file 274} // namespace Vulkan
diff --git a/src/video_core/renderer_vulkan/renderer_vulkan.h b/src/video_core/renderer_vulkan/renderer_vulkan.h
index a472c5dc9..f513397f0 100644
--- a/src/video_core/renderer_vulkan/renderer_vulkan.h
+++ b/src/video_core/renderer_vulkan/renderer_vulkan.h
@@ -36,14 +36,10 @@ public:
36 explicit RendererVulkan(Core::Frontend::EmuWindow& window, Core::System& system); 36 explicit RendererVulkan(Core::Frontend::EmuWindow& window, Core::System& system);
37 ~RendererVulkan() override; 37 ~RendererVulkan() override;
38 38
39 /// Swap buffers (render frame)
40 void SwapBuffers(const Tegra::FramebufferConfig* framebuffer) override;
41
42 /// Initialize the renderer
43 bool Init() override; 39 bool Init() override;
44
45 /// Shutdown the renderer
46 void ShutDown() override; 40 void ShutDown() override;
41 void SwapBuffers(const Tegra::FramebufferConfig* framebuffer) override;
42 void TryPresent(int timeout_ms) override;
47 43
48private: 44private:
49 std::optional<vk::DebugUtilsMessengerEXT> CreateDebugCallback( 45 std::optional<vk::DebugUtilsMessengerEXT> CreateDebugCallback(
diff --git a/src/yuzu/bootmanager.cpp b/src/yuzu/bootmanager.cpp
index 99e0ac61e..704c5ecdd 100644
--- a/src/yuzu/bootmanager.cpp
+++ b/src/yuzu/bootmanager.cpp
@@ -147,88 +147,129 @@ private:
147 QOffscreenSurface* surface; 147 QOffscreenSurface* surface;
148}; 148};
149 149
150OpenGLWindow::OpenGLWindow(QWindow* parent, QWidget* event_handler, QOpenGLContext* shared_context) 150class ChildRenderWindow : public QWindow {
151 : QWindow(parent), event_handler(event_handler), 151public:
152 context(new QOpenGLContext(shared_context->parent())) { 152 ChildRenderWindow(QWindow* parent, QWidget* event_handler)
153 : QWindow{parent}, event_handler{event_handler} {}
154
155 virtual ~ChildRenderWindow() = default;
156
157 virtual void Present() = 0;
158
159protected:
160 bool event(QEvent* event) override {
161 switch (event->type()) {
162 case QEvent::UpdateRequest:
163 Present();
164 return true;
165 case QEvent::MouseButtonPress:
166 case QEvent::MouseButtonRelease:
167 case QEvent::MouseButtonDblClick:
168 case QEvent::MouseMove:
169 case QEvent::KeyPress:
170 case QEvent::KeyRelease:
171 case QEvent::FocusIn:
172 case QEvent::FocusOut:
173 case QEvent::FocusAboutToChange:
174 case QEvent::Enter:
175 case QEvent::Leave:
176 case QEvent::Wheel:
177 case QEvent::TabletMove:
178 case QEvent::TabletPress:
179 case QEvent::TabletRelease:
180 case QEvent::TabletEnterProximity:
181 case QEvent::TabletLeaveProximity:
182 case QEvent::TouchBegin:
183 case QEvent::TouchUpdate:
184 case QEvent::TouchEnd:
185 case QEvent::InputMethodQuery:
186 case QEvent::TouchCancel:
187 return QCoreApplication::sendEvent(event_handler, event);
188 case QEvent::Drop:
189 GetMainWindow()->DropAction(static_cast<QDropEvent*>(event));
190 return true;
191 case QEvent::DragResponse:
192 case QEvent::DragEnter:
193 case QEvent::DragLeave:
194 case QEvent::DragMove:
195 GetMainWindow()->AcceptDropEvent(static_cast<QDropEvent*>(event));
196 return true;
197 default:
198 return QWindow::event(event);
199 }
200 }
153 201
154 // disable vsync for any shared contexts 202 void exposeEvent(QExposeEvent* event) override {
155 auto format = shared_context->format(); 203 QWindow::requestUpdate();
156 format.setSwapInterval(Settings::values.use_vsync ? 1 : 0); 204 QWindow::exposeEvent(event);
157 this->setFormat(format); 205 }
158 206
159 context->setShareContext(shared_context); 207private:
160 context->setScreen(this->screen()); 208 QWidget* event_handler{};
161 context->setFormat(format); 209};
162 context->create();
163 210
164 setSurfaceType(QWindow::OpenGLSurface); 211class OpenGLWindow final : public ChildRenderWindow {
212public:
213 OpenGLWindow(QWindow* parent, QWidget* event_handler, QOpenGLContext* shared_context)
214 : ChildRenderWindow{parent, event_handler},
215 context(new QOpenGLContext(shared_context->parent())) {
165 216
166 // TODO: One of these flags might be interesting: WA_OpaquePaintEvent, WA_NoBackground, 217 // disable vsync for any shared contexts
167 // WA_DontShowOnScreen, WA_DeleteOnClose 218 auto format = shared_context->format();
168} 219 format.setSwapInterval(Settings::values.use_vsync ? 1 : 0);
220 this->setFormat(format);
169 221
170OpenGLWindow::~OpenGLWindow() { 222 context->setShareContext(shared_context);
171 context->doneCurrent(); 223 context->setScreen(this->screen());
172} 224 context->setFormat(format);
225 context->create();
173 226
174void OpenGLWindow::Present() { 227 setSurfaceType(QWindow::OpenGLSurface);
175 if (!isExposed())
176 return;
177 228
178 context->makeCurrent(this); 229 // TODO: One of these flags might be interesting: WA_OpaquePaintEvent, WA_NoBackground,
179 Core::System::GetInstance().Renderer().TryPresent(100); 230 // WA_DontShowOnScreen, WA_DeleteOnClose
180 context->swapBuffers(this); 231 }
181 auto f = context->versionFunctions<QOpenGLFunctions_4_3_Core>();
182 f->glFinish();
183 QWindow::requestUpdate();
184}
185 232
186bool OpenGLWindow::event(QEvent* event) { 233 ~OpenGLWindow() override {
187 switch (event->type()) { 234 context->doneCurrent();
188 case QEvent::UpdateRequest:
189 Present();
190 return true;
191 case QEvent::MouseButtonPress:
192 case QEvent::MouseButtonRelease:
193 case QEvent::MouseButtonDblClick:
194 case QEvent::MouseMove:
195 case QEvent::KeyPress:
196 case QEvent::KeyRelease:
197 case QEvent::FocusIn:
198 case QEvent::FocusOut:
199 case QEvent::FocusAboutToChange:
200 case QEvent::Enter:
201 case QEvent::Leave:
202 case QEvent::Wheel:
203 case QEvent::TabletMove:
204 case QEvent::TabletPress:
205 case QEvent::TabletRelease:
206 case QEvent::TabletEnterProximity:
207 case QEvent::TabletLeaveProximity:
208 case QEvent::TouchBegin:
209 case QEvent::TouchUpdate:
210 case QEvent::TouchEnd:
211 case QEvent::InputMethodQuery:
212 case QEvent::TouchCancel:
213 return QCoreApplication::sendEvent(event_handler, event);
214 case QEvent::Drop:
215 GetMainWindow()->DropAction(static_cast<QDropEvent*>(event));
216 return true;
217 case QEvent::DragResponse:
218 case QEvent::DragEnter:
219 case QEvent::DragLeave:
220 case QEvent::DragMove:
221 GetMainWindow()->AcceptDropEvent(static_cast<QDropEvent*>(event));
222 return true;
223 default:
224 return QWindow::event(event);
225 } 235 }
226}
227 236
228void OpenGLWindow::exposeEvent(QExposeEvent* event) { 237 void Present() override {
229 QWindow::requestUpdate(); 238 if (!isExposed()) {
230 QWindow::exposeEvent(event); 239 return;
231} 240 }
241
242 context->makeCurrent(this);
243 Core::System::GetInstance().Renderer().TryPresent(100);
244 context->swapBuffers(this);
245 auto f = context->versionFunctions<QOpenGLFunctions_4_3_Core>();
246 f->glFinish();
247 QWindow::requestUpdate();
248 }
249
250private:
251 QOpenGLContext* context{};
252};
253
254#ifdef HAS_VULKAN
255class VulkanWindow final : public ChildRenderWindow {
256public:
257 VulkanWindow(QWindow* parent, QWidget* event_handler, QVulkanInstance* instance)
258 : ChildRenderWindow{parent, event_handler} {
259 setSurfaceType(QSurface::SurfaceType::VulkanSurface);
260 setVulkanInstance(instance);
261 }
262
263 ~VulkanWindow() override = default;
264
265 void Present() override {
266 // TODO(bunnei): ImplementMe
267 }
268
269private:
270 QWidget* event_handler{};
271};
272#endif
232 273
233GRenderWindow::GRenderWindow(QWidget* parent_, EmuThread* emu_thread) 274GRenderWindow::GRenderWindow(QWidget* parent_, EmuThread* emu_thread)
234 : QWidget(parent_), emu_thread(emu_thread) { 275 : QWidget(parent_), emu_thread(emu_thread) {
@@ -251,11 +292,15 @@ GRenderWindow::~GRenderWindow() {
251} 292}
252 293
253void GRenderWindow::MakeCurrent() { 294void GRenderWindow::MakeCurrent() {
254 core_context->MakeCurrent(); 295 if (core_context) {
296 core_context->MakeCurrent();
297 }
255} 298}
256 299
257void GRenderWindow::DoneCurrent() { 300void GRenderWindow::DoneCurrent() {
258 core_context->DoneCurrent(); 301 if (core_context) {
302 core_context->DoneCurrent();
303 }
259} 304}
260 305
261void GRenderWindow::PollEvents() { 306void GRenderWindow::PollEvents() {
@@ -274,7 +319,7 @@ void GRenderWindow::RetrieveVulkanHandlers(void* get_instance_proc_addr, void* i
274#ifdef HAS_VULKAN 319#ifdef HAS_VULKAN
275 const auto instance_proc_addr = vk_instance->getInstanceProcAddr("vkGetInstanceProcAddr"); 320 const auto instance_proc_addr = vk_instance->getInstanceProcAddr("vkGetInstanceProcAddr");
276 const VkInstance instance_copy = vk_instance->vkInstance(); 321 const VkInstance instance_copy = vk_instance->vkInstance();
277 const VkSurfaceKHR surface_copy = vk_instance->surfaceForWindow(child); 322 const VkSurfaceKHR surface_copy = vk_instance->surfaceForWindow(child_window);
278 323
279 std::memcpy(get_instance_proc_addr, &instance_proc_addr, sizeof(instance_proc_addr)); 324 std::memcpy(get_instance_proc_addr, &instance_proc_addr, sizeof(instance_proc_addr));
280 std::memcpy(instance, &instance_copy, sizeof(instance_copy)); 325 std::memcpy(instance, &instance_copy, sizeof(instance_copy));
@@ -535,7 +580,6 @@ bool GRenderWindow::InitializeOpenGL() {
535 layout()->addWidget(child_widget); 580 layout()->addWidget(child_widget);
536 581
537 core_context = CreateSharedContext(); 582 core_context = CreateSharedContext();
538 resize(Layout::ScreenUndocked::Width, Layout::ScreenUndocked::Height);
539 583
540 return true; 584 return true;
541} 585}
@@ -565,7 +609,14 @@ bool GRenderWindow::InitializeVulkan() {
565 return false; 609 return false;
566 } 610 }
567 611
568 child = new GVKWidgetInternal(this, vk_instance.get()); 612 GMainWindow* parent = GetMainWindow();
613 QWindow* parent_win_handle = parent ? parent->windowHandle() : nullptr;
614 child_window = new VulkanWindow(parent_win_handle, this, vk_instance.get());
615 child_window->create();
616 child_widget = createWindowContainer(child_window, this);
617 child_widget->resize(Layout::ScreenUndocked::Width, Layout::ScreenUndocked::Height);
618 layout()->addWidget(child_widget);
619
569 return true; 620 return true;
570#else 621#else
571 QMessageBox::critical(this, tr("Vulkan not available!"), 622 QMessageBox::critical(this, tr("Vulkan not available!"),
diff --git a/src/yuzu/bootmanager.h b/src/yuzu/bootmanager.h
index 37bc4f043..6710a6e7f 100644
--- a/src/yuzu/bootmanager.h
+++ b/src/yuzu/bootmanager.h
@@ -27,14 +27,6 @@ class QOpenGLContext;
27class QVulkanInstance; 27class QVulkanInstance;
28#endif 28#endif
29 29
30class GWidgetInternal;
31class GGLWidgetInternal;
32class GVKWidgetInternal;
33class GMainWindow;
34class GRenderWindow;
35class QSurface;
36class QOpenGLContext;
37
38namespace VideoCore { 30namespace VideoCore {
39enum class LoadCallbackStage; 31enum class LoadCallbackStage;
40} 32}
@@ -123,24 +115,6 @@ signals:
123 void LoadProgress(VideoCore::LoadCallbackStage stage, std::size_t value, std::size_t total); 115 void LoadProgress(VideoCore::LoadCallbackStage stage, std::size_t value, std::size_t total);
124}; 116};
125 117
126class OpenGLWindow : public QWindow {
127 Q_OBJECT
128public:
129 explicit OpenGLWindow(QWindow* parent, QWidget* event_handler, QOpenGLContext* shared_context);
130
131 ~OpenGLWindow();
132
133 void Present();
134
135protected:
136 bool event(QEvent* event) override;
137 void exposeEvent(QExposeEvent* event) override;
138
139private:
140 QOpenGLContext* context;
141 QWidget* event_handler;
142};
143
144class GRenderWindow : public QWidget, public Core::Frontend::EmuWindow { 118class GRenderWindow : public QWidget, public Core::Frontend::EmuWindow {
145 Q_OBJECT 119 Q_OBJECT
146 120
diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2_vk.cpp b/src/yuzu_cmd/emu_window/emu_window_sdl2_vk.cpp
index f5f6675b5..abcc58165 100644
--- a/src/yuzu_cmd/emu_window/emu_window_sdl2_vk.cpp
+++ b/src/yuzu_cmd/emu_window/emu_window_sdl2_vk.cpp
@@ -160,4 +160,6 @@ bool EmuWindow_SDL2_VK::UseStandardLayers(PFN_vkGetInstanceProcAddr vkGetInstanc
160 }) != layers.end(); 160 }) != layers.end();
161} 161}
162 162
163void EmuWindow_SDL2_VK::Present() {} 163void EmuWindow_SDL2_VK::Present() {
164 // TODO (bunnei): ImplementMe
165}