VideoCommon: rewrite custom textures
This commit is contained in:
parent
a09d854636
commit
51bfc4c52a
|
@ -13,14 +13,14 @@
|
||||||
#include "Common/FileUtil.h"
|
#include "Common/FileUtil.h"
|
||||||
#include "Common/StringUtil.h"
|
#include "Common/StringUtil.h"
|
||||||
|
|
||||||
|
#include "Core/ConfigManager.h"
|
||||||
|
|
||||||
#include "VideoCommon/HiresTextures.h"
|
#include "VideoCommon/HiresTextures.h"
|
||||||
|
#include "VideoCommon/VideoConfig.h"
|
||||||
|
|
||||||
namespace HiresTextures
|
std::unordered_map<std::string, std::string> HiresTexture::textureMap;
|
||||||
{
|
|
||||||
|
|
||||||
static std::map<std::string, std::string> textureMap;
|
void HiresTexture::Init(const std::string& gameCode)
|
||||||
|
|
||||||
void Init(const std::string& gameCode)
|
|
||||||
{
|
{
|
||||||
textureMap.clear();
|
textureMap.clear();
|
||||||
|
|
||||||
|
@ -80,85 +80,87 @@ void Init(const std::string& gameCode)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool HiresTexExists(const std::string& filename)
|
HiresTexture* HiresTexture::Search(const u8* texture, size_t texture_size, const u8* tlut, size_t tlut_size, u32 width, u32 height, int format)
|
||||||
{
|
{
|
||||||
return textureMap.find(filename) != textureMap.end();
|
u64 tex_hash = GetHashHiresTexture(texture, (int)texture_size, g_ActiveConfig.iSafeTextureCache_ColorSamples);
|
||||||
|
u64 tlut_hash = 0;
|
||||||
|
u64 hash = tex_hash;
|
||||||
|
if (tlut_size)
|
||||||
|
{
|
||||||
|
tlut_hash = GetHashHiresTexture(tlut, (int)tlut_size, g_ActiveConfig.iSafeTextureCache_ColorSamples);
|
||||||
|
hash ^= tlut_hash;
|
||||||
}
|
}
|
||||||
|
|
||||||
PC_TexFormat GetHiresTex(const std::string& filename, unsigned int* pWidth, unsigned int* pHeight, unsigned int* required_size, int texformat, unsigned int data_size, u8* data)
|
HiresTexture* ret = nullptr;
|
||||||
|
std::string base_filename = StringFromFormat("%s_%08x_%i", SConfig::GetInstance().m_LocalCoreStartupParameter.m_strUniqueID.c_str(), (u32)hash, format);
|
||||||
|
for (int level = 0;; level++)
|
||||||
{
|
{
|
||||||
if (textureMap.find(filename) == textureMap.end())
|
std::string filename = base_filename;
|
||||||
return PC_TEX_FMT_NONE;
|
if (level)
|
||||||
|
{
|
||||||
|
filename += StringFromFormat("_mip%u", level);
|
||||||
|
}
|
||||||
|
|
||||||
int width;
|
if (textureMap.find(filename) != textureMap.end())
|
||||||
int height;
|
{
|
||||||
int channels;
|
Level l;
|
||||||
|
|
||||||
File::IOFile file;
|
File::IOFile file;
|
||||||
file.Open(textureMap[filename], "rb");
|
file.Open(textureMap[filename], "rb");
|
||||||
std::vector<u8> buffer(file.GetSize());
|
std::vector<u8> buffer(file.GetSize());
|
||||||
file.ReadBytes(buffer.data(), file.GetSize());
|
file.ReadBytes(buffer.data(), file.GetSize());
|
||||||
|
|
||||||
u8* temp = SOIL_load_image_from_memory(buffer.data(), (int)buffer.size(), &width, &height, &channels, SOIL_LOAD_RGBA);
|
int channels;
|
||||||
|
l.data = SOIL_load_image_from_memory(buffer.data(), (int)buffer.size(), (int*)&l.width, (int*)&l.height, &channels, SOIL_LOAD_RGBA);
|
||||||
|
l.data_size = (size_t)l.width * l.height * 4;
|
||||||
|
|
||||||
if (temp == nullptr)
|
if (l.data == nullptr)
|
||||||
{
|
{
|
||||||
ERROR_LOG(VIDEO, "Custom texture %s failed to load", textureMap[filename].c_str());
|
ERROR_LOG(VIDEO, "Custom texture %s failed to load", filename.c_str());
|
||||||
return PC_TEX_FMT_NONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
*pWidth = width;
|
|
||||||
*pHeight = height;
|
|
||||||
|
|
||||||
//int offset = 0;
|
|
||||||
PC_TexFormat returnTex = PC_TEX_FMT_NONE;
|
|
||||||
|
|
||||||
// TODO(neobrain): This function currently has no way to enforce RGBA32
|
|
||||||
// output, which however is required on some configurations to function
|
|
||||||
// properly. As a lazy workaround, we hence disable the optimized code
|
|
||||||
// path for now.
|
|
||||||
#if 0
|
|
||||||
switch (texformat)
|
|
||||||
{
|
|
||||||
case GX_TF_I4:
|
|
||||||
case GX_TF_I8:
|
|
||||||
case GX_TF_IA4:
|
|
||||||
case GX_TF_IA8:
|
|
||||||
*required_size = width * height * 8;
|
|
||||||
if (data_size < *required_size)
|
|
||||||
goto cleanup;
|
|
||||||
|
|
||||||
for (int i = 0; i < width * height * 4; i += 4)
|
|
||||||
{
|
|
||||||
// Rather than use a luminosity function, just use the most intense color for luminance
|
|
||||||
// TODO(neobrain): Isn't this kind of.. stupid?
|
|
||||||
data[offset++] = *std::max_element(temp+i, temp+i+3);
|
|
||||||
data[offset++] = temp[i+3];
|
|
||||||
}
|
|
||||||
returnTex = PC_TEX_FMT_IA8;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
*required_size = width * height * 4;
|
|
||||||
if (data_size < *required_size)
|
|
||||||
goto cleanup;
|
|
||||||
|
|
||||||
memcpy(data, temp, width * height * 4);
|
|
||||||
returnTex = PC_TEX_FMT_RGBA32;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
*required_size = width * height * 4;
|
|
||||||
if (data_size < *required_size)
|
|
||||||
goto cleanup;
|
|
||||||
|
|
||||||
memcpy(data, temp, width * height * 4);
|
if (!level)
|
||||||
returnTex = PC_TEX_FMT_RGBA32;
|
{
|
||||||
#endif
|
if (l.width * height != l.height * width)
|
||||||
|
ERROR_LOG(VIDEO, "Invalid custom texture size %dx%d for texture %s. The aspect differs from the native size %dx%d.",
|
||||||
INFO_LOG(VIDEO, "Loading custom texture from %s", textureMap[filename].c_str());
|
l.width, l.height, filename.c_str(), width, height);
|
||||||
cleanup:
|
if (l.width % width || l.height % height)
|
||||||
SOIL_free_image_data(temp);
|
WARN_LOG(VIDEO, "Invalid custom texture size %dx%d for texture %s. Please use an integer upscaling factor based on the native size %dx%d.",
|
||||||
return returnTex;
|
l.width, l.height, filename.c_str(), width, height);
|
||||||
|
width = l.width;
|
||||||
|
height = l.height;
|
||||||
|
}
|
||||||
|
else if (width != l.width || height != l.height)
|
||||||
|
{
|
||||||
|
ERROR_LOG(VIDEO, "Invalid custom texture size %dx%d for texture %s. This mipmap layer _must_ be %dx%d.",
|
||||||
|
l.width, l.height, filename.c_str(), width, height);
|
||||||
|
SOIL_free_image_data(l.data);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// calculate the size of the next mipmap
|
||||||
|
width >>= 1;
|
||||||
|
height >>= 1;
|
||||||
|
|
||||||
|
if (!ret)
|
||||||
|
ret = new HiresTexture();
|
||||||
|
ret->m_levels.push_back(l);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
HiresTexture::~HiresTexture()
|
||||||
|
{
|
||||||
|
for (auto& l : m_levels)
|
||||||
|
{
|
||||||
|
SOIL_free_image_data(l.data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,15 +4,36 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <map>
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <unordered_map>
|
||||||
#include "VideoCommon/TextureDecoder.h"
|
#include "VideoCommon/TextureDecoder.h"
|
||||||
#include "VideoCommon/VideoCommon.h"
|
#include "VideoCommon/VideoCommon.h"
|
||||||
|
|
||||||
namespace HiresTextures
|
class HiresTexture
|
||||||
{
|
{
|
||||||
void Init(const std::string& gameCode);
|
public:
|
||||||
bool HiresTexExists(const std::string& filename);
|
static void Init(const std::string& gameCode);
|
||||||
PC_TexFormat GetHiresTex(const std::string& fileName, unsigned int* pWidth, unsigned int* pHeight, unsigned int* required_size, int texformat, unsigned int data_size, u8* data);
|
|
||||||
|
|
||||||
}
|
static HiresTexture* Search(
|
||||||
|
const u8* texture, size_t texture_size,
|
||||||
|
const u8* tlut, size_t tlut_size,
|
||||||
|
u32 width, u32 height,
|
||||||
|
int format
|
||||||
|
);
|
||||||
|
|
||||||
|
~HiresTexture();
|
||||||
|
|
||||||
|
struct Level
|
||||||
|
{
|
||||||
|
u8* data;
|
||||||
|
size_t data_size;
|
||||||
|
u32 width, height;
|
||||||
|
};
|
||||||
|
std::vector<Level> m_levels;
|
||||||
|
|
||||||
|
static std::unordered_map<std::string, std::string> textureMap;
|
||||||
|
|
||||||
|
private:
|
||||||
|
HiresTexture() {}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
|
@ -28,7 +28,7 @@ enum
|
||||||
TextureCache *g_texture_cache;
|
TextureCache *g_texture_cache;
|
||||||
|
|
||||||
GC_ALIGNED16(u8 *TextureCache::temp) = nullptr;
|
GC_ALIGNED16(u8 *TextureCache::temp) = nullptr;
|
||||||
unsigned int TextureCache::temp_size;
|
size_t TextureCache::temp_size;
|
||||||
|
|
||||||
TextureCache::TexCache TextureCache::textures;
|
TextureCache::TexCache TextureCache::textures;
|
||||||
TextureCache::RenderTargetPool TextureCache::render_target_pool;
|
TextureCache::RenderTargetPool TextureCache::render_target_pool;
|
||||||
|
@ -41,6 +41,16 @@ TextureCache::TCacheEntryBase::~TCacheEntryBase()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TextureCache::CheckTempSize(size_t required_size)
|
||||||
|
{
|
||||||
|
if (required_size <= temp_size)
|
||||||
|
return;
|
||||||
|
|
||||||
|
temp_size = required_size;
|
||||||
|
FreeAlignedMemory(temp);
|
||||||
|
temp = (u8*)AllocateAlignedMemory(temp_size, 16);
|
||||||
|
}
|
||||||
|
|
||||||
TextureCache::TextureCache()
|
TextureCache::TextureCache()
|
||||||
{
|
{
|
||||||
temp_size = 2048 * 2048 * 4;
|
temp_size = 2048 * 2048 * 4;
|
||||||
|
@ -50,7 +60,7 @@ TextureCache::TextureCache()
|
||||||
TexDecoder_SetTexFmtOverlayOptions(g_ActiveConfig.bTexFmtOverlayEnable, g_ActiveConfig.bTexFmtOverlayCenter);
|
TexDecoder_SetTexFmtOverlayOptions(g_ActiveConfig.bTexFmtOverlayEnable, g_ActiveConfig.bTexFmtOverlayCenter);
|
||||||
|
|
||||||
if (g_ActiveConfig.bHiresTextures && !g_ActiveConfig.bDumpTextures)
|
if (g_ActiveConfig.bHiresTextures && !g_ActiveConfig.bDumpTextures)
|
||||||
HiresTextures::Init(SConfig::GetInstance().m_LocalCoreStartupParameter.m_strUniqueID);
|
HiresTexture::Init(SConfig::GetInstance().m_LocalCoreStartupParameter.m_strUniqueID);
|
||||||
|
|
||||||
SetHash64Function(g_ActiveConfig.bHiresTextures || g_ActiveConfig.bDumpTextures);
|
SetHash64Function(g_ActiveConfig.bHiresTextures || g_ActiveConfig.bDumpTextures);
|
||||||
|
|
||||||
|
@ -98,7 +108,7 @@ void TextureCache::OnConfigChanged(VideoConfig& config)
|
||||||
g_texture_cache->Invalidate();
|
g_texture_cache->Invalidate();
|
||||||
|
|
||||||
if (g_ActiveConfig.bHiresTextures)
|
if (g_ActiveConfig.bHiresTextures)
|
||||||
HiresTextures::Init(SConfig::GetInstance().m_LocalCoreStartupParameter.m_strUniqueID);
|
HiresTexture::Init(SConfig::GetInstance().m_LocalCoreStartupParameter.m_strUniqueID);
|
||||||
|
|
||||||
SetHash64Function(g_ActiveConfig.bHiresTextures || g_ActiveConfig.bDumpTextures);
|
SetHash64Function(g_ActiveConfig.bHiresTextures || g_ActiveConfig.bDumpTextures);
|
||||||
TexDecoder_SetTexFmtOverlayOptions(g_ActiveConfig.bTexFmtOverlayEnable, g_ActiveConfig.bTexFmtOverlayCenter);
|
TexDecoder_SetTexFmtOverlayOptions(g_ActiveConfig.bTexFmtOverlayEnable, g_ActiveConfig.bTexFmtOverlayCenter);
|
||||||
|
@ -253,69 +263,6 @@ void TextureCache::ClearRenderTargets()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TextureCache::CheckForCustomTextureLODs(u64 tex_hash, int texformat, unsigned int levels)
|
|
||||||
{
|
|
||||||
if (levels == 1)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// Just checking if the necessary files exist, if they can't be loaded or have incorrect dimensions LODs will be black
|
|
||||||
std::string texBasePathTemp = StringFromFormat("%s_%08x_%i", SConfig::GetInstance().m_LocalCoreStartupParameter.m_strUniqueID.c_str(), (u32) (tex_hash & 0x00000000FFFFFFFFLL), texformat);
|
|
||||||
|
|
||||||
for (unsigned int level = 1; level < levels; ++level)
|
|
||||||
{
|
|
||||||
std::string texPathTemp = StringFromFormat("%s_mip%u", texBasePathTemp.c_str(), level);
|
|
||||||
if (!HiresTextures::HiresTexExists(texPathTemp))
|
|
||||||
{
|
|
||||||
if (level > 1)
|
|
||||||
WARN_LOG(VIDEO, "Couldn't find custom texture LOD with index %u (filename: %s), disabling custom LODs for this texture", level, texPathTemp.c_str());
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
PC_TexFormat TextureCache::LoadCustomTexture(u64 tex_hash, int texformat, unsigned int level, unsigned int* widthp, unsigned int* heightp)
|
|
||||||
{
|
|
||||||
std::string texPathTemp;
|
|
||||||
unsigned int newWidth = 0;
|
|
||||||
unsigned int newHeight = 0;
|
|
||||||
u32 tex_hash_u32 = tex_hash & 0x00000000FFFFFFFFLL;
|
|
||||||
|
|
||||||
if (level == 0)
|
|
||||||
texPathTemp = StringFromFormat("%s_%08x_%i", SConfig::GetInstance().m_LocalCoreStartupParameter.m_strUniqueID.c_str(), tex_hash_u32, texformat);
|
|
||||||
else
|
|
||||||
texPathTemp = StringFromFormat("%s_%08x_%i_mip%u", SConfig::GetInstance().m_LocalCoreStartupParameter.m_strUniqueID.c_str(), tex_hash_u32, texformat, level);
|
|
||||||
|
|
||||||
unsigned int required_size = 0;
|
|
||||||
PC_TexFormat ret = HiresTextures::GetHiresTex(texPathTemp, &newWidth, &newHeight, &required_size, texformat, temp_size, temp);
|
|
||||||
if (ret == PC_TEX_FMT_NONE && temp_size < required_size)
|
|
||||||
{
|
|
||||||
// Allocate more memory and try again
|
|
||||||
// TODO: Should probably check if newWidth and newHeight are texture dimensions which are actually supported by the current video backend
|
|
||||||
temp_size = required_size;
|
|
||||||
FreeAlignedMemory(temp);
|
|
||||||
temp = (u8*)AllocateAlignedMemory(temp_size, 16);
|
|
||||||
ret = HiresTextures::GetHiresTex(texPathTemp, &newWidth, &newHeight, &required_size, texformat, temp_size, temp);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ret != PC_TEX_FMT_NONE)
|
|
||||||
{
|
|
||||||
unsigned int width = *widthp, height = *heightp;
|
|
||||||
if (level > 0 && (newWidth != width || newHeight != height))
|
|
||||||
ERROR_LOG(VIDEO, "Invalid custom texture size %dx%d for texture %s. This mipmap layer _must_ be %dx%d.", newWidth, newHeight, texPathTemp.c_str(), width, height);
|
|
||||||
if (newWidth * height != newHeight * width)
|
|
||||||
ERROR_LOG(VIDEO, "Invalid custom texture size %dx%d for texture %s. The aspect differs from the native size %dx%d.", newWidth, newHeight, texPathTemp.c_str(), width, height);
|
|
||||||
if (newWidth % width || newHeight % height)
|
|
||||||
WARN_LOG(VIDEO, "Invalid custom texture size %dx%d for texture %s. Please use an integer upscaling factor based on the native size %dx%d.", newWidth, newHeight, texPathTemp.c_str(), width, height);
|
|
||||||
|
|
||||||
*widthp = newWidth;
|
|
||||||
*heightp = newHeight;
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
void TextureCache::DumpTexture(TCacheEntryBase* entry, unsigned int level)
|
void TextureCache::DumpTexture(TCacheEntryBase* entry, unsigned int level)
|
||||||
{
|
{
|
||||||
std::string filename;
|
std::string filename;
|
||||||
|
@ -399,9 +346,10 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int const stage,
|
||||||
|
|
||||||
// TODO: This doesn't hash GB tiles for preloaded RGBA8 textures (instead, it's hashing more data from the low tmem bank than it should)
|
// TODO: This doesn't hash GB tiles for preloaded RGBA8 textures (instead, it's hashing more data from the low tmem bank than it should)
|
||||||
tex_hash = GetHash64(src_data, texture_size, g_ActiveConfig.iSafeTextureCache_ColorSamples);
|
tex_hash = GetHash64(src_data, texture_size, g_ActiveConfig.iSafeTextureCache_ColorSamples);
|
||||||
|
u32 palette_size = 0;
|
||||||
if (isPaletteTexture)
|
if (isPaletteTexture)
|
||||||
{
|
{
|
||||||
const u32 palette_size = TexDecoder_GetPaletteSize(texformat);
|
palette_size = TexDecoder_GetPaletteSize(texformat);
|
||||||
tlut_hash = GetHash64(&texMem[tlutaddr], palette_size, g_ActiveConfig.iSafeTextureCache_ColorSamples);
|
tlut_hash = GetHash64(&texMem[tlutaddr], palette_size, g_ActiveConfig.iSafeTextureCache_ColorSamples);
|
||||||
|
|
||||||
// NOTE: For non-paletted textures, texID is equal to the texture address.
|
// NOTE: For non-paletted textures, texID is equal to the texture address.
|
||||||
|
@ -473,17 +421,23 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int const stage,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool using_custom_texture = false;
|
std::unique_ptr<HiresTexture> hires_tex;
|
||||||
|
|
||||||
if (g_ActiveConfig.bHiresTextures)
|
if (g_ActiveConfig.bHiresTextures)
|
||||||
{
|
{
|
||||||
pcfmt = LoadCustomTexture(tex_hash, texformat, 0, &width, &height);
|
hires_tex.reset(HiresTexture::Search(
|
||||||
if (pcfmt != PC_TEX_FMT_NONE)
|
src_data, texture_size,
|
||||||
|
&texMem[tlutaddr], palette_size,
|
||||||
|
width, height,
|
||||||
|
texformat
|
||||||
|
));
|
||||||
|
|
||||||
|
if (hires_tex)
|
||||||
{
|
{
|
||||||
if (expandedWidth != width || expandedHeight != height)
|
auto& l = hires_tex->m_levels[0];
|
||||||
|
if (l.width != width || l.height != height)
|
||||||
{
|
{
|
||||||
expandedWidth = width;
|
width = l.width;
|
||||||
expandedHeight = height;
|
height = l.height;
|
||||||
|
|
||||||
// If we thought we could reuse the texture before, make sure to pool it now!
|
// If we thought we could reuse the texture before, make sure to pool it now!
|
||||||
if (entry)
|
if (entry)
|
||||||
|
@ -492,11 +446,15 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int const stage,
|
||||||
entry = nullptr;
|
entry = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
using_custom_texture = true;
|
expandedWidth = l.width;
|
||||||
|
expandedHeight = l.height;
|
||||||
|
CheckTempSize(l.data_size);
|
||||||
|
memcpy(temp, l.data, l.data_size);
|
||||||
|
pcfmt = PC_TEX_FMT_RGBA32;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!using_custom_texture)
|
if (!hires_tex)
|
||||||
{
|
{
|
||||||
if (!(texformat == GX_TF_RGBA8 && from_tmem))
|
if (!(texformat == GX_TF_RGBA8 && from_tmem))
|
||||||
{
|
{
|
||||||
|
@ -511,7 +469,7 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int const stage,
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 texLevels = use_mipmaps ? (maxlevel + 1) : 1;
|
u32 texLevels = use_mipmaps ? (maxlevel + 1) : 1;
|
||||||
const bool using_custom_lods = using_custom_texture && CheckForCustomTextureLODs(tex_hash, texformat, texLevels);
|
const bool using_custom_lods = hires_tex && hires_tex->m_levels.size() >= texLevels;
|
||||||
// Only load native mips if their dimensions fit to our virtual texture dimensions
|
// Only load native mips if their dimensions fit to our virtual texture dimensions
|
||||||
const bool use_native_mips = use_mipmaps && !using_custom_lods && (width == nativeW && height == nativeH);
|
const bool use_native_mips = use_mipmaps && !using_custom_lods && (width == nativeW && height == nativeH);
|
||||||
texLevels = (use_native_mips || using_custom_lods) ? texLevels : 1; // TODO: Should be forced to 1 for non-pow2 textures (e.g. efb copies with automatically adjusted IR)
|
texLevels = (use_native_mips || using_custom_lods) ? texLevels : 1; // TODO: Should be forced to 1 for non-pow2 textures (e.g. efb copies with automatically adjusted IR)
|
||||||
|
@ -549,7 +507,7 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int const stage,
|
||||||
else
|
else
|
||||||
entry->type = TCET_NORMAL;
|
entry->type = TCET_NORMAL;
|
||||||
|
|
||||||
if (g_ActiveConfig.bDumpTextures && !using_custom_texture)
|
if (g_ActiveConfig.bDumpTextures && !hires_tex)
|
||||||
DumpTexture(entry, 0);
|
DumpTexture(entry, 0);
|
||||||
|
|
||||||
u32 level = 1;
|
u32 level = 1;
|
||||||
|
@ -592,11 +550,10 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int const stage,
|
||||||
{
|
{
|
||||||
for (; level != texLevels; ++level)
|
for (; level != texLevels; ++level)
|
||||||
{
|
{
|
||||||
unsigned int mip_width = CalculateLevelSize(width, level);
|
auto& l = hires_tex->m_levels[level];
|
||||||
unsigned int mip_height = CalculateLevelSize(height, level);
|
CheckTempSize(l.data_size);
|
||||||
|
memcpy(temp, l.data, l.data_size);
|
||||||
LoadCustomTexture(tex_hash, texformat, level, &mip_width, &mip_height);
|
entry->Load(l.width, l.height, l.width, level);
|
||||||
entry->Load(mip_width, mip_height, mip_width, level);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -117,12 +117,11 @@ protected:
|
||||||
TextureCache();
|
TextureCache();
|
||||||
|
|
||||||
static GC_ALIGNED16(u8 *temp);
|
static GC_ALIGNED16(u8 *temp);
|
||||||
static unsigned int temp_size;
|
static size_t temp_size;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
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);
|
|
||||||
static void DumpTexture(TCacheEntryBase* entry, unsigned int level);
|
static void DumpTexture(TCacheEntryBase* entry, unsigned int level);
|
||||||
|
static void CheckTempSize(size_t required_size);
|
||||||
|
|
||||||
static TCacheEntryBase* AllocateRenderTarget(unsigned int width, unsigned int height);
|
static TCacheEntryBase* AllocateRenderTarget(unsigned int width, unsigned int height);
|
||||||
static void FreeRenderTarget(TCacheEntryBase* entry);
|
static void FreeRenderTarget(TCacheEntryBase* entry);
|
||||||
|
|
Loading…
Reference in New Issue