citra_qt: Add physical device selection dialog
This commit is contained in:
28
dist/qt_themes/qdarkstyle/style.qss
vendored
28
dist/qt_themes/qdarkstyle/style.qss
vendored
@ -1,3 +1,31 @@
|
|||||||
|
QPushButton#TogglableStatusBarButton {
|
||||||
|
color: #959595;
|
||||||
|
border: 1px solid transparent;
|
||||||
|
background-color: transparent;
|
||||||
|
padding: 0px 3px 0px 3px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
QPushButton#TogglableStatusBarButton:checked {
|
||||||
|
color: palette(text);
|
||||||
|
}
|
||||||
|
|
||||||
|
QPushButton#TogglableStatusBarButton:hover {
|
||||||
|
border: 1px solid #76797C;
|
||||||
|
}
|
||||||
|
|
||||||
|
QPushButton#GraphicsAPIStatusBarButton {
|
||||||
|
color: #656565;
|
||||||
|
border: 1px solid transparent;
|
||||||
|
background-color: transparent;
|
||||||
|
padding: 0px 3px 0px 3px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
QPushButton#GraphicsAPIStatusBarButton:hover {
|
||||||
|
border: 1px solid #76797C;
|
||||||
|
}
|
||||||
|
|
||||||
QToolTip {
|
QToolTip {
|
||||||
border: 1px solid #76797C;
|
border: 1px solid #76797C;
|
||||||
background-color: #5A7566;
|
background-color: #5A7566;
|
||||||
|
5
externals/CMakeLists.txt
vendored
5
externals/CMakeLists.txt
vendored
@ -161,3 +161,8 @@ if(ANDROID)
|
|||||||
add_subdirectory(libyuv)
|
add_subdirectory(libyuv)
|
||||||
target_include_directories(yuv INTERFACE ./libyuv/include)
|
target_include_directories(yuv INTERFACE ./libyuv/include)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
# VMA
|
||||||
|
add_library(vma INTERFACE)
|
||||||
|
target_include_directories(vma INTERFACE ./vma)
|
||||||
|
|
||||||
|
@ -260,7 +260,7 @@ endif()
|
|||||||
create_target_directory_groups(citra-qt)
|
create_target_directory_groups(citra-qt)
|
||||||
|
|
||||||
target_link_libraries(citra-qt PRIVATE audio_core common core input_common network video_core)
|
target_link_libraries(citra-qt PRIVATE audio_core common core input_common network video_core)
|
||||||
target_link_libraries(citra-qt PRIVATE Boost::boost glad nihstro-headers Qt5::Widgets Qt5::Multimedia)
|
target_link_libraries(citra-qt PRIVATE Boost::boost glad vma nihstro-headers Qt5::Widgets Qt5::Multimedia)
|
||||||
target_link_libraries(citra-qt PRIVATE ${PLATFORM_LIBRARIES} Threads::Threads)
|
target_link_libraries(citra-qt PRIVATE ${PLATFORM_LIBRARIES} Threads::Threads)
|
||||||
|
|
||||||
if (NOT WIN32)
|
if (NOT WIN32)
|
||||||
|
@ -485,6 +485,7 @@ void Config::ReadRendererValues() {
|
|||||||
Settings::values.graphics_api = static_cast<Settings::GraphicsAPI>(
|
Settings::values.graphics_api = static_cast<Settings::GraphicsAPI>(
|
||||||
ReadSetting(QStringLiteral("graphics_api"), static_cast<u32>(Settings::GraphicsAPI::OpenGL))
|
ReadSetting(QStringLiteral("graphics_api"), static_cast<u32>(Settings::GraphicsAPI::OpenGL))
|
||||||
.toUInt());
|
.toUInt());
|
||||||
|
Settings::values.physical_device = ReadSetting(QStringLiteral("physical_device"), 0).toUInt();
|
||||||
Settings::values.renderer_debug = ReadSetting(QStringLiteral("renderer_debug"), false).toBool();
|
Settings::values.renderer_debug = ReadSetting(QStringLiteral("renderer_debug"), false).toBool();
|
||||||
Settings::values.use_hw_renderer =
|
Settings::values.use_hw_renderer =
|
||||||
ReadSetting(QStringLiteral("use_hw_renderer"), true).toBool();
|
ReadSetting(QStringLiteral("use_hw_renderer"), true).toBool();
|
||||||
@ -1000,6 +1001,7 @@ void Config::SaveRendererValues() {
|
|||||||
|
|
||||||
WriteSetting(QStringLiteral("graphics_api"), static_cast<u32>(Settings::values.graphics_api),
|
WriteSetting(QStringLiteral("graphics_api"), static_cast<u32>(Settings::values.graphics_api),
|
||||||
static_cast<u32>(Settings::GraphicsAPI::OpenGL));
|
static_cast<u32>(Settings::GraphicsAPI::OpenGL));
|
||||||
|
WriteSetting(QStringLiteral("physical_device"), Settings::values.physical_device, 0);
|
||||||
WriteSetting(QStringLiteral("renderer_debug"), Settings::values.renderer_debug, false);
|
WriteSetting(QStringLiteral("renderer_debug"), Settings::values.renderer_debug, false);
|
||||||
WriteSetting(QStringLiteral("use_hw_renderer"), Settings::values.use_hw_renderer, true);
|
WriteSetting(QStringLiteral("use_hw_renderer"), Settings::values.use_hw_renderer, true);
|
||||||
WriteSetting(QStringLiteral("use_hw_shader"), Settings::values.use_hw_shader, true);
|
WriteSetting(QStringLiteral("use_hw_shader"), Settings::values.use_hw_shader, true);
|
||||||
|
@ -10,10 +10,12 @@
|
|||||||
#include "core/core.h"
|
#include "core/core.h"
|
||||||
#include "core/settings.h"
|
#include "core/settings.h"
|
||||||
#include "ui_configure_graphics.h"
|
#include "ui_configure_graphics.h"
|
||||||
|
#include "video_core/renderer_vulkan/vk_instance.h"
|
||||||
|
|
||||||
ConfigureGraphics::ConfigureGraphics(QWidget* parent)
|
ConfigureGraphics::ConfigureGraphics(QWidget* parent)
|
||||||
: QWidget(parent), ui(std::make_unique<Ui::ConfigureGraphics>()) {
|
: QWidget(parent), ui(std::make_unique<Ui::ConfigureGraphics>()) {
|
||||||
ui->setupUi(this);
|
ui->setupUi(this);
|
||||||
|
DiscoverPhysicalDevices();
|
||||||
SetConfiguration();
|
SetConfiguration();
|
||||||
|
|
||||||
const bool not_running = !Core::System::GetInstance().IsPoweredOn();
|
const bool not_running = !Core::System::GetInstance().IsPoweredOn();
|
||||||
@ -24,6 +26,10 @@ ConfigureGraphics::ConfigureGraphics(QWidget* parent)
|
|||||||
ui->graphics_api_combo->setEnabled(not_running);
|
ui->graphics_api_combo->setEnabled(not_running);
|
||||||
ui->toggle_shader_jit->setEnabled(not_running);
|
ui->toggle_shader_jit->setEnabled(not_running);
|
||||||
ui->toggle_disk_shader_cache->setEnabled(hw_renderer_enabled && not_running);
|
ui->toggle_disk_shader_cache->setEnabled(hw_renderer_enabled && not_running);
|
||||||
|
SetPhysicalDeviceComboVisibility(ui->graphics_api_combo->currentIndex());
|
||||||
|
|
||||||
|
connect(ui->graphics_api_combo, qOverload<int>(&QComboBox::currentIndexChanged), this,
|
||||||
|
&ConfigureGraphics::SetPhysicalDeviceComboVisibility);
|
||||||
|
|
||||||
connect(ui->toggle_hw_renderer, &QCheckBox::toggled, this, [this] {
|
connect(ui->toggle_hw_renderer, &QCheckBox::toggled, this, [this] {
|
||||||
auto checked = ui->toggle_hw_renderer->isChecked();
|
auto checked = ui->toggle_hw_renderer->isChecked();
|
||||||
@ -75,6 +81,7 @@ void ConfigureGraphics::SetConfiguration() {
|
|||||||
ui->toggle_disk_shader_cache->setChecked(Settings::values.use_disk_shader_cache);
|
ui->toggle_disk_shader_cache->setChecked(Settings::values.use_disk_shader_cache);
|
||||||
ui->toggle_vsync_new->setChecked(Settings::values.use_vsync_new);
|
ui->toggle_vsync_new->setChecked(Settings::values.use_vsync_new);
|
||||||
ui->graphics_api_combo->setCurrentIndex(static_cast<int>(Settings::values.graphics_api));
|
ui->graphics_api_combo->setCurrentIndex(static_cast<int>(Settings::values.graphics_api));
|
||||||
|
ui->physical_device_combo->setCurrentIndex(static_cast<int>(Settings::values.physical_device));
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConfigureGraphics::ApplyConfiguration() {
|
void ConfigureGraphics::ApplyConfiguration() {
|
||||||
@ -86,8 +93,27 @@ void ConfigureGraphics::ApplyConfiguration() {
|
|||||||
Settings::values.use_disk_shader_cache = ui->toggle_disk_shader_cache->isChecked();
|
Settings::values.use_disk_shader_cache = ui->toggle_disk_shader_cache->isChecked();
|
||||||
Settings::values.use_vsync_new = ui->toggle_vsync_new->isChecked();
|
Settings::values.use_vsync_new = ui->toggle_vsync_new->isChecked();
|
||||||
Settings::values.graphics_api = static_cast<Settings::GraphicsAPI>(ui->graphics_api_combo->currentIndex());
|
Settings::values.graphics_api = static_cast<Settings::GraphicsAPI>(ui->graphics_api_combo->currentIndex());
|
||||||
|
Settings::values.physical_device = static_cast<u16>(ui->physical_device_combo->currentIndex());
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConfigureGraphics::RetranslateUI() {
|
void ConfigureGraphics::RetranslateUI() {
|
||||||
ui->retranslateUi(this);
|
ui->retranslateUi(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ConfigureGraphics::DiscoverPhysicalDevices() {
|
||||||
|
Vulkan::Instance instance{};
|
||||||
|
const auto physical_devices = instance.GetPhysicalDevices();
|
||||||
|
|
||||||
|
ui->physical_device_combo->clear();
|
||||||
|
for (const vk::PhysicalDevice& physical_device : physical_devices) {
|
||||||
|
const QString name = QString::fromLocal8Bit(physical_device.getProperties().deviceName);
|
||||||
|
ui->physical_device_combo->addItem(name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConfigureGraphics::SetPhysicalDeviceComboVisibility(int index) {
|
||||||
|
const auto graphics_api = static_cast<Settings::GraphicsAPI>(index);
|
||||||
|
const bool is_visible = graphics_api == Settings::GraphicsAPI::Vulkan;
|
||||||
|
ui->physical_device_label->setVisible(is_visible);
|
||||||
|
ui->physical_device_combo->setVisible(is_visible);
|
||||||
|
}
|
||||||
|
@ -24,6 +24,11 @@ public:
|
|||||||
|
|
||||||
void UpdateBackgroundColorButton(const QColor& color);
|
void UpdateBackgroundColorButton(const QColor& color);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void DiscoverPhysicalDevices();
|
||||||
|
void SetPhysicalDeviceComboVisibility(int index);
|
||||||
|
|
||||||
|
private:
|
||||||
std::unique_ptr<Ui::ConfigureGraphics> ui;
|
std::unique_ptr<Ui::ConfigureGraphics> ui;
|
||||||
QColor bg_color;
|
QColor bg_color;
|
||||||
};
|
};
|
||||||
|
@ -21,15 +21,15 @@
|
|||||||
</property>
|
</property>
|
||||||
<layout class="QVBoxLayout" name="verticalLayout">
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
<item>
|
<item>
|
||||||
<widget class="QGroupBox" name="rendererBox">
|
<widget class="QGroupBox" name="apiBox">
|
||||||
<property name="title">
|
<property name="title">
|
||||||
<string>Renderer</string>
|
<string>API Settings</string>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_6">
|
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||||
<item>
|
<item>
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||||
<item>
|
<item>
|
||||||
<widget class="QLabel" name="label">
|
<widget class="QLabel" name="graphics_api_label">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Graphics API</string>
|
<string>Graphics API</string>
|
||||||
</property>
|
</property>
|
||||||
@ -56,6 +56,29 @@
|
|||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="physical_device_label">
|
||||||
|
<property name="text">
|
||||||
|
<string>Physical device</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QComboBox" name="physical_device_combo"/>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QGroupBox" name="rendererBox">
|
||||||
|
<property name="title">
|
||||||
|
<string>Renderer</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_6">
|
||||||
<item>
|
<item>
|
||||||
<widget class="QCheckBox" name="toggle_hw_renderer">
|
<widget class="QCheckBox" name="toggle_hw_renderer">
|
||||||
<property name="toolTip">
|
<property name="toolTip">
|
||||||
|
@ -59,6 +59,7 @@
|
|||||||
#include "common/microprofile.h"
|
#include "common/microprofile.h"
|
||||||
#include "common/scm_rev.h"
|
#include "common/scm_rev.h"
|
||||||
#include "common/scope_exit.h"
|
#include "common/scope_exit.h"
|
||||||
|
#include "common/string_util.h"
|
||||||
#ifdef ARCHITECTURE_x86_64
|
#ifdef ARCHITECTURE_x86_64
|
||||||
#include "common/x64/cpu_detect.h"
|
#include "common/x64/cpu_detect.h"
|
||||||
#endif
|
#endif
|
||||||
@ -280,6 +281,23 @@ void GMainWindow::InitializeWidgets() {
|
|||||||
message_label->setAlignment(Qt::AlignLeft);
|
message_label->setAlignment(Qt::AlignLeft);
|
||||||
statusBar()->addPermanentWidget(message_label, 1);
|
statusBar()->addPermanentWidget(message_label, 1);
|
||||||
|
|
||||||
|
// Setup Graphics API button
|
||||||
|
graphics_api_button = new QPushButton();
|
||||||
|
graphics_api_button->setCheckable(true);
|
||||||
|
graphics_api_button->setObjectName(QStringLiteral("GraphicsAPIStatusBarButton"));
|
||||||
|
graphics_api_button->setFocusPolicy(Qt::NoFocus);
|
||||||
|
UpdateAPIIndicator(false);
|
||||||
|
|
||||||
|
connect(graphics_api_button, &QPushButton::clicked, this, [this] {
|
||||||
|
if (emulation_running) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
UpdateAPIIndicator(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
statusBar()->addPermanentWidget(graphics_api_button);
|
||||||
|
|
||||||
progress_bar = new QProgressBar();
|
progress_bar = new QProgressBar();
|
||||||
progress_bar->hide();
|
progress_bar->hide();
|
||||||
statusBar()->addPermanentWidget(progress_bar);
|
statusBar()->addPermanentWidget(progress_bar);
|
||||||
@ -299,8 +317,9 @@ void GMainWindow::InitializeWidgets() {
|
|||||||
label->setVisible(false);
|
label->setVisible(false);
|
||||||
label->setFrameStyle(QFrame::NoFrame);
|
label->setFrameStyle(QFrame::NoFrame);
|
||||||
label->setContentsMargins(4, 0, 4, 0);
|
label->setContentsMargins(4, 0, 4, 0);
|
||||||
statusBar()->addPermanentWidget(label, 0);
|
statusBar()->addPermanentWidget(label);
|
||||||
}
|
}
|
||||||
|
|
||||||
statusBar()->addPermanentWidget(multiplayer_state->GetStatusText(), 0);
|
statusBar()->addPermanentWidget(multiplayer_state->GetStatusText(), 0);
|
||||||
statusBar()->addPermanentWidget(multiplayer_state->GetStatusIcon(), 0);
|
statusBar()->addPermanentWidget(multiplayer_state->GetStatusIcon(), 0);
|
||||||
statusBar()->setVisible(true);
|
statusBar()->setVisible(true);
|
||||||
@ -1780,6 +1799,7 @@ void GMainWindow::OnConfigure() {
|
|||||||
} else {
|
} else {
|
||||||
setMouseTracking(false);
|
setMouseTracking(false);
|
||||||
}
|
}
|
||||||
|
UpdateAPIIndicator(false);
|
||||||
} else {
|
} else {
|
||||||
Settings::values.input_profiles = old_input_profiles;
|
Settings::values.input_profiles = old_input_profiles;
|
||||||
Settings::values.touch_from_button_maps = old_touch_from_button_maps;
|
Settings::values.touch_from_button_maps = old_touch_from_button_maps;
|
||||||
@ -2091,6 +2111,33 @@ void GMainWindow::ShowMouseCursor() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GMainWindow::UpdateAPIIndicator(bool override) {
|
||||||
|
static std::array graphics_apis = {
|
||||||
|
QStringLiteral("OPENGL"),
|
||||||
|
QStringLiteral("OPENGLES"),
|
||||||
|
QStringLiteral("VULKAN")
|
||||||
|
};
|
||||||
|
|
||||||
|
static std::array graphics_api_colors = {
|
||||||
|
QStringLiteral("#00ccdd"),
|
||||||
|
QStringLiteral("#ba2a8d"),
|
||||||
|
QStringLiteral("#91242a")
|
||||||
|
};
|
||||||
|
|
||||||
|
u32 api_index = static_cast<u32>(Settings::values.graphics_api);
|
||||||
|
if (override) {
|
||||||
|
api_index = (api_index + 1) % graphics_apis.size();
|
||||||
|
Settings::values.graphics_api =
|
||||||
|
static_cast<Settings::GraphicsAPI>(api_index);
|
||||||
|
}
|
||||||
|
|
||||||
|
const QString style_sheet =
|
||||||
|
QStringLiteral("QPushButton { font-weight: bold; color: %0; }").arg(graphics_api_colors[api_index]);
|
||||||
|
|
||||||
|
graphics_api_button->setText(graphics_apis[api_index]);
|
||||||
|
graphics_api_button->setStyleSheet(style_sheet);
|
||||||
|
}
|
||||||
|
|
||||||
void GMainWindow::OnMouseActivity() {
|
void GMainWindow::OnMouseActivity() {
|
||||||
ShowMouseCursor();
|
ShowMouseCursor();
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
#include <QMainWindow>
|
#include <QMainWindow>
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
#include <QTranslator>
|
#include <QTranslator>
|
||||||
|
#include <QPushButton>
|
||||||
#include "citra_qt/compatibility_list.h"
|
#include "citra_qt/compatibility_list.h"
|
||||||
#include "citra_qt/hotkeys.h"
|
#include "citra_qt/hotkeys.h"
|
||||||
#include "common/announce_multiplayer_room.h"
|
#include "common/announce_multiplayer_room.h"
|
||||||
@ -234,6 +235,7 @@ private:
|
|||||||
void InstallCIA(QStringList filepaths);
|
void InstallCIA(QStringList filepaths);
|
||||||
void HideMouseCursor();
|
void HideMouseCursor();
|
||||||
void ShowMouseCursor();
|
void ShowMouseCursor();
|
||||||
|
void UpdateAPIIndicator(bool override);
|
||||||
|
|
||||||
std::unique_ptr<Ui::MainWindow> ui;
|
std::unique_ptr<Ui::MainWindow> ui;
|
||||||
|
|
||||||
@ -248,6 +250,7 @@ private:
|
|||||||
QLabel* emu_speed_label = nullptr;
|
QLabel* emu_speed_label = nullptr;
|
||||||
QLabel* game_fps_label = nullptr;
|
QLabel* game_fps_label = nullptr;
|
||||||
QLabel* emu_frametime_label = nullptr;
|
QLabel* emu_frametime_label = nullptr;
|
||||||
|
QPushButton* graphics_api_button = nullptr;
|
||||||
QTimer status_bar_update_timer;
|
QTimer status_bar_update_timer;
|
||||||
bool message_label_used_for_movie = false;
|
bool message_label_used_for_movie = false;
|
||||||
|
|
||||||
|
@ -169,6 +169,7 @@ struct Values {
|
|||||||
|
|
||||||
// Renderer
|
// Renderer
|
||||||
GraphicsAPI graphics_api;
|
GraphicsAPI graphics_api;
|
||||||
|
u16 physical_device;
|
||||||
bool renderer_debug;
|
bool renderer_debug;
|
||||||
bool use_hw_renderer;
|
bool use_hw_renderer;
|
||||||
bool use_hw_shader;
|
bool use_hw_shader;
|
||||||
|
@ -187,9 +187,8 @@ create_target_directory_groups(video_core)
|
|||||||
|
|
||||||
# Include Vulkan headers
|
# Include Vulkan headers
|
||||||
target_include_directories(video_core PRIVATE ../../externals/vulkan-headers/include)
|
target_include_directories(video_core PRIVATE ../../externals/vulkan-headers/include)
|
||||||
target_include_directories(video_core PRIVATE ../../externals/vma)
|
|
||||||
target_link_libraries(video_core PUBLIC common core)
|
target_link_libraries(video_core PUBLIC common core)
|
||||||
target_link_libraries(video_core PRIVATE glad glm::glm SPIRV glslang nihstro-headers Boost::serialization)
|
target_link_libraries(video_core PRIVATE glad vma glm::glm SPIRV glslang nihstro-headers Boost::serialization)
|
||||||
set_target_properties(video_core PROPERTIES INTERPROCEDURAL_OPTIMIZATION ${ENABLE_LTO})
|
set_target_properties(video_core PROPERTIES INTERPROCEDURAL_OPTIMIZATION ${ENABLE_LTO})
|
||||||
|
|
||||||
if (ARCHITECTURE_x86_64)
|
if (ARCHITECTURE_x86_64)
|
||||||
|
@ -1077,44 +1077,7 @@ bool RasterizerCache<T>::ValidateByReinterpretation(const Surface& surface, cons
|
|||||||
auto src_rect = reinterpret_surface->GetScaledSubRect(reinterpret_params);
|
auto src_rect = reinterpret_surface->GetScaledSubRect(reinterpret_params);
|
||||||
auto dest_rect = surface->GetScaledSubRect(reinterpret_params);
|
auto dest_rect = surface->GetScaledSubRect(reinterpret_params);
|
||||||
|
|
||||||
if (!texture_filterer->IsNull() && reinterpret_surface->res_scale == 1 &&
|
reinterpreter->Reinterpret(reinterpret_surface->texture, src_rect, surface->texture, dest_rect);
|
||||||
surface->res_scale == resolution_scale_factor) {
|
|
||||||
// The destination surface is either a framebuffer, or a filtered texture.
|
|
||||||
// Create an intermediate surface to convert to before blitting to the
|
|
||||||
// destination.
|
|
||||||
const u32 width = dest_rect.GetHeight() / resolution_scale_factor;
|
|
||||||
const u32 height = dest_rect.GetWidth() / resolution_scale_factor;
|
|
||||||
const Common::Rectangle<u32> tmp_rect{0, width, height, 0};
|
|
||||||
|
|
||||||
OGLTexture tmp_tex = AllocateSurfaceTexture(dst_format, height, width);
|
|
||||||
reinterpreter->Reinterpret(reinterpret_surface->texture, src_rect, tmp_tex,
|
|
||||||
tmp_rect);
|
|
||||||
|
|
||||||
if (!texture_filterer->Filter(tmp_tex, tmp_rect, surface->texture, dest_rect, type)) {
|
|
||||||
const TextureBlit texture_blit = {
|
|
||||||
.surface_type = type,
|
|
||||||
.src_level = 0,
|
|
||||||
.dst_level = 0,
|
|
||||||
.src_layer = 0,
|
|
||||||
.dst_layer = 0,
|
|
||||||
.src_region = Region2D{
|
|
||||||
.start = {0, 0},
|
|
||||||
.end = {width, height}
|
|
||||||
},
|
|
||||||
.dst_region = Region2D{
|
|
||||||
.start = {dest_rect.left, dest_rect.bottom},
|
|
||||||
.end = {dest_rect.right, dest_rect.top}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
runtime.BlitTextures(tmp_tex, surface->texture, texture_blit);
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
reinterpreter->Reinterpret(reinterpret_surface->texture, src_rect, surface->texture,
|
|
||||||
dest_rect);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}*/
|
}*/
|
||||||
|
@ -129,9 +129,9 @@ void TextureRuntime::FormatConvert(const Surface& surface, bool upload,
|
|||||||
std::span<std::byte> source, std::span<std::byte> dest) {
|
std::span<std::byte> source, std::span<std::byte> dest) {
|
||||||
const VideoCore::PixelFormat format = surface.pixel_format;
|
const VideoCore::PixelFormat format = surface.pixel_format;
|
||||||
if (format == VideoCore::PixelFormat::RGBA8 && driver.IsOpenGLES()) {
|
if (format == VideoCore::PixelFormat::RGBA8 && driver.IsOpenGLES()) {
|
||||||
Pica::Texture::ConvertABGRToRGBA(source, dest);
|
return Pica::Texture::ConvertABGRToRGBA(source, dest);
|
||||||
} else if (format == VideoCore::PixelFormat::RGB8 && driver.IsOpenGLES()) {
|
} else if (format == VideoCore::PixelFormat::RGB8 && driver.IsOpenGLES()) {
|
||||||
Pica::Texture::ConvertBGRToRGB(source, dest);
|
return Pica::Texture::ConvertBGRToRGB(source, dest);
|
||||||
} else {
|
} else {
|
||||||
ASSERT(dest.size() >= source.size());
|
ASSERT(dest.size() >= source.size());
|
||||||
std::memcpy(dest.data(), source.data(), source.size());
|
std::memcpy(dest.data(), source.data(), source.size());
|
||||||
|
@ -154,7 +154,8 @@ struct ScreenRectVertex {
|
|||||||
constexpr u32 VERTEX_BUFFER_SIZE = sizeof(ScreenRectVertex) * 8192;
|
constexpr u32 VERTEX_BUFFER_SIZE = sizeof(ScreenRectVertex) * 8192;
|
||||||
|
|
||||||
RendererVulkan::RendererVulkan(Frontend::EmuWindow& window)
|
RendererVulkan::RendererVulkan(Frontend::EmuWindow& window)
|
||||||
: RendererBase{window}, instance{window, Settings::values.renderer_debug}, scheduler{instance, *this},
|
: RendererBase{window}, instance{window, Settings::values.physical_device, Settings::values.renderer_debug},
|
||||||
|
scheduler{instance, *this},
|
||||||
renderpass_cache{instance, scheduler}, runtime{instance, scheduler, renderpass_cache},
|
renderpass_cache{instance, scheduler}, runtime{instance, scheduler, renderpass_cache},
|
||||||
swapchain{instance, renderpass_cache},
|
swapchain{instance, renderpass_cache},
|
||||||
vertex_buffer{instance, scheduler, VERTEX_BUFFER_SIZE, vk::BufferUsageFlagBits::eVertexBuffer, {}} {
|
vertex_buffer{instance, scheduler, VERTEX_BUFFER_SIZE, vk::BufferUsageFlagBits::eVertexBuffer, {}} {
|
||||||
|
@ -38,7 +38,38 @@ vk::Format ToVkFormat(VideoCore::PixelFormat format) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Instance::Instance(Frontend::EmuWindow& window, bool enable_validation) {
|
Instance::Instance() {
|
||||||
|
// Fetch instance independant function pointers
|
||||||
|
vk::DynamicLoader dl;
|
||||||
|
auto vkGetInstanceProcAddr = dl.getProcAddress<PFN_vkGetInstanceProcAddr>("vkGetInstanceProcAddr");
|
||||||
|
VULKAN_HPP_DEFAULT_DISPATCHER.init(vkGetInstanceProcAddr);
|
||||||
|
|
||||||
|
const vk::ApplicationInfo application_info = {
|
||||||
|
.pApplicationName = "Citra",
|
||||||
|
.applicationVersion = VK_MAKE_VERSION(1, 0, 0),
|
||||||
|
.pEngineName = "Citra Vulkan",
|
||||||
|
.engineVersion = VK_MAKE_VERSION(1, 0, 0),
|
||||||
|
.apiVersion = VK_API_VERSION_1_0
|
||||||
|
};
|
||||||
|
|
||||||
|
const vk::InstanceCreateInfo instance_info = {
|
||||||
|
.pApplicationInfo = &application_info
|
||||||
|
};
|
||||||
|
|
||||||
|
instance = vk::createInstance(instance_info);
|
||||||
|
|
||||||
|
// Load required function pointers for querying the physical device
|
||||||
|
VULKAN_HPP_DEFAULT_DISPATCHER.vkEnumeratePhysicalDevices =
|
||||||
|
PFN_vkEnumeratePhysicalDevices(vkGetInstanceProcAddr(instance, "vkEnumeratePhysicalDevices"));
|
||||||
|
VULKAN_HPP_DEFAULT_DISPATCHER.vkGetPhysicalDeviceProperties =
|
||||||
|
PFN_vkGetPhysicalDeviceProperties(vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceProperties"));
|
||||||
|
VULKAN_HPP_DEFAULT_DISPATCHER.vkDestroyInstance =
|
||||||
|
PFN_vkDestroyInstance(vkGetInstanceProcAddr(instance, "vkDestroyInstance"));
|
||||||
|
|
||||||
|
physical_devices = instance.enumeratePhysicalDevices();
|
||||||
|
}
|
||||||
|
|
||||||
|
Instance::Instance(Frontend::EmuWindow& window, u32 physical_device_index, bool enable_validation) {
|
||||||
auto window_info = window.GetWindowInfo();
|
auto window_info = window.GetWindowInfo();
|
||||||
|
|
||||||
// Fetch instance independant function pointers
|
// Fetch instance independant function pointers
|
||||||
@ -53,6 +84,7 @@ Instance::Instance(Frontend::EmuWindow& window, bool enable_validation) {
|
|||||||
const u32 available_version = vk::enumerateInstanceVersion();
|
const u32 available_version = vk::enumerateInstanceVersion();
|
||||||
if (available_version < VK_API_VERSION_1_1) {
|
if (available_version < VK_API_VERSION_1_1) {
|
||||||
LOG_CRITICAL(Render_Vulkan, "Vulkan 1.0 is not supported, 1.1 is required!");
|
LOG_CRITICAL(Render_Vulkan, "Vulkan 1.0 is not supported, 1.1 is required!");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const vk::ApplicationInfo application_info = {
|
const vk::ApplicationInfo application_info = {
|
||||||
@ -76,9 +108,16 @@ Instance::Instance(Frontend::EmuWindow& window, bool enable_validation) {
|
|||||||
instance = vk::createInstance(instance_info);
|
instance = vk::createInstance(instance_info);
|
||||||
surface = CreateSurface(instance, window);
|
surface = CreateSurface(instance, window);
|
||||||
|
|
||||||
// TODO: GPU select dialog
|
// Pick physical device
|
||||||
auto physical_devices = instance.enumeratePhysicalDevices();
|
physical_devices = instance.enumeratePhysicalDevices();
|
||||||
physical_device = physical_devices[1];
|
if (const u16 physical_device_count = static_cast<u16>(physical_devices.size());
|
||||||
|
physical_device_index >= physical_devices.size()) {
|
||||||
|
LOG_CRITICAL(Render_Vulkan, "Invalid physical device index {} provided when only {} devices exist",
|
||||||
|
physical_device_index, physical_device_count);
|
||||||
|
UNREACHABLE();
|
||||||
|
}
|
||||||
|
|
||||||
|
physical_device = physical_devices[physical_device_index];
|
||||||
device_properties = physical_device.getProperties();
|
device_properties = physical_device.getProperties();
|
||||||
|
|
||||||
CreateDevice();
|
CreateDevice();
|
||||||
@ -86,10 +125,12 @@ Instance::Instance(Frontend::EmuWindow& window, bool enable_validation) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Instance::~Instance() {
|
Instance::~Instance() {
|
||||||
device.waitIdle();
|
if (device) {
|
||||||
vmaDestroyAllocator(allocator);
|
vmaDestroyAllocator(allocator);
|
||||||
device.destroy();
|
device.destroy();
|
||||||
instance.destroySurfaceKHR(surface);
|
instance.destroySurfaceKHR(surface);
|
||||||
|
}
|
||||||
|
|
||||||
instance.destroy();
|
instance.destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,7 +5,8 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <unordered_map>
|
#include <span>
|
||||||
|
#include <vector>
|
||||||
#include "video_core/rasterizer_cache/pixel_format.h"
|
#include "video_core/rasterizer_cache/pixel_format.h"
|
||||||
#include "video_core/renderer_vulkan/vk_common.h"
|
#include "video_core/renderer_vulkan/vk_common.h"
|
||||||
|
|
||||||
@ -27,7 +28,8 @@ struct FormatTraits {
|
|||||||
/// The global Vulkan instance
|
/// The global Vulkan instance
|
||||||
class Instance {
|
class Instance {
|
||||||
public:
|
public:
|
||||||
Instance(Frontend::EmuWindow& window, bool enable_validation);
|
Instance(); ///< Portable constructor used to query physical devices
|
||||||
|
Instance(Frontend::EmuWindow& window, u32 physical_device_index, bool enable_validation);
|
||||||
~Instance();
|
~Instance();
|
||||||
|
|
||||||
/// Returns the FormatTraits struct for the provided pixel format
|
/// Returns the FormatTraits struct for the provided pixel format
|
||||||
@ -53,10 +55,16 @@ public:
|
|||||||
return device;
|
return device;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the VMA allocator handle
|
||||||
VmaAllocator GetAllocator() const {
|
VmaAllocator GetAllocator() const {
|
||||||
return allocator;
|
return allocator;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns a list of the available physical devices
|
||||||
|
std::span<const vk::PhysicalDevice> GetPhysicalDevices() const {
|
||||||
|
return physical_devices;
|
||||||
|
}
|
||||||
|
|
||||||
/// Retrieve queue information
|
/// Retrieve queue information
|
||||||
u32 GetGraphicsQueueFamilyIndex() const {
|
u32 GetGraphicsQueueFamilyIndex() const {
|
||||||
return graphics_queue_family_index;
|
return graphics_queue_family_index;
|
||||||
@ -131,6 +139,7 @@ private:
|
|||||||
VmaAllocator allocator;
|
VmaAllocator allocator;
|
||||||
vk::Queue present_queue;
|
vk::Queue present_queue;
|
||||||
vk::Queue graphics_queue;
|
vk::Queue graphics_queue;
|
||||||
|
std::vector<vk::PhysicalDevice> physical_devices;
|
||||||
std::array<FormatTraits, VideoCore::PIXEL_FORMAT_COUNT> format_table;
|
std::array<FormatTraits, VideoCore::PIXEL_FORMAT_COUNT> format_table;
|
||||||
u32 present_queue_family_index = 0;
|
u32 present_queue_family_index = 0;
|
||||||
u32 graphics_queue_family_index = 0;
|
u32 graphics_queue_family_index = 0;
|
||||||
|
@ -661,10 +661,6 @@ bool Surface::NeedsConvert() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
u32 Surface::GetInternalBytesPerPixel() const {
|
u32 Surface::GetInternalBytesPerPixel() const {
|
||||||
if (alloc.format == vk::Format::eD32SfloatS8Uint) {
|
|
||||||
return 8;
|
|
||||||
}
|
|
||||||
|
|
||||||
return vk::blockSize(alloc.format);
|
return vk::blockSize(alloc.format);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -227,7 +227,7 @@ void ConvertBGRToRGB(std::span<const std::byte> source, std::span<std::byte> des
|
|||||||
u32 bgr{};
|
u32 bgr{};
|
||||||
std::memcpy(&bgr, source.data() + i, 3);
|
std::memcpy(&bgr, source.data() + i, 3);
|
||||||
const u32 rgb = Common::swap32(bgr << 8);
|
const u32 rgb = Common::swap32(bgr << 8);
|
||||||
std::memcpy(dest.data(), &rgb, 3);
|
std::memcpy(dest.data() + i, &rgb, 3);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user