TextureCacheBase: Support dumping individual mipmaps.
This commit is contained in:
parent
a8ad59ee3e
commit
a5e68ab10e
|
@ -195,7 +195,7 @@ PC_TexFormat TextureCache::LoadCustomTexture(u64 tex_hash, int texformat, unsign
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextureCache::DumpTexture(TCacheEntryBase* entry)
|
void TextureCache::DumpTexture(TCacheEntryBase* entry, unsigned int level)
|
||||||
{
|
{
|
||||||
char szTemp[MAX_PATH];
|
char szTemp[MAX_PATH];
|
||||||
std::string szDir = File::GetUserPath(D_DUMPTEXTURES_IDX) +
|
std::string szDir = File::GetUserPath(D_DUMPTEXTURES_IDX) +
|
||||||
|
@ -205,12 +205,23 @@ void TextureCache::DumpTexture(TCacheEntryBase* entry)
|
||||||
if (false == File::Exists(szDir) || false == File::IsDirectory(szDir))
|
if (false == File::Exists(szDir) || false == File::IsDirectory(szDir))
|
||||||
File::CreateDir(szDir.c_str());
|
File::CreateDir(szDir.c_str());
|
||||||
|
|
||||||
|
// For compatibility with old texture packs, don't print the LOD index for level 0.
|
||||||
|
// TODO: TLUT format should actually be stored in filename? :/
|
||||||
|
if (level == 0)
|
||||||
|
{
|
||||||
sprintf(szTemp, "%s/%s_%08x_%i.png", szDir.c_str(),
|
sprintf(szTemp, "%s/%s_%08x_%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); // TODO: TLUT format should actually be here as well? :/
|
(u32) (entry->hash & 0x00000000FFFFFFFFLL), entry->format & 0xFFFF);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sprintf(szTemp, "%s/%s_%08x_%i_mip%d.png", szDir.c_str(),
|
||||||
|
SConfig::GetInstance().m_LocalCoreStartupParameter.m_strUniqueID.c_str(),
|
||||||
|
(u32) (entry->hash & 0x00000000FFFFFFFFLL), entry->format & 0xFFFF, level);
|
||||||
|
}
|
||||||
|
|
||||||
if (false == File::Exists(szTemp))
|
if (false == File::Exists(szTemp))
|
||||||
entry->Save(szTemp);
|
entry->Save(szTemp, level);
|
||||||
}
|
}
|
||||||
|
|
||||||
TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int stage,
|
TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int stage,
|
||||||
|
@ -357,6 +368,10 @@ 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)
|
||||||
|
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)
|
||||||
{
|
{
|
||||||
|
@ -389,6 +404,10 @@ 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)
|
||||||
|
DumpTexture(entry, level);
|
||||||
|
|
||||||
*ptr += ((std::max(mipWidth, bsw) * std::max(mipHeight, bsh) * bsdepth) >> 1);
|
*ptr += ((std::max(mipWidth, bsw) * std::max(mipHeight, bsh) * bsdepth) >> 1);
|
||||||
mipWidth >>= 1;
|
mipWidth >>= 1;
|
||||||
mipHeight >>= 1;
|
mipHeight >>= 1;
|
||||||
|
@ -396,10 +415,6 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int stage,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: won't this cause loaded hires textures to be dumped as well?
|
|
||||||
if (g_ActiveConfig.bDumpTextures)
|
|
||||||
DumpTexture(entry);
|
|
||||||
|
|
||||||
INCSTAT(stats.numTexturesCreated);
|
INCSTAT(stats.numTexturesCreated);
|
||||||
SETSTAT(stats.numTexturesAlive, textures.size());
|
SETSTAT(stats.numTexturesAlive, textures.size());
|
||||||
|
|
||||||
|
|
|
@ -84,7 +84,7 @@ public:
|
||||||
virtual ~TCacheEntryBase();
|
virtual ~TCacheEntryBase();
|
||||||
|
|
||||||
virtual void Bind(unsigned int stage) = 0;
|
virtual void Bind(unsigned int stage) = 0;
|
||||||
virtual bool Save(const char filename[]) = 0;
|
virtual bool Save(const char filename[], unsigned int level) = 0;
|
||||||
|
|
||||||
virtual void Load(unsigned int width, unsigned int height,
|
virtual void Load(unsigned int width, unsigned int height,
|
||||||
unsigned int expanded_width, unsigned int level, bool autogen_mips) = 0;
|
unsigned int expanded_width, unsigned int level, bool autogen_mips) = 0;
|
||||||
|
@ -113,7 +113,6 @@ public:
|
||||||
unsigned int expanded_width, unsigned int tex_levels, PC_TexFormat pcfmt) = 0;
|
unsigned int expanded_width, unsigned int tex_levels, PC_TexFormat pcfmt) = 0;
|
||||||
virtual TCacheEntryBase* CreateRenderTargetTexture(unsigned int scaled_tex_w, unsigned int scaled_tex_h) = 0;
|
virtual TCacheEntryBase* CreateRenderTargetTexture(unsigned int scaled_tex_w, unsigned int scaled_tex_h) = 0;
|
||||||
|
|
||||||
|
|
||||||
static TCacheEntryBase* Load(unsigned int stage, u32 address, unsigned int width, unsigned int height,
|
static TCacheEntryBase* Load(unsigned int stage, u32 address, unsigned int width, unsigned int height,
|
||||||
int format, unsigned int tlutaddr, int tlutfmt, bool UseNativeMips, unsigned int maxlevel, bool from_tmem);
|
int format, unsigned int tlutaddr, int tlutfmt, bool UseNativeMips, unsigned int maxlevel, bool from_tmem);
|
||||||
static void CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFormat, unsigned int srcFormat,
|
static void CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFormat, unsigned int srcFormat,
|
||||||
|
@ -128,7 +127,7 @@ protected:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static PC_TexFormat LoadCustomTexture(u64 tex_hash, int texformat, unsigned int& width, unsigned int& height, u8* dest);
|
static PC_TexFormat LoadCustomTexture(u64 tex_hash, int texformat, unsigned int& width, unsigned int& height, u8* dest);
|
||||||
static void DumpTexture(TCacheEntryBase* entry);
|
static void DumpTexture(TCacheEntryBase* entry, unsigned int level);
|
||||||
|
|
||||||
|
|
||||||
typedef std::map<u32, TCacheEntryBase*> TexCache;
|
typedef std::map<u32, TCacheEntryBase*> TexCache;
|
||||||
|
|
|
@ -45,8 +45,16 @@ void TextureCache::TCacheEntry::Bind(unsigned int stage)
|
||||||
D3D::context->PSSetShaderResources(stage, 1, &texture->GetSRV());
|
D3D::context->PSSetShaderResources(stage, 1, &texture->GetSRV());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TextureCache::TCacheEntry::Save(const char filename[])
|
bool TextureCache::TCacheEntry::Save(const char filename[], unsigned int level)
|
||||||
{
|
{
|
||||||
|
// TODO: Somehow implement this (D3DX11 doesn't support dumping individual LODs)
|
||||||
|
static bool warn_once = true;
|
||||||
|
if (level && warn_once)
|
||||||
|
{
|
||||||
|
WARN_LOG(VIDEO, "Dumping individual LOD not supported by D3D11 backend!");
|
||||||
|
warn_once = false;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
return SUCCEEDED(PD3DX11SaveTextureToFileA(D3D::context, texture->GetTex(), D3DX11_IFF_PNG, filename));
|
return SUCCEEDED(PD3DX11SaveTextureToFileA(D3D::context, texture->GetTex(), D3DX11_IFF_PNG, filename));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -49,7 +49,7 @@ private:
|
||||||
const float *colmat);
|
const float *colmat);
|
||||||
|
|
||||||
void Bind(unsigned int stage);
|
void Bind(unsigned int stage);
|
||||||
bool Save(const char filename[]);
|
bool Save(const char filename[], unsigned int level);
|
||||||
};
|
};
|
||||||
|
|
||||||
TCacheEntryBase* CreateTexture(unsigned int width, unsigned int height,
|
TCacheEntryBase* CreateTexture(unsigned int width, unsigned int height,
|
||||||
|
|
|
@ -58,9 +58,17 @@ void TextureCache::TCacheEntry::Bind(unsigned int stage)
|
||||||
D3D::SetTexture(stage, texture);
|
D3D::SetTexture(stage, texture);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TextureCache::TCacheEntry::Save(const char filename[])
|
bool TextureCache::TCacheEntry::Save(const char filename[], unsigned int level)
|
||||||
{
|
{
|
||||||
return SUCCEEDED(PD3DXSaveTextureToFileA(filename, D3DXIFF_PNG, texture, 0));
|
IDirect3DSurface9* surface;
|
||||||
|
HRESULT hr = texture->GetSurfaceLevel(level, &surface);
|
||||||
|
if (FAILED(hr))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
hr = PD3DXSaveSurfaceToFileA(filename, D3DXIFF_PNG, surface, NULL, NULL);
|
||||||
|
surface->Release();
|
||||||
|
|
||||||
|
return SUCCEEDED(hr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextureCache::TCacheEntry::Load(unsigned int width, unsigned int height,
|
void TextureCache::TCacheEntry::Load(unsigned int width, unsigned int height,
|
||||||
|
|
|
@ -52,7 +52,7 @@ private:
|
||||||
const float *colmat);
|
const float *colmat);
|
||||||
|
|
||||||
void Bind(unsigned int stage);
|
void Bind(unsigned int stage);
|
||||||
bool Save(const char filename[]);
|
bool Save(const char filename[], unsigned int level);
|
||||||
};
|
};
|
||||||
|
|
||||||
TCacheEntryBase* CreateTexture(unsigned int width, unsigned int height,
|
TCacheEntryBase* CreateTexture(unsigned int width, unsigned int height,
|
||||||
|
|
|
@ -76,11 +76,13 @@ static const GLint c_WrapSettings[4] = {
|
||||||
GL_REPEAT,
|
GL_REPEAT,
|
||||||
};
|
};
|
||||||
|
|
||||||
bool SaveTexture(const char* filename, u32 textarget, u32 tex, int width, int height)
|
bool SaveTexture(const char* filename, u32 textarget, u32 tex, int virtual_width, int virtual_height, unsigned int level)
|
||||||
{
|
{
|
||||||
|
int width = std::max(virtual_width >> level, 1);
|
||||||
|
int height = std::max(virtual_height >> level, 1);
|
||||||
std::vector<u32> data(width * height);
|
std::vector<u32> data(width * height);
|
||||||
glBindTexture(textarget, tex);
|
glBindTexture(textarget, tex);
|
||||||
glGetTexImage(textarget, 0, GL_BGRA, GL_UNSIGNED_BYTE, &data[0]);
|
glGetTexImage(textarget, level, GL_BGRA, GL_UNSIGNED_BYTE, &data[0]);
|
||||||
|
|
||||||
const GLenum err = GL_REPORT_ERROR();
|
const GLenum err = GL_REPORT_ERROR();
|
||||||
if (GL_NO_ERROR != err)
|
if (GL_NO_ERROR != err)
|
||||||
|
@ -119,13 +121,13 @@ void TextureCache::TCacheEntry::Bind(unsigned int stage)
|
||||||
SetTextureParameters(tm0, tm1);
|
SetTextureParameters(tm0, tm1);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TextureCache::TCacheEntry::Save(const char filename[])
|
bool TextureCache::TCacheEntry::Save(const char filename[], unsigned int level)
|
||||||
{
|
{
|
||||||
// TODO: make ogl dump PNGs
|
// TODO: make ogl dump PNGs
|
||||||
std::string tga_filename(filename);
|
std::string tga_filename(filename);
|
||||||
tga_filename.replace(tga_filename.size() - 3, 3, "tga");
|
tga_filename.replace(tga_filename.size() - 3, 3, "tga");
|
||||||
|
|
||||||
return SaveTexture(tga_filename.c_str(), GL_TEXTURE_2D, texture, virtual_width, virtual_height);
|
return SaveTexture(tga_filename.c_str(), GL_TEXTURE_2D, texture, virtual_width, virtual_height, level);
|
||||||
}
|
}
|
||||||
|
|
||||||
TextureCache::TCacheEntryBase* TextureCache::CreateTexture(unsigned int width,
|
TextureCache::TCacheEntryBase* TextureCache::CreateTexture(unsigned int width,
|
||||||
|
@ -347,7 +349,7 @@ void TextureCache::TCacheEntry::FromRenderTarget(u32 dstAddr, unsigned int dstFo
|
||||||
{
|
{
|
||||||
static int count = 0;
|
static int count = 0;
|
||||||
SaveTexture(StringFromFormat("%sefb_frame_%i.tga", File::GetUserPath(D_DUMPTEXTURES_IDX).c_str(),
|
SaveTexture(StringFromFormat("%sefb_frame_%i.tga", File::GetUserPath(D_DUMPTEXTURES_IDX).c_str(),
|
||||||
count++).c_str(), GL_TEXTURE_2D, texture, virtual_width, virtual_height);
|
count++).c_str(), GL_TEXTURE_2D, texture, virtual_width, virtual_height, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -62,7 +62,7 @@ private:
|
||||||
const float *colmat);
|
const float *colmat);
|
||||||
|
|
||||||
void Bind(unsigned int stage);
|
void Bind(unsigned int stage);
|
||||||
bool Save(const char filename[]);
|
bool Save(const char filename[], unsigned int level);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void SetTextureParameters(const TexMode0 &newmode, const TexMode1 &newmode1);
|
void SetTextureParameters(const TexMode0 &newmode, const TexMode1 &newmode1);
|
||||||
|
@ -76,7 +76,7 @@ private:
|
||||||
TCacheEntryBase* CreateRenderTargetTexture(unsigned int scaled_tex_w, unsigned int scaled_tex_h);
|
TCacheEntryBase* CreateRenderTargetTexture(unsigned int scaled_tex_w, unsigned int scaled_tex_h);
|
||||||
};
|
};
|
||||||
|
|
||||||
bool SaveTexture(const char* filename, u32 textarget, u32 tex, int width, int height);
|
bool SaveTexture(const char* filename, u32 textarget, u32 tex, int virtual_width, int virtual_height, unsigned int level);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -163,13 +163,14 @@ void VertexManager::vFlush()
|
||||||
// 0s are probably for no manual wrapping needed.
|
// 0s are probably for no manual wrapping needed.
|
||||||
PixelShaderManager::SetTexDims(i, tentry->native_width, tentry->native_height, 0, 0);
|
PixelShaderManager::SetTexDims(i, tentry->native_width, tentry->native_height, 0, 0);
|
||||||
|
|
||||||
|
// TODO: Dump this code, it's redundant.
|
||||||
if (g_ActiveConfig.iLog & CONF_SAVETEXTURES)
|
if (g_ActiveConfig.iLog & CONF_SAVETEXTURES)
|
||||||
{
|
{
|
||||||
// save the textures
|
// save the textures
|
||||||
char strfile[255];
|
char strfile[255];
|
||||||
sprintf(strfile, "%stex%.3d_%d.tga",
|
sprintf(strfile, "%stex%.3d_%d.tga",
|
||||||
File::GetUserPath(D_DUMPFRAMES_IDX).c_str(), g_Config.iSaveTargetId, i);
|
File::GetUserPath(D_DUMPFRAMES_IDX).c_str(), g_Config.iSaveTargetId, i);
|
||||||
tentry->Save(strfile);
|
tentry->Save(strfile, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
Loading…
Reference in New Issue