mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-31 05:40:04 +00:00 
			
		
		
		
	custom_tex_manager: Allow old hash in the dumper (#6832)
This commit is contained in:
		
							parent
							
								
									35e208b447
								
							
						
					
					
						commit
						baf3ea4beb
					
				
					 5 changed files with 73 additions and 44 deletions
				
			
		|  | @ -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); | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue