code: Prepare frontend for vulkan support

This commit is contained in:
GPUCode
2023-05-03 23:52:26 +03:00
parent 891290abd9
commit ba44bf9b0d
10 changed files with 147 additions and 12 deletions

View File

@@ -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
)

View File

@@ -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<EmuWindow_SDL2_GL>(fullscreen, is_secondary);
case Settings::GraphicsAPI::Vulkan:
return std::make_unique<EmuWindow_SDL2_VK>(fullscreen, is_secondary);
case Settings::GraphicsAPI::Software:
return std::make_unique<EmuWindow_SDL2_SW>(fullscreen, is_secondary);
}

View File

@@ -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

View File

@@ -0,0 +1,87 @@
// Copyright 2023 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include <cstdlib>
#include <memory>
#include <string>
#include <SDL.h>
#include <SDL_syswm.h>
#include <fmt/format.h>
#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<void*>(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<void*>(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<void*>(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<Frontend::GraphicsContext> EmuWindow_SDL2_VK::CreateSharedContext() const {
return std::make_unique<DummyContext>();
}

View File

@@ -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 <memory>
#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<Frontend::GraphicsContext> CreateSharedContext() const override;
};

View File

@@ -217,9 +217,17 @@ private:
class DummyContext : public Frontend::GraphicsContext {};
template <bool is_native = true>
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<true> {
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<true> {
public:
explicit VulkanRenderWidget(GRenderWindow* parent) : RenderWidget(parent) {
windowHandle()->setSurfaceType(QWindow::VulkanSurface);
}
};
struct SoftwareRenderWidget : public RenderWidget<false> {
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<DummyContext>();
return true;
}
void GRenderWindow::InitializeSoftware() {
child_widget = new SoftwareRenderWidget(this);
main_context = std::make_unique<DummyContext>();

View File

@@ -182,6 +182,7 @@ private:
void OnMinimalClientAreaChangeRequest(std::pair<u32, u32> minimal_size) override;
bool InitializeOpenGL();
bool InitializeVulkan();
void InitializeSoftware();
bool LoadOpenGL();

View File

@@ -8,6 +8,7 @@
#include <array>
#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

View File

@@ -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<bool> allow_plugin_loader{true, "allow_plugin_loader"};
// Renderer
SwitchableSetting<GraphicsAPI> graphics_api{GraphicsAPI::OpenGL, "graphics_api"};
SwitchableSetting<GraphicsAPI, true> graphics_api{GraphicsAPI::OpenGL, GraphicsAPI::Software,
GraphicsAPI::Vulkan, "graphics_api"};
Setting<bool> use_gles{false, "use_gles"};
Setting<bool> renderer_debug{false, "renderer_debug"};
SwitchableSetting<bool> use_hw_shader{true, "use_hw_shader"};

View File

@@ -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<T>::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);