Merge pull request #4453 from degasus/custom_texture

CustomTexture: Drop old texture format.
This commit is contained in:
Markus Wick 2018-01-21 11:22:49 +01:00 committed by GitHub
commit fca56d532a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 49 additions and 273 deletions

View File

@ -332,64 +332,6 @@ static u64 GetCRC32(const u8* src, u32 len, u32 samples)
#endif #endif
/*
* NOTE: This hash function is used for custom texture loading/dumping, so
* it should not be changed, which would require all custom textures to be
* recalculated for their new hash values. If the hashing function is
* changed, make sure this one is still used when the legacy parameter is
* true.
*/
u64 GetHashHiresTexture(const u8* src, u32 len, u32 samples)
{
const u64 m = 0xc6a4a7935bd1e995;
u64 h = len * m;
const int r = 47;
u32 Step = (len / 8);
const u64* data = (const u64*)src;
const u64* end = data + Step;
if (samples == 0)
samples = std::max(Step, 1u);
Step = Step / samples;
if (Step < 1)
Step = 1;
while (data < end)
{
u64 k = data[0];
data += Step;
k *= m;
k ^= k >> r;
k *= m;
h ^= k;
h *= m;
}
const u8* data2 = (const u8*)end;
switch (len & 7)
{
case 7:
h ^= u64(data2[6]) << 48;
case 6:
h ^= u64(data2[5]) << 40;
case 5:
h ^= u64(data2[4]) << 32;
case 4:
h ^= u64(data2[3]) << 24;
case 3:
h ^= u64(data2[2]) << 16;
case 2:
h ^= u64(data2[1]) << 8;
case 1:
h ^= u64(data2[0]);
h *= m;
};
h ^= h >> r;
h *= m;
h ^= h >> r;
return h;
}
#else #else
// CRC32 hash using the SSE4.2 instruction // CRC32 hash using the SSE4.2 instruction
@ -553,63 +495,6 @@ static u64 GetMurmurHash3(const u8* src, u32 len, u32 samples)
return *((u64*)&out); return *((u64*)&out);
} }
/*
* FIXME: The old 32-bit version of this hash made different hashes than the
* 64-bit version. Until someone can make a new version of the 32-bit one that
* makes identical hashes, this is just a c/p of the 64-bit one.
*/
u64 GetHashHiresTexture(const u8* src, u32 len, u32 samples)
{
const u64 m = 0xc6a4a7935bd1e995ULL;
u64 h = len * m;
const int r = 47;
u32 Step = (len / 8);
const u64* data = (const u64*)src;
const u64* end = data + Step;
if (samples == 0)
samples = std::max(Step, 1u);
Step = Step / samples;
if (Step < 1)
Step = 1;
while (data < end)
{
u64 k = data[0];
data += Step;
k *= m;
k ^= k >> r;
k *= m;
h ^= k;
h *= m;
}
const u8* data2 = (const u8*)end;
switch (len & 7)
{
case 7:
h ^= u64(data2[6]) << 48;
case 6:
h ^= u64(data2[5]) << 40;
case 5:
h ^= u64(data2[4]) << 32;
case 4:
h ^= u64(data2[3]) << 24;
case 3:
h ^= u64(data2[2]) << 16;
case 2:
h ^= u64(data2[1]) << 8;
case 1:
h ^= u64(data2[0]);
h *= m;
};
h ^= h >> r;
h *= m;
h ^= h >> r;
return h;
}
#endif #endif
u64 GetHash64(const u8* src, u32 len, u32 samples) u64 GetHash64(const u8* src, u32 len, u32 samples)

View File

@ -11,6 +11,5 @@
u32 HashFletcher(const u8* data_u8, size_t length); // FAST. Length & 1 == 0. u32 HashFletcher(const u8* data_u8, size_t length); // FAST. Length & 1 == 0.
u32 HashAdler32(const u8* data, size_t len); // Fairly accurate, slightly slower u32 HashAdler32(const u8* data, size_t len); // Fairly accurate, slightly slower
u32 HashEctor(const u8* ptr, int length); // JUNK. DO NOT USE FOR NEW THINGS u32 HashEctor(const u8* ptr, int length); // JUNK. DO NOT USE FOR NEW THINGS
u64 GetHashHiresTexture(const u8* src, u32 len, u32 samples = 0);
u64 GetHash64(const u8* src, u32 len, u32 samples); u64 GetHash64(const u8* src, u32 len, u32 samples);
void SetHash64Function(); void SetHash64Function();

View File

@ -38,8 +38,6 @@ const ConfigInfo<bool> GFX_OVERLAY_STATS{{System::GFX, "Settings", "OverlayStats
const ConfigInfo<bool> GFX_OVERLAY_PROJ_STATS{{System::GFX, "Settings", "OverlayProjStats"}, false}; const ConfigInfo<bool> GFX_OVERLAY_PROJ_STATS{{System::GFX, "Settings", "OverlayProjStats"}, false};
const ConfigInfo<bool> GFX_DUMP_TEXTURES{{System::GFX, "Settings", "DumpTextures"}, false}; const ConfigInfo<bool> GFX_DUMP_TEXTURES{{System::GFX, "Settings", "DumpTextures"}, false};
const ConfigInfo<bool> GFX_HIRES_TEXTURES{{System::GFX, "Settings", "HiresTextures"}, false}; const ConfigInfo<bool> GFX_HIRES_TEXTURES{{System::GFX, "Settings", "HiresTextures"}, false};
const ConfigInfo<bool> GFX_CONVERT_HIRES_TEXTURES{{System::GFX, "Settings", "ConvertHiresTextures"},
false};
const ConfigInfo<bool> GFX_CACHE_HIRES_TEXTURES{{System::GFX, "Settings", "CacheHiresTextures"}, const ConfigInfo<bool> GFX_CACHE_HIRES_TEXTURES{{System::GFX, "Settings", "CacheHiresTextures"},
false}; false};
const ConfigInfo<bool> GFX_DUMP_EFB_TARGET{{System::GFX, "Settings", "DumpEFBTarget"}, false}; const ConfigInfo<bool> GFX_DUMP_EFB_TARGET{{System::GFX, "Settings", "DumpEFBTarget"}, false};

View File

@ -32,7 +32,6 @@ extern const ConfigInfo<bool> GFX_OVERLAY_STATS;
extern const ConfigInfo<bool> GFX_OVERLAY_PROJ_STATS; extern const ConfigInfo<bool> GFX_OVERLAY_PROJ_STATS;
extern const ConfigInfo<bool> GFX_DUMP_TEXTURES; extern const ConfigInfo<bool> GFX_DUMP_TEXTURES;
extern const ConfigInfo<bool> GFX_HIRES_TEXTURES; extern const ConfigInfo<bool> GFX_HIRES_TEXTURES;
extern const ConfigInfo<bool> GFX_CONVERT_HIRES_TEXTURES;
extern const ConfigInfo<bool> GFX_CACHE_HIRES_TEXTURES; extern const ConfigInfo<bool> GFX_CACHE_HIRES_TEXTURES;
extern const ConfigInfo<bool> GFX_DUMP_EFB_TARGET; extern const ConfigInfo<bool> GFX_DUMP_EFB_TARGET;
extern const ConfigInfo<bool> GFX_DUMP_XFB_TARGET; extern const ConfigInfo<bool> GFX_DUMP_XFB_TARGET;

View File

@ -33,7 +33,6 @@ bool IsSettingSaveable(const Config::ConfigLocation& config_location)
Config::GFX_SHOW_NETPLAY_MESSAGES.location, Config::GFX_LOG_RENDER_TIME_TO_FILE.location, Config::GFX_SHOW_NETPLAY_MESSAGES.location, Config::GFX_LOG_RENDER_TIME_TO_FILE.location,
Config::GFX_OVERLAY_STATS.location, Config::GFX_OVERLAY_PROJ_STATS.location, Config::GFX_OVERLAY_STATS.location, Config::GFX_OVERLAY_PROJ_STATS.location,
Config::GFX_DUMP_TEXTURES.location, Config::GFX_HIRES_TEXTURES.location, Config::GFX_DUMP_TEXTURES.location, Config::GFX_HIRES_TEXTURES.location,
Config::GFX_CONVERT_HIRES_TEXTURES.location, Config::GFX_CACHE_HIRES_TEXTURES.location,
Config::GFX_DUMP_EFB_TARGET.location, Config::GFX_DUMP_FRAMES_AS_IMAGES.location, Config::GFX_DUMP_EFB_TARGET.location, Config::GFX_DUMP_FRAMES_AS_IMAGES.location,
Config::GFX_FREE_LOOK.location, Config::GFX_USE_FFV1.location, Config::GFX_FREE_LOOK.location, Config::GFX_USE_FFV1.location,
Config::GFX_DUMP_FORMAT.location, Config::GFX_DUMP_CODEC.location, Config::GFX_DUMP_FORMAT.location, Config::GFX_DUMP_CODEC.location,

View File

@ -44,8 +44,6 @@ static std::unordered_map<std::string, std::shared_ptr<HiresTexture>> s_textureC
static std::mutex s_textureCacheMutex; static std::mutex s_textureCacheMutex;
static std::mutex s_textureCacheAquireMutex; // for high priority access static std::mutex s_textureCacheAquireMutex; // for high priority access
static Common::Flag s_textureCacheAbortLoading; static Common::Flag s_textureCacheAbortLoading;
static bool s_check_native_format;
static bool s_check_new_format;
static std::thread s_prefetcher; static std::thread s_prefetcher;
@ -57,9 +55,6 @@ HiresTexture::Level::Level() : data(nullptr, SOIL_free_image_data)
void HiresTexture::Init() void HiresTexture::Init()
{ {
s_check_native_format = false;
s_check_new_format = false;
Update(); Update();
} }
@ -112,12 +107,6 @@ void HiresTexture::Update()
std::string filename; std::string filename;
SplitPath(path, nullptr, &filename, nullptr); SplitPath(path, nullptr, &filename, nullptr);
if (filename.substr(0, code.length()) == code)
{
s_textureMap[filename] = {path, false};
s_check_native_format = true;
}
if (filename.substr(0, s_format_prefix.length()) == s_format_prefix) if (filename.substr(0, s_format_prefix.length()) == s_format_prefix)
{ {
const size_t arb_index = filename.rfind("_arb"); const size_t arb_index = filename.rfind("_arb");
@ -125,7 +114,6 @@ void HiresTexture::Update()
if (has_arbitrary_mipmaps) if (has_arbitrary_mipmaps)
filename.erase(arb_index, 4); filename.erase(arb_index, 4);
s_textureMap[filename] = {path, has_arbitrary_mipmaps}; s_textureMap[filename] = {path, has_arbitrary_mipmaps};
s_check_new_format = true;
} }
} }
@ -228,154 +216,64 @@ std::string HiresTexture::GenBaseName(const u8* texture, size_t texture_size, co
size_t tlut_size, u32 width, u32 height, TextureFormat format, size_t tlut_size, u32 width, u32 height, TextureFormat format,
bool has_mipmaps, bool dump) bool has_mipmaps, bool dump)
{ {
std::string name = ""; if (!dump && s_textureMap.empty())
bool convert = false; return "";
if (!dump && s_check_native_format)
// checking for min/max on paletted textures
u32 min = 0xffff;
u32 max = 0;
switch (tlut_size)
{ {
// try to load the old format first case 0:
u64 tex_hash = GetHashHiresTexture(texture, (int)texture_size, break;
g_ActiveConfig.iSafeTextureCache_ColorSamples); case 16 * 2:
u64 tlut_hash = tlut_size ? GetHashHiresTexture(tlut, (int)tlut_size, for (size_t i = 0; i < texture_size; i++)
g_ActiveConfig.iSafeTextureCache_ColorSamples) :
0;
name = StringFromFormat("%s_%08x_%i", SConfig::GetInstance().GetGameID().c_str(),
(u32)(tex_hash ^ tlut_hash), (u16)format);
if (s_textureMap.find(name) != s_textureMap.end())
{ {
if (g_ActiveConfig.bConvertHiresTextures) min = std::min<u32>(min, texture[i] & 0xf);
convert = true; min = std::min<u32>(min, texture[i] >> 4);
else max = std::max<u32>(max, texture[i] & 0xf);
return name; max = std::max<u32>(max, texture[i] >> 4);
} }
break;
case 256 * 2:
for (size_t i = 0; i < texture_size; i++)
{
min = std::min<u32>(min, texture[i]);
max = std::max<u32>(max, texture[i]);
}
break;
case 16384 * 2:
for (size_t i = 0; i < texture_size / 2; i++)
{
min = std::min<u32>(min, Common::swap16(((u16*)texture)[i]) & 0x3fff);
max = std::max<u32>(max, Common::swap16(((u16*)texture)[i]) & 0x3fff);
}
break;
}
if (tlut_size > 0)
{
tlut_size = 2 * (max + 1 - min);
tlut += 2 * min;
} }
if (dump || s_check_new_format || convert) u64 tex_hash = XXH64(texture, texture_size, 0);
{ u64 tlut_hash = tlut_size ? XXH64(tlut, tlut_size, 0) : 0;
// checking for min/max on paletted textures
u32 min = 0xffff;
u32 max = 0;
switch (tlut_size)
{
case 0:
break;
case 16 * 2:
for (size_t i = 0; i < texture_size; i++)
{
min = std::min<u32>(min, texture[i] & 0xf);
min = std::min<u32>(min, texture[i] >> 4);
max = std::max<u32>(max, texture[i] & 0xf);
max = std::max<u32>(max, texture[i] >> 4);
}
break;
case 256 * 2:
for (size_t i = 0; i < texture_size; i++)
{
min = std::min<u32>(min, texture[i]);
max = std::max<u32>(max, texture[i]);
}
break;
case 16384 * 2:
for (size_t i = 0; i < texture_size / 2; i++)
{
min = std::min<u32>(min, Common::swap16(((u16*)texture)[i]) & 0x3fff);
max = std::max<u32>(max, Common::swap16(((u16*)texture)[i]) & 0x3fff);
}
break;
}
if (tlut_size > 0)
{
tlut_size = 2 * (max + 1 - min);
tlut += 2 * min;
}
u64 tex_hash = XXH64(texture, texture_size, 0); std::string basename = s_format_prefix + StringFromFormat("%dx%d%s_%016" PRIx64, width, height,
u64 tlut_hash = tlut_size ? XXH64(tlut, tlut_size, 0) : 0; has_mipmaps ? "_m" : "", tex_hash);
std::string tlutname = tlut_size ? StringFromFormat("_%016" PRIx64, tlut_hash) : "";
std::string formatname = StringFromFormat("_%d", static_cast<int>(format));
std::string fullname = basename + tlutname + formatname;
std::string basename = s_format_prefix + StringFromFormat("%dx%d%s_%016" PRIx64, width, height, // try to match a wildcard template
has_mipmaps ? "_m" : "", tex_hash); if (!dump && s_textureMap.find(basename + "_*" + formatname) != s_textureMap.end())
std::string tlutname = tlut_size ? StringFromFormat("_%016" PRIx64, tlut_hash) : ""; return basename + "_*" + formatname;
std::string formatname = StringFromFormat("_%d", static_cast<int>(format));
std::string fullname = basename + tlutname + formatname;
for (int level = 0; level < 10 && convert; level++) // else generate the complete texture
{ if (dump || s_textureMap.find(fullname) != s_textureMap.end())
std::string oldname = name; return fullname;
if (level)
oldname += StringFromFormat("_mip%d", level);
// skip not existing levels return "";
if (s_textureMap.find(oldname) == s_textureMap.end())
continue;
for (int i = 0;; i++)
{
// for hash collisions, padd with an integer
std::string newname = fullname;
if (level)
newname += StringFromFormat("_mip%d", level);
if (i)
newname += StringFromFormat(".%d", i);
// new texture
if (s_textureMap.find(newname) == s_textureMap.end())
{
std::string src = s_textureMap[oldname].path;
size_t postfix = src.find_last_of('.');
std::string dst = src.substr(0, postfix - oldname.length()) + newname +
src.substr(postfix, src.length() - postfix);
if (File::Rename(src, dst))
{
s_textureMap.erase(oldname);
s_textureMap[newname] = {dst, false};
s_check_new_format = true;
OSD::AddMessage(StringFromFormat("Rename custom texture %s to %s", oldname.c_str(),
newname.c_str()),
5000);
}
else
{
ERROR_LOG(VIDEO, "rename failed");
}
break;
}
else
{
// dst fail already exist, compare content
std::string a, b;
File::ReadFileToString(s_textureMap[oldname].path, a);
File::ReadFileToString(s_textureMap[newname].path, b);
if (a == b && a != "")
{
// equal, so remove
if (File::Delete(s_textureMap[oldname].path))
{
s_textureMap.erase(oldname);
OSD::AddMessage(
StringFromFormat("Delete double old custom texture %s", oldname.c_str()), 5000);
}
else
{
ERROR_LOG(VIDEO, "delete failed");
}
break;
}
// else continue in this loop with the next higher padding variable
}
}
}
// try to match a wildcard template
if (!dump && s_textureMap.find(basename + "_*" + formatname) != s_textureMap.end())
return basename + "_*" + formatname;
// else generate the complete texture
if (dump || s_textureMap.find(fullname) != s_textureMap.end())
return fullname;
}
return name;
} }
u32 HiresTexture::CalculateMipCount(u32 width, u32 height) u32 HiresTexture::CalculateMipCount(u32 width, u32 height)

View File

@ -75,7 +75,6 @@ void VideoConfig::Refresh()
bOverlayProjStats = Config::Get(Config::GFX_OVERLAY_PROJ_STATS); bOverlayProjStats = Config::Get(Config::GFX_OVERLAY_PROJ_STATS);
bDumpTextures = Config::Get(Config::GFX_DUMP_TEXTURES); bDumpTextures = Config::Get(Config::GFX_DUMP_TEXTURES);
bHiresTextures = Config::Get(Config::GFX_HIRES_TEXTURES); bHiresTextures = Config::Get(Config::GFX_HIRES_TEXTURES);
bConvertHiresTextures = Config::Get(Config::GFX_CONVERT_HIRES_TEXTURES);
bCacheHiresTextures = Config::Get(Config::GFX_CACHE_HIRES_TEXTURES); bCacheHiresTextures = Config::Get(Config::GFX_CACHE_HIRES_TEXTURES);
bDumpEFBTarget = Config::Get(Config::GFX_DUMP_EFB_TARGET); bDumpEFBTarget = Config::Get(Config::GFX_DUMP_EFB_TARGET);
bDumpXFBTarget = Config::Get(Config::GFX_DUMP_XFB_TARGET); bDumpXFBTarget = Config::Get(Config::GFX_DUMP_XFB_TARGET);

View File

@ -93,7 +93,6 @@ struct VideoConfig final
// Utility // Utility
bool bDumpTextures; bool bDumpTextures;
bool bHiresTextures; bool bHiresTextures;
bool bConvertHiresTextures;
bool bCacheHiresTextures; bool bCacheHiresTextures;
bool bDumpEFBTarget; bool bDumpEFBTarget;
bool bDumpXFBTarget; bool bDumpXFBTarget;