Custom textures rewrite (#6452)

* common: Add thread pool from yuzu

* Is really useful for asynchronous operations like shader compilation and custom textures, will be used in following PRs

* core: Improve ImageInterface

* Provide a default implementation so frontends don't have to duplicate code registering the lodepng version

* Add a dds version too which we will use in the next commit

* rasterizer_cache: Rewrite custom textures

* There's just too much to talk about here, look at the PR description for more details

* rasterizer_cache: Implement basic pack configuration file

* custom_tex_manager: Flip dumped textures

* custom_tex_manager: Optimize custom texture hashing

* If no convertions are needed then we can hash the decoded data directly removing the needed for duplicate decode

* custom_tex_manager: Implement asynchronous texture loading

* The file loading and decoding is offloaded into worker threads, while the upload itself still occurs in the main thread to avoid having to manage shared contexts

* Address review comments

* custom_tex_manager: Introduce custom material support

* video_core: Move custom textures to separate directory

* Also split the files to make the code cleaner

* gl_texture_runtime: Generate mipmaps for material

* custom_tex_manager: Prevent memory overflow when preloading

* externals: Add dds-ktx as submodule

* string_util: Return vector from SplitString

* No code benefits from passing it as an argument

* custom_textures: Use json config file

* gl_rasterizer: Only bind material for unit 0

* Address review comments
This commit is contained in:
GPUCode 2023-04-27 07:38:28 +03:00 committed by GitHub
parent d16dce6d99
commit 06f3c90cfb
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
87 changed files with 2154 additions and 544 deletions

View file

@ -368,6 +368,7 @@ public final class SettingsFragmentPresenter {
SettingSection utilitySection = mSettings.getSection(Settings.SECTION_UTILITY);
Setting dumpTextures = utilitySection.getSetting(SettingsFile.KEY_DUMP_TEXTURES);
Setting customTextures = utilitySection.getSetting(SettingsFile.KEY_CUSTOM_TEXTURES);
Setting asyncCustomLoading = utilitySection.getSetting(SettingsFile.KEY_ASYNC_CUSTOM_LOADING);
//Setting preloadTextures = utilitySection.getSetting(SettingsFile.KEY_PRELOAD_TEXTURES);
sl.add(new HeaderSetting(null, null, R.string.renderer, 0));
@ -389,6 +390,7 @@ public final class SettingsFragmentPresenter {
sl.add(new HeaderSetting(null, null, R.string.utility, 0));
sl.add(new CheckBoxSetting(SettingsFile.KEY_DUMP_TEXTURES, Settings.SECTION_UTILITY, R.string.dump_textures, R.string.dump_textures_description, false, dumpTextures));
sl.add(new CheckBoxSetting(SettingsFile.KEY_CUSTOM_TEXTURES, Settings.SECTION_UTILITY, R.string.custom_textures, R.string.custom_textures_description, false, customTextures));
sl.add(new CheckBoxSetting(SettingsFile.KEY_ASYNC_CUSTOM_LOADING, Settings.SECTION_UTILITY, R.string.async_custom_loading, R.string.async_custom_loading_description, true, asyncCustomLoading));
//Disabled until custom texture implementation gets rewrite, current one overloads RAM and crashes Citra.
//sl.add(new CheckBoxSetting(SettingsFile.KEY_PRELOAD_TEXTURES, Settings.SECTION_UTILITY, R.string.preload_textures, R.string.preload_textures_description, false, preloadTextures));
}

View file

@ -73,6 +73,7 @@ public final class SettingsFile {
public static final String KEY_DUMP_TEXTURES = "dump_textures";
public static final String KEY_CUSTOM_TEXTURES = "custom_textures";
public static final String KEY_PRELOAD_TEXTURES = "preload_textures";
public static final String KEY_ASYNC_CUSTOM_LOADING = "async_custom_loading";
public static final String KEY_AUDIO_OUTPUT_ENGINE = "output_engine";
public static final String KEY_ENABLE_AUDIO_STRETCHING = "enable_audio_stretching";

View file

@ -25,8 +25,6 @@ add_library(citra-android SHARED
game_settings.h
id_cache.cpp
id_cache.h
lodepng_image_interface.cpp
lodepng_image_interface.h
mic.cpp
mic.h
native.cpp
@ -36,6 +34,6 @@ add_library(citra-android SHARED
)
target_link_libraries(citra-android PRIVATE audio_core common core input_common network)
target_link_libraries(citra-android PRIVATE android camera2ndk EGL glad inih jnigraphics lodepng log mediandk yuv)
target_link_libraries(citra-android PRIVATE android camera2ndk EGL glad inih jnigraphics log mediandk yuv)
set(CPACK_PACKAGE_EXECUTABLES ${CPACK_PACKAGE_EXECUTABLES} citra-android)

View file

@ -62,8 +62,7 @@ JNIEXPORT void JNICALL Java_org_citra_citra_1emu_features_cheats_model_Cheat_set
JNIEXPORT jint JNICALL Java_org_citra_citra_1emu_features_cheats_model_Cheat_isValidGatewayCode(
JNIEnv* env, jclass, jstring j_code) {
const std::string code = GetJString(env, j_code);
std::vector<std::string> code_lines;
Common::SplitString(code, '\n', code_lines);
const auto code_lines = Common::SplitString(code, '\n');
for (int i = 0; i < code_lines.size(); ++i) {
Cheats::GatewayCheat::CheatLine cheat_line(code_lines[i]);

View file

@ -195,6 +195,7 @@ void Config::ReadValues() {
ReadSetting("Utility", Settings::values.dump_textures);
ReadSetting("Utility", Settings::values.custom_textures);
ReadSetting("Utility", Settings::values.preload_textures);
ReadSetting("Utility", Settings::values.async_custom_loading);
// Audio
ReadSetting("Audio", Settings::values.audio_emulation);

View file

@ -213,6 +213,10 @@ custom_textures =
# 0 (default): Off, 1: On
preload_textures =
# Loads custom textures asynchronously with background threads.
# 0: Off, 1 (default): On
async_custom_loading =
[Audio]
# Whether or not to enable DSP LLE
# 0 (default): No, 1: Yes

View file

@ -1,44 +0,0 @@
// Copyright 2019 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include <lodepng.h>
#include "common/file_util.h"
#include "common/logging/log.h"
#include "jni/lodepng_image_interface.h"
bool LodePNGImageInterface::DecodePNG(std::vector<u8>& dst, u32& width, u32& height,
const std::string& path) {
FileUtil::IOFile file(path, "rb");
size_t read_size = file.GetSize();
std::vector<u8> in(read_size);
if (file.ReadBytes(&in[0], read_size) != read_size) {
LOG_CRITICAL(Frontend, "Failed to decode {}", path);
}
u32 lodepng_ret = lodepng::decode(dst, width, height, in);
if (lodepng_ret) {
LOG_CRITICAL(Frontend, "Failed to decode {} because {}", path,
lodepng_error_text(lodepng_ret));
return false;
}
return true;
}
bool LodePNGImageInterface::EncodePNG(const std::string& path, const std::vector<u8>& src,
u32 width, u32 height) {
std::vector<u8> out;
u32 lodepng_ret = lodepng::encode(out, src, width, height);
if (lodepng_ret) {
LOG_CRITICAL(Frontend, "Failed to encode {} because {}", path,
lodepng_error_text(lodepng_ret));
return false;
}
FileUtil::IOFile file(path, "wb");
if (file.WriteBytes(&out[0], out.size()) != out.size()) {
LOG_CRITICAL(Frontend, "Failed to save encode to path={}", path);
return false;
}
return true;
}

View file

@ -1,14 +0,0 @@
// Copyright 2019 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
#include "core/frontend/image_interface.h"
class LodePNGImageInterface final : public Frontend::ImageInterface {
public:
bool DecodePNG(std::vector<u8>& dst, u32& width, u32& height, const std::string& path) override;
bool EncodePNG(const std::string& path, const std::vector<u8>& src, u32 width,
u32 height) override;
};

View file

@ -39,7 +39,6 @@
#include "jni/game_settings.h"
#include "jni/id_cache.h"
#include "jni/input_manager.h"
#include "jni/lodepng_image_interface.h"
#include "jni/mic.h"
#include "jni/native.h"
#include "jni/ndk_motion.h"
@ -184,9 +183,6 @@ static Core::System::ResultStatus RunCitra(const std::string& filepath) {
system.RegisterMiiSelector(std::make_shared<MiiSelector::AndroidMiiSelector>());
system.RegisterSoftwareKeyboard(std::make_shared<SoftwareKeyboard::AndroidKeyboard>());
// Register generic image interface
Core::System::GetInstance().RegisterImageInterface(std::make_shared<LodePNGImageInterface>());
// Register real Mic factory
Frontend::Mic::RegisterRealMicFactory(std::make_unique<Mic::AndroidFactory>());

View file

@ -116,6 +116,8 @@
<string name="custom_textures_description">Uses custom textures found in load/textures/[GAME ID]</string>
<string name="preload_textures">Preload custom textures</string>
<string name="preload_textures_description">Loads all custom textures into memory. This feature can use a lot of memory.</string>
<string name="async_custom_loading">Async custom texture loading</string>
<string name="async_custom_loading_description">Loads custom textures in the background with worker threads to reduce loading stutter.</string>
<!-- Premium strings -->
<string name="premium_text">Premium</string>
<string name="premium_settings_upsell">Upgrade to Premium and support Citra!</string>