From 5940361b812711c7014c9ace40bd7e385e37223c Mon Sep 17 00:00:00 2001 From: Khangaroo Date: Tue, 6 Aug 2019 12:24:07 -0400 Subject: [PATCH] new-line that clang-format didn't fix address some comments --- .../configuration/configure_input.cpp | 36 ++-- src/common/detached_tasks.cpp | 3 +- src/common/texture.cpp | 20 +-- src/common/texture.h | 4 + src/core/core.cpp | 62 +++++-- src/core/core.h | 2 + src/core/custom_tex_cache.cpp | 12 +- src/core/custom_tex_cache.h | 15 +- src/core/hle/service/cecd/cecd.cpp | 3 +- src/core/movie.h | 4 +- src/input_common/udp/client.cpp | 6 +- src/tests/core/arm/arm_test_common.cpp | 3 +- src/tests/core/hle/kernel/hle_ipc.cpp | 6 +- src/tests/core/memory/memory.cpp | 3 +- .../renderer_opengl/gl_rasterizer_cache.cpp | 162 ++++++++++-------- .../renderer_opengl/gl_rasterizer_cache.h | 7 + 16 files changed, 210 insertions(+), 138 deletions(-) diff --git a/src/citra_qt/configuration/configure_input.cpp b/src/citra_qt/configuration/configure_input.cpp index 8cac708b8..642d5f14a 100644 --- a/src/citra_qt/configuration/configure_input.cpp +++ b/src/citra_qt/configuration/configure_input.cpp @@ -161,16 +161,15 @@ ConfigureInput::ConfigureInput(QWidget* parent) continue; button_map[button_id]->setContextMenuPolicy(Qt::CustomContextMenu); connect(button_map[button_id], &QPushButton::clicked, [=]() { - HandleClick( - button_map[button_id], - [=](const Common::ParamPackage& params) { - buttons_param[button_id] = params; - // If the user closes the dialog, the changes are reverted in - // `GMainWindow::OnConfigure()` - ApplyConfiguration(); - Settings::SaveProfile(ui->profile->currentIndex()); - }, - InputCommon::Polling::DeviceType::Button); + HandleClick(button_map[button_id], + [=](const Common::ParamPackage& params) { + buttons_param[button_id] = params; + // If the user closes the dialog, the changes are reverted in + // `GMainWindow::OnConfigure()` + ApplyConfiguration(); + Settings::SaveProfile(ui->profile->currentIndex()); + }, + InputCommon::Polling::DeviceType::Button); }); connect(button_map[button_id], &QPushButton::customContextMenuRequested, [=](const QPoint& menu_location) { @@ -199,15 +198,14 @@ ConfigureInput::ConfigureInput(QWidget* parent) analog_map_buttons[analog_id][sub_button_id]->setContextMenuPolicy( Qt::CustomContextMenu); connect(analog_map_buttons[analog_id][sub_button_id], &QPushButton::clicked, [=]() { - HandleClick( - analog_map_buttons[analog_id][sub_button_id], - [=](const Common::ParamPackage& params) { - SetAnalogButton(params, analogs_param[analog_id], - analog_sub_buttons[sub_button_id]); - ApplyConfiguration(); - Settings::SaveProfile(ui->profile->currentIndex()); - }, - InputCommon::Polling::DeviceType::Button); + HandleClick(analog_map_buttons[analog_id][sub_button_id], + [=](const Common::ParamPackage& params) { + SetAnalogButton(params, analogs_param[analog_id], + analog_sub_buttons[sub_button_id]); + ApplyConfiguration(); + Settings::SaveProfile(ui->profile->currentIndex()); + }, + InputCommon::Polling::DeviceType::Button); }); connect(analog_map_buttons[analog_id][sub_button_id], &QPushButton::customContextMenuRequested, [=](const QPoint& menu_location) { diff --git a/src/common/detached_tasks.cpp b/src/common/detached_tasks.cpp index f2b4939df..f268d6021 100644 --- a/src/common/detached_tasks.cpp +++ b/src/common/detached_tasks.cpp @@ -34,7 +34,8 @@ void DetachedTasks::AddTask(std::function task) { std::unique_lock lock{instance->mutex}; --instance->count; std::notify_all_at_thread_exit(instance->cv, std::move(lock)); - }).detach(); + }) + .detach(); } } // namespace Common diff --git a/src/common/texture.cpp b/src/common/texture.cpp index 0729aeba1..2ec939288 100644 --- a/src/common/texture.cpp +++ b/src/common/texture.cpp @@ -1,3 +1,8 @@ +// Copyright 2019 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include #include #include "common/assert.h" #include "common/common_types.h" @@ -6,17 +11,12 @@ namespace Common { void FlipRGBA8Texture(std::vector& tex, u64 width, u64 height) { ASSERT(tex.size() == width * height * 4); const u64 line_size = width * 4; - u8* temp_row = new u8[line_size]; - u32 offset_1; - u32 offset_2; for (u64 line = 0; line < height / 2; line++) { - offset_1 = line * line_size; - offset_2 = (height - line - 1) * line_size; + const u32 offset_1 = line * line_size; + const u32 offset_2 = (height - line - 1) * line_size; // Swap lines - std::memcpy(temp_row, &tex[offset_1], line_size); - std::memcpy(&tex[offset_1], &tex[offset_2], line_size); - std::memcpy(&tex[offset_2], temp_row, line_size); + std::swap_ranges(tex.begin() + offset_1, tex.begin() + offset_1 + line_size, + tex.begin() + offset_2); } - delete[] temp_row; } -} // namespace Common \ No newline at end of file +} // namespace Common diff --git a/src/common/texture.h b/src/common/texture.h index b58338123..bdb03e8b4 100644 --- a/src/common/texture.h +++ b/src/common/texture.h @@ -1,3 +1,7 @@ +// Copyright 2019 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + #pragma once #include diff --git a/src/core/core.cpp b/src/core/core.cpp index 64f41865b..2bdceb659 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -18,14 +18,11 @@ #include "core/cheats/cheats.h" #include "core/core.h" #include "core/core_timing.h" -<<<<<<< HEAD #include "core/dumping/backend.h" #ifdef ENABLE_FFMPEG_VIDEO_DUMPER #include "core/dumping/ffmpeg_backend.h" #endif -======= #include "core/custom_tex_cache.h" ->>>>>>> 387a49d7... fix crashes, add custom texture cache, load textures from load directory #include "core/gdbstub/gdbstub.h" #include "core/hle/kernel/client_port.h" #include "core/hle/kernel/kernel.h" @@ -102,6 +99,48 @@ System::ResultStatus System::SingleStep() { return RunLoop(false); } +void System::PreloadCustomTextures() { + // Custom textures are currently stored as + // load/textures/[TitleID]/tex1_[width]x[height]_[64-bit hash]_[format].png + const std::string load_path = + fmt::format("{}textures/{:016X}/", FileUtil::GetUserPath(FileUtil::UserPath::LoadDir), + Kernel().GetCurrentProcess()->codeset->program_id); + + if (FileUtil::Exists(load_path)) { + FileUtil::FSTEntry texture_files; + FileUtil::ScanDirectoryTree(load_path, texture_files); + for (const auto& file : texture_files.children) { + if (file.isDirectory) + continue; + if (file.virtualName.substr(0, 5) != "tex1_") + continue; + + u32 width; + u32 height; + u64 hash; + u32 format; // unused + // TODO: more modern way of doing this + if (std::sscanf(file.virtualName.c_str(), "tex1_%ux%u_%llX_%u.png", &width, &height, + &hash, &format) == 4) { + u32 png_width; + u32 png_height; + std::vector decoded_png; + + u32 lodepng_ret = + lodepng::decode(decoded_png, png_width, png_height, file.physicalName); + if (lodepng_ret) { + LOG_CRITICAL(Render_OpenGL, "Failed to preload custom texture: {}", + lodepng_error_text(lodepng_ret)); + } else { + LOG_INFO(Render_OpenGL, "Preloaded custom texture from {}", file.physicalName); + Common::FlipRGBA8Texture(decoded_png, png_width, png_height); + custom_tex_cache->CacheTexture(hash, decoded_png, png_width, png_height); + } + } + } + } +} + System::ResultStatus System::Load(Frontend::EmuWindow& emu_window, const std::string& filepath) { app_loader = Loader::GetLoader(filepath); if (!app_loader) { @@ -152,18 +191,13 @@ System::ResultStatus System::Load(Frontend::EmuWindow& emu_window, const std::st } } cheat_engine = std::make_unique(*this); -<<<<<<< HEAD u64 title_id{0}; if (app_loader->ReadProgramId(title_id) != Loader::ResultStatus::Success) { LOG_ERROR(Core, "Failed to find title id for ROM (Error {})", static_cast(load_result)); } perf_stats = std::make_unique(title_id); -======= custom_tex_cache = std::make_unique(); -<<<<<<< HEAD ->>>>>>> 387a49d7... fix crashes, add custom texture cache, load textures from load directory -======= if (Settings::values.preload_textures) { // Custom textures are currently stored as // load/textures/[TitleID]/tex1_[width]x[height]_[64-bit hash]_[format].png @@ -206,7 +240,8 @@ System::ResultStatus System::Load(Frontend::EmuWindow& emu_window, const std::st } } } ->>>>>>> 015582b2... implement custom texture preload + if (Settings::values.preload_textures) + PreloadCustomTextures(); status = ResultStatus::Success; m_emu_window = &emu_window; m_filepath = filepath; @@ -242,8 +277,8 @@ System::ResultStatus System::Init(Frontend::EmuWindow& emu_window, u32 system_mo timing = std::make_unique(); - kernel = std::make_unique( - *memory, *timing, [this] { PrepareReschedule(); }, system_mode); + kernel = std::make_unique(*memory, *timing, + [this] { PrepareReschedule(); }, system_mode); if (Settings::values.use_cpu_jit) { #ifdef ARCHITECTURE_x86_64 @@ -345,21 +380,20 @@ const Cheats::CheatEngine& System::CheatEngine() const { return *cheat_engine; } -<<<<<<< HEAD VideoDumper::Backend& System::VideoDumper() { return *video_dumper; } const VideoDumper::Backend& System::VideoDumper() const { return *video_dumper; -======= +} + Core::CustomTexCache& System::CustomTexCache() { return *custom_tex_cache; } const Core::CustomTexCache& System::CustomTexCache() const { return *custom_tex_cache; ->>>>>>> 387a49d7... fix crashes, add custom texture cache, load textures from load directory } void System::RegisterMiiSelector(std::shared_ptr mii_selector) { diff --git a/src/core/core.h b/src/core/core.h index 5cd9c5ea6..e3050e29a 100644 --- a/src/core/core.h +++ b/src/core/core.h @@ -223,6 +223,8 @@ public: /// Gets a const reference to the custom texture cache system const Core::CustomTexCache& CustomTexCache() const; + /// Handles loading all custom textures from disk into cache. + void PreloadCustomTextures(); FrameLimiter frame_limiter; void SetStatus(ResultStatus new_status, const char* details = nullptr) { diff --git a/src/core/custom_tex_cache.cpp b/src/core/custom_tex_cache.cpp index ed8eabafd..ace998c76 100644 --- a/src/core/custom_tex_cache.cpp +++ b/src/core/custom_tex_cache.cpp @@ -1,10 +1,18 @@ +// Copyright 2019 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + #include #include #include "common/common_types.h" #include "custom_tex_cache.h" namespace Core { -const bool CustomTexCache::IsTextureDumped(const u64 hash) { +CustomTexCache::CustomTexCache() {} + +CustomTexCache::~CustomTexCache() {} + +bool CustomTexCache::IsTextureDumped(u64 hash) const { return dumped_textures.find(hash) != dumped_textures.end(); } @@ -12,7 +20,7 @@ void CustomTexCache::SetTextureDumped(const u64 hash) { dumped_textures[hash] = true; } -const bool CustomTexCache::IsTextureCached(const u64 hash) { +bool CustomTexCache::IsTextureCached(u64 hash) const { return custom_textures.find(hash) != custom_textures.end(); } diff --git a/src/core/custom_tex_cache.h b/src/core/custom_tex_cache.h index a6c226fe6..4cae738dd 100644 --- a/src/core/custom_tex_cache.h +++ b/src/core/custom_tex_cache.h @@ -1,3 +1,7 @@ +// Copyright 2019 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + #pragma once #include @@ -14,12 +18,15 @@ struct CustomTexInfo { // TODO: think of a better name for this class... class CustomTexCache { public: - const bool IsTextureDumped(const u64 hash); - void SetTextureDumped(const u64 hash); + CustomTexCache(); + ~CustomTexCache(); - const bool IsTextureCached(const u64 hash); + bool IsTextureDumped(u64 hash) const; + void SetTextureDumped(u64 hash); + + bool IsTextureCached(u64 hash) const; const CustomTexInfo& LookupTexture(const u64 hash); - void CacheTexture(const u64 hash, const std::vector& tex, u32 width, u32 height); + void CacheTexture(u64 hash, const std::vector& tex, u32 width, u32 height); private: std::unordered_map dumped_textures; diff --git a/src/core/hle/service/cecd/cecd.cpp b/src/core/hle/service/cecd/cecd.cpp index cc7565d2a..281f48026 100644 --- a/src/core/hle/service/cecd/cecd.cpp +++ b/src/core/hle/service/cecd/cecd.cpp @@ -1340,8 +1340,7 @@ void Module::CheckAndUpdateFile(const CecDataPathType path_type, const u32 ncch_ case CecDataPathType::MboxData: case CecDataPathType::MboxIcon: case CecDataPathType::MboxTitle: - default: { - } + default: {} } } diff --git a/src/core/movie.h b/src/core/movie.h index b9f1ee478..f1be86946 100644 --- a/src/core/movie.h +++ b/src/core/movie.h @@ -41,8 +41,8 @@ public: return s_instance; } - void StartPlayback( - const std::string& movie_file, std::function completion_callback = [] {}); + void StartPlayback(const std::string& movie_file, + std::function completion_callback = [] {}); void StartRecording(const std::string& movie_file); /// Prepare to override the clock before playing back movies diff --git a/src/input_common/udp/client.cpp b/src/input_common/udp/client.cpp index f0f76493e..887436550 100644 --- a/src/input_common/udp/client.cpp +++ b/src/input_common/udp/client.cpp @@ -217,7 +217,8 @@ void TestCommunication(const std::string& host, u16 port, u8 pad_index, u32 clie success_callback(); else failure_callback(); - }).detach(); + }) + .detach(); } CalibrationConfigurationJob::CalibrationConfigurationJob( @@ -268,7 +269,8 @@ CalibrationConfigurationJob::CalibrationConfigurationJob( complete_event.Wait(); socket.Stop(); worker_thread.join(); - }).detach(); + }) + .detach(); } CalibrationConfigurationJob::~CalibrationConfigurationJob() { diff --git a/src/tests/core/arm/arm_test_common.cpp b/src/tests/core/arm/arm_test_common.cpp index 88566d7f2..dbbc21c8c 100644 --- a/src/tests/core/arm/arm_test_common.cpp +++ b/src/tests/core/arm/arm_test_common.cpp @@ -17,8 +17,7 @@ TestEnvironment::TestEnvironment(bool mutable_memory_) timing = std::make_unique(); memory = std::make_unique(); - kernel = std::make_unique( - *memory, *timing, [] {}, 0); + kernel = std::make_unique(*memory, *timing, [] {}, 0); kernel->SetCurrentProcess(kernel->CreateProcess(kernel->CreateCodeSet("", 0))); page_table = &kernel->GetCurrentProcess()->vm_manager.page_table; diff --git a/src/tests/core/hle/kernel/hle_ipc.cpp b/src/tests/core/hle/kernel/hle_ipc.cpp index 367c3b7ea..fb549f829 100644 --- a/src/tests/core/hle/kernel/hle_ipc.cpp +++ b/src/tests/core/hle/kernel/hle_ipc.cpp @@ -23,8 +23,7 @@ static std::shared_ptr MakeObject(Kernel::KernelSystem& kernel) { TEST_CASE("HLERequestContext::PopulateFromIncomingCommandBuffer", "[core][kernel]") { Core::Timing timing; Memory::MemorySystem memory; - Kernel::KernelSystem kernel( - memory, timing, [] {}, 0); + Kernel::KernelSystem kernel(memory, timing, [] {}, 0); auto [server, client] = kernel.CreateSessionPair(); HLERequestContext context(kernel, std::move(server), nullptr); @@ -236,8 +235,7 @@ TEST_CASE("HLERequestContext::PopulateFromIncomingCommandBuffer", "[core][kernel TEST_CASE("HLERequestContext::WriteToOutgoingCommandBuffer", "[core][kernel]") { Core::Timing timing; Memory::MemorySystem memory; - Kernel::KernelSystem kernel( - memory, timing, [] {}, 0); + Kernel::KernelSystem kernel(memory, timing, [] {}, 0); auto [server, client] = kernel.CreateSessionPair(); HLERequestContext context(kernel, std::move(server), nullptr); diff --git a/src/tests/core/memory/memory.cpp b/src/tests/core/memory/memory.cpp index b33a08adf..4a6d54bf7 100644 --- a/src/tests/core/memory/memory.cpp +++ b/src/tests/core/memory/memory.cpp @@ -13,8 +13,7 @@ TEST_CASE("Memory::IsValidVirtualAddress", "[core][memory]") { Core::Timing timing; Memory::MemorySystem memory; - Kernel::KernelSystem kernel( - memory, timing, [] {}, 0); + Kernel::KernelSystem kernel(memory, timing, [] {}, 0); SECTION("these regions should not be mapped on an empty process") { auto process = kernel.CreateProcess(kernel.CreateCodeSet("", 0)); CHECK(Memory::IsValidVirtualAddress(*process, Memory::PROCESS_IMAGE_VADDR) == false); diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp index b88ab7848..f0e8c3d27 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp @@ -856,6 +856,81 @@ void CachedSurface::FlushGLBuffer(PAddr flush_start, PAddr flush_end) { } } +bool CachedSurface::LoadCustomTextures(u64 tex_hash, Core::CustomTexInfo& tex_info, + Common::Rectangle& custom_rect) { + bool result = false; + auto& custom_tex_cache = Core::System::GetInstance().CustomTexCache(); + const std::string load_path = + fmt::format("{}textures/{:016X}/tex1_{}x{}_{:016X}_{}.png", + FileUtil::GetUserPath(FileUtil::UserPath::LoadDir), + Core::System::GetInstance().Kernel().GetCurrentProcess()->codeset->program_id, + width, height, tex_hash, static_cast(pixel_format)); + + if (!custom_tex_cache.IsTextureCached(tex_hash)) { + if (FileUtil::Exists(load_path)) { + u32 lodepng_ret = + lodepng::decode(tex_info.tex, tex_info.width, tex_info.height, load_path); + if (lodepng_ret) { + LOG_CRITICAL(Render_OpenGL, "Failed to load custom texture: {}", + lodepng_error_text(lodepng_ret)); + } else { + LOG_INFO(Render_OpenGL, "Loaded custom texture from {}", load_path); + Common::FlipRGBA8Texture(tex_info.tex, tex_info.width, tex_info.height); + custom_tex_cache.CacheTexture(tex_hash, tex_info.tex, tex_info.width, + tex_info.height); + result = true; + } + } + } else { + tex_info = custom_tex_cache.LookupTexture(tex_hash); + result = true; + } + + if (result) { + custom_rect.left = (custom_rect.left / width) * tex_info.width; + custom_rect.top = (custom_rect.top / height) * tex_info.height; + custom_rect.right = (custom_rect.right / width) * tex_info.width; + custom_rect.bottom = (custom_rect.bottom / height) * tex_info.height; + } + + return result; +} + +bool CachedSurface::GetDumpPath(u64 tex_hash, std::string& path) { + auto& custom_tex_cache = Core::System::GetInstance().CustomTexCache(); + path = + fmt::format("{}textures/{:016X}/", FileUtil::GetUserPath(FileUtil::UserPath::DumpDir), + Core::System::GetInstance().Kernel().GetCurrentProcess()->codeset->program_id); + if (!FileUtil::CreateFullPath(path)) { + LOG_ERROR(Render, "Unable to create {}", path); + return false; + } + + path += fmt::format("tex1_{}x{}_{:016X}_{}.png", width, height, tex_hash, + static_cast(pixel_format)); + if (!custom_tex_cache.IsTextureDumped(tex_hash) && !FileUtil::Exists(path)) { + custom_tex_cache.SetTextureDumped(tex_hash); + return true; + } + return false; +} + +void CachedSurface::DumpTexture(GLuint target_tex, const std::string& dump_path) { + // Dump texture to RGBA8 and encode as PNG + LOG_INFO(Render_OpenGL, "Dumping texture to {}", dump_path); + std::vector decoded_texture; + decoded_texture.resize(width * height * 4); + glBindTexture(GL_TEXTURE_2D, target_tex); + glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, &decoded_texture[0]); + glBindTexture(GL_TEXTURE_2D, 0); + Common::FlipRGBA8Texture(decoded_texture, width, height); + u32 png_error = lodepng::encode(dump_path, decoded_texture, width, height); + if (png_error) { + LOG_CRITICAL(Render_OpenGL, "Failed to save decoded texture! {}", + lodepng_error_text(png_error)); + } +} + MICROPROFILE_DEFINE(OpenGL_TextureUL, "OpenGL", "Texture Upload", MP_RGB(128, 192, 64)); void CachedSurface::UploadGLTexture(const Common::Rectangle& rect, GLuint read_fb_handle, GLuint draw_fb_handle) { @@ -871,9 +946,7 @@ void CachedSurface::UploadGLTexture(const Common::Rectangle& rect, GLuint r bool dump_tex = false; bool use_custom_tex = false; std::string dump_path; // Has to be declared here for logging later - std::vector decoded_png; - u32 png_width = 0; - u32 png_height = 0; + Core::CustomTexInfo custom_tex_info; u64 tex_hash = 0; Common::Rectangle custom_rect = rect; // Required for rect to function properly with custom textures @@ -881,56 +954,11 @@ void CachedSurface::UploadGLTexture(const Common::Rectangle& rect, GLuint r if (Settings::values.dump_textures || Settings::values.custom_textures) tex_hash = Common::ComputeHash64(gl_buffer.get(), gl_buffer_size); - if (Settings::values.custom_textures) { - const std::string load_path = fmt::format( - "{}textures/{:016X}/tex1_{}x{}_{:016X}_{}.png", - FileUtil::GetUserPath(FileUtil::UserPath::LoadDir), - Core::System::GetInstance().Kernel().GetCurrentProcess()->codeset->program_id, width, - height, tex_hash, static_cast(pixel_format)); + if (Settings::values.custom_textures) + use_custom_tex = LoadCustomTextures(tex_hash, custom_tex_info, custom_rect); - if (!custom_tex_cache.IsTextureCached(tex_hash)) { - if (FileUtil::Exists(load_path)) { - u32 lodepng_ret = lodepng::decode(decoded_png, png_width, png_height, load_path); - if (lodepng_ret) - LOG_CRITICAL(Render_OpenGL, "Failed to load custom texture: {}", - lodepng_error_text(lodepng_ret)); - else { - LOG_INFO(Render_OpenGL, "Loaded custom texture from {}", load_path); - Common::FlipRGBA8Texture(decoded_png, png_width, png_height); - custom_tex_cache.CacheTexture(tex_hash, decoded_png, png_width, png_height); - use_custom_tex = true; - } - } - } else { - const auto custom_tex_info = custom_tex_cache.LookupTexture(tex_hash); - decoded_png = custom_tex_info.tex; - png_width = custom_tex_info.width; - png_height = custom_tex_info.height; - use_custom_tex = true; - } - - if (png_width && png_height) { - custom_rect.left = (custom_rect.left / width) * png_width; - custom_rect.top = (custom_rect.top / height) * png_height; - custom_rect.right = (custom_rect.right / width) * png_width; - custom_rect.bottom = (custom_rect.bottom / height) * png_height; - } - } - - if (Settings::values.dump_textures && !use_custom_tex) { - dump_path = fmt::format( - "{}textures/{:016X}/", FileUtil::GetUserPath(FileUtil::UserPath::DumpDir), - Core::System::GetInstance().Kernel().GetCurrentProcess()->codeset->program_id); - if (!FileUtil::CreateFullPath(dump_path)) - LOG_ERROR(Render, "Unable to create {}", dump_path); - - dump_path += fmt::format("tex1_{}x{}_{:016X}_{}.png", width, height, tex_hash, - static_cast(pixel_format)); - if (!custom_tex_cache.IsTextureDumped(tex_hash) && !FileUtil::Exists(dump_path)) { - custom_tex_cache.SetTextureDumped(tex_hash); - dump_tex = true; - } - } + if (Settings::values.dump_textures && !use_custom_tex) + dump_tex = GetDumpPath(tex_hash, dump_path); // Load data from memory to the surface GLint x0 = static_cast(custom_rect.left); @@ -950,7 +978,7 @@ void CachedSurface::UploadGLTexture(const Common::Rectangle& rect, GLuint r unscaled_tex.Create(); if (use_custom_tex) { AllocateSurfaceTexture(unscaled_tex.handle, GetFormatTuple(PixelFormat::RGBA8), - png_width, png_height); + custom_tex_info.width, custom_tex_info.height); } else { AllocateSurfaceTexture(unscaled_tex.handle, tuple, custom_rect.GetWidth(), custom_rect.GetHeight()); @@ -975,36 +1003,22 @@ void CachedSurface::UploadGLTexture(const Common::Rectangle& rect, GLuint r &gl_buffer[buffer_offset]); } else { if (res_scale == 1) { - AllocateSurfaceTexture(texture.handle, GetFormatTuple(PixelFormat::RGBA8), png_width, - png_height); + AllocateSurfaceTexture(texture.handle, GetFormatTuple(PixelFormat::RGBA8), + custom_tex_info.width, custom_tex_info.height); cur_state.texture_units[0].texture_2d = texture.handle; cur_state.Apply(); } // always going to be using rgba8 - glPixelStorei(GL_UNPACK_ROW_LENGTH, static_cast(png_width)); + glPixelStorei(GL_UNPACK_ROW_LENGTH, static_cast(custom_tex_info.width)); glActiveTexture(GL_TEXTURE0); - glTexSubImage2D(GL_TEXTURE_2D, 0, x0, y0, png_width, png_height, GL_RGBA, GL_UNSIGNED_BYTE, - decoded_png.data()); + glTexSubImage2D(GL_TEXTURE_2D, 0, x0, y0, custom_tex_info.width, custom_tex_info.height, + GL_RGBA, GL_UNSIGNED_BYTE, custom_tex_info.tex.data()); } glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); - if (dump_tex) { - // Dump texture to RGBA8 and encode as PNG - LOG_INFO(Render_OpenGL, "Dumping texture to {}", dump_path); - std::vector decoded_texture; - decoded_texture.resize(width * height * 4); - glBindTexture(GL_TEXTURE_2D, target_tex); - glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, &decoded_texture[0]); - glBindTexture(GL_TEXTURE_2D, 0); - Common::FlipRGBA8Texture(decoded_texture, width, height); - u32 png_error = lodepng::encode(dump_path, decoded_texture, width, height); - if (png_error) { - LOG_CRITICAL(Render_OpenGL, "Failed to save decoded texture! {}", - lodepng_error_text(png_error)); - } - custom_tex_cache.SetTextureDumped(tex_hash); - } + if (dump_tex) + DumpTexture(target_tex, dump_path); cur_state.texture_units[0].texture_2d = old_tex; cur_state.Apply(); diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.h b/src/video_core/renderer_opengl/gl_rasterizer_cache.h index 962cbceb6..4d8f2d8bc 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer_cache.h +++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.h @@ -25,6 +25,7 @@ #include "common/common_funcs.h" #include "common/common_types.h" #include "common/math_util.h" +#include "core/custom_tex_cache.h" #include "core/hw/gpu.h" #include "video_core/regs_framebuffer.h" #include "video_core/regs_texturing.h" @@ -377,6 +378,12 @@ struct CachedSurface : SurfaceParams, std::enable_shared_from_this& custom_rect); + bool GetDumpPath(u64 tex_hash, std::string& path); + void DumpTexture(GLuint target_tex, const std::string& dump_path); + // Upload/Download data in gl_buffer in/to this surface's texture void UploadGLTexture(const Common::Rectangle& rect, GLuint read_fb_handle, GLuint draw_fb_handle);