custom_tex_manager: Allow old hash in the dumper (#6832)
This commit is contained in:
		@@ -321,12 +321,12 @@ System::ResultStatus System::Load(Frontend::EmuWindow& emu_window, const std::st
 | 
			
		||||
    cheat_engine = std::make_unique<Cheats::CheatEngine>(title_id, *this);
 | 
			
		||||
    perf_stats = std::make_unique<PerfStats>(title_id);
 | 
			
		||||
 | 
			
		||||
    if (Settings::values.dump_textures) {
 | 
			
		||||
        custom_tex_manager->PrepareDumping(title_id);
 | 
			
		||||
    }
 | 
			
		||||
    if (Settings::values.custom_textures) {
 | 
			
		||||
        custom_tex_manager->FindCustomTextures();
 | 
			
		||||
    }
 | 
			
		||||
    if (Settings::values.dump_textures) {
 | 
			
		||||
        custom_tex_manager->WriteConfig();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    status = ResultStatus::Success;
 | 
			
		||||
    m_emu_window = &emu_window;
 | 
			
		||||
 
 | 
			
		||||
@@ -90,19 +90,12 @@ void CustomTexManager::FindCustomTextures() {
 | 
			
		||||
        CreateWorkers();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const u64 program_id = system.Kernel().GetCurrentProcess()->codeset->program_id;
 | 
			
		||||
    const std::string load_path =
 | 
			
		||||
        fmt::format("{}textures/{:016X}/", GetUserPath(FileUtil::UserPath::LoadDir), program_id);
 | 
			
		||||
 | 
			
		||||
    if (!FileUtil::Exists(load_path)) {
 | 
			
		||||
        FileUtil::CreateFullPath(load_path);
 | 
			
		||||
    const u64 title_id = system.Kernel().GetCurrentProcess()->codeset->program_id;
 | 
			
		||||
    const auto textures = GetTextures(title_id);
 | 
			
		||||
    if (!ReadConfig(title_id)) {
 | 
			
		||||
        use_new_hash = false;
 | 
			
		||||
        skip_mipmap = true;
 | 
			
		||||
    }
 | 
			
		||||
    ReadConfig(load_path);
 | 
			
		||||
 | 
			
		||||
    FileUtil::FSTEntry texture_dir;
 | 
			
		||||
    std::vector<FileUtil::FSTEntry> textures;
 | 
			
		||||
    FileUtil::ScanDirectoryTree(load_path, texture_dir, 64);
 | 
			
		||||
    FileUtil::GetAllFilesFromNestedEntries(texture_dir, textures);
 | 
			
		||||
 | 
			
		||||
    custom_textures.reserve(textures.size());
 | 
			
		||||
    for (const FileUtil::FSTEntry& file : textures) {
 | 
			
		||||
@@ -137,8 +130,8 @@ bool CustomTexManager::ParseFilename(const FileUtil::FSTEntry& file, CustomTextu
 | 
			
		||||
    if (file_format == CustomFileFormat::None) {
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
    if (file_format == CustomFileFormat::DDS && refuse_dds) {
 | 
			
		||||
        LOG_ERROR(Render, "Legacy pack is attempting to use DDS textures, skipping!");
 | 
			
		||||
    if (file_format == CustomFileFormat::DDS && skip_mipmap) {
 | 
			
		||||
        LOG_ERROR(Render, "Mipmap skip is incompatible with DDS textures, skipping!");
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
    texture->file_format = file_format;
 | 
			
		||||
@@ -176,10 +169,14 @@ bool CustomTexManager::ParseFilename(const FileUtil::FSTEntry& file, CustomTextu
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void CustomTexManager::WriteConfig() {
 | 
			
		||||
    const u64 program_id = system.Kernel().GetCurrentProcess()->codeset->program_id;
 | 
			
		||||
void CustomTexManager::PrepareDumping(u64 title_id) {
 | 
			
		||||
    // If a pack exists in the load folder that uses the old hash
 | 
			
		||||
    // dump textures using the old hash.
 | 
			
		||||
    ReadConfig(title_id, true);
 | 
			
		||||
 | 
			
		||||
    // Write template config file
 | 
			
		||||
    const std::string dump_path =
 | 
			
		||||
        fmt::format("{}textures/{:016X}/", GetUserPath(FileUtil::UserPath::DumpDir), program_id);
 | 
			
		||||
        fmt::format("{}textures/{:016X}/", GetUserPath(FileUtil::UserPath::DumpDir), title_id);
 | 
			
		||||
    const std::string pack_config = dump_path + "pack.json";
 | 
			
		||||
    if (FileUtil::Exists(pack_config)) {
 | 
			
		||||
        return;
 | 
			
		||||
@@ -307,18 +304,23 @@ bool CustomTexManager::Decode(Material* material, std::function<bool()>&& upload
 | 
			
		||||
    return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void CustomTexManager::ReadConfig(const std::string& load_path) {
 | 
			
		||||
bool CustomTexManager::ReadConfig(u64 title_id, bool options_only) {
 | 
			
		||||
    const std::string load_path =
 | 
			
		||||
        fmt::format("{}textures/{:016X}/", GetUserPath(FileUtil::UserPath::LoadDir), title_id);
 | 
			
		||||
    if (!FileUtil::Exists(load_path)) {
 | 
			
		||||
        FileUtil::CreateFullPath(load_path);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const std::string config_path = load_path + "pack.json";
 | 
			
		||||
    FileUtil::IOFile config_file{config_path, "r"};
 | 
			
		||||
    if (!config_file.IsOpen()) {
 | 
			
		||||
        LOG_INFO(Render, "Unable to find pack config file, using legacy defaults");
 | 
			
		||||
        refuse_dds = true;
 | 
			
		||||
        return;
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
    std::string config(config_file.GetSize(), '\0');
 | 
			
		||||
    const std::size_t read_size = config_file.ReadBytes(config.data(), config.size());
 | 
			
		||||
    if (!read_size) {
 | 
			
		||||
        return;
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    nlohmann::json json = nlohmann::json::parse(config, nullptr, false, true);
 | 
			
		||||
@@ -327,7 +329,10 @@ void CustomTexManager::ReadConfig(const std::string& load_path) {
 | 
			
		||||
    skip_mipmap = options["skip_mipmap"].get<bool>();
 | 
			
		||||
    flip_png_files = options["flip_png_files"].get<bool>();
 | 
			
		||||
    use_new_hash = options["use_new_hash"].get<bool>();
 | 
			
		||||
    refuse_dds = skip_mipmap || !use_new_hash;
 | 
			
		||||
 | 
			
		||||
    if (options_only) {
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const auto& textures = json["textures"];
 | 
			
		||||
    for (const auto& material : textures.items()) {
 | 
			
		||||
@@ -355,6 +360,21 @@ void CustomTexManager::ReadConfig(const std::string& load_path) {
 | 
			
		||||
            LOG_ERROR(Render, "Material with key {} is invalid", material.key());
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
std::vector<FileUtil::FSTEntry> CustomTexManager::GetTextures(u64 title_id) {
 | 
			
		||||
    const std::string load_path =
 | 
			
		||||
        fmt::format("{}textures/{:016X}/", GetUserPath(FileUtil::UserPath::LoadDir), title_id);
 | 
			
		||||
    if (!FileUtil::Exists(load_path)) {
 | 
			
		||||
        FileUtil::CreateFullPath(load_path);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    FileUtil::FSTEntry texture_dir;
 | 
			
		||||
    std::vector<FileUtil::FSTEntry> textures;
 | 
			
		||||
    FileUtil::ScanDirectoryTree(load_path, texture_dir, 64);
 | 
			
		||||
    FileUtil::GetAllFilesFromNestedEntries(texture_dir, textures);
 | 
			
		||||
    return textures;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void CustomTexManager::CreateWorkers() {
 | 
			
		||||
 
 | 
			
		||||
@@ -40,8 +40,11 @@ public:
 | 
			
		||||
    /// Searches the load directory assigned to program_id for any custom textures and loads them
 | 
			
		||||
    void FindCustomTextures();
 | 
			
		||||
 | 
			
		||||
    /// Reads the pack configuration file
 | 
			
		||||
    bool ReadConfig(u64 title_id, bool options_only = false);
 | 
			
		||||
 | 
			
		||||
    /// Saves the pack configuration file template to the dump directory if it doesn't exist.
 | 
			
		||||
    void WriteConfig();
 | 
			
		||||
    void PrepareDumping(u64 title_id);
 | 
			
		||||
 | 
			
		||||
    /// Preloads all registered custom textures
 | 
			
		||||
    void PreloadTextures(const std::atomic_bool& stop_run,
 | 
			
		||||
@@ -70,8 +73,8 @@ private:
 | 
			
		||||
    /// Parses the custom texture filename (hash, material type, etc).
 | 
			
		||||
    bool ParseFilename(const FileUtil::FSTEntry& file, CustomTexture* texture);
 | 
			
		||||
 | 
			
		||||
    /// Reads the pack configuration file
 | 
			
		||||
    void ReadConfig(const std::string& load_path);
 | 
			
		||||
    /// Returns a vector of all custom texture files.
 | 
			
		||||
    std::vector<FileUtil::FSTEntry> GetTextures(u64 title_id);
 | 
			
		||||
 | 
			
		||||
    /// Creates the thread workers.
 | 
			
		||||
    void CreateWorkers();
 | 
			
		||||
@@ -87,10 +90,9 @@ private:
 | 
			
		||||
    std::unique_ptr<Common::ThreadWorker> workers;
 | 
			
		||||
    bool textures_loaded{false};
 | 
			
		||||
    bool async_custom_loading{true};
 | 
			
		||||
    bool skip_mipmap{true};
 | 
			
		||||
    bool skip_mipmap{false};
 | 
			
		||||
    bool flip_png_files{true};
 | 
			
		||||
    bool use_new_hash{false};
 | 
			
		||||
    bool refuse_dds{false};
 | 
			
		||||
    bool use_new_hash{true};
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
} // namespace VideoCore
 | 
			
		||||
 
 | 
			
		||||
@@ -993,7 +993,7 @@ void RasterizerCache<T>::UploadSurface(Surface& surface, SurfaceInterval interva
 | 
			
		||||
                  runtime.NeedsConversion(surface.pixel_format));
 | 
			
		||||
 | 
			
		||||
    if (dump_textures && False(surface.flags & SurfaceFlagBits::Custom)) {
 | 
			
		||||
        const u64 hash = Common::ComputeHash64(upload_data.data(), upload_data.size());
 | 
			
		||||
        const u64 hash = ComputeHash(load_info, upload_data);
 | 
			
		||||
        const u32 level = surface.LevelOf(load_info.addr);
 | 
			
		||||
        custom_tex_manager.DumpTexture(load_info, level, upload_data, hash);
 | 
			
		||||
    }
 | 
			
		||||
@@ -1007,6 +1007,20 @@ void RasterizerCache<T>::UploadSurface(Surface& surface, SurfaceInterval interva
 | 
			
		||||
    surface.Upload(upload, staging);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <class T>
 | 
			
		||||
u64 RasterizerCache<T>::ComputeHash(const SurfaceParams& load_info, std::span<u8> upload_data) {
 | 
			
		||||
    if (!custom_tex_manager.UseNewHash()) {
 | 
			
		||||
        const u32 width = load_info.width;
 | 
			
		||||
        const u32 height = load_info.height;
 | 
			
		||||
        const u32 bpp = GetFormatBytesPerPixel(load_info.pixel_format);
 | 
			
		||||
        auto decoded = std::vector<u8>(width * height * bpp);
 | 
			
		||||
        DecodeTexture(load_info, load_info.addr, load_info.end, upload_data, decoded, false);
 | 
			
		||||
        return Common::ComputeHash64(decoded.data(), decoded.size());
 | 
			
		||||
    } else {
 | 
			
		||||
        return Common::ComputeHash64(upload_data.data(), upload_data.size());
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <class T>
 | 
			
		||||
bool RasterizerCache<T>::UploadCustomSurface(SurfaceId surface_id, SurfaceInterval interval) {
 | 
			
		||||
    MICROPROFILE_SCOPE(RasterizerCache_UploadSurface);
 | 
			
		||||
@@ -1021,18 +1035,7 @@ bool RasterizerCache<T>::UploadCustomSurface(SurfaceId surface_id, SurfaceInterv
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const auto upload_data = source_ptr.GetWriteBytes(load_info.end - load_info.addr);
 | 
			
		||||
    const u64 hash = [&] {
 | 
			
		||||
        if (!custom_tex_manager.UseNewHash()) {
 | 
			
		||||
            const u32 width = load_info.width;
 | 
			
		||||
            const u32 height = load_info.height;
 | 
			
		||||
            const u32 bpp = surface.GetInternalBytesPerPixel();
 | 
			
		||||
            auto decoded = std::vector<u8>(width * height * bpp);
 | 
			
		||||
            DecodeTexture(load_info, load_info.addr, load_info.end, upload_data, decoded, false);
 | 
			
		||||
            return Common::ComputeHash64(decoded.data(), decoded.size());
 | 
			
		||||
        } else {
 | 
			
		||||
            return Common::ComputeHash64(upload_data.data(), upload_data.size());
 | 
			
		||||
        }
 | 
			
		||||
    }();
 | 
			
		||||
    const u64 hash = ComputeHash(load_info, upload_data);
 | 
			
		||||
 | 
			
		||||
    const u32 level = surface.LevelOf(load_info.addr);
 | 
			
		||||
    Material* material = custom_tex_manager.GetMaterial(hash);
 | 
			
		||||
 
 | 
			
		||||
@@ -7,6 +7,7 @@
 | 
			
		||||
#include <functional>
 | 
			
		||||
#include <list>
 | 
			
		||||
#include <optional>
 | 
			
		||||
#include <span>
 | 
			
		||||
#include <unordered_map>
 | 
			
		||||
#include <vector>
 | 
			
		||||
#include <boost/icl/interval_map.hpp>
 | 
			
		||||
@@ -167,6 +168,9 @@ private:
 | 
			
		||||
    /// Transfers ownership of a memory region from src_surface to dest_surface
 | 
			
		||||
    void DuplicateSurface(SurfaceId src_id, SurfaceId dst_id);
 | 
			
		||||
 | 
			
		||||
    /// Computes the hash of the provided texture data.
 | 
			
		||||
    u64 ComputeHash(const SurfaceParams& load_info, std::span<u8> upload_data);
 | 
			
		||||
 | 
			
		||||
    /// Update surface's texture for given region when necessary
 | 
			
		||||
    void ValidateSurface(SurfaceId surface, PAddr addr, u32 size);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user