From ba44bf9b0d74778d42e0e2ba8a43a2e094e66746 Mon Sep 17 00:00:00 2001 From: GPUCode Date: Wed, 3 May 2023 23:52:26 +0300 Subject: [PATCH] code: Prepare frontend for vulkan support --- src/citra/CMakeLists.txt | 2 + src/citra/citra.cpp | 3 + src/citra/default_ini.h | 2 +- src/citra/emu_window/emu_window_sdl2_vk.cpp | 87 +++++++++++++++++++ src/citra/emu_window/emu_window_sdl2_vk.h | 17 ++++ src/citra_qt/bootmanager.cpp | 38 ++++++-- src/citra_qt/bootmanager.h | 1 + src/common/logging/log.h | 2 + src/common/settings.h | 4 +- .../rasterizer_cache/rasterizer_cache.h | 3 - 10 files changed, 147 insertions(+), 12 deletions(-) create mode 100644 src/citra/emu_window/emu_window_sdl2_vk.cpp create mode 100644 src/citra/emu_window/emu_window_sdl2_vk.h diff --git a/src/citra/CMakeLists.txt b/src/citra/CMakeLists.txt index 8b1b59bb9..2fa5740fd 100644 --- a/src/citra/CMakeLists.txt +++ b/src/citra/CMakeLists.txt @@ -12,6 +12,8 @@ add_executable(citra emu_window/emu_window_sdl2_gl.h emu_window/emu_window_sdl2_sw.cpp emu_window/emu_window_sdl2_sw.h + emu_window/emu_window_sdl2_vk.cpp + emu_window/emu_window_sdl2_vk.h precompiled_headers.h resource.h ) diff --git a/src/citra/citra.cpp b/src/citra/citra.cpp index b2b447a03..24958061b 100644 --- a/src/citra/citra.cpp +++ b/src/citra/citra.cpp @@ -15,6 +15,7 @@ #include "citra/emu_window/emu_window_sdl2.h" #include "citra/emu_window/emu_window_sdl2_gl.h" #include "citra/emu_window/emu_window_sdl2_sw.h" +#include "citra/emu_window/emu_window_sdl2_vk.h" #include "common/common_paths.h" #include "common/detached_tasks.h" #include "common/file_util.h" @@ -365,6 +366,8 @@ int main(int argc, char** argv) { switch (Settings::values.graphics_api.GetValue()) { case Settings::GraphicsAPI::OpenGL: return std::make_unique(fullscreen, is_secondary); + case Settings::GraphicsAPI::Vulkan: + return std::make_unique(fullscreen, is_secondary); case Settings::GraphicsAPI::Software: return std::make_unique(fullscreen, is_secondary); } diff --git a/src/citra/default_ini.h b/src/citra/default_ini.h index c958a8a96..0b199c1ee 100644 --- a/src/citra/default_ini.h +++ b/src/citra/default_ini.h @@ -99,7 +99,7 @@ cpu_clock_percentage = [Renderer] # Whether to render using OpenGL or Software -# 0: Software, 1: OpenGL (default) +# 0: Software, 1: OpenGL (default), 2: Vulkan (default) graphics_api = # Whether to render using GLES or OpenGL diff --git a/src/citra/emu_window/emu_window_sdl2_vk.cpp b/src/citra/emu_window/emu_window_sdl2_vk.cpp new file mode 100644 index 000000000..9b4b60c1d --- /dev/null +++ b/src/citra/emu_window/emu_window_sdl2_vk.cpp @@ -0,0 +1,87 @@ +// Copyright 2023 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include +#include +#include +#include +#include +#include +#include "citra/emu_window/emu_window_sdl2_vk.h" +#include "common/logging/log.h" +#include "common/scm_rev.h" + +class DummyContext : public Frontend::GraphicsContext {}; + +EmuWindow_SDL2_VK::EmuWindow_SDL2_VK(bool fullscreen, bool is_secondary) + : EmuWindow_SDL2{is_secondary} { + const std::string window_title = fmt::format("Citra {} | {}-{}", Common::g_build_fullname, + Common::g_scm_branch, Common::g_scm_desc); + render_window = + SDL_CreateWindow(window_title.c_str(), + SDL_WINDOWPOS_UNDEFINED, // x position + SDL_WINDOWPOS_UNDEFINED, // y position + Core::kScreenTopWidth, Core::kScreenTopHeight + Core::kScreenBottomHeight, + SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI); + SDL_SysWMinfo wm; + SDL_VERSION(&wm.version); + if (SDL_GetWindowWMInfo(render_window, &wm) == SDL_FALSE) { + LOG_CRITICAL(Frontend, "Failed to get information from the window manager"); + std::exit(EXIT_FAILURE); + } + + if (fullscreen) { + Fullscreen(); + ShowCursor(false); + } + + switch (wm.subsystem) { +#ifdef SDL_VIDEO_DRIVER_WINDOWS + case SDL_SYSWM_TYPE::SDL_SYSWM_WINDOWS: + window_info.type = Frontend::WindowSystemType::Windows; + window_info.render_surface = reinterpret_cast(wm.info.win.window); + break; +#endif +#ifdef SDL_VIDEO_DRIVER_X11 + case SDL_SYSWM_TYPE::SDL_SYSWM_X11: + window_info.type = Frontend::WindowSystemType::X11; + window_info.display_connection = wm.info.x11.display; + window_info.render_surface = reinterpret_cast(wm.info.x11.window); + break; +#endif +#ifdef SDL_VIDEO_DRIVER_WAYLAND + case SDL_SYSWM_TYPE::SDL_SYSWM_WAYLAND: + window_info.type = Frontend::WindowSystemType::Wayland; + window_info.display_connection = wm.info.wl.display; + window_info.render_surface = wm.info.wl.surface; + break; +#endif +#ifdef SDL_VIDEO_DRIVER_COCOA + case SDL_SYSWM_TYPE::SDL_SYSWM_COCOA: + window_info.type = Frontend::WindowSystemType::Cocoa; + window_info.render_surface = SDL_Metal_CreateView(render_window); + break; +#endif +#ifdef SDL_VIDEO_DRIVER_ANDROID + case SDL_SYSWM_TYPE::SDL_SYSWM_ANDROID: + window_info.type = Frontend::WindowSystemType::Android; + window_info.render_surface = reinterpret_cast(wm.info.android.window); + break; +#endif + default: + LOG_CRITICAL(Frontend, "Window manager subsystem {} not implemented", wm.subsystem); + std::exit(EXIT_FAILURE); + break; + } + + OnResize(); + OnMinimalClientAreaChangeRequest(GetActiveConfig().min_client_area_size); + SDL_PumpEvents(); +} + +EmuWindow_SDL2_VK::~EmuWindow_SDL2_VK() = default; + +std::unique_ptr EmuWindow_SDL2_VK::CreateSharedContext() const { + return std::make_unique(); +} diff --git a/src/citra/emu_window/emu_window_sdl2_vk.h b/src/citra/emu_window/emu_window_sdl2_vk.h new file mode 100644 index 000000000..76dc2c041 --- /dev/null +++ b/src/citra/emu_window/emu_window_sdl2_vk.h @@ -0,0 +1,17 @@ +// Copyright 2023 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include +#include "citra/emu_window/emu_window_sdl2.h" +#include "core/frontend/emu_window.h" + +class EmuWindow_SDL2_VK final : public EmuWindow_SDL2 { +public: + explicit EmuWindow_SDL2_VK(bool fullscreen, bool is_secondary); + ~EmuWindow_SDL2_VK() override; + + std::unique_ptr CreateSharedContext() const override; +}; diff --git a/src/citra_qt/bootmanager.cpp b/src/citra_qt/bootmanager.cpp index 1aa460eb2..0e1e9d302 100644 --- a/src/citra_qt/bootmanager.cpp +++ b/src/citra_qt/bootmanager.cpp @@ -217,9 +217,17 @@ private: class DummyContext : public Frontend::GraphicsContext {}; +template class RenderWidget : public QWidget { public: RenderWidget(GRenderWindow* parent) : QWidget(parent) { + if constexpr (is_native) { + setAttribute(Qt::WA_NativeWindow); + setAttribute(Qt::WA_PaintOnScreen); + if (GetWindowSystemType() == Frontend::WindowSystemType::Wayland) { + setAttribute(Qt::WA_DontCreateNativeAncestors); + } + } setMouseTracking(true); } @@ -238,15 +246,10 @@ public: }; #ifdef HAS_OPENGL -class OpenGLRenderWidget : public RenderWidget { +class OpenGLRenderWidget : public RenderWidget { public: explicit OpenGLRenderWidget(GRenderWindow* parent, bool is_secondary) : RenderWidget(parent), is_secondary(is_secondary) { - setAttribute(Qt::WA_NativeWindow); - setAttribute(Qt::WA_PaintOnScreen); - if (GetWindowSystemType() == Frontend::WindowSystemType::Wayland) { - setAttribute(Qt::WA_DontCreateNativeAncestors); - } windowHandle()->setSurfaceType(QWindow::OpenGLSurface); } @@ -280,7 +283,14 @@ private: }; #endif -struct SoftwareRenderWidget : public RenderWidget { +class VulkanRenderWidget : public RenderWidget { +public: + explicit VulkanRenderWidget(GRenderWindow* parent) : RenderWidget(parent) { + windowHandle()->setSurfaceType(QWindow::VulkanSurface); + } +}; + +struct SoftwareRenderWidget : public RenderWidget { explicit SoftwareRenderWidget(GRenderWindow* parent) : RenderWidget(parent) {} void Present() override { @@ -613,6 +623,11 @@ bool GRenderWindow::InitRenderTarget() { return false; } break; + case Settings::GraphicsAPI::Vulkan: + if (!InitializeVulkan()) { + return false; + } + break; } // Update the Window System information with the new render target @@ -698,6 +713,15 @@ bool GRenderWindow::InitializeOpenGL() { #endif } +bool GRenderWindow::InitializeVulkan() { + auto child = new VulkanRenderWidget(this); + child_widget = child; + child_widget->windowHandle()->create(); + main_context = std::make_unique(); + + return true; +} + void GRenderWindow::InitializeSoftware() { child_widget = new SoftwareRenderWidget(this); main_context = std::make_unique(); diff --git a/src/citra_qt/bootmanager.h b/src/citra_qt/bootmanager.h index f0019886d..d2493b087 100644 --- a/src/citra_qt/bootmanager.h +++ b/src/citra_qt/bootmanager.h @@ -182,6 +182,7 @@ private: void OnMinimalClientAreaChangeRequest(std::pair minimal_size) override; bool InitializeOpenGL(); + bool InitializeVulkan(); void InitializeSoftware(); bool LoadOpenGL(); diff --git a/src/common/logging/log.h b/src/common/logging/log.h index cf3cf0dea..8cd98db14 100644 --- a/src/common/logging/log.h +++ b/src/common/logging/log.h @@ -8,6 +8,7 @@ #include #include "common/common_types.h" #include "common/logging/formatter.h" + namespace Log { // trims up to and including the last of ../, ..\, src/, src\ in a string @@ -103,6 +104,7 @@ enum class Class : ClassType { Render, ///< Emulator video output and hardware acceleration Render_Software, ///< Software renderer backend Render_OpenGL, ///< OpenGL backend + Render_Vulkan, ///< Vulkan backend Audio, ///< Audio emulation Audio_DSP, ///< The HLE and LLE implementations of the DSP Audio_Sink, ///< Emulator audio output backend diff --git a/src/common/settings.h b/src/common/settings.h index 0d980406f..61db1a787 100644 --- a/src/common/settings.h +++ b/src/common/settings.h @@ -20,6 +20,7 @@ namespace Settings { enum class GraphicsAPI { Software = 0, OpenGL = 1, + Vulkan = 2, }; enum class InitClock : u32 { @@ -425,7 +426,8 @@ struct Values { Setting allow_plugin_loader{true, "allow_plugin_loader"}; // Renderer - SwitchableSetting graphics_api{GraphicsAPI::OpenGL, "graphics_api"}; + SwitchableSetting graphics_api{GraphicsAPI::OpenGL, GraphicsAPI::Software, + GraphicsAPI::Vulkan, "graphics_api"}; Setting use_gles{false, "use_gles"}; Setting renderer_debug{false, "renderer_debug"}; SwitchableSetting use_hw_shader{true, "use_hw_shader"}; diff --git a/src/video_core/rasterizer_cache/rasterizer_cache.h b/src/video_core/rasterizer_cache/rasterizer_cache.h index 316678bdf..547c69bad 100644 --- a/src/video_core/rasterizer_cache/rasterizer_cache.h +++ b/src/video_core/rasterizer_cache/rasterizer_cache.h @@ -22,7 +22,6 @@ namespace VideoCore { MICROPROFILE_DECLARE(RasterizerCache_CopySurface); MICROPROFILE_DECLARE(RasterizerCache_UploadSurface); -MICROPROFILE_DECLARE(RasterizerCache_ValidateSurface); MICROPROFILE_DECLARE(RasterizerCache_DownloadSurface); MICROPROFILE_DECLARE(RasterizerCache_Invalidation); @@ -913,8 +912,6 @@ void RasterizerCache::ValidateSurface(SurfaceId surface_id, PAddr addr, u32 s return; } - MICROPROFILE_SCOPE(RasterizerCache_ValidateSurface); - Surface& surface = slot_surfaces[surface_id]; const SurfaceInterval validate_interval(addr, addr + size);