From 2da4c9ca901b2500fe5ecf27d7aa86173cf76a03 Mon Sep 17 00:00:00 2001 From: GPUCode Date: Wed, 5 Oct 2022 18:03:38 +0300 Subject: [PATCH] citra_qt: Add physical device selection dialog --- dist/qt_themes/qdarkstyle/style.qss | 28 +++++++++ externals/CMakeLists.txt | 5 ++ src/citra_qt/CMakeLists.txt | 2 +- src/citra_qt/configuration/config.cpp | 2 + .../configuration/configure_graphics.cpp | 26 +++++++++ .../configuration/configure_graphics.h | 5 ++ .../configuration/configure_graphics.ui | 31 ++++++++-- src/citra_qt/main.cpp | 49 +++++++++++++++- src/citra_qt/main.h | 3 + src/core/settings.h | 1 + src/video_core/CMakeLists.txt | 3 +- .../rasterizer_cache/rasterizer_cache.h | 39 +------------ .../renderer_opengl/gl_texture_runtime.cpp | 4 +- .../renderer_vulkan/renderer_vulkan.cpp | 3 +- .../renderer_vulkan/vk_instance.cpp | 57 ++++++++++++++++--- src/video_core/renderer_vulkan/vk_instance.h | 13 ++++- .../renderer_vulkan/vk_texture_runtime.cpp | 4 -- src/video_core/texture/texture_decode.cpp | 2 +- 18 files changed, 213 insertions(+), 64 deletions(-) diff --git a/dist/qt_themes/qdarkstyle/style.qss b/dist/qt_themes/qdarkstyle/style.qss index a5eee211e..094c7629a 100644 --- a/dist/qt_themes/qdarkstyle/style.qss +++ b/dist/qt_themes/qdarkstyle/style.qss @@ -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 { border: 1px solid #76797C; background-color: #5A7566; diff --git a/externals/CMakeLists.txt b/externals/CMakeLists.txt index 99930796d..8f049aaa2 100644 --- a/externals/CMakeLists.txt +++ b/externals/CMakeLists.txt @@ -161,3 +161,8 @@ if(ANDROID) add_subdirectory(libyuv) target_include_directories(yuv INTERFACE ./libyuv/include) endif() + +# VMA +add_library(vma INTERFACE) +target_include_directories(vma INTERFACE ./vma) + diff --git a/src/citra_qt/CMakeLists.txt b/src/citra_qt/CMakeLists.txt index 46117f9e9..32647c2f2 100644 --- a/src/citra_qt/CMakeLists.txt +++ b/src/citra_qt/CMakeLists.txt @@ -260,7 +260,7 @@ endif() 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 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) if (NOT WIN32) diff --git a/src/citra_qt/configuration/config.cpp b/src/citra_qt/configuration/config.cpp index e9fa88508..a802283f3 100644 --- a/src/citra_qt/configuration/config.cpp +++ b/src/citra_qt/configuration/config.cpp @@ -485,6 +485,7 @@ void Config::ReadRendererValues() { Settings::values.graphics_api = static_cast( ReadSetting(QStringLiteral("graphics_api"), static_cast(Settings::GraphicsAPI::OpenGL)) .toUInt()); + Settings::values.physical_device = ReadSetting(QStringLiteral("physical_device"), 0).toUInt(); Settings::values.renderer_debug = ReadSetting(QStringLiteral("renderer_debug"), false).toBool(); Settings::values.use_hw_renderer = ReadSetting(QStringLiteral("use_hw_renderer"), true).toBool(); @@ -1000,6 +1001,7 @@ void Config::SaveRendererValues() { WriteSetting(QStringLiteral("graphics_api"), static_cast(Settings::values.graphics_api), static_cast(Settings::GraphicsAPI::OpenGL)); + WriteSetting(QStringLiteral("physical_device"), Settings::values.physical_device, 0); WriteSetting(QStringLiteral("renderer_debug"), Settings::values.renderer_debug, false); WriteSetting(QStringLiteral("use_hw_renderer"), Settings::values.use_hw_renderer, true); WriteSetting(QStringLiteral("use_hw_shader"), Settings::values.use_hw_shader, true); diff --git a/src/citra_qt/configuration/configure_graphics.cpp b/src/citra_qt/configuration/configure_graphics.cpp index 036b74800..ea4132c6a 100644 --- a/src/citra_qt/configuration/configure_graphics.cpp +++ b/src/citra_qt/configuration/configure_graphics.cpp @@ -10,10 +10,12 @@ #include "core/core.h" #include "core/settings.h" #include "ui_configure_graphics.h" +#include "video_core/renderer_vulkan/vk_instance.h" ConfigureGraphics::ConfigureGraphics(QWidget* parent) : QWidget(parent), ui(std::make_unique()) { ui->setupUi(this); + DiscoverPhysicalDevices(); SetConfiguration(); const bool not_running = !Core::System::GetInstance().IsPoweredOn(); @@ -24,6 +26,10 @@ ConfigureGraphics::ConfigureGraphics(QWidget* parent) ui->graphics_api_combo->setEnabled(not_running); ui->toggle_shader_jit->setEnabled(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(&QComboBox::currentIndexChanged), this, + &ConfigureGraphics::SetPhysicalDeviceComboVisibility); connect(ui->toggle_hw_renderer, &QCheckBox::toggled, this, [this] { 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_vsync_new->setChecked(Settings::values.use_vsync_new); ui->graphics_api_combo->setCurrentIndex(static_cast(Settings::values.graphics_api)); + ui->physical_device_combo->setCurrentIndex(static_cast(Settings::values.physical_device)); } 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_vsync_new = ui->toggle_vsync_new->isChecked(); Settings::values.graphics_api = static_cast(ui->graphics_api_combo->currentIndex()); + Settings::values.physical_device = static_cast(ui->physical_device_combo->currentIndex()); } void ConfigureGraphics::RetranslateUI() { 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(index); + const bool is_visible = graphics_api == Settings::GraphicsAPI::Vulkan; + ui->physical_device_label->setVisible(is_visible); + ui->physical_device_combo->setVisible(is_visible); +} diff --git a/src/citra_qt/configuration/configure_graphics.h b/src/citra_qt/configuration/configure_graphics.h index 9ed932090..3bc05686d 100644 --- a/src/citra_qt/configuration/configure_graphics.h +++ b/src/citra_qt/configuration/configure_graphics.h @@ -24,6 +24,11 @@ public: void UpdateBackgroundColorButton(const QColor& color); +private: + void DiscoverPhysicalDevices(); + void SetPhysicalDeviceComboVisibility(int index); + +private: std::unique_ptr ui; QColor bg_color; }; diff --git a/src/citra_qt/configuration/configure_graphics.ui b/src/citra_qt/configuration/configure_graphics.ui index 36a105452..0dda1f100 100644 --- a/src/citra_qt/configuration/configure_graphics.ui +++ b/src/citra_qt/configuration/configure_graphics.ui @@ -21,15 +21,15 @@ - + - Renderer + API Settings - + - + Graphics API @@ -56,6 +56,29 @@ + + + + + + Physical device + + + + + + + + + + + + + + + Renderer + + diff --git a/src/citra_qt/main.cpp b/src/citra_qt/main.cpp index 34913fee4..92ea7b21b 100644 --- a/src/citra_qt/main.cpp +++ b/src/citra_qt/main.cpp @@ -59,6 +59,7 @@ #include "common/microprofile.h" #include "common/scm_rev.h" #include "common/scope_exit.h" +#include "common/string_util.h" #ifdef ARCHITECTURE_x86_64 #include "common/x64/cpu_detect.h" #endif @@ -280,6 +281,23 @@ void GMainWindow::InitializeWidgets() { message_label->setAlignment(Qt::AlignLeft); 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->hide(); statusBar()->addPermanentWidget(progress_bar); @@ -299,8 +317,9 @@ void GMainWindow::InitializeWidgets() { label->setVisible(false); label->setFrameStyle(QFrame::NoFrame); label->setContentsMargins(4, 0, 4, 0); - statusBar()->addPermanentWidget(label, 0); + statusBar()->addPermanentWidget(label); } + statusBar()->addPermanentWidget(multiplayer_state->GetStatusText(), 0); statusBar()->addPermanentWidget(multiplayer_state->GetStatusIcon(), 0); statusBar()->setVisible(true); @@ -1780,6 +1799,7 @@ void GMainWindow::OnConfigure() { } else { setMouseTracking(false); } + UpdateAPIIndicator(false); } else { Settings::values.input_profiles = old_input_profiles; 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(Settings::values.graphics_api); + if (override) { + api_index = (api_index + 1) % graphics_apis.size(); + Settings::values.graphics_api = + static_cast(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() { ShowMouseCursor(); } diff --git a/src/citra_qt/main.h b/src/citra_qt/main.h index 970f19cad..483476cc1 100644 --- a/src/citra_qt/main.h +++ b/src/citra_qt/main.h @@ -9,6 +9,7 @@ #include #include #include +#include #include "citra_qt/compatibility_list.h" #include "citra_qt/hotkeys.h" #include "common/announce_multiplayer_room.h" @@ -234,6 +235,7 @@ private: void InstallCIA(QStringList filepaths); void HideMouseCursor(); void ShowMouseCursor(); + void UpdateAPIIndicator(bool override); std::unique_ptr ui; @@ -248,6 +250,7 @@ private: QLabel* emu_speed_label = nullptr; QLabel* game_fps_label = nullptr; QLabel* emu_frametime_label = nullptr; + QPushButton* graphics_api_button = nullptr; QTimer status_bar_update_timer; bool message_label_used_for_movie = false; diff --git a/src/core/settings.h b/src/core/settings.h index ed479c322..c4421cc79 100644 --- a/src/core/settings.h +++ b/src/core/settings.h @@ -169,6 +169,7 @@ struct Values { // Renderer GraphicsAPI graphics_api; + u16 physical_device; bool renderer_debug; bool use_hw_renderer; bool use_hw_shader; diff --git a/src/video_core/CMakeLists.txt b/src/video_core/CMakeLists.txt index 7423d3e6b..ad47a8f24 100644 --- a/src/video_core/CMakeLists.txt +++ b/src/video_core/CMakeLists.txt @@ -187,9 +187,8 @@ create_target_directory_groups(video_core) # Include Vulkan headers 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 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}) if (ARCHITECTURE_x86_64) diff --git a/src/video_core/rasterizer_cache/rasterizer_cache.h b/src/video_core/rasterizer_cache/rasterizer_cache.h index b5cdb5301..3055f9e2d 100644 --- a/src/video_core/rasterizer_cache/rasterizer_cache.h +++ b/src/video_core/rasterizer_cache/rasterizer_cache.h @@ -1077,44 +1077,7 @@ bool RasterizerCache::ValidateByReinterpretation(const Surface& surface, cons auto src_rect = reinterpret_surface->GetScaledSubRect(reinterpret_params); auto dest_rect = surface->GetScaledSubRect(reinterpret_params); - if (!texture_filterer->IsNull() && reinterpret_surface->res_scale == 1 && - 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 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); - } - + reinterpreter->Reinterpret(reinterpret_surface->texture, src_rect, surface->texture, dest_rect); return true; } }*/ diff --git a/src/video_core/renderer_opengl/gl_texture_runtime.cpp b/src/video_core/renderer_opengl/gl_texture_runtime.cpp index ae6ed6f84..c714c3828 100644 --- a/src/video_core/renderer_opengl/gl_texture_runtime.cpp +++ b/src/video_core/renderer_opengl/gl_texture_runtime.cpp @@ -129,9 +129,9 @@ void TextureRuntime::FormatConvert(const Surface& surface, bool upload, std::span source, std::span dest) { const VideoCore::PixelFormat format = surface.pixel_format; 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()) { - Pica::Texture::ConvertBGRToRGB(source, dest); + return Pica::Texture::ConvertBGRToRGB(source, dest); } else { ASSERT(dest.size() >= source.size()); std::memcpy(dest.data(), source.data(), source.size()); diff --git a/src/video_core/renderer_vulkan/renderer_vulkan.cpp b/src/video_core/renderer_vulkan/renderer_vulkan.cpp index 84adf6761..f923b0c28 100644 --- a/src/video_core/renderer_vulkan/renderer_vulkan.cpp +++ b/src/video_core/renderer_vulkan/renderer_vulkan.cpp @@ -154,7 +154,8 @@ struct ScreenRectVertex { constexpr u32 VERTEX_BUFFER_SIZE = sizeof(ScreenRectVertex) * 8192; 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}, swapchain{instance, renderpass_cache}, vertex_buffer{instance, scheduler, VERTEX_BUFFER_SIZE, vk::BufferUsageFlagBits::eVertexBuffer, {}} { diff --git a/src/video_core/renderer_vulkan/vk_instance.cpp b/src/video_core/renderer_vulkan/vk_instance.cpp index 9c7172852..d8414ccea 100644 --- a/src/video_core/renderer_vulkan/vk_instance.cpp +++ b/src/video_core/renderer_vulkan/vk_instance.cpp @@ -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("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(); // Fetch instance independant function pointers @@ -53,6 +84,7 @@ Instance::Instance(Frontend::EmuWindow& window, bool enable_validation) { const u32 available_version = vk::enumerateInstanceVersion(); if (available_version < VK_API_VERSION_1_1) { LOG_CRITICAL(Render_Vulkan, "Vulkan 1.0 is not supported, 1.1 is required!"); + return; } const vk::ApplicationInfo application_info = { @@ -76,9 +108,16 @@ Instance::Instance(Frontend::EmuWindow& window, bool enable_validation) { instance = vk::createInstance(instance_info); surface = CreateSurface(instance, window); - // TODO: GPU select dialog - auto physical_devices = instance.enumeratePhysicalDevices(); - physical_device = physical_devices[1]; + // Pick physical device + physical_devices = instance.enumeratePhysicalDevices(); + if (const u16 physical_device_count = static_cast(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(); CreateDevice(); @@ -86,10 +125,12 @@ Instance::Instance(Frontend::EmuWindow& window, bool enable_validation) { } Instance::~Instance() { - device.waitIdle(); - vmaDestroyAllocator(allocator); - device.destroy(); - instance.destroySurfaceKHR(surface); + if (device) { + vmaDestroyAllocator(allocator); + device.destroy(); + instance.destroySurfaceKHR(surface); + } + instance.destroy(); } diff --git a/src/video_core/renderer_vulkan/vk_instance.h b/src/video_core/renderer_vulkan/vk_instance.h index f5476c7fe..09f490beb 100644 --- a/src/video_core/renderer_vulkan/vk_instance.h +++ b/src/video_core/renderer_vulkan/vk_instance.h @@ -5,7 +5,8 @@ #pragma once #include -#include +#include +#include #include "video_core/rasterizer_cache/pixel_format.h" #include "video_core/renderer_vulkan/vk_common.h" @@ -27,7 +28,8 @@ struct FormatTraits { /// The global Vulkan instance class Instance { 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(); /// Returns the FormatTraits struct for the provided pixel format @@ -53,10 +55,16 @@ public: return device; } + /// Returns the VMA allocator handle VmaAllocator GetAllocator() const { return allocator; } + /// Returns a list of the available physical devices + std::span GetPhysicalDevices() const { + return physical_devices; + } + /// Retrieve queue information u32 GetGraphicsQueueFamilyIndex() const { return graphics_queue_family_index; @@ -131,6 +139,7 @@ private: VmaAllocator allocator; vk::Queue present_queue; vk::Queue graphics_queue; + std::vector physical_devices; std::array format_table; u32 present_queue_family_index = 0; u32 graphics_queue_family_index = 0; diff --git a/src/video_core/renderer_vulkan/vk_texture_runtime.cpp b/src/video_core/renderer_vulkan/vk_texture_runtime.cpp index cacfcf651..c1a857201 100644 --- a/src/video_core/renderer_vulkan/vk_texture_runtime.cpp +++ b/src/video_core/renderer_vulkan/vk_texture_runtime.cpp @@ -661,10 +661,6 @@ bool Surface::NeedsConvert() const { } u32 Surface::GetInternalBytesPerPixel() const { - if (alloc.format == vk::Format::eD32SfloatS8Uint) { - return 8; - } - return vk::blockSize(alloc.format); } diff --git a/src/video_core/texture/texture_decode.cpp b/src/video_core/texture/texture_decode.cpp index 272dab8d0..87a4c6beb 100644 --- a/src/video_core/texture/texture_decode.cpp +++ b/src/video_core/texture/texture_decode.cpp @@ -227,7 +227,7 @@ void ConvertBGRToRGB(std::span source, std::span des u32 bgr{}; std::memcpy(&bgr, source.data() + i, 3); const u32 rgb = Common::swap32(bgr << 8); - std::memcpy(dest.data(), &rgb, 3); + std::memcpy(dest.data() + i, &rgb, 3); } }