custom_tex_manager: Allow multiple hash mappings per texture

This commit is contained in:
GPUCode
2023-05-01 14:08:01 +03:00
parent 4f9af86cba
commit f5668cdb25
7 changed files with 47 additions and 37 deletions

View File

@@ -112,12 +112,15 @@ void CustomTexManager::FindCustomTextures() {
if (!ParseFilename(file, texture)) {
continue;
}
auto& material = material_map[texture->hash];
for (const u64 hash : texture->hashes) {
auto& material = material_map[hash];
if (!material) {
material = std::make_unique<Material>();
}
material->hash = hash;
material->AddMapTexture(texture);
}
}
textures_loaded = true;
}
@@ -146,21 +149,25 @@ bool CustomTexManager::ParseFilename(const FileUtil::FSTEntry& file, CustomTextu
parts.pop_back();
}
// First check if the path is mapped directly to a hash
// before trying to parse the texture filename.
// First look if this file is mapped to any number of hashes.
std::vector<u64>& hashes = texture->hashes;
const auto it = path_to_hash_map.find(file.virtualName);
if (it != path_to_hash_map.end()) {
texture->hash = it->second;
} else {
hashes = it->second;
}
// It's also possible for pack creators to retain the default texture name
// still map the texture to another hash. Support that as well.
u32 width;
u32 height;
u32 format;
unsigned long long hash{};
if (std::sscanf(parts.back().c_str(), "tex1_%ux%u_%llX_%u", &width, &height, &hash,
&format) != 4) {
return false;
}
texture->hash = hash;
const bool is_parsed = std::sscanf(parts.back().c_str(), "tex1_%ux%u_%llX_%u", &width, &height,
&hash, &format) == 4;
const bool is_mapped =
!hashes.empty() && std::find(hashes.begin(), hashes.end(), hash) != hashes.end();
if (is_parsed && !is_mapped) {
hashes.push_back(hash);
}
texture->path = file.physicalName;
@@ -182,9 +189,9 @@ void CustomTexManager::WriteConfig() {
json["description"] = "A graphics pack";
auto& options = json["options"];
options["skip_mipmap"] = skip_mipmap;
options["flip_png_files"] = flip_png_files;
options["use_new_hash"] = use_new_hash;
options["skip_mipmap"] = false;
options["flip_png_files"] = true;
options["use_new_hash"] = true;
FileUtil::IOFile file{pack_config, "w"};
const std::string output = json.dump(4);
@@ -303,7 +310,7 @@ void CustomTexManager::ReadConfig(const std::string& load_path) {
return;
}
nlohmann::json json = nlohmann::json::parse(config);
nlohmann::json json = nlohmann::json::parse(config, nullptr, false, true);
const auto& options = json["options"];
skip_mipmap = options["skip_mipmap"].get<bool>();
@@ -322,13 +329,7 @@ void CustomTexManager::ReadConfig(const std::string& load_path) {
const auto parse = [&](const std::string& file) {
const std::string filename{FileUtil::GetFilename(file)};
auto [it, new_hash] = path_to_hash_map.try_emplace(filename);
if (!new_hash) {
LOG_ERROR(Render,
"File {} with key {} already exists and is mapped to {:#016X}, skipping",
file, material.key(), path_to_hash_map[filename]);
return;
}
it->second = hash;
it->second.push_back(hash);
};
const auto value = material.value();
if (value.is_string()) {

View File

@@ -79,7 +79,7 @@ private:
Frontend::ImageInterface& image_interface;
std::unordered_set<u64> dumped_textures;
std::unordered_map<u64, std::unique_ptr<Material>> material_map;
std::unordered_map<std::string, u64> path_to_hash_map;
std::unordered_map<std::string, std::vector<u64>> path_to_hash_map;
std::vector<std::unique_ptr<CustomTexture>> custom_textures;
std::list<AsyncUpload> async_uploads;
std::unique_ptr<Common::ThreadWorker> workers;

View File

@@ -55,6 +55,11 @@ CustomTexture::CustomTexture(Frontend::ImageInterface& image_interface_)
CustomTexture::~CustomTexture() = default;
void CustomTexture::LoadFromDisk(bool flip_png) {
std::scoped_lock lock{decode_mutex};
if (IsLoaded()) {
return;
}
FileUtil::IOFile file{path, "rb"};
std::vector<u8> input(file.GetSize());
if (file.ReadBytes(input.data(), input.size()) != input.size()) {
@@ -71,7 +76,6 @@ void CustomTexture::LoadFromDisk(bool flip_png) {
break;
default:
LOG_ERROR(Render, "Unknown file format {}", file_format);
return;
}
}
@@ -102,8 +106,7 @@ void Material::LoadFromDisk(bool flip_png) noexcept {
}
texture->LoadFromDisk(flip_png);
size += texture->data.size();
LOG_DEBUG(Render, "Loading {} map {} with hash {:#016X}", MapTypeName(texture->type),
texture->path, texture->hash);
LOG_DEBUG(Render, "Loading {} map {}", MapTypeName(texture->type), texture->path);
}
if (!textures[0]) {
LOG_ERROR(Render, "Unable to create material without color texture!");
@@ -121,7 +124,7 @@ void Material::LoadFromDisk(bool flip_png) noexcept {
LOG_ERROR(Render,
"{} map {} of material with hash {:#016X} has dimentions {}x{} "
"which do not match the color texture dimentions {}x{}",
MapTypeName(texture->type), texture->path, texture->hash, texture->width,
MapTypeName(texture->type), texture->path, hash, texture->width,
texture->height, width, height);
state = DecodeState::Failed;
return;

View File

@@ -6,6 +6,7 @@
#include <array>
#include <atomic>
#include <mutex>
#include <span>
#include <string>
#include <vector>
@@ -39,7 +40,7 @@ public:
void LoadFromDisk(bool flip_png);
[[nodiscard]] bool IsParsed() const noexcept {
return file_format != CustomFileFormat::None && hash != 0;
return file_format != CustomFileFormat::None && !hashes.empty();
}
[[nodiscard]] bool IsLoaded() const noexcept {
@@ -56,7 +57,8 @@ public:
std::string path;
u32 width;
u32 height;
u64 hash;
std::vector<u64> hashes;
std::mutex decode_mutex;
CustomPixelFormat format;
CustomFileFormat file_format;
std::vector<u8> data;
@@ -67,6 +69,7 @@ struct Material {
u32 width;
u32 height;
u64 size;
u64 hash;
CustomPixelFormat format;
std::array<CustomTexture*, MAX_MAPS> textures;
std::atomic<DecodeState> state{};

View File

@@ -2,12 +2,15 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
#include <type_traits>
#include <boost/container/small_vector.hpp>
#include <boost/range/iterator_range.hpp>
#include "common/alignment.h"
#include "common/logging/log.h"
#include "common/microprofile.h"
#include "common/settings.h"
#include "core/memory.h"
#include "video_core/custom_textures/custom_tex_manager.h"
#include "video_core/rasterizer_cache/rasterizer_cache_base.h"

View File

@@ -674,7 +674,7 @@ Framebuffer::Framebuffer(TextureRuntime& runtime, const Surface* color, u32 colo
Framebuffer::~Framebuffer() = default;
Sampler::Sampler(TextureRuntime& runtime, VideoCore::SamplerParams params) {
Sampler::Sampler(TextureRuntime&, VideoCore::SamplerParams params) {
const GLenum mag_filter = PicaToGL::TextureMagFilterMode(params.mag_filter);
const GLenum min_filter = PicaToGL::TextureMinFilterMode(params.min_filter, params.mip_filter);
const GLenum wrap_s = PicaToGL::WrapMode(params.wrap_s);

View File

@@ -213,7 +213,7 @@ private:
class Sampler {
public:
explicit Sampler(TextureRuntime& runtime, VideoCore::SamplerParams params);
explicit Sampler(TextureRuntime&, VideoCore::SamplerParams params);
~Sampler();
Sampler(const Sampler&) = delete;