diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/video_core/renderer_vulkan/renderer_vulkan.cpp | 15 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/renderer_vulkan.h | 8 | ||||
| -rw-r--r-- | src/yuzu/bootmanager.cpp | 205 | ||||
| -rw-r--r-- | src/yuzu/bootmanager.h | 26 | ||||
| -rw-r--r-- | src/yuzu_cmd/emu_window/emu_window_sdl2_vk.cpp | 4 |
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 | ||
| 108 | void RendererVulkan::SwapBuffers(const Tegra::FramebufferConfig* framebuffer) { | 108 | void 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 | ||
| 143 | void RendererVulkan::TryPresent(int /*timeout_ms*/) { | ||
| 144 | // TODO (bunnei): ImplementMe | ||
| 145 | } | ||
| 146 | |||
| 138 | bool RendererVulkan::Init() { | 147 | bool 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 | ||
| 48 | private: | 44 | private: |
| 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 | ||
| 150 | OpenGLWindow::OpenGLWindow(QWindow* parent, QWidget* event_handler, QOpenGLContext* shared_context) | 150 | class ChildRenderWindow : public QWindow { |
| 151 | : QWindow(parent), event_handler(event_handler), | 151 | public: |
| 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 | |||
| 159 | protected: | ||
| 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); | 207 | private: |
| 160 | context->setScreen(this->screen()); | 208 | QWidget* event_handler{}; |
| 161 | context->setFormat(format); | 209 | }; |
| 162 | context->create(); | ||
| 163 | 210 | ||
| 164 | setSurfaceType(QWindow::OpenGLSurface); | 211 | class OpenGLWindow final : public ChildRenderWindow { |
| 212 | public: | ||
| 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 | ||
| 170 | OpenGLWindow::~OpenGLWindow() { | 222 | context->setShareContext(shared_context); |
| 171 | context->doneCurrent(); | 223 | context->setScreen(this->screen()); |
| 172 | } | 224 | context->setFormat(format); |
| 225 | context->create(); | ||
| 173 | 226 | ||
| 174 | void 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 | ||
| 186 | bool 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 | ||
| 228 | void 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 | |||
| 250 | private: | ||
| 251 | QOpenGLContext* context{}; | ||
| 252 | }; | ||
| 253 | |||
| 254 | #ifdef HAS_VULKAN | ||
| 255 | class VulkanWindow final : public ChildRenderWindow { | ||
| 256 | public: | ||
| 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 | |||
| 269 | private: | ||
| 270 | QWidget* event_handler{}; | ||
| 271 | }; | ||
| 272 | #endif | ||
| 232 | 273 | ||
| 233 | GRenderWindow::GRenderWindow(QWidget* parent_, EmuThread* emu_thread) | 274 | GRenderWindow::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 | ||
| 253 | void GRenderWindow::MakeCurrent() { | 294 | void GRenderWindow::MakeCurrent() { |
| 254 | core_context->MakeCurrent(); | 295 | if (core_context) { |
| 296 | core_context->MakeCurrent(); | ||
| 297 | } | ||
| 255 | } | 298 | } |
| 256 | 299 | ||
| 257 | void GRenderWindow::DoneCurrent() { | 300 | void GRenderWindow::DoneCurrent() { |
| 258 | core_context->DoneCurrent(); | 301 | if (core_context) { |
| 302 | core_context->DoneCurrent(); | ||
| 303 | } | ||
| 259 | } | 304 | } |
| 260 | 305 | ||
| 261 | void GRenderWindow::PollEvents() { | 306 | void 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; | |||
| 27 | class QVulkanInstance; | 27 | class QVulkanInstance; |
| 28 | #endif | 28 | #endif |
| 29 | 29 | ||
| 30 | class GWidgetInternal; | ||
| 31 | class GGLWidgetInternal; | ||
| 32 | class GVKWidgetInternal; | ||
| 33 | class GMainWindow; | ||
| 34 | class GRenderWindow; | ||
| 35 | class QSurface; | ||
| 36 | class QOpenGLContext; | ||
| 37 | |||
| 38 | namespace VideoCore { | 30 | namespace VideoCore { |
| 39 | enum class LoadCallbackStage; | 31 | enum 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 | ||
| 126 | class OpenGLWindow : public QWindow { | ||
| 127 | Q_OBJECT | ||
| 128 | public: | ||
| 129 | explicit OpenGLWindow(QWindow* parent, QWidget* event_handler, QOpenGLContext* shared_context); | ||
| 130 | |||
| 131 | ~OpenGLWindow(); | ||
| 132 | |||
| 133 | void Present(); | ||
| 134 | |||
| 135 | protected: | ||
| 136 | bool event(QEvent* event) override; | ||
| 137 | void exposeEvent(QExposeEvent* event) override; | ||
| 138 | |||
| 139 | private: | ||
| 140 | QOpenGLContext* context; | ||
| 141 | QWidget* event_handler; | ||
| 142 | }; | ||
| 143 | |||
| 144 | class GRenderWindow : public QWidget, public Core::Frontend::EmuWindow { | 118 | class 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 | ||
| 163 | void EmuWindow_SDL2_VK::Present() {} | 163 | void EmuWindow_SDL2_VK::Present() { |
| 164 | // TODO (bunnei): ImplementMe | ||
| 165 | } | ||