code: Prepare frontend for vulkan support
This commit is contained in:
@@ -12,6 +12,8 @@ add_executable(citra
|
|||||||
emu_window/emu_window_sdl2_gl.h
|
emu_window/emu_window_sdl2_gl.h
|
||||||
emu_window/emu_window_sdl2_sw.cpp
|
emu_window/emu_window_sdl2_sw.cpp
|
||||||
emu_window/emu_window_sdl2_sw.h
|
emu_window/emu_window_sdl2_sw.h
|
||||||
|
emu_window/emu_window_sdl2_vk.cpp
|
||||||
|
emu_window/emu_window_sdl2_vk.h
|
||||||
precompiled_headers.h
|
precompiled_headers.h
|
||||||
resource.h
|
resource.h
|
||||||
)
|
)
|
||||||
|
@@ -15,6 +15,7 @@
|
|||||||
#include "citra/emu_window/emu_window_sdl2.h"
|
#include "citra/emu_window/emu_window_sdl2.h"
|
||||||
#include "citra/emu_window/emu_window_sdl2_gl.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_sw.h"
|
||||||
|
#include "citra/emu_window/emu_window_sdl2_vk.h"
|
||||||
#include "common/common_paths.h"
|
#include "common/common_paths.h"
|
||||||
#include "common/detached_tasks.h"
|
#include "common/detached_tasks.h"
|
||||||
#include "common/file_util.h"
|
#include "common/file_util.h"
|
||||||
@@ -365,6 +366,8 @@ int main(int argc, char** argv) {
|
|||||||
switch (Settings::values.graphics_api.GetValue()) {
|
switch (Settings::values.graphics_api.GetValue()) {
|
||||||
case Settings::GraphicsAPI::OpenGL:
|
case Settings::GraphicsAPI::OpenGL:
|
||||||
return std::make_unique<EmuWindow_SDL2_GL>(fullscreen, is_secondary);
|
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:
|
case Settings::GraphicsAPI::Software:
|
||||||
return std::make_unique<EmuWindow_SDL2_SW>(fullscreen, is_secondary);
|
return std::make_unique<EmuWindow_SDL2_SW>(fullscreen, is_secondary);
|
||||||
}
|
}
|
||||||
|
@@ -99,7 +99,7 @@ cpu_clock_percentage =
|
|||||||
|
|
||||||
[Renderer]
|
[Renderer]
|
||||||
# Whether to render using OpenGL or Software
|
# Whether to render using OpenGL or Software
|
||||||
# 0: Software, 1: OpenGL (default)
|
# 0: Software, 1: OpenGL (default), 2: Vulkan (default)
|
||||||
graphics_api =
|
graphics_api =
|
||||||
|
|
||||||
# Whether to render using GLES or OpenGL
|
# Whether to render using GLES or OpenGL
|
||||||
|
87
src/citra/emu_window/emu_window_sdl2_vk.cpp
Normal file
87
src/citra/emu_window/emu_window_sdl2_vk.cpp
Normal 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>();
|
||||||
|
}
|
17
src/citra/emu_window/emu_window_sdl2_vk.h
Normal file
17
src/citra/emu_window/emu_window_sdl2_vk.h
Normal 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;
|
||||||
|
};
|
@@ -217,9 +217,17 @@ private:
|
|||||||
|
|
||||||
class DummyContext : public Frontend::GraphicsContext {};
|
class DummyContext : public Frontend::GraphicsContext {};
|
||||||
|
|
||||||
|
template <bool is_native = true>
|
||||||
class RenderWidget : public QWidget {
|
class RenderWidget : public QWidget {
|
||||||
public:
|
public:
|
||||||
RenderWidget(GRenderWindow* parent) : QWidget(parent) {
|
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);
|
setMouseTracking(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -238,15 +246,10 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
#ifdef HAS_OPENGL
|
#ifdef HAS_OPENGL
|
||||||
class OpenGLRenderWidget : public RenderWidget {
|
class OpenGLRenderWidget : public RenderWidget<true> {
|
||||||
public:
|
public:
|
||||||
explicit OpenGLRenderWidget(GRenderWindow* parent, bool is_secondary)
|
explicit OpenGLRenderWidget(GRenderWindow* parent, bool is_secondary)
|
||||||
: RenderWidget(parent), is_secondary(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);
|
windowHandle()->setSurfaceType(QWindow::OpenGLSurface);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -280,7 +283,14 @@ private:
|
|||||||
};
|
};
|
||||||
#endif
|
#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) {}
|
explicit SoftwareRenderWidget(GRenderWindow* parent) : RenderWidget(parent) {}
|
||||||
|
|
||||||
void Present() override {
|
void Present() override {
|
||||||
@@ -613,6 +623,11 @@ bool GRenderWindow::InitRenderTarget() {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case Settings::GraphicsAPI::Vulkan:
|
||||||
|
if (!InitializeVulkan()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update the Window System information with the new render target
|
// Update the Window System information with the new render target
|
||||||
@@ -698,6 +713,15 @@ bool GRenderWindow::InitializeOpenGL() {
|
|||||||
#endif
|
#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() {
|
void GRenderWindow::InitializeSoftware() {
|
||||||
child_widget = new SoftwareRenderWidget(this);
|
child_widget = new SoftwareRenderWidget(this);
|
||||||
main_context = std::make_unique<DummyContext>();
|
main_context = std::make_unique<DummyContext>();
|
||||||
|
@@ -182,6 +182,7 @@ private:
|
|||||||
void OnMinimalClientAreaChangeRequest(std::pair<u32, u32> minimal_size) override;
|
void OnMinimalClientAreaChangeRequest(std::pair<u32, u32> minimal_size) override;
|
||||||
|
|
||||||
bool InitializeOpenGL();
|
bool InitializeOpenGL();
|
||||||
|
bool InitializeVulkan();
|
||||||
void InitializeSoftware();
|
void InitializeSoftware();
|
||||||
bool LoadOpenGL();
|
bool LoadOpenGL();
|
||||||
|
|
||||||
|
@@ -8,6 +8,7 @@
|
|||||||
#include <array>
|
#include <array>
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
#include "common/logging/formatter.h"
|
#include "common/logging/formatter.h"
|
||||||
|
|
||||||
namespace Log {
|
namespace Log {
|
||||||
|
|
||||||
// trims up to and including the last of ../, ..\, src/, src\ in a string
|
// 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, ///< Emulator video output and hardware acceleration
|
||||||
Render_Software, ///< Software renderer backend
|
Render_Software, ///< Software renderer backend
|
||||||
Render_OpenGL, ///< OpenGL backend
|
Render_OpenGL, ///< OpenGL backend
|
||||||
|
Render_Vulkan, ///< Vulkan backend
|
||||||
Audio, ///< Audio emulation
|
Audio, ///< Audio emulation
|
||||||
Audio_DSP, ///< The HLE and LLE implementations of the DSP
|
Audio_DSP, ///< The HLE and LLE implementations of the DSP
|
||||||
Audio_Sink, ///< Emulator audio output backend
|
Audio_Sink, ///< Emulator audio output backend
|
||||||
|
@@ -20,6 +20,7 @@ namespace Settings {
|
|||||||
enum class GraphicsAPI {
|
enum class GraphicsAPI {
|
||||||
Software = 0,
|
Software = 0,
|
||||||
OpenGL = 1,
|
OpenGL = 1,
|
||||||
|
Vulkan = 2,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class InitClock : u32 {
|
enum class InitClock : u32 {
|
||||||
@@ -425,7 +426,8 @@ struct Values {
|
|||||||
Setting<bool> allow_plugin_loader{true, "allow_plugin_loader"};
|
Setting<bool> allow_plugin_loader{true, "allow_plugin_loader"};
|
||||||
|
|
||||||
// Renderer
|
// 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> use_gles{false, "use_gles"};
|
||||||
Setting<bool> renderer_debug{false, "renderer_debug"};
|
Setting<bool> renderer_debug{false, "renderer_debug"};
|
||||||
SwitchableSetting<bool> use_hw_shader{true, "use_hw_shader"};
|
SwitchableSetting<bool> use_hw_shader{true, "use_hw_shader"};
|
||||||
|
@@ -22,7 +22,6 @@ namespace VideoCore {
|
|||||||
|
|
||||||
MICROPROFILE_DECLARE(RasterizerCache_CopySurface);
|
MICROPROFILE_DECLARE(RasterizerCache_CopySurface);
|
||||||
MICROPROFILE_DECLARE(RasterizerCache_UploadSurface);
|
MICROPROFILE_DECLARE(RasterizerCache_UploadSurface);
|
||||||
MICROPROFILE_DECLARE(RasterizerCache_ValidateSurface);
|
|
||||||
MICROPROFILE_DECLARE(RasterizerCache_DownloadSurface);
|
MICROPROFILE_DECLARE(RasterizerCache_DownloadSurface);
|
||||||
MICROPROFILE_DECLARE(RasterizerCache_Invalidation);
|
MICROPROFILE_DECLARE(RasterizerCache_Invalidation);
|
||||||
|
|
||||||
@@ -913,8 +912,6 @@ void RasterizerCache<T>::ValidateSurface(SurfaceId surface_id, PAddr addr, u32 s
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
MICROPROFILE_SCOPE(RasterizerCache_ValidateSurface);
|
|
||||||
|
|
||||||
Surface& surface = slot_surfaces[surface_id];
|
Surface& surface = slot_surfaces[surface_id];
|
||||||
const SurfaceInterval validate_interval(addr, addr + size);
|
const SurfaceInterval validate_interval(addr, addr + size);
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user