TextureCacheBase: Support loading custom mipmaps.
This commit is contained in:
parent
a5e68ab10e
commit
41d37ab0a0
|
@ -90,7 +90,13 @@ void Init(const char *gameCode)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PC_TexFormat GetHiresTex(const char *fileName, unsigned int *pWidth, unsigned int *pHeight, int texformat, u8 *data)
|
bool HiresTexExists(const char* filename)
|
||||||
|
{
|
||||||
|
std::string key(filename);
|
||||||
|
return textureMap.find(key) != textureMap.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
PC_TexFormat GetHiresTex(const char *fileName, unsigned int *pWidth, unsigned int *pHeight, unsigned int *required_size, int texformat, unsigned int data_size, u8 *data)
|
||||||
{
|
{
|
||||||
std::string key(fileName);
|
std::string key(fileName);
|
||||||
|
|
||||||
|
|
|
@ -25,7 +25,8 @@
|
||||||
namespace HiresTextures
|
namespace HiresTextures
|
||||||
{
|
{
|
||||||
void Init(const char *gameCode);
|
void Init(const char *gameCode);
|
||||||
PC_TexFormat GetHiresTex(const char *fileName, unsigned int *pWidth, unsigned int *pHeight, int texformat, u8 *data);
|
bool HiresTexExists(const char *filename);
|
||||||
|
PC_TexFormat GetHiresTex(const char *fileName, unsigned int *pWidth, unsigned int *pHeight, unsigned int *required_size, int texformat, unsigned int data_size, u8 *data);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -178,13 +178,39 @@ void TextureCache::ClearRenderTargets()
|
||||||
iter->second->type = TCET_NORMAL;
|
iter->second->type = TCET_NORMAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
PC_TexFormat TextureCache::LoadCustomTexture(u64 tex_hash, int texformat, unsigned int& width, unsigned int& height, u8* dest)
|
bool TextureCache::CheckForCustomTextureLODs(u64 tex_hash, int texformat, unsigned int levels)
|
||||||
|
{
|
||||||
|
// Just checking if the necessary files exist, if they can't be loaded or have incorrect dimensions LODs will be black
|
||||||
|
char texBasePathTemp[MAX_PATH];
|
||||||
|
char texPathTemp[MAX_PATH];
|
||||||
|
|
||||||
|
sprintf(texBasePathTemp, "%s_%08x_%i", SConfig::GetInstance().m_LocalCoreStartupParameter.m_strUniqueID.c_str(), (u32) (tex_hash & 0x00000000FFFFFFFFLL), texformat);
|
||||||
|
|
||||||
|
for (unsigned int level = 1; level < levels; ++level)
|
||||||
|
{
|
||||||
|
sprintf(texPathTemp, "%s_mip%i", texBasePathTemp, level);
|
||||||
|
if (!HiresTextures::HiresTexExists(texPathTemp))
|
||||||
|
{
|
||||||
|
if (level > 1)
|
||||||
|
WARN_LOG(VIDEO, "Couldn't find custom texture LOD with index %i (filename: %s), disabling custom LODs for this texture", level, texPathTemp);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
PC_TexFormat TextureCache::LoadCustomTexture(u64 tex_hash, int texformat, unsigned int level, unsigned int& width, unsigned int& height, u8* dest)
|
||||||
{
|
{
|
||||||
char texPathTemp[MAX_PATH];
|
char texPathTemp[MAX_PATH];
|
||||||
unsigned int newWidth = 0;
|
unsigned int newWidth = 0;
|
||||||
unsigned int newHeight = 0;
|
unsigned int newHeight = 0;
|
||||||
|
|
||||||
sprintf(texPathTemp, "%s_%08x_%i", SConfig::GetInstance().m_LocalCoreStartupParameter.m_strUniqueID.c_str(), (u32) (tex_hash & 0x00000000FFFFFFFFLL), texformat);
|
if (level == 0)
|
||||||
|
sprintf(texPathTemp, "%s_%08x_%i", SConfig::GetInstance().m_LocalCoreStartupParameter.m_strUniqueID.c_str(), (u32) (tex_hash & 0x00000000FFFFFFFFLL), texformat);
|
||||||
|
else
|
||||||
|
sprintf(texPathTemp, "%s_%08x_%i_mip%i", SConfig::GetInstance().m_LocalCoreStartupParameter.m_strUniqueID.c_str(), (u32) (tex_hash & 0x00000000FFFFFFFFLL), texformat, level);
|
||||||
|
|
||||||
PC_TexFormat ret = HiresTextures::GetHiresTex(texPathTemp, &newWidth, &newHeight, texformat, dest);
|
PC_TexFormat ret = HiresTextures::GetHiresTex(texPathTemp, &newWidth, &newHeight, texformat, dest);
|
||||||
|
|
||||||
if (ret != PC_TEX_FMT_NONE)
|
if (ret != PC_TEX_FMT_NONE)
|
||||||
|
@ -215,7 +241,7 @@ void TextureCache::DumpTexture(TCacheEntryBase* entry, unsigned int level)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
sprintf(szTemp, "%s/%s_%08x_%i_mip%d.png", szDir.c_str(),
|
sprintf(szTemp, "%s/%s_%08x_%i_mip%i.png", szDir.c_str(),
|
||||||
SConfig::GetInstance().m_LocalCoreStartupParameter.m_strUniqueID.c_str(),
|
SConfig::GetInstance().m_LocalCoreStartupParameter.m_strUniqueID.c_str(),
|
||||||
(u32) (entry->hash & 0x00000000FFFFFFFFLL), entry->format & 0xFFFF, level);
|
(u32) (entry->hash & 0x00000000FFFFFFFFLL), entry->format & 0xFFFF, level);
|
||||||
}
|
}
|
||||||
|
@ -240,6 +266,9 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int stage,
|
||||||
const unsigned int nativeW = width;
|
const unsigned int nativeW = width;
|
||||||
const unsigned int nativeH = height;
|
const unsigned int nativeH = height;
|
||||||
|
|
||||||
|
bool using_custom_texture = false;
|
||||||
|
bool using_custom_lods = false;
|
||||||
|
|
||||||
u32 texID = address;
|
u32 texID = address;
|
||||||
u64 tex_hash = TEXHASH_INVALID; // Hash assigned to texcache entry (also used to generate filenames used for texture dumping and custom texture lookup)
|
u64 tex_hash = TEXHASH_INVALID; // Hash assigned to texcache entry (also used to generate filenames used for texture dumping and custom texture lookup)
|
||||||
u64 tlut_hash = TEXHASH_INVALID;
|
u64 tlut_hash = TEXHASH_INVALID;
|
||||||
|
@ -321,11 +350,12 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int stage,
|
||||||
|
|
||||||
if (g_ActiveConfig.bHiresTextures)
|
if (g_ActiveConfig.bHiresTextures)
|
||||||
{
|
{
|
||||||
pcfmt = LoadCustomTexture(tex_hash, texformat, width, height, temp);
|
pcfmt = LoadCustomTexture(tex_hash, texformat, 0, width, height, temp);
|
||||||
if (pcfmt != PC_TEX_FMT_NONE)
|
if (pcfmt != PC_TEX_FMT_NONE)
|
||||||
{
|
{
|
||||||
expandedWidth = width;
|
expandedWidth = width;
|
||||||
expandedHeight = height;
|
expandedHeight = height;
|
||||||
|
using_custom_texture = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -336,13 +366,12 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int stage,
|
||||||
|
|
||||||
bool isPow2;
|
bool isPow2;
|
||||||
unsigned int texLevels;
|
unsigned int texLevels;
|
||||||
UseNativeMips = UseNativeMips && (width == nativeW && height == nativeH); // Only load native mips if their dimensions fit to our virtual texture dimensions
|
|
||||||
isPow2 = !((width & (width - 1)) || (height & (height - 1)));
|
isPow2 = !((width & (width - 1)) || (height & (height - 1)));
|
||||||
texLevels = (isPow2 && UseNativeMips && maxlevel) ?
|
texLevels = (isPow2 && maxlevel) ? GetPow2(std::max(width, height)) : !isPow2;
|
||||||
GetPow2(std::max(width, height)) : !isPow2;
|
texLevels = maxlevel ? std::min(texLevels, maxlevel + 1) : texLevels;
|
||||||
|
using_custom_lods = using_custom_texture && CheckForCustomTextureLODs(tex_hash, texformat, texLevels);
|
||||||
if ((texLevels > (maxlevel + 1)) && maxlevel)
|
UseNativeMips = UseNativeMips && !using_custom_lods && (width == nativeW && height == nativeH); // Only load native mips if their dimensions fit to our virtual texture dimensions
|
||||||
texLevels = maxlevel + 1;
|
texLevels = (UseNativeMips || using_custom_lods) ? texLevels : !isPow2;
|
||||||
|
|
||||||
// create the entry/texture
|
// create the entry/texture
|
||||||
if (NULL == entry) {
|
if (NULL == entry) {
|
||||||
|
@ -368,12 +397,11 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int stage,
|
||||||
// load texture
|
// load texture
|
||||||
entry->Load(width, height, expandedWidth, 0, (texLevels == 0));
|
entry->Load(width, height, expandedWidth, 0, (texLevels == 0));
|
||||||
|
|
||||||
// TODO: won't this cause loaded hires textures to be dumped as well?
|
if (g_ActiveConfig.bDumpTextures && !using_custom_texture)
|
||||||
if (g_ActiveConfig.bDumpTextures)
|
|
||||||
DumpTexture(entry, 0);
|
DumpTexture(entry, 0);
|
||||||
|
|
||||||
// load mips - TODO: Loading mipmaps from tmem is untested!
|
// load mips - TODO: Loading mipmaps from tmem is untested!
|
||||||
if (texLevels > 1 && pcfmt != PC_TEX_FMT_NONE)
|
if (texLevels > 1 && pcfmt != PC_TEX_FMT_NONE && UseNativeMips)
|
||||||
{
|
{
|
||||||
const unsigned int bsdepth = TexDecoder_GetTexelSizeInNibbles(texformat);
|
const unsigned int bsdepth = TexDecoder_GetTexelSizeInNibbles(texformat);
|
||||||
|
|
||||||
|
@ -404,7 +432,6 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int stage,
|
||||||
TexDecoder_Decode(temp, *ptr, expandedWidth, expandedHeight, texformat, tlutaddr, tlutfmt, g_ActiveConfig.backend_info.bUseRGBATextures);
|
TexDecoder_Decode(temp, *ptr, expandedWidth, expandedHeight, texformat, tlutaddr, tlutfmt, g_ActiveConfig.backend_info.bUseRGBATextures);
|
||||||
entry->Load(currentWidth, currentHeight, expandedWidth, level, false);
|
entry->Load(currentWidth, currentHeight, expandedWidth, level, false);
|
||||||
|
|
||||||
// TODO: won't this cause loaded hires textures to be dumped as well?
|
|
||||||
if (g_ActiveConfig.bDumpTextures)
|
if (g_ActiveConfig.bDumpTextures)
|
||||||
DumpTexture(entry, level);
|
DumpTexture(entry, level);
|
||||||
|
|
||||||
|
@ -414,6 +441,25 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int stage,
|
||||||
++level;
|
++level;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (texLevels > 1 && pcfmt != PC_TEX_FMT_NONE && using_custom_lods)
|
||||||
|
{
|
||||||
|
unsigned int level = 1;
|
||||||
|
unsigned int mipWidth = (width + 1) >> 1;
|
||||||
|
unsigned int mipHeight = (height + 1) >> 1;
|
||||||
|
|
||||||
|
while ((mipHeight || mipWidth) && (level < texLevels))
|
||||||
|
{
|
||||||
|
unsigned int currentWidth = (mipWidth > 0) ? mipWidth : 1;
|
||||||
|
unsigned int currentHeight = (mipHeight > 0) ? mipHeight : 1;
|
||||||
|
|
||||||
|
LoadCustomTexture(tex_hash, texformat, level, currentWidth, currentHeight, temp);
|
||||||
|
entry->Load(currentWidth, currentHeight, currentWidth, level, false);
|
||||||
|
|
||||||
|
mipWidth >>= 1;
|
||||||
|
mipHeight >>= 1;
|
||||||
|
++level;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
INCSTAT(stats.numTexturesCreated);
|
INCSTAT(stats.numTexturesCreated);
|
||||||
SETSTAT(stats.numTexturesAlive, textures.size());
|
SETSTAT(stats.numTexturesAlive, textures.size());
|
||||||
|
|
|
@ -126,7 +126,8 @@ protected:
|
||||||
static GC_ALIGNED16(u8 *temp);
|
static GC_ALIGNED16(u8 *temp);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static PC_TexFormat LoadCustomTexture(u64 tex_hash, int texformat, unsigned int& width, unsigned int& height, u8* dest);
|
static bool CheckForCustomTextureLODs(u64 tex_hash, int texformat, unsigned int levels);
|
||||||
|
static PC_TexFormat LoadCustomTexture(u64 tex_hash, int texformat, unsigned int level, unsigned int& width, unsigned int& height, u8* dest);
|
||||||
static void DumpTexture(TCacheEntryBase* entry, unsigned int level);
|
static void DumpTexture(TCacheEntryBase* entry, unsigned int level);
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue