build: Add flags to toggle specific renderer backends. (#7375)

This commit is contained in:
Steveice10 2024-01-21 23:29:46 -08:00 committed by GitHub
parent 77fce3cf82
commit 82294425e3
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
18 changed files with 443 additions and 211 deletions

View file

@ -185,10 +185,15 @@ add_executable(citra-qt
util/spinbox.h
util/util.cpp
util/util.h
util/vk_device_info.cpp
util/vk_device_info.h
)
if (ENABLE_VULKAN)
target_sources(citra-qt PRIVATE
util/vk_device_info.cpp
util/vk_device_info.h
)
endif()
file(GLOB COMPAT_LIST
${PROJECT_BINARY_DIR}/dist/compatibility_list/compatibility_list.qrc
${PROJECT_BINARY_DIR}/dist/compatibility_list/compatibility_list.json)
@ -300,8 +305,16 @@ endif()
create_target_directory_groups(citra-qt)
target_link_libraries(citra-qt PRIVATE audio_core citra_common citra_core input_common network video_core)
target_link_libraries(citra-qt PRIVATE Boost::boost glad nihstro-headers Qt6::Widgets Qt6::Multimedia Qt6::Concurrent)
target_link_libraries(citra-qt PRIVATE ${PLATFORM_LIBRARIES} Threads::Threads vulkan-headers)
target_link_libraries(citra-qt PRIVATE Boost::boost nihstro-headers Qt6::Widgets Qt6::Multimedia Qt6::Concurrent)
target_link_libraries(citra-qt PRIVATE ${PLATFORM_LIBRARIES} Threads::Threads)
if (ENABLE_OPENGL)
target_link_libraries(citra-qt PRIVATE glad)
endif()
if (ENABLE_VULKAN)
target_link_libraries(citra-qt PRIVATE vulkan-headers)
endif()
if (NOT WIN32)
target_include_directories(citra-qt PRIVATE ${Qt6Gui_PRIVATE_INCLUDE_DIRS})

View file

@ -26,7 +26,7 @@
#include "video_core/renderer_base.h"
#include "video_core/renderer_software/renderer_software.h"
#ifdef HAS_OPENGL
#ifdef ENABLE_OPENGL
#include <glad/glad.h>
#include <QOffscreenSurface>
@ -137,7 +137,7 @@ void EmuThread::run() {
#endif
}
#ifdef HAS_OPENGL
#ifdef ENABLE_OPENGL
static std::unique_ptr<QOpenGLContext> CreateQOpenGLContext(bool gles) {
QSurfaceFormat format;
if (gles) {
@ -258,7 +258,7 @@ public:
virtual ~RenderWidget() = default;
};
#ifdef HAS_OPENGL
#ifdef ENABLE_OPENGL
class OpenGLRenderWidget : public RenderWidget {
public:
explicit OpenGLRenderWidget(GRenderWindow* parent, Core::System& system_, bool is_secondary)
@ -305,6 +305,7 @@ private:
};
#endif
#ifdef ENABLE_VULKAN
class VulkanRenderWidget : public RenderWidget {
public:
explicit VulkanRenderWidget(GRenderWindow* parent) : RenderWidget(parent) {
@ -324,7 +325,9 @@ public:
return nullptr;
}
};
#endif
#ifdef ENABLE_SOFTWARE_RENDERER
struct SoftwareRenderWidget : public RenderWidget {
explicit SoftwareRenderWidget(GRenderWindow* parent, Core::System& system_)
: RenderWidget(parent), system(system_) {}
@ -377,6 +380,7 @@ struct SoftwareRenderWidget : public RenderWidget {
private:
Core::System& system;
};
#endif
static Frontend::WindowSystemType GetWindowSystemType() {
// Determine WSI type based on Qt platform.
@ -636,17 +640,40 @@ bool GRenderWindow::InitRenderTarget() {
const auto graphics_api = Settings::values.graphics_api.GetValue();
switch (graphics_api) {
#ifdef ENABLE_SOFTWARE_RENDERER
case Settings::GraphicsAPI::Software:
InitializeSoftware();
break;
#endif
#ifdef ENABLE_OPENGL
case Settings::GraphicsAPI::OpenGL:
if (!InitializeOpenGL() || !LoadOpenGL()) {
return false;
}
break;
#endif
#ifdef ENABLE_VULKAN
case Settings::GraphicsAPI::Vulkan:
InitializeVulkan();
break;
#endif
default:
LOG_CRITICAL(Frontend,
"Unknown or unsupported graphics API {}, falling back to available default",
graphics_api);
#ifdef ENABLE_OPENGL
if (!InitializeOpenGL() || !LoadOpenGL()) {
return false;
}
#elif ENABLE_VULKAN
InitializeVulkan();
#elif ENABLE_SOFTWARE_RENDERER
InitializeSoftware();
#else
// TODO: Add a null renderer backend for this, perhaps.
#error "At least one renderer must be enabled."
#endif
break;
}
// Update the Window System information with the new render target
@ -700,8 +727,8 @@ void GRenderWindow::OnMinimalClientAreaChangeRequest(std::pair<u32, u32> minimal
setMinimumSize(minimal_size.first, minimal_size.second);
}
#ifdef ENABLE_OPENGL
bool GRenderWindow::InitializeOpenGL() {
#ifdef HAS_OPENGL
if (!QOpenGLContext::supportsThreadedOpenGL()) {
QMessageBox::warning(this, tr("OpenGL not available!"),
tr("OpenGL shared contexts are not supported."));
@ -726,33 +753,13 @@ bool GRenderWindow::InitializeOpenGL() {
child_widget->windowHandle()->setFormat(format);
return true;
#else
QMessageBox::warning(this, tr("OpenGL not available!"),
tr("Citra has not been compiled with OpenGL support."));
return false;
#endif
}
void GRenderWindow::InitializeVulkan() {
auto child = new VulkanRenderWidget(this);
child_widget = child;
child_widget->windowHandle()->create();
main_context = std::make_unique<DummyContext>();
}
void GRenderWindow::InitializeSoftware() {
child_widget = new SoftwareRenderWidget(this, system);
main_context = std::make_unique<DummyContext>();
}
#ifdef HAS_OPENGL
static void* GetProcAddressGL(const char* name) {
return reinterpret_cast<void*>(QOpenGLContext::currentContext()->getProcAddress(name));
}
#endif
bool GRenderWindow::LoadOpenGL() {
#ifdef HAS_OPENGL
auto context = CreateSharedContext();
auto scope = context->Acquire();
const auto gles = context->IsGLES();
@ -785,12 +792,24 @@ bool GRenderWindow::LoadOpenGL() {
}
return true;
#else
QMessageBox::warning(this, tr("OpenGL not available!"),
tr("Citra has not been compiled with OpenGL support."));
return false;
#endif
}
#endif
#ifdef ENABLE_VULKAN
void GRenderWindow::InitializeVulkan() {
auto child = new VulkanRenderWidget(this);
child_widget = child;
child_widget->windowHandle()->create();
main_context = std::make_unique<DummyContext>();
}
#endif
#ifdef ENABLE_SOFTWARE_RENDERER
void GRenderWindow::InitializeSoftware() {
child_widget = new SoftwareRenderWidget(this, system);
main_context = std::make_unique<DummyContext>();
}
#endif
void GRenderWindow::OnEmulationStarting(EmuThread* emu_thread) {
this->emu_thread = emu_thread;
@ -805,7 +824,7 @@ void GRenderWindow::showEvent(QShowEvent* event) {
}
std::unique_ptr<Frontend::GraphicsContext> GRenderWindow::CreateSharedContext() const {
#ifdef HAS_OPENGL
#ifdef ENABLE_OPENGL
const auto graphics_api = Settings::values.graphics_api.GetValue();
if (graphics_api == Settings::GraphicsAPI::OpenGL) {
auto gl_context = static_cast<OpenGLSharedContext*>(main_context.get());

View file

@ -186,10 +186,16 @@ private:
void OnMinimalClientAreaChangeRequest(std::pair<u32, u32> minimal_size) override;
#ifdef ENABLE_OPENGL
bool InitializeOpenGL();
void InitializeVulkan();
void InitializeSoftware();
bool LoadOpenGL();
#endif
#ifdef ENABLE_VULKAN
void InitializeVulkan();
#endif
#ifdef ENABLE_SOFTWARE_RENDERER
void InitializeSoftware();
#endif
QWidget* child_widget = nullptr;

View file

@ -13,7 +13,9 @@
#include "common/logging/backend.h"
#include "common/settings.h"
#include "ui_configure_debug.h"
#ifdef ENABLE_VULKAN
#include "video_core/renderer_vulkan/vk_instance.h"
#endif
// The QSlider doesn't have an easy way to set a custom step amount,
// so we can just convert from the sliders range (0 - 79) to the expected
@ -36,6 +38,7 @@ ConfigureDebug::ConfigureDebug(bool is_powered_on_, QWidget* parent)
QDesktopServices::openUrl(QUrl::fromLocalFile(path));
});
#ifdef ENABLE_VULKAN
connect(ui->toggle_renderer_debug, &QCheckBox::clicked, this, [this](bool checked) {
if (checked && Settings::values.graphics_api.GetValue() == Settings::GraphicsAPI::Vulkan) {
try {
@ -65,6 +68,7 @@ ConfigureDebug::ConfigureDebug(bool is_powered_on_, QWidget* parent)
}
}
});
#endif
ui->toggle_cpu_jit->setEnabled(!is_powered_on);
ui->toggle_renderer_debug->setEnabled(!is_powered_on);

View file

@ -7,7 +7,9 @@
#include "citra_qt/configuration/configure_enhancements.h"
#include "common/settings.h"
#include "ui_configure_enhancements.h"
#ifdef ENABLE_OPENGL
#include "video_core/renderer_opengl/post_processing_opengl.h"
#endif
ConfigureEnhancements::ConfigureEnhancements(QWidget* parent)
: QWidget(parent), ui(std::make_unique<Ui::ConfigureEnhancements>()) {
@ -117,12 +119,14 @@ void ConfigureEnhancements::updateShaders(Settings::StereoRenderOption stereo_op
ui->shader_combobox->setCurrentIndex(0);
#ifdef ENABLE_OPENGL
for (const auto& shader : OpenGL::GetPostProcessingShaderList(
stereo_option == Settings::StereoRenderOption::Anaglyph)) {
ui->shader_combobox->addItem(QString::fromStdString(shader));
if (current_shader == shader)
ui->shader_combobox->setCurrentIndex(ui->shader_combobox->count() - 1);
}
#endif
}
void ConfigureEnhancements::RetranslateUI() {

View file

@ -3,11 +3,14 @@
// Refer to the license.txt file included.
#include <QColorDialog>
#include <QStandardItemModel>
#include "citra_qt/configuration/configuration_shared.h"
#include "citra_qt/configuration/configure_graphics.h"
#include "common/settings.h"
#include "ui_configure_graphics.h"
#ifdef ENABLE_VULKAN
#include "video_core/renderer_vulkan/vk_instance.h"
#endif
ConfigureGraphics::ConfigureGraphics(std::span<const QString> physical_devices, bool is_powered_on,
QWidget* parent)
@ -27,12 +30,32 @@ ConfigureGraphics::ConfigureGraphics(std::span<const QString> physical_devices,
// Set the index to -1 to ensure the below lambda is called with setCurrentIndex
ui->graphics_api_combo->setCurrentIndex(-1);
auto graphics_api_combo_model =
qobject_cast<QStandardItemModel*>(ui->graphics_api_combo->model());
#ifndef ENABLE_SOFTWARE_RENDERER
const auto software_item =
graphics_api_combo_model->item(static_cast<u32>(Settings::GraphicsAPI::Software));
software_item->setFlags(software_item->flags() & ~Qt::ItemIsEnabled);
#endif
#ifndef ENABLE_OPENGL
const auto opengl_item =
graphics_api_combo_model->item(static_cast<u32>(Settings::GraphicsAPI::OpenGL));
opengl_item->setFlags(opengl_item->flags() & ~Qt::ItemIsEnabled);
#endif
#ifndef ENABLE_VULKAN
const auto vulkan_item =
graphics_api_combo_model->item(static_cast<u32>(Settings::GraphicsAPI::Vulkan));
vulkan_item->setFlags(vulkan_item->flags() & ~Qt::ItemIsEnabled);
#else
if (physical_devices.empty()) {
const u32 index = static_cast<u32>(Settings::GraphicsAPI::Vulkan);
ui->graphics_api_combo->removeItem(index);
const auto vulkan_item =
graphics_api_combo_model->item(static_cast<u32>(Settings::GraphicsAPI::Vulkan));
vulkan_item->setFlags(vulkan_item->flags() & ~Qt::ItemIsEnabled);
ui->physical_device_combo->setVisible(false);
ui->spirv_shader_gen->setVisible(false);
}
#endif
connect(ui->graphics_api_combo, qOverload<int>(&QComboBox::currentIndexChanged), this,
[this](int index) {

View file

@ -519,6 +519,7 @@ void GameList::UpdateColumnVisibility() {
tree_view->setColumnHidden(COLUMN_SIZE, !UISettings::values.show_size_column);
}
#ifdef ENABLE_OPENGL
void ForEachOpenGLCacheFile(u64 program_id, auto func) {
for (const std::string_view cache_type : {"separable", "conventional"}) {
const std::string path = fmt::format("{}opengl/precompiled/{}/{:016X}.bin",
@ -528,6 +529,7 @@ void ForEachOpenGLCacheFile(u64 program_id, auto func) {
func(file);
}
}
#endif
void GameList::AddGamePopup(QMenu& context_menu, const QString& path, const QString& name,
u64 program_id, u64 extdata_id, Service::FS::MediaType media_type) {
@ -545,8 +547,10 @@ void GameList::AddGamePopup(QMenu& context_menu, const QString& path, const QStr
QMenu* shader_menu = context_menu.addMenu(tr("Disk Shader Cache"));
QAction* open_shader_cache_location = shader_menu->addAction(tr("Open Shader Cache Location"));
shader_menu->addSeparator();
#ifdef ENABLE_OPENGL
QAction* delete_opengl_disk_shader_cache =
shader_menu->addAction(tr("Delete OpenGL Shader Cache"));
#endif
QMenu* uninstall_menu = context_menu.addMenu(tr("Uninstall"));
QAction* uninstall_all = uninstall_menu->addAction(tr("Everything"));
@ -564,9 +568,11 @@ void GameList::AddGamePopup(QMenu& context_menu, const QString& path, const QStr
const bool is_application = program_id_high == 0x00040000 || program_id_high == 0x00040002 ||
program_id_high == 0x00040010;
#ifdef ENABLE_OPENGL
bool opengl_cache_exists = false;
ForEachOpenGLCacheFile(
program_id, [&opengl_cache_exists](QFile& file) { opengl_cache_exists |= file.exists(); });
#endif
std::string sdmc_dir = FileUtil::GetUserPath(FileUtil::UserPath::SDMCDir);
open_save_location->setEnabled(
@ -603,7 +609,9 @@ void GameList::AddGamePopup(QMenu& context_menu, const QString& path, const QStr
open_mods_location->setEnabled(is_application);
dump_romfs->setEnabled(is_application);
#ifdef ENABLE_OPENGL
delete_opengl_disk_shader_cache->setEnabled(opengl_cache_exists);
#endif
uninstall_all->setEnabled(is_installed || has_update || has_dlc);
uninstall_game->setEnabled(is_installed);
@ -669,9 +677,11 @@ void GameList::AddGamePopup(QMenu& context_menu, const QString& path, const QStr
emit OpenFolderRequested(program_id, GameListOpenTarget::SHADER_CACHE);
}
});
#ifdef ENABLE_OPENGL
connect(delete_opengl_disk_shader_cache, &QAction::triggered, this, [program_id] {
ForEachOpenGLCacheFile(program_id, [](QFile& file) { file.remove(); });
});
#endif
connect(uninstall_all, &QAction::triggered, this, [=, this] {
QMessageBox::StandardButton answer = QMessageBox::question(
this, tr("Citra"),

View file

@ -270,6 +270,7 @@ GMainWindow::GMainWindow(Core::System& system_)
connect(&mouse_hide_timer, &QTimer::timeout, this, &GMainWindow::HideMouseCursor);
connect(ui->menubar, &QMenuBar::hovered, this, &GMainWindow::OnMouseActivity);
#ifdef ENABLE_VULKAN
physical_devices = GetVulkanPhysicalDevices();
if (physical_devices.empty()) {
QMessageBox::warning(this, tr("No Suitable Vulkan Devices Detected"),
@ -277,6 +278,7 @@ GMainWindow::GMainWindow(Core::System& system_)
"Your GPU may not support Vulkan 1.1, or you do not "
"have the latest graphics driver."));
}
#endif
#if ENABLE_QT_UPDATER
if (UISettings::values.check_for_update_on_start) {
@ -2689,6 +2691,22 @@ void GMainWindow::UpdateAPIIndicator(bool update) {
u32 api_index = static_cast<u32>(Settings::values.graphics_api.GetValue());
if (update) {
api_index = (api_index + 1) % graphics_apis.size();
// Skip past any disabled renderers.
#ifndef ENABLE_SOFTWARE_RENDERER
if (api_index == static_cast<u32>(Settings::GraphicsAPI::Software)) {
api_index = (api_index + 1) % graphics_apis.size();
}
#endif
#ifndef ENABLE_OPENGL
if (api_index == static_cast<u32>(Settings::GraphicsAPI::OpenGL)) {
api_index = (api_index + 1) % graphics_apis.size();
}
#endif
#ifndef ENABLE_VULKAN
if (api_index == static_cast<u32>(Settings::GraphicsAPI::Vulkan)) {
api_index = (api_index + 1) % graphics_apis.size();
}
#endif
Settings::values.graphics_api = static_cast<Settings::GraphicsAPI>(api_index);
}
@ -3164,8 +3182,11 @@ int main(int argc, char* argv[]) {
chdir(bin_path.c_str());
#endif
#ifdef ENABLE_OPENGL
QCoreApplication::setAttribute(Qt::AA_DontCheckOpenGLContextThreadAffinity);
QCoreApplication::setAttribute(Qt::AA_ShareOpenGLContexts);
#endif
QApplication app(argc, argv);
// Qt changes the locale and causes issues in float conversion using std::to_string() when