From 34692ab826abc8f8faa61bdb2280b742424528f1 Mon Sep 17 00:00:00 2001 From: "Jasper St. Pierre" Date: Sat, 7 Dec 2013 15:14:29 -0500 Subject: Remove unnecessary Src/ folders --- Source/Core/VideoCommon/TextureCacheBase.cpp | 881 +++++++++++++++++++++++++++ 1 file changed, 881 insertions(+) create mode 100644 Source/Core/VideoCommon/TextureCacheBase.cpp (limited to 'Source/Core/VideoCommon/TextureCacheBase.cpp') diff --git a/Source/Core/VideoCommon/TextureCacheBase.cpp b/Source/Core/VideoCommon/TextureCacheBase.cpp new file mode 100644 index 0000000000..8555bd736d --- /dev/null +++ b/Source/Core/VideoCommon/TextureCacheBase.cpp @@ -0,0 +1,881 @@ +// Copyright 2013 Dolphin Emulator Project +// Licensed under GPLv2 +// Refer to the license.txt file included. + +#include "MemoryUtil.h" + +#include "VideoConfig.h" +#include "Statistics.h" +#include "HiresTextures.h" +#include "RenderBase.h" +#include "FileUtil.h" + +#include "TextureCacheBase.h" +#include "Debugger.h" +#include "ConfigManager.h" +#include "HW/Memmap.h" + +// ugly +extern int frameCount; + +enum +{ + TEXTURE_KILL_THRESHOLD = 200, +}; + +TextureCache *g_texture_cache; + +GC_ALIGNED16(u8 *TextureCache::temp) = NULL; +unsigned int TextureCache::temp_size; + +TextureCache::TexCache TextureCache::textures; + +TextureCache::BackupConfig TextureCache::backup_config; + +bool invalidate_texture_cache_requested; + +TextureCache::TCacheEntryBase::~TCacheEntryBase() +{ +} + +TextureCache::TextureCache() +{ + temp_size = 2048 * 2048 * 4; + if (!temp) + temp = (u8*)AllocateAlignedMemory(temp_size, 16); + + TexDecoder_SetTexFmtOverlayOptions(g_ActiveConfig.bTexFmtOverlayEnable, g_ActiveConfig.bTexFmtOverlayCenter); + + if(g_ActiveConfig.bHiresTextures && !g_ActiveConfig.bDumpTextures) + HiresTextures::Init(SConfig::GetInstance().m_LocalCoreStartupParameter.m_strUniqueID.c_str()); + + SetHash64Function(g_ActiveConfig.bHiresTextures || g_ActiveConfig.bDumpTextures); + + invalidate_texture_cache_requested = false; +} + +void TextureCache::RequestInvalidateTextureCache() +{ + invalidate_texture_cache_requested = true; +} + +void TextureCache::Invalidate() +{ + TexCache::iterator + iter = textures.begin(), + tcend = textures.end(); + for (; iter != tcend; ++iter) + delete iter->second; + + textures.clear(); +} + +TextureCache::~TextureCache() +{ + Invalidate(); + if (temp) + { + FreeAlignedMemory(temp); + temp = NULL; + } +} + +void TextureCache::OnConfigChanged(VideoConfig& config) +{ + if (g_texture_cache) + { + // TODO: Invalidating texcache is really stupid in some of these cases + if (config.iSafeTextureCache_ColorSamples != backup_config.s_colorsamples || + config.bTexFmtOverlayEnable != backup_config.s_texfmt_overlay || + config.bTexFmtOverlayCenter != backup_config.s_texfmt_overlay_center || + config.bHiresTextures != backup_config.s_hires_textures || + invalidate_texture_cache_requested) + { + g_texture_cache->Invalidate(); + + if(g_ActiveConfig.bHiresTextures) + HiresTextures::Init(SConfig::GetInstance().m_LocalCoreStartupParameter.m_strUniqueID.c_str()); + + SetHash64Function(g_ActiveConfig.bHiresTextures || g_ActiveConfig.bDumpTextures); + TexDecoder_SetTexFmtOverlayOptions(g_ActiveConfig.bTexFmtOverlayEnable, g_ActiveConfig.bTexFmtOverlayCenter); + + invalidate_texture_cache_requested = false; + } + + // TODO: Probably shouldn't clear all render targets here, just mark them dirty or something. + if (config.bEFBCopyCacheEnable != backup_config.s_copy_cache_enable || // TODO: not sure if this is needed? + config.bCopyEFBToTexture != backup_config.s_copy_efb_to_texture || + config.bCopyEFBScaled != backup_config.s_copy_efb_scaled || + config.bEFBCopyEnable != backup_config.s_copy_efb || + config.iEFBScale != backup_config.s_efb_scale) + { + g_texture_cache->ClearRenderTargets(); + } + } + + backup_config.s_colorsamples = config.iSafeTextureCache_ColorSamples; + backup_config.s_copy_efb_to_texture = config.bCopyEFBToTexture; + backup_config.s_copy_efb_scaled = config.bCopyEFBScaled; + backup_config.s_copy_efb = config.bEFBCopyEnable; + backup_config.s_efb_scale = config.iEFBScale; + backup_config.s_texfmt_overlay = config.bTexFmtOverlayEnable; + backup_config.s_texfmt_overlay_center = config.bTexFmtOverlayCenter; + backup_config.s_hires_textures = config.bHiresTextures; + backup_config.s_copy_cache_enable = config.bEFBCopyCacheEnable; +} + +void TextureCache::Cleanup() +{ + TexCache::iterator iter = textures.begin(); + TexCache::iterator tcend = textures.end(); + while (iter != tcend) + { + if ( frameCount > TEXTURE_KILL_THRESHOLD + iter->second->frameCount + + // EFB copies living on the host GPU are unrecoverable and thus shouldn't be deleted + && ! iter->second->IsEfbCopy() ) + { + delete iter->second; + textures.erase(iter++); + } + else + { + ++iter; + } + } +} + +void TextureCache::InvalidateRange(u32 start_address, u32 size) +{ + TexCache::iterator + iter = textures.begin(), + tcend = textures.end(); + while (iter != tcend) + { + const int rangePosition = iter->second->IntersectsMemoryRange(start_address, size); + if (0 == rangePosition) + { + delete iter->second; + textures.erase(iter++); + } + else + { + ++iter; + } + } +} + +void TextureCache::MakeRangeDynamic(u32 start_address, u32 size) +{ + TexCache::iterator + iter = textures.lower_bound(start_address), + tcend = textures.upper_bound(start_address + size); + + if (iter != textures.begin()) + iter--; + + for (; iter != tcend; ++iter) + { + const int rangePosition = iter->second->IntersectsMemoryRange(start_address, size); + if (0 == rangePosition) + { + iter->second->SetHashes(TEXHASH_INVALID); + } + } +} + +bool TextureCache::Find(u32 start_address, u64 hash) +{ + TexCache::iterator iter = textures.lower_bound(start_address); + + if (iter->second->hash == hash) + return true; + + return false; +} + +int TextureCache::TCacheEntryBase::IntersectsMemoryRange(u32 range_address, u32 range_size) const +{ + if (addr + size_in_bytes < range_address) + return -1; + + if (addr >= range_address + range_size) + return 1; + + return 0; +} + +void TextureCache::ClearRenderTargets() +{ + TexCache::iterator + iter = textures.begin(), + tcend = textures.end(); + + while (iter != tcend) + { + if (iter->second->type == TCET_EC_VRAM) + { + delete iter->second; + textures.erase(iter++); + } + else + { + ++iter; + } + } +} + +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 + 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) +{ + char texPathTemp[MAX_PATH]; + unsigned int newWidth = 0; + unsigned int newHeight = 0; + + 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); + + 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) + { + width = newWidth; + height = newHeight; + } + return ret; +} + +void TextureCache::DumpTexture(TCacheEntryBase* entry, unsigned int level) +{ + std::string filename; + std::string szDir = File::GetUserPath(D_DUMPTEXTURES_IDX) + + SConfig::GetInstance().m_LocalCoreStartupParameter.m_strUniqueID; + + // make sure that the directory exists + if (false == File::Exists(szDir) || false == File::IsDirectory(szDir)) + 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) + { + filename = StringFromFormat("%s/%s_%08x_%i.png", szDir.c_str(), + SConfig::GetInstance().m_LocalCoreStartupParameter.m_strUniqueID.c_str(), + (u32)(entry->hash & 0x00000000FFFFFFFFLL), entry->format & 0xFFFF); + } + else + { + filename = StringFromFormat("%s/%s_%08x_%i_mip%i.png", szDir.c_str(), + SConfig::GetInstance().m_LocalCoreStartupParameter.m_strUniqueID.c_str(), + (u32) (entry->hash & 0x00000000FFFFFFFFLL), entry->format & 0xFFFF, level); + } + + if (!File::Exists(filename)) + entry->Save(filename, level); +} + +static u32 CalculateLevelSize(u32 level_0_size, u32 level) +{ + return (level_0_size + ((1 << level) - 1)) >> level; +} + +// Used by TextureCache::Load +static TextureCache::TCacheEntryBase* ReturnEntry(unsigned int stage, TextureCache::TCacheEntryBase* entry) +{ + entry->frameCount = frameCount; + entry->Bind(stage); + + GFX_DEBUGGER_PAUSE_AT(NEXT_TEXTURE_CHANGE, true); + + return entry; +} + +TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int const stage, + u32 const address, unsigned int width, unsigned int height, int const texformat, + unsigned int const tlutaddr, int const tlutfmt, bool const use_mipmaps, unsigned int maxlevel, bool const from_tmem) +{ + if (0 == address) + return NULL; + + // TexelSizeInNibbles(format) * width * height / 16; + const unsigned int bsw = TexDecoder_GetBlockWidthInTexels(texformat) - 1; + const unsigned int bsh = TexDecoder_GetBlockHeightInTexels(texformat) - 1; + + unsigned int expandedWidth = (width + bsw) & (~bsw); + unsigned int expandedHeight = (height + bsh) & (~bsh); + const unsigned int nativeW = width; + const unsigned int nativeH = height; + + u32 texID = address; + // Hash assigned to texcache entry (also used to generate filenames used for texture dumping and custom texture lookup) + u64 tex_hash = TEXHASH_INVALID; + u64 tlut_hash = TEXHASH_INVALID; + + u32 full_format = texformat; + PC_TexFormat pcfmt = PC_TEX_FMT_NONE; + + const bool isPaletteTexture = (texformat == GX_TF_C4 || texformat == GX_TF_C8 || texformat == GX_TF_C14X2); + if (isPaletteTexture) + full_format = texformat | (tlutfmt << 16); + + const u32 texture_size = TexDecoder_GetTextureSizeInBytes(expandedWidth, expandedHeight, texformat); + + const u8* src_data; + if (from_tmem) + src_data = &texMem[bpmem.tex[stage / 4].texImage1[stage % 4].tmem_even * TMEM_LINE_SIZE]; + else + src_data = Memory::GetPointer(address); + + // 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); + if (isPaletteTexture) + { + const u32 palette_size = TexDecoder_GetPaletteSize(texformat); + tlut_hash = GetHash64(&texMem[tlutaddr], palette_size, g_ActiveConfig.iSafeTextureCache_ColorSamples); + + // NOTE: For non-paletted textures, texID is equal to the texture address. + // A paletted texture, however, may have multiple texIDs assigned though depending on the currently used tlut. + // This (changing texID depending on the tlut_hash) is a trick to get around + // an issue with Metroid Prime's fonts (it has multiple sets of fonts on each other + // stored in a single texture and uses the palette to make different characters + // visible or invisible. Thus, unless we want to recreate the textures for every drawn character, + // we must make sure that a paletted texture gets assigned multiple IDs for each tlut used. + // + // TODO: Because texID isn't always the same as the address now, CopyRenderTargetToTexture might be broken now + texID ^= ((u32)tlut_hash) ^(u32)(tlut_hash >> 32); + tex_hash ^= tlut_hash; + } + + // D3D doesn't like when the specified mipmap count would require more than one 1x1-sized LOD in the mipmap chain + // e.g. 64x64 with 7 LODs would have the mipmap chain 64x64,32x32,16x16,8x8,4x4,2x2,1x1,1x1, so we limit the mipmap count to 6 there + while (g_ActiveConfig.backend_info.bUseMinimalMipCount && max(expandedWidth, expandedHeight) >> maxlevel == 0) + --maxlevel; + + TCacheEntryBase *entry = textures[texID]; + if (entry) + { + // 1. Calculate reference hash: + // calculated from RAM texture data for normal textures. Hashes for paletted textures are modified by tlut_hash. 0 for virtual EFB copies. + if (g_ActiveConfig.bCopyEFBToTexture && entry->IsEfbCopy()) + tex_hash = TEXHASH_INVALID; + + // 2. a) For EFB copies, only the hash and the texture address need to match + if (entry->IsEfbCopy() && tex_hash == entry->hash && address == entry->addr) + { + entry->type = TCET_EC_VRAM; + + // TODO: Print a warning if the format changes! In this case, + // we could reinterpret the internal texture object data to the new pixel format + // (similar to what is already being done in Renderer::ReinterpretPixelFormat()) + return ReturnEntry(stage, entry); + } + + // 2. b) For normal textures, all texture parameters need to match + if (address == entry->addr && tex_hash == entry->hash && full_format == entry->format && + entry->num_mipmaps > maxlevel && entry->native_width == nativeW && entry->native_height == nativeH) + { + return ReturnEntry(stage, entry); + } + + // 3. If we reach this line, we'll have to upload the new texture data to VRAM. + // If we're lucky, the texture parameters didn't change and we can reuse the internal texture object instead of destroying and recreating it. + // + // TODO: Don't we need to force texture decoding to RGBA8 for dynamic EFB copies? + // TODO: Actually, it should be enough if the internal texture format matches... + if ((entry->type == TCET_NORMAL && width == entry->virtual_width && height == entry->virtual_height + && full_format == entry->format && entry->num_mipmaps > maxlevel) + || (entry->type == TCET_EC_DYNAMIC && entry->native_width == width && entry->native_height == height)) + { + // reuse the texture + } + else + { + // delete the texture and make a new one + delete entry; + entry = NULL; + } + } + + bool using_custom_texture = false; + + if (g_ActiveConfig.bHiresTextures) + { + // This function may modify width/height. + pcfmt = LoadCustomTexture(tex_hash, texformat, 0, width, height); + if (pcfmt != PC_TEX_FMT_NONE) + { + if (expandedWidth != width || expandedHeight != height) + { + expandedWidth = width; + expandedHeight = height; + + // If we thought we could reuse the texture before, make sure to pool it now! + if(entry) + { + delete entry; + entry = NULL; + } + } + using_custom_texture = true; + } + } + + if (!using_custom_texture) + { + if (!(texformat == GX_TF_RGBA8 && from_tmem)) + { + pcfmt = TexDecoder_Decode(temp, src_data, expandedWidth, + expandedHeight, texformat, tlutaddr, tlutfmt, g_ActiveConfig.backend_info.bUseRGBATextures); + } + else + { + u8* src_data_gb = &texMem[bpmem.tex[stage/4].texImage2[stage%4].tmem_odd * TMEM_LINE_SIZE]; + pcfmt = TexDecoder_DecodeRGBA8FromTmem(temp, src_data, src_data_gb, expandedWidth, expandedHeight); + } + } + + u32 texLevels = use_mipmaps ? (maxlevel + 1) : 1; + const bool using_custom_lods = using_custom_texture && CheckForCustomTextureLODs(tex_hash, texformat, texLevels); + // 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); + 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) + + // create the entry/texture + if (NULL == entry) + { + textures[texID] = entry = g_texture_cache->CreateTexture(width, height, expandedWidth, texLevels, pcfmt); + + // Sometimes, we can get around recreating a texture if only the number of mip levels changes + // e.g. if our texture cache entry got too many mipmap levels we can limit the number of used levels by setting the appropriate render states + // Thus, we don't update this member for every Load, but just whenever the texture gets recreated + + // TODO: This is the wrong value. We should be storing the number of levels our actual texture has. + // But that will currently make the above "existing entry" tests fail as "texLevels" is not calculated until after. + // Currently, we might try to reuse a texture which appears to have more levels than actual, maybe.. + entry->num_mipmaps = maxlevel + 1; + entry->type = TCET_NORMAL; + + GFX_DEBUGGER_PAUSE_AT(NEXT_NEW_TEXTURE, true); + } + else + { + // load texture (CreateTexture also loads level 0) + entry->Load(width, height, expandedWidth, 0); + } + + entry->SetGeneralParameters(address, texture_size, full_format, entry->num_mipmaps); + entry->SetDimensions(nativeW, nativeH, width, height); + entry->hash = tex_hash; + + if (entry->IsEfbCopy() && !g_ActiveConfig.bCopyEFBToTexture) + entry->type = TCET_EC_DYNAMIC; + else + entry->type = TCET_NORMAL; + + if (g_ActiveConfig.bDumpTextures && !using_custom_texture) + DumpTexture(entry, 0); + + u32 level = 1; + // load mips - TODO: Loading mipmaps from tmem is untested! + if (pcfmt != PC_TEX_FMT_NONE) + { + if (use_native_mips) + { + src_data += texture_size; + + const u8* ptr_even = NULL; + const u8* ptr_odd = NULL; + if (from_tmem) + { + ptr_even = &texMem[bpmem.tex[stage/4].texImage1[stage%4].tmem_even * TMEM_LINE_SIZE + texture_size]; + ptr_odd = &texMem[bpmem.tex[stage/4].texImage2[stage%4].tmem_odd * TMEM_LINE_SIZE]; + } + + for (; level != texLevels; ++level) + { + const u32 mip_width = CalculateLevelSize(width, level); + const u32 mip_height = CalculateLevelSize(height, level); + const u32 expanded_mip_width = (mip_width + bsw) & (~bsw); + const u32 expanded_mip_height = (mip_height + bsh) & (~bsh); + + const u8*& mip_src_data = from_tmem + ? ((level % 2) ? ptr_odd : ptr_even) + : src_data; + TexDecoder_Decode(temp, mip_src_data, expanded_mip_width, expanded_mip_height, texformat, tlutaddr, tlutfmt, g_ActiveConfig.backend_info.bUseRGBATextures); + mip_src_data += TexDecoder_GetTextureSizeInBytes(expanded_mip_width, expanded_mip_height, texformat); + + entry->Load(mip_width, mip_height, expanded_mip_width, level); + + if (g_ActiveConfig.bDumpTextures) + DumpTexture(entry, level); + } + } + else if (using_custom_lods) + { + for (; level != texLevels; ++level) + { + unsigned int mip_width = CalculateLevelSize(width, level); + unsigned int mip_height = CalculateLevelSize(height, level); + + LoadCustomTexture(tex_hash, texformat, level, mip_width, mip_height); + entry->Load(mip_width, mip_height, mip_width, level); + } + } + } + + INCSTAT(stats.numTexturesCreated); + SETSTAT(stats.numTexturesAlive, textures.size()); + + return ReturnEntry(stage, entry); +} + +void TextureCache::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFormat, unsigned int srcFormat, + const EFBRectangle& srcRect, bool isIntensity, bool scaleByHalf) +{ + // Emulation methods: + // + // - EFB to RAM: + // Encodes the requested EFB data at its native resolution to the emulated RAM using shaders. + // Load() decodes the data from there again (using TextureDecoder) if the EFB copy is being used as a texture again. + // Advantage: CPU can read data from the EFB copy and we don't lose any important updates to the texture + // Disadvantage: Encoding+decoding steps often are redundant because only some games read or modify EFB copies before using them as textures. + // + // - EFB to texture: + // Copies the requested EFB data to a texture object in VRAM, performing any color conversion using shaders. + // Advantage: Works for many games, since in most cases EFB copies aren't read or modified at all before being used as a texture again. + // Since we don't do any further encoding or decoding here, this method is much faster. + // It also allows enhancing the visual quality by doing scaled EFB copies. + // + // - Hybrid EFB copies: + // 1a) Whenever this function gets called, encode the requested EFB data to RAM (like EFB to RAM) + // 1b) Set type to TCET_EC_DYNAMIC for all texture cache entries in the destination address range. + // If EFB copy caching is enabled, further checks will (try to) prevent redundant EFB copies. + // 2) Check if a texture cache entry for the specified dstAddr already exists (i.e. if an EFB copy was triggered to that address before): + // 2a) Entry doesn't exist: + // - Also copy the requested EFB data to a texture object in VRAM (like EFB to texture) + // - Create a texture cache entry for the target (type = TCET_EC_VRAM) + // - Store a hash of the encoded RAM data in the texcache entry. + // 2b) Entry exists AND type is TCET_EC_VRAM: + // - Like case 2a, but reuse the old texcache entry instead of creating a new one. + // 2c) Entry exists AND type is TCET_EC_DYNAMIC: + // - Only encode the texture to RAM (like EFB to RAM) and store a hash of the encoded data in the existing texcache entry. + // - Do NOT copy the requested EFB data to a VRAM object. Reason: the texture is dynamic, i.e. the CPU is modifying it. Storing a VRAM copy is useless, because we'd always end up deleting it and reloading the data from RAM anyway. + // 3) If the EFB copy gets used as a texture, compare the source RAM hash with the hash you stored when encoding the EFB data to RAM. + // 3a) If the two hashes match AND type is TCET_EC_VRAM, reuse the VRAM copy you created + // 3b) If the two hashes differ AND type is TCET_EC_VRAM, screw your existing VRAM copy. Set type to TCET_EC_DYNAMIC. + // Redecode the source RAM data to a VRAM object. The entry basically behaves like a normal texture now. + // 3c) If type is TCET_EC_DYNAMIC, treat the EFB copy like a normal texture. + // Advantage: Non-dynamic EFB copies can be visually enhanced like with EFB to texture. + // Compatibility is as good as EFB to RAM. + // Disadvantage: Slower than EFB to texture and often even slower than EFB to RAM. + // EFB copy cache depends on accurate texture hashing being enabled. However, with accurate hashing you end up being as slow as without a copy cache anyway. + // + // Disadvantage of all methods: Calling this function requires the GPU to perform a pipeline flush which stalls any further CPU processing. + // + // For historical reasons, Dolphin doesn't actually implement "pure" EFB to RAM emulation, but only EFB to texture and hybrid EFB copies. + + float colmat[28] = {0}; + float *const fConstAdd = colmat + 16; + float *const ColorMask = colmat + 20; + ColorMask[0] = ColorMask[1] = ColorMask[2] = ColorMask[3] = 255.0f; + ColorMask[4] = ColorMask[5] = ColorMask[6] = ColorMask[7] = 1.0f / 255.0f; + unsigned int cbufid = -1; + bool efbHasAlpha = bpmem.zcontrol.pixel_format == PIXELFMT_RGBA6_Z24; + + if (srcFormat == PIXELFMT_Z24) + { + switch (dstFormat) + { + case 0: // Z4 + colmat[3] = colmat[7] = colmat[11] = colmat[15] = 1.0f; + cbufid = 0; + break; + case 1: // Z8 + case 8: // Z8 + colmat[0] = colmat[4] = colmat[8] = colmat[12] = 1.0f; + cbufid = 1; + break; + + case 3: // Z16 + colmat[1] = colmat[5] = colmat[9] = colmat[12] = 1.0f; + cbufid = 2; + break; + + case 11: // Z16 (reverse order) + colmat[0] = colmat[4] = colmat[8] = colmat[13] = 1.0f; + cbufid = 3; + break; + + case 6: // Z24X8 + colmat[0] = colmat[5] = colmat[10] = 1.0f; + cbufid = 4; + break; + + case 9: // Z8M + colmat[1] = colmat[5] = colmat[9] = colmat[13] = 1.0f; + cbufid = 5; + break; + + case 10: // Z8L + colmat[2] = colmat[6] = colmat[10] = colmat[14] = 1.0f; + cbufid = 6; + break; + + case 12: // Z16L - copy lower 16 depth bits + // expected to be used as an IA8 texture (upper 8 bits stored as intensity, lower 8 bits stored as alpha) + // Used e.g. in Zelda: Skyward Sword + colmat[1] = colmat[5] = colmat[9] = colmat[14] = 1.0f; + cbufid = 7; + break; + + default: + ERROR_LOG(VIDEO, "Unknown copy zbuf format: 0x%x", dstFormat); + colmat[2] = colmat[5] = colmat[8] = 1.0f; + cbufid = 8; + break; + } + } + else if (isIntensity) + { + fConstAdd[0] = fConstAdd[1] = fConstAdd[2] = 16.0f/255.0f; + switch (dstFormat) + { + case 0: // I4 + case 1: // I8 + case 2: // IA4 + case 3: // IA8 + case 8: // I8 + // TODO - verify these coefficients + colmat[0] = 0.257f; colmat[1] = 0.504f; colmat[2] = 0.098f; + colmat[4] = 0.257f; colmat[5] = 0.504f; colmat[6] = 0.098f; + colmat[8] = 0.257f; colmat[9] = 0.504f; colmat[10] = 0.098f; + + if (dstFormat < 2 || dstFormat == 8) + { + colmat[12] = 0.257f; colmat[13] = 0.504f; colmat[14] = 0.098f; + fConstAdd[3] = 16.0f/255.0f; + if (dstFormat == 0) + { + ColorMask[0] = ColorMask[1] = ColorMask[2] = 15.0f; + ColorMask[4] = ColorMask[5] = ColorMask[6] = 1.0f / 15.0f; + cbufid = 9; + } + else + { + cbufid = 10; + } + } + else// alpha + { + colmat[15] = 1; + if (dstFormat == 2) + { + ColorMask[0] = ColorMask[1] = ColorMask[2] = ColorMask[3] = 15.0f; + ColorMask[4] = ColorMask[5] = ColorMask[6] = ColorMask[7] = 1.0f / 15.0f; + cbufid = 11; + } + else + { + cbufid = 12; + } + + } + break; + + default: + ERROR_LOG(VIDEO, "Unknown copy intensity format: 0x%x", dstFormat); + colmat[0] = colmat[5] = colmat[10] = colmat[15] = 1.0f; + cbufid = 13; + break; + } + } + else + { + switch (dstFormat) + { + case 0: // R4 + colmat[0] = colmat[4] = colmat[8] = colmat[12] = 1; + ColorMask[0] = 15.0f; + ColorMask[4] = 1.0f / 15.0f; + cbufid = 14; + break; + case 1: // R8 + case 8: // R8 + colmat[0] = colmat[4] = colmat[8] = colmat[12] = 1; + cbufid = 15; + break; + + case 2: // RA4 + colmat[0] = colmat[4] = colmat[8] = colmat[15] = 1.0f; + ColorMask[0] = ColorMask[3] = 15.0f; + ColorMask[4] = ColorMask[7] = 1.0f / 15.0f; + + cbufid = 16; + if(!efbHasAlpha) { + ColorMask[3] = 0.0f; + fConstAdd[3] = 1.0f; + cbufid = 17; + } + break; + case 3: // RA8 + colmat[0] = colmat[4] = colmat[8] = colmat[15] = 1.0f; + + cbufid = 18; + if(!efbHasAlpha) { + ColorMask[3] = 0.0f; + fConstAdd[3] = 1.0f; + cbufid = 19; + } + break; + + case 7: // A8 + colmat[3] = colmat[7] = colmat[11] = colmat[15] = 1.0f; + + cbufid = 20; + if(!efbHasAlpha) { + ColorMask[3] = 0.0f; + fConstAdd[0] = 1.0f; + fConstAdd[1] = 1.0f; + fConstAdd[2] = 1.0f; + fConstAdd[3] = 1.0f; + cbufid = 21; + } + break; + + case 9: // G8 + colmat[1] = colmat[5] = colmat[9] = colmat[13] = 1.0f; + cbufid = 22; + break; + case 10: // B8 + colmat[2] = colmat[6] = colmat[10] = colmat[14] = 1.0f; + cbufid = 23; + break; + + case 11: // RG8 + colmat[0] = colmat[4] = colmat[8] = colmat[13] = 1.0f; + cbufid = 24; + break; + + case 12: // GB8 + colmat[1] = colmat[5] = colmat[9] = colmat[14] = 1.0f; + cbufid = 25; + break; + + case 4: // RGB565 + colmat[0] = colmat[5] = colmat[10] = 1.0f; + ColorMask[0] = ColorMask[2] = 31.0f; + ColorMask[4] = ColorMask[6] = 1.0f / 31.0f; + ColorMask[1] = 63.0f; + ColorMask[5] = 1.0f / 63.0f; + fConstAdd[3] = 1.0f; // set alpha to 1 + cbufid = 26; + break; + + case 5: // RGB5A3 + colmat[0] = colmat[5] = colmat[10] = colmat[15] = 1.0f; + ColorMask[0] = ColorMask[1] = ColorMask[2] = 31.0f; + ColorMask[4] = ColorMask[5] = ColorMask[6] = 1.0f / 31.0f; + ColorMask[3] = 7.0f; + ColorMask[7] = 1.0f / 7.0f; + + cbufid = 27; + if(!efbHasAlpha) { + ColorMask[3] = 0.0f; + fConstAdd[3] = 1.0f; + cbufid = 28; + } + break; + case 6: // RGBA8 + colmat[0] = colmat[5] = colmat[10] = colmat[15] = 1.0f; + + cbufid = 29; + if(!efbHasAlpha) { + ColorMask[3] = 0.0f; + fConstAdd[3] = 1.0f; + cbufid = 30; + } + break; + + default: + ERROR_LOG(VIDEO, "Unknown copy color format: 0x%x", dstFormat); + colmat[0] = colmat[5] = colmat[10] = colmat[15] = 1.0f; + cbufid = 31; + break; + } + } + + const unsigned int tex_w = scaleByHalf ? srcRect.GetWidth()/2 : srcRect.GetWidth(); + const unsigned int tex_h = scaleByHalf ? srcRect.GetHeight()/2 : srcRect.GetHeight(); + + unsigned int scaled_tex_w = g_ActiveConfig.bCopyEFBScaled ? Renderer::EFBToScaledX(tex_w) : tex_w; + unsigned int scaled_tex_h = g_ActiveConfig.bCopyEFBScaled ? Renderer::EFBToScaledY(tex_h) : tex_h; + + + TCacheEntryBase *entry = textures[dstAddr]; + if (entry) + { + if (entry->type == TCET_EC_DYNAMIC && entry->native_width == tex_w && entry->native_height == tex_h) + { + scaled_tex_w = tex_w; + scaled_tex_h = tex_h; + } + else if (!(entry->type == TCET_EC_VRAM && entry->virtual_width == scaled_tex_w && entry->virtual_height == scaled_tex_h)) + { + // remove it and recreate it as a render target + delete entry; + entry = NULL; + } + } + + if (NULL == entry) + { + // create the texture + textures[dstAddr] = entry = g_texture_cache->CreateRenderTargetTexture(scaled_tex_w, scaled_tex_h); + + // TODO: Using the wrong dstFormat, dumb... + entry->SetGeneralParameters(dstAddr, 0, dstFormat, 1); + entry->SetDimensions(tex_w, tex_h, scaled_tex_w, scaled_tex_h); + entry->SetHashes(TEXHASH_INVALID); + entry->type = TCET_EC_VRAM; + } + + entry->frameCount = frameCount; + + entry->FromRenderTarget(dstAddr, dstFormat, srcFormat, srcRect, isIntensity, scaleByHalf, cbufid, colmat); +} -- cgit v1.2.3 From 01351795f01d113a587fe51c904cdba84536f230 Mon Sep 17 00:00:00 2001 From: degasus Date: Fri, 3 Jan 2014 14:30:12 +0100 Subject: TextureCache: Warn for invalid custom textures At the moment, custom textures with: - invalid mipmap size - invalid aspect ratio - non-fractional scaling factors are allowed. But they can't be loaded fine by the backend, so generate a warning if someone trys to load them. --- Source/Core/VideoCommon/TextureCacheBase.cpp | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'Source/Core/VideoCommon/TextureCacheBase.cpp') diff --git a/Source/Core/VideoCommon/TextureCacheBase.cpp b/Source/Core/VideoCommon/TextureCacheBase.cpp index 8555bd736d..a3224bcf08 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/TextureCacheBase.cpp @@ -255,11 +255,12 @@ PC_TexFormat TextureCache::LoadCustomTexture(u64 tex_hash, int texformat, unsign char texPathTemp[MAX_PATH]; unsigned int newWidth = 0; unsigned int newHeight = 0; + u32 tex_hash_u32 = tex_hash & 0x00000000FFFFFFFFLL; if (level == 0) - sprintf(texPathTemp, "%s_%08x_%i", SConfig::GetInstance().m_LocalCoreStartupParameter.m_strUniqueID.c_str(), (u32) (tex_hash & 0x00000000FFFFFFFFLL), texformat); + sprintf(texPathTemp, "%s_%08x_%i", SConfig::GetInstance().m_LocalCoreStartupParameter.m_strUniqueID.c_str(), tex_hash_u32, texformat); else - sprintf(texPathTemp, "%s_%08x_%i_mip%i", SConfig::GetInstance().m_LocalCoreStartupParameter.m_strUniqueID.c_str(), (u32) (tex_hash & 0x00000000FFFFFFFFLL), texformat, level); + sprintf(texPathTemp, "%s_%08x_%i_mip%i", 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); @@ -275,6 +276,13 @@ PC_TexFormat TextureCache::LoadCustomTexture(u64 tex_hash, int texformat, unsign if (ret != PC_TEX_FMT_NONE) { + 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, 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, 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, width, height); + width = newWidth; height = newHeight; } -- cgit v1.2.3 From 404624bf0b0125e5a408021c616ee9b9e2dde382 Mon Sep 17 00:00:00 2001 From: Tillmann Karras Date: Wed, 12 Feb 2014 16:00:34 +0100 Subject: Turn loops into range-based form and some things suggested by cppcheck and compiler warnings. --- Source/Core/VideoCommon/TextureCacheBase.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Source/Core/VideoCommon/TextureCacheBase.cpp') diff --git a/Source/Core/VideoCommon/TextureCacheBase.cpp b/Source/Core/VideoCommon/TextureCacheBase.cpp index a3224bcf08..6903f778c7 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/TextureCacheBase.cpp @@ -172,7 +172,7 @@ void TextureCache::MakeRangeDynamic(u32 start_address, u32 size) tcend = textures.upper_bound(start_address + size); if (iter != textures.begin()) - iter--; + --iter; for (; iter != tcend; ++iter) { -- cgit v1.2.3 From 3fd87a7636ff434118a5d7f7334550be8db55c0b Mon Sep 17 00:00:00 2001 From: Lioncash Date: Sun, 16 Feb 2014 23:51:41 -0500 Subject: Second and final pass of clearing out tabs. --- Source/Core/VideoCommon/TextureCacheBase.cpp | 74 ++++++++++++++-------------- 1 file changed, 37 insertions(+), 37 deletions(-) (limited to 'Source/Core/VideoCommon/TextureCacheBase.cpp') diff --git a/Source/Core/VideoCommon/TextureCacheBase.cpp b/Source/Core/VideoCommon/TextureCacheBase.cpp index 6903f778c7..6748228b2f 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/TextureCacheBase.cpp @@ -130,7 +130,7 @@ void TextureCache::Cleanup() TexCache::iterator tcend = textures.end(); while (iter != tcend) { - if ( frameCount > TEXTURE_KILL_THRESHOLD + iter->second->frameCount + if (frameCount > TEXTURE_KILL_THRESHOLD + iter->second->frameCount // EFB copies living on the host GPU are unrecoverable and thus shouldn't be deleted && ! iter->second->IsEfbCopy() ) @@ -378,12 +378,12 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int const stage, tlut_hash = GetHash64(&texMem[tlutaddr], palette_size, g_ActiveConfig.iSafeTextureCache_ColorSamples); // NOTE: For non-paletted textures, texID is equal to the texture address. - // A paletted texture, however, may have multiple texIDs assigned though depending on the currently used tlut. - // This (changing texID depending on the tlut_hash) is a trick to get around - // an issue with Metroid Prime's fonts (it has multiple sets of fonts on each other - // stored in a single texture and uses the palette to make different characters - // visible or invisible. Thus, unless we want to recreate the textures for every drawn character, - // we must make sure that a paletted texture gets assigned multiple IDs for each tlut used. + // A paletted texture, however, may have multiple texIDs assigned though depending on the currently used tlut. + // This (changing texID depending on the tlut_hash) is a trick to get around + // an issue with Metroid Prime's fonts (it has multiple sets of fonts on each other + // stored in a single texture and uses the palette to make different characters + // visible or invisible. Thus, unless we want to recreate the textures for every drawn character, + // we must make sure that a paletted texture gets assigned multiple IDs for each tlut used. // // TODO: Because texID isn't always the same as the address now, CopyRenderTargetToTexture might be broken now texID ^= ((u32)tlut_hash) ^(u32)(tlut_hash >> 32); @@ -579,40 +579,40 @@ void TextureCache::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFormat // Emulation methods: // // - EFB to RAM: - // Encodes the requested EFB data at its native resolution to the emulated RAM using shaders. - // Load() decodes the data from there again (using TextureDecoder) if the EFB copy is being used as a texture again. - // Advantage: CPU can read data from the EFB copy and we don't lose any important updates to the texture - // Disadvantage: Encoding+decoding steps often are redundant because only some games read or modify EFB copies before using them as textures. + // Encodes the requested EFB data at its native resolution to the emulated RAM using shaders. + // Load() decodes the data from there again (using TextureDecoder) if the EFB copy is being used as a texture again. + // Advantage: CPU can read data from the EFB copy and we don't lose any important updates to the texture + // Disadvantage: Encoding+decoding steps often are redundant because only some games read or modify EFB copies before using them as textures. // // - EFB to texture: - // Copies the requested EFB data to a texture object in VRAM, performing any color conversion using shaders. - // Advantage: Works for many games, since in most cases EFB copies aren't read or modified at all before being used as a texture again. - // Since we don't do any further encoding or decoding here, this method is much faster. - // It also allows enhancing the visual quality by doing scaled EFB copies. + // Copies the requested EFB data to a texture object in VRAM, performing any color conversion using shaders. + // Advantage: Works for many games, since in most cases EFB copies aren't read or modified at all before being used as a texture again. + // Since we don't do any further encoding or decoding here, this method is much faster. + // It also allows enhancing the visual quality by doing scaled EFB copies. // // - Hybrid EFB copies: - // 1a) Whenever this function gets called, encode the requested EFB data to RAM (like EFB to RAM) - // 1b) Set type to TCET_EC_DYNAMIC for all texture cache entries in the destination address range. - // If EFB copy caching is enabled, further checks will (try to) prevent redundant EFB copies. - // 2) Check if a texture cache entry for the specified dstAddr already exists (i.e. if an EFB copy was triggered to that address before): - // 2a) Entry doesn't exist: - // - Also copy the requested EFB data to a texture object in VRAM (like EFB to texture) - // - Create a texture cache entry for the target (type = TCET_EC_VRAM) - // - Store a hash of the encoded RAM data in the texcache entry. - // 2b) Entry exists AND type is TCET_EC_VRAM: - // - Like case 2a, but reuse the old texcache entry instead of creating a new one. - // 2c) Entry exists AND type is TCET_EC_DYNAMIC: - // - Only encode the texture to RAM (like EFB to RAM) and store a hash of the encoded data in the existing texcache entry. - // - Do NOT copy the requested EFB data to a VRAM object. Reason: the texture is dynamic, i.e. the CPU is modifying it. Storing a VRAM copy is useless, because we'd always end up deleting it and reloading the data from RAM anyway. - // 3) If the EFB copy gets used as a texture, compare the source RAM hash with the hash you stored when encoding the EFB data to RAM. - // 3a) If the two hashes match AND type is TCET_EC_VRAM, reuse the VRAM copy you created - // 3b) If the two hashes differ AND type is TCET_EC_VRAM, screw your existing VRAM copy. Set type to TCET_EC_DYNAMIC. - // Redecode the source RAM data to a VRAM object. The entry basically behaves like a normal texture now. - // 3c) If type is TCET_EC_DYNAMIC, treat the EFB copy like a normal texture. - // Advantage: Non-dynamic EFB copies can be visually enhanced like with EFB to texture. - // Compatibility is as good as EFB to RAM. - // Disadvantage: Slower than EFB to texture and often even slower than EFB to RAM. - // EFB copy cache depends on accurate texture hashing being enabled. However, with accurate hashing you end up being as slow as without a copy cache anyway. + // 1a) Whenever this function gets called, encode the requested EFB data to RAM (like EFB to RAM) + // 1b) Set type to TCET_EC_DYNAMIC for all texture cache entries in the destination address range. + // If EFB copy caching is enabled, further checks will (try to) prevent redundant EFB copies. + // 2) Check if a texture cache entry for the specified dstAddr already exists (i.e. if an EFB copy was triggered to that address before): + // 2a) Entry doesn't exist: + // - Also copy the requested EFB data to a texture object in VRAM (like EFB to texture) + // - Create a texture cache entry for the target (type = TCET_EC_VRAM) + // - Store a hash of the encoded RAM data in the texcache entry. + // 2b) Entry exists AND type is TCET_EC_VRAM: + // - Like case 2a, but reuse the old texcache entry instead of creating a new one. + // 2c) Entry exists AND type is TCET_EC_DYNAMIC: + // - Only encode the texture to RAM (like EFB to RAM) and store a hash of the encoded data in the existing texcache entry. + // - Do NOT copy the requested EFB data to a VRAM object. Reason: the texture is dynamic, i.e. the CPU is modifying it. Storing a VRAM copy is useless, because we'd always end up deleting it and reloading the data from RAM anyway. + // 3) If the EFB copy gets used as a texture, compare the source RAM hash with the hash you stored when encoding the EFB data to RAM. + // 3a) If the two hashes match AND type is TCET_EC_VRAM, reuse the VRAM copy you created + // 3b) If the two hashes differ AND type is TCET_EC_VRAM, screw your existing VRAM copy. Set type to TCET_EC_DYNAMIC. + // Redecode the source RAM data to a VRAM object. The entry basically behaves like a normal texture now. + // 3c) If type is TCET_EC_DYNAMIC, treat the EFB copy like a normal texture. + // Advantage: Non-dynamic EFB copies can be visually enhanced like with EFB to texture. + // Compatibility is as good as EFB to RAM. + // Disadvantage: Slower than EFB to texture and often even slower than EFB to RAM. + // EFB copy cache depends on accurate texture hashing being enabled. However, with accurate hashing you end up being as slow as without a copy cache anyway. // // Disadvantage of all methods: Calling this function requires the GPU to perform a pipeline flush which stalls any further CPU processing. // -- cgit v1.2.3 From 2afe2152712981e21d6bda6f029292ed2b1cf91e Mon Sep 17 00:00:00 2001 From: Lioncash Date: Mon, 17 Feb 2014 05:18:15 -0500 Subject: Convert all includes to relative paths. --- Source/Core/VideoCommon/TextureCacheBase.cpp | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) (limited to 'Source/Core/VideoCommon/TextureCacheBase.cpp') diff --git a/Source/Core/VideoCommon/TextureCacheBase.cpp b/Source/Core/VideoCommon/TextureCacheBase.cpp index 6748228b2f..5abce6fdee 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/TextureCacheBase.cpp @@ -2,18 +2,18 @@ // Licensed under GPLv2 // Refer to the license.txt file included. -#include "MemoryUtil.h" - -#include "VideoConfig.h" -#include "Statistics.h" -#include "HiresTextures.h" -#include "RenderBase.h" -#include "FileUtil.h" - -#include "TextureCacheBase.h" -#include "Debugger.h" -#include "ConfigManager.h" -#include "HW/Memmap.h" +#include "Common/FileUtil.h" +#include "Common/MemoryUtil.h" + +#include "Core/ConfigManager.h" +#include "Core/HW/Memmap.h" + +#include "VideoCommon/Debugger.h" +#include "VideoCommon/HiresTextures.h" +#include "VideoCommon/RenderBase.h" +#include "VideoCommon/Statistics.h" +#include "VideoCommon/TextureCacheBase.h" +#include "VideoCommon/VideoConfig.h" // ugly extern int frameCount; -- cgit v1.2.3 From 315a8ba1c04bf8cffd9b04096be898ac462fa89e Mon Sep 17 00:00:00 2001 From: Tillmann Karras Date: Sun, 23 Feb 2014 23:03:39 +0100 Subject: Various changes suggested by cppcheck - remove unused variables - reduce the scope where it makes sense - correct limits (did you know that strcat()'s last parameter does not include the \0 that is always added?) - set some free()'d pointers to NULL --- Source/Core/VideoCommon/TextureCacheBase.cpp | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) (limited to 'Source/Core/VideoCommon/TextureCacheBase.cpp') diff --git a/Source/Core/VideoCommon/TextureCacheBase.cpp b/Source/Core/VideoCommon/TextureCacheBase.cpp index 5abce6fdee..9ea6fae5ad 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/TextureCacheBase.cpp @@ -73,11 +73,8 @@ void TextureCache::Invalidate() TextureCache::~TextureCache() { Invalidate(); - if (temp) - { - FreeAlignedMemory(temp); - temp = NULL; - } + FreeAlignedMemory(temp); + temp = NULL; } void TextureCache::OnConfigChanged(VideoConfig& config) @@ -238,11 +235,11 @@ bool TextureCache::CheckForCustomTextureLODs(u64 tex_hash, int texformat, unsign for (unsigned int level = 1; level < levels; ++level) { - sprintf(texPathTemp, "%s_mip%i", texBasePathTemp, level); + sprintf(texPathTemp, "%s_mip%u", 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); + WARN_LOG(VIDEO, "Couldn't find custom texture LOD with index %u (filename: %s), disabling custom LODs for this texture", level, texPathTemp); return false; } @@ -260,7 +257,7 @@ PC_TexFormat TextureCache::LoadCustomTexture(u64 tex_hash, int texformat, unsign if (level == 0) sprintf(texPathTemp, "%s_%08x_%i", SConfig::GetInstance().m_LocalCoreStartupParameter.m_strUniqueID.c_str(), tex_hash_u32, texformat); else - sprintf(texPathTemp, "%s_%08x_%i_mip%i", SConfig::GetInstance().m_LocalCoreStartupParameter.m_strUniqueID.c_str(), tex_hash_u32, texformat, level); + sprintf(texPathTemp, "%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); -- cgit v1.2.3 From c89f04a7c5256d92b75e9868df9af6cfb7050559 Mon Sep 17 00:00:00 2001 From: Tillmann Karras Date: Mon, 3 Mar 2014 06:25:15 +0100 Subject: clang-modernize -loop-convert and some manual adjustments --- Source/Core/VideoCommon/TextureCacheBase.cpp | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) (limited to 'Source/Core/VideoCommon/TextureCacheBase.cpp') diff --git a/Source/Core/VideoCommon/TextureCacheBase.cpp b/Source/Core/VideoCommon/TextureCacheBase.cpp index 9ea6fae5ad..1c9bb0ba2a 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/TextureCacheBase.cpp @@ -61,12 +61,10 @@ void TextureCache::RequestInvalidateTextureCache() void TextureCache::Invalidate() { - TexCache::iterator - iter = textures.begin(), - tcend = textures.end(); - for (; iter != tcend; ++iter) - delete iter->second; - + for (auto& tex : textures) + { + delete tex.second; + } textures.clear(); } -- cgit v1.2.3 From d802d392811be44d34ae9cd23f616db93e54c50f Mon Sep 17 00:00:00 2001 From: Tillmann Karras Date: Sun, 9 Mar 2014 21:14:26 +0100 Subject: clang-modernize -use-nullptr and s/\bNULL\b/nullptr/g for *.cpp/h/mm files not compiled on my machine --- Source/Core/VideoCommon/TextureCacheBase.cpp | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'Source/Core/VideoCommon/TextureCacheBase.cpp') diff --git a/Source/Core/VideoCommon/TextureCacheBase.cpp b/Source/Core/VideoCommon/TextureCacheBase.cpp index 1c9bb0ba2a..c5f4f127f2 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/TextureCacheBase.cpp @@ -25,7 +25,7 @@ enum TextureCache *g_texture_cache; -GC_ALIGNED16(u8 *TextureCache::temp) = NULL; +GC_ALIGNED16(u8 *TextureCache::temp) = nullptr; unsigned int TextureCache::temp_size; TextureCache::TexCache TextureCache::textures; @@ -72,7 +72,7 @@ TextureCache::~TextureCache() { Invalidate(); FreeAlignedMemory(temp); - temp = NULL; + temp = nullptr; } void TextureCache::OnConfigChanged(VideoConfig& config) @@ -334,7 +334,7 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int const stage, unsigned int const tlutaddr, int const tlutfmt, bool const use_mipmaps, unsigned int maxlevel, bool const from_tmem) { if (0 == address) - return NULL; + return nullptr; // TexelSizeInNibbles(format) * width * height / 16; const unsigned int bsw = TexDecoder_GetBlockWidthInTexels(texformat) - 1; @@ -431,7 +431,7 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int const stage, { // delete the texture and make a new one delete entry; - entry = NULL; + entry = nullptr; } } @@ -452,7 +452,7 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int const stage, if(entry) { delete entry; - entry = NULL; + entry = nullptr; } } using_custom_texture = true; @@ -480,7 +480,7 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int const stage, 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) // create the entry/texture - if (NULL == entry) + if (nullptr == entry) { textures[texID] = entry = g_texture_cache->CreateTexture(width, height, expandedWidth, texLevels, pcfmt); @@ -522,8 +522,8 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int const stage, { src_data += texture_size; - const u8* ptr_even = NULL; - const u8* ptr_odd = NULL; + const u8* ptr_even = nullptr; + const u8* ptr_odd = nullptr; if (from_tmem) { ptr_even = &texMem[bpmem.tex[stage/4].texImage1[stage%4].tmem_even * TMEM_LINE_SIZE + texture_size]; @@ -862,11 +862,11 @@ void TextureCache::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFormat { // remove it and recreate it as a render target delete entry; - entry = NULL; + entry = nullptr; } } - if (NULL == entry) + if (nullptr == entry) { // create the texture textures[dstAddr] = entry = g_texture_cache->CreateRenderTargetTexture(scaled_tex_w, scaled_tex_h); -- cgit v1.2.3 From 31cfc73a09a8685cbab20502b4bc132e98e2feb5 Mon Sep 17 00:00:00 2001 From: Matthew Parlane Date: Tue, 11 Mar 2014 00:30:55 +1300 Subject: Fixes spacing for "for", "while", "switch" and "if" Also moved && and || to ends of lines instead of start. Fixed misc vertical alignments and some { needed newlining. --- Source/Core/VideoCommon/TextureCacheBase.cpp | 34 ++++++++++++++++------------ 1 file changed, 19 insertions(+), 15 deletions(-) (limited to 'Source/Core/VideoCommon/TextureCacheBase.cpp') diff --git a/Source/Core/VideoCommon/TextureCacheBase.cpp b/Source/Core/VideoCommon/TextureCacheBase.cpp index c5f4f127f2..7bbbc4aff6 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/TextureCacheBase.cpp @@ -46,7 +46,7 @@ TextureCache::TextureCache() 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.c_str()); SetHash64Function(g_ActiveConfig.bHiresTextures || g_ActiveConfig.bDumpTextures); @@ -88,7 +88,7 @@ void TextureCache::OnConfigChanged(VideoConfig& config) { g_texture_cache->Invalidate(); - if(g_ActiveConfig.bHiresTextures) + if (g_ActiveConfig.bHiresTextures) HiresTextures::Init(SConfig::GetInstance().m_LocalCoreStartupParameter.m_strUniqueID.c_str()); SetHash64Function(g_ActiveConfig.bHiresTextures || g_ActiveConfig.bDumpTextures); @@ -125,10 +125,9 @@ void TextureCache::Cleanup() TexCache::iterator tcend = textures.end(); while (iter != tcend) { - if (frameCount > TEXTURE_KILL_THRESHOLD + iter->second->frameCount - - // EFB copies living on the host GPU are unrecoverable and thus shouldn't be deleted - && ! iter->second->IsEfbCopy() ) + if (frameCount > TEXTURE_KILL_THRESHOLD + iter->second->frameCount && + // EFB copies living on the host GPU are unrecoverable and thus shouldn't be deleted + !iter->second->IsEfbCopy()) { delete iter->second; textures.erase(iter++); @@ -421,9 +420,14 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int const stage, // // TODO: Don't we need to force texture decoding to RGBA8 for dynamic EFB copies? // TODO: Actually, it should be enough if the internal texture format matches... - if ((entry->type == TCET_NORMAL && width == entry->virtual_width && height == entry->virtual_height - && full_format == entry->format && entry->num_mipmaps > maxlevel) - || (entry->type == TCET_EC_DYNAMIC && entry->native_width == width && entry->native_height == height)) + if ((entry->type == TCET_NORMAL && + width == entry->virtual_width && + height == entry->virtual_height && + full_format == entry->format && + entry->num_mipmaps > maxlevel) || + (entry->type == TCET_EC_DYNAMIC && + entry->native_width == width && + entry->native_height == height)) { // reuse the texture } @@ -449,7 +453,7 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int const stage, expandedHeight = height; // If we thought we could reuse the texture before, make sure to pool it now! - if(entry) + if (entry) { delete entry; entry = nullptr; @@ -750,7 +754,7 @@ void TextureCache::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFormat ColorMask[4] = ColorMask[7] = 1.0f / 15.0f; cbufid = 16; - if(!efbHasAlpha) { + if (!efbHasAlpha) { ColorMask[3] = 0.0f; fConstAdd[3] = 1.0f; cbufid = 17; @@ -760,7 +764,7 @@ void TextureCache::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFormat colmat[0] = colmat[4] = colmat[8] = colmat[15] = 1.0f; cbufid = 18; - if(!efbHasAlpha) { + if (!efbHasAlpha) { ColorMask[3] = 0.0f; fConstAdd[3] = 1.0f; cbufid = 19; @@ -771,7 +775,7 @@ void TextureCache::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFormat colmat[3] = colmat[7] = colmat[11] = colmat[15] = 1.0f; cbufid = 20; - if(!efbHasAlpha) { + if (!efbHasAlpha) { ColorMask[3] = 0.0f; fConstAdd[0] = 1.0f; fConstAdd[1] = 1.0f; @@ -818,7 +822,7 @@ void TextureCache::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFormat ColorMask[7] = 1.0f / 7.0f; cbufid = 27; - if(!efbHasAlpha) { + if (!efbHasAlpha) { ColorMask[3] = 0.0f; fConstAdd[3] = 1.0f; cbufid = 28; @@ -828,7 +832,7 @@ void TextureCache::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFormat colmat[0] = colmat[5] = colmat[10] = colmat[15] = 1.0f; cbufid = 29; - if(!efbHasAlpha) { + if (!efbHasAlpha) { ColorMask[3] = 0.0f; fConstAdd[3] = 1.0f; cbufid = 30; -- cgit v1.2.3 From a82675b7d581421fa80d5d5c53253cf1d5c1a26d Mon Sep 17 00:00:00 2001 From: Lioncash Date: Wed, 12 Mar 2014 15:33:41 -0400 Subject: Kill off some usages of c_str. Also changes some function params, but this is ok. Some simplifications were also able to be made (ie. killing off strcmps with ==, etc). --- Source/Core/VideoCommon/TextureCacheBase.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'Source/Core/VideoCommon/TextureCacheBase.cpp') diff --git a/Source/Core/VideoCommon/TextureCacheBase.cpp b/Source/Core/VideoCommon/TextureCacheBase.cpp index 7bbbc4aff6..6c9ef30e28 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/TextureCacheBase.cpp @@ -47,7 +47,7 @@ TextureCache::TextureCache() TexDecoder_SetTexFmtOverlayOptions(g_ActiveConfig.bTexFmtOverlayEnable, g_ActiveConfig.bTexFmtOverlayCenter); if (g_ActiveConfig.bHiresTextures && !g_ActiveConfig.bDumpTextures) - HiresTextures::Init(SConfig::GetInstance().m_LocalCoreStartupParameter.m_strUniqueID.c_str()); + HiresTextures::Init(SConfig::GetInstance().m_LocalCoreStartupParameter.m_strUniqueID); SetHash64Function(g_ActiveConfig.bHiresTextures || g_ActiveConfig.bDumpTextures); @@ -89,7 +89,7 @@ void TextureCache::OnConfigChanged(VideoConfig& config) g_texture_cache->Invalidate(); if (g_ActiveConfig.bHiresTextures) - HiresTextures::Init(SConfig::GetInstance().m_LocalCoreStartupParameter.m_strUniqueID.c_str()); + HiresTextures::Init(SConfig::GetInstance().m_LocalCoreStartupParameter.m_strUniqueID); SetHash64Function(g_ActiveConfig.bHiresTextures || g_ActiveConfig.bDumpTextures); TexDecoder_SetTexFmtOverlayOptions(g_ActiveConfig.bTexFmtOverlayEnable, g_ActiveConfig.bTexFmtOverlayCenter); @@ -290,8 +290,8 @@ void TextureCache::DumpTexture(TCacheEntryBase* entry, unsigned int level) SConfig::GetInstance().m_LocalCoreStartupParameter.m_strUniqueID; // make sure that the directory exists - if (false == File::Exists(szDir) || false == File::IsDirectory(szDir)) - File::CreateDir(szDir.c_str()); + if (!File::Exists(szDir) || !File::IsDirectory(szDir)) + File::CreateDir(szDir); // For compatibility with old texture packs, don't print the LOD index for level 0. // TODO: TLUT format should actually be stored in filename? :/ @@ -421,8 +421,8 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int const stage, // TODO: Don't we need to force texture decoding to RGBA8 for dynamic EFB copies? // TODO: Actually, it should be enough if the internal texture format matches... if ((entry->type == TCET_NORMAL && - width == entry->virtual_width && - height == entry->virtual_height && + width == entry->virtual_width && + height == entry->virtual_height && full_format == entry->format && entry->num_mipmaps > maxlevel) || (entry->type == TCET_EC_DYNAMIC && -- cgit v1.2.3 From 8941f19cdb01bbe8c40851240d02019ed6e13a32 Mon Sep 17 00:00:00 2001 From: Tony Wasserka Date: Sun, 23 Mar 2014 21:44:23 +0100 Subject: BPMemory: Expose the pixel_format and zformat fields in PE_CONTROL as enumerations. --- Source/Core/VideoCommon/TextureCacheBase.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'Source/Core/VideoCommon/TextureCacheBase.cpp') diff --git a/Source/Core/VideoCommon/TextureCacheBase.cpp b/Source/Core/VideoCommon/TextureCacheBase.cpp index 6c9ef30e28..04b25cb4fc 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/TextureCacheBase.cpp @@ -572,7 +572,7 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int const stage, return ReturnEntry(stage, entry); } -void TextureCache::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFormat, unsigned int srcFormat, +void TextureCache::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFormat, PEControl::PixelFormat srcFormat, const EFBRectangle& srcRect, bool isIntensity, bool scaleByHalf) { // Emulation methods: @@ -623,9 +623,9 @@ void TextureCache::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFormat ColorMask[0] = ColorMask[1] = ColorMask[2] = ColorMask[3] = 255.0f; ColorMask[4] = ColorMask[5] = ColorMask[6] = ColorMask[7] = 1.0f / 255.0f; unsigned int cbufid = -1; - bool efbHasAlpha = bpmem.zcontrol.pixel_format == PIXELFMT_RGBA6_Z24; + bool efbHasAlpha = bpmem.zcontrol.pixel_format == PEControl::RGBA6_Z24; - if (srcFormat == PIXELFMT_Z24) + if (srcFormat == PEControl::Z24) { switch (dstFormat) { -- cgit v1.2.3 From 664c8d30a055f4762a2a60be77c1c8eaec1a5d85 Mon Sep 17 00:00:00 2001 From: Pierre Bourdon Date: Sat, 29 Mar 2014 11:05:44 +0100 Subject: Remove all trailing whitespaces from our codebase. --- Source/Core/VideoCommon/TextureCacheBase.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'Source/Core/VideoCommon/TextureCacheBase.cpp') diff --git a/Source/Core/VideoCommon/TextureCacheBase.cpp b/Source/Core/VideoCommon/TextureCacheBase.cpp index 04b25cb4fc..6742ac21c5 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/TextureCacheBase.cpp @@ -752,7 +752,7 @@ void TextureCache::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFormat colmat[0] = colmat[4] = colmat[8] = colmat[15] = 1.0f; ColorMask[0] = ColorMask[3] = 15.0f; ColorMask[4] = ColorMask[7] = 1.0f / 15.0f; - + cbufid = 16; if (!efbHasAlpha) { ColorMask[3] = 0.0f; @@ -762,7 +762,7 @@ void TextureCache::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFormat break; case 3: // RA8 colmat[0] = colmat[4] = colmat[8] = colmat[15] = 1.0f; - + cbufid = 18; if (!efbHasAlpha) { ColorMask[3] = 0.0f; @@ -773,7 +773,7 @@ void TextureCache::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFormat case 7: // A8 colmat[3] = colmat[7] = colmat[11] = colmat[15] = 1.0f; - + cbufid = 20; if (!efbHasAlpha) { ColorMask[3] = 0.0f; @@ -820,7 +820,7 @@ void TextureCache::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFormat ColorMask[4] = ColorMask[5] = ColorMask[6] = 1.0f / 31.0f; ColorMask[3] = 7.0f; ColorMask[7] = 1.0f / 7.0f; - + cbufid = 27; if (!efbHasAlpha) { ColorMask[3] = 0.0f; @@ -830,7 +830,7 @@ void TextureCache::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFormat break; case 6: // RGBA8 colmat[0] = colmat[5] = colmat[10] = colmat[15] = 1.0f; - + cbufid = 29; if (!efbHasAlpha) { ColorMask[3] = 0.0f; -- cgit v1.2.3 From 49b0eef393f4d321928fb0b6093d58a7637cf1da Mon Sep 17 00:00:00 2001 From: Lioncash Date: Fri, 2 May 2014 22:47:04 -0400 Subject: Remove the min/max functions in CommonFuncs. The algorithm header has the same functions. --- Source/Core/VideoCommon/TextureCacheBase.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'Source/Core/VideoCommon/TextureCacheBase.cpp') diff --git a/Source/Core/VideoCommon/TextureCacheBase.cpp b/Source/Core/VideoCommon/TextureCacheBase.cpp index 6742ac21c5..33ac8e604b 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/TextureCacheBase.cpp @@ -2,6 +2,8 @@ // Licensed under GPLv2 // Refer to the license.txt file included. +#include + #include "Common/FileUtil.h" #include "Common/MemoryUtil.h" @@ -386,7 +388,7 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int const stage, // D3D doesn't like when the specified mipmap count would require more than one 1x1-sized LOD in the mipmap chain // e.g. 64x64 with 7 LODs would have the mipmap chain 64x64,32x32,16x16,8x8,4x4,2x2,1x1,1x1, so we limit the mipmap count to 6 there - while (g_ActiveConfig.backend_info.bUseMinimalMipCount && max(expandedWidth, expandedHeight) >> maxlevel == 0) + while (g_ActiveConfig.backend_info.bUseMinimalMipCount && std::max(expandedWidth, expandedHeight) >> maxlevel == 0) --maxlevel; TCacheEntryBase *entry = textures[texID]; -- cgit v1.2.3 From ce54c1e571a7f79c173dd8f949003255ba95670a Mon Sep 17 00:00:00 2001 From: Lioncash Date: Tue, 3 Jun 2014 01:08:54 -0400 Subject: Kill off replaceable usages of s[n]printf. --- Source/Core/VideoCommon/TextureCacheBase.cpp | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) (limited to 'Source/Core/VideoCommon/TextureCacheBase.cpp') diff --git a/Source/Core/VideoCommon/TextureCacheBase.cpp b/Source/Core/VideoCommon/TextureCacheBase.cpp index 33ac8e604b..edb0f49ac2 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/TextureCacheBase.cpp @@ -3,9 +3,11 @@ // Refer to the license.txt file included. #include +#include #include "Common/FileUtil.h" #include "Common/MemoryUtil.h" +#include "Common/StringUtil.h" #include "Core/ConfigManager.h" #include "Core/HW/Memmap.h" @@ -227,36 +229,34 @@ bool TextureCache::CheckForCustomTextureLODs(u64 tex_hash, int texformat, unsign return false; // 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); + 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) { - sprintf(texPathTemp, "%s_mip%u", texBasePathTemp, 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); + 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& width, unsigned int& height) { - char texPathTemp[MAX_PATH]; + std::string texPathTemp; unsigned int newWidth = 0; unsigned int newHeight = 0; u32 tex_hash_u32 = tex_hash & 0x00000000FFFFFFFFLL; if (level == 0) - sprintf(texPathTemp, "%s_%08x_%i", SConfig::GetInstance().m_LocalCoreStartupParameter.m_strUniqueID.c_str(), tex_hash_u32, texformat); + texPathTemp = StringFromFormat("%s_%08x_%i", SConfig::GetInstance().m_LocalCoreStartupParameter.m_strUniqueID.c_str(), tex_hash_u32, texformat); else - sprintf(texPathTemp, "%s_%08x_%i_mip%u", SConfig::GetInstance().m_LocalCoreStartupParameter.m_strUniqueID.c_str(), tex_hash_u32, texformat, level); + 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); @@ -273,11 +273,11 @@ PC_TexFormat TextureCache::LoadCustomTexture(u64 tex_hash, int texformat, unsign if (ret != PC_TEX_FMT_NONE) { 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, width, 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, width, height); + 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, width, 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); width = newWidth; height = newHeight; -- cgit v1.2.3 From 6d3f249dcc746cc7845ef88ddb8ce3bcc9221aca Mon Sep 17 00:00:00 2001 From: degasus Date: Tue, 8 Jul 2014 15:58:25 +0200 Subject: mark all local variables as static --- Source/Core/VideoCommon/TextureCacheBase.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Source/Core/VideoCommon/TextureCacheBase.cpp') diff --git a/Source/Core/VideoCommon/TextureCacheBase.cpp b/Source/Core/VideoCommon/TextureCacheBase.cpp index edb0f49ac2..33d6b3b919 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/TextureCacheBase.cpp @@ -36,7 +36,7 @@ TextureCache::TexCache TextureCache::textures; TextureCache::BackupConfig TextureCache::backup_config; -bool invalidate_texture_cache_requested; +static bool invalidate_texture_cache_requested; TextureCache::TCacheEntryBase::~TCacheEntryBase() { -- cgit v1.2.3 From 81ed17be53e7fed93147dc0d334a6c1d45f4e3c8 Mon Sep 17 00:00:00 2001 From: degasus Date: Tue, 8 Jul 2014 16:49:33 +0200 Subject: avoid the extern keyword in .cpp files --- Source/Core/VideoCommon/TextureCacheBase.cpp | 3 --- 1 file changed, 3 deletions(-) (limited to 'Source/Core/VideoCommon/TextureCacheBase.cpp') diff --git a/Source/Core/VideoCommon/TextureCacheBase.cpp b/Source/Core/VideoCommon/TextureCacheBase.cpp index 33d6b3b919..d43e209a72 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/TextureCacheBase.cpp @@ -19,9 +19,6 @@ #include "VideoCommon/TextureCacheBase.h" #include "VideoCommon/VideoConfig.h" -// ugly -extern int frameCount; - enum { TEXTURE_KILL_THRESHOLD = 200, -- cgit v1.2.3 From 4af8d9d2487c58953e919769db33b20bc062d6ea Mon Sep 17 00:00:00 2001 From: Lioncash Date: Sat, 30 Aug 2014 16:51:27 -0400 Subject: VideoCommon: Clean up brace placements --- Source/Core/VideoCommon/TextureCacheBase.cpp | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) (limited to 'Source/Core/VideoCommon/TextureCacheBase.cpp') diff --git a/Source/Core/VideoCommon/TextureCacheBase.cpp b/Source/Core/VideoCommon/TextureCacheBase.cpp index d43e209a72..9e8cb9387f 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/TextureCacheBase.cpp @@ -753,7 +753,8 @@ void TextureCache::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFormat ColorMask[4] = ColorMask[7] = 1.0f / 15.0f; cbufid = 16; - if (!efbHasAlpha) { + if (!efbHasAlpha) + { ColorMask[3] = 0.0f; fConstAdd[3] = 1.0f; cbufid = 17; @@ -763,7 +764,8 @@ void TextureCache::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFormat colmat[0] = colmat[4] = colmat[8] = colmat[15] = 1.0f; cbufid = 18; - if (!efbHasAlpha) { + if (!efbHasAlpha) + { ColorMask[3] = 0.0f; fConstAdd[3] = 1.0f; cbufid = 19; @@ -774,7 +776,8 @@ void TextureCache::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFormat colmat[3] = colmat[7] = colmat[11] = colmat[15] = 1.0f; cbufid = 20; - if (!efbHasAlpha) { + if (!efbHasAlpha) + { ColorMask[3] = 0.0f; fConstAdd[0] = 1.0f; fConstAdd[1] = 1.0f; @@ -821,7 +824,8 @@ void TextureCache::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFormat ColorMask[7] = 1.0f / 7.0f; cbufid = 27; - if (!efbHasAlpha) { + if (!efbHasAlpha) + { ColorMask[3] = 0.0f; fConstAdd[3] = 1.0f; cbufid = 28; @@ -831,7 +835,8 @@ void TextureCache::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFormat colmat[0] = colmat[5] = colmat[10] = colmat[15] = 1.0f; cbufid = 29; - if (!efbHasAlpha) { + if (!efbHasAlpha) + { ColorMask[3] = 0.0f; fConstAdd[3] = 1.0f; cbufid = 30; -- cgit v1.2.3 From d8d9bc8c6c679d86fef3b0f3f547ea584d30c561 Mon Sep 17 00:00:00 2001 From: Yuriy O'Donnell Date: Thu, 12 Jun 2014 01:04:42 +0200 Subject: Render: Implemented simple render target pool This avoids creating and destroying render targets every frame, which is a significant CPU overhead. Old render targets are destroyed after 3 frames. --- Source/Core/VideoCommon/TextureCacheBase.cpp | 62 ++++++++++++++++++++++++++-- 1 file changed, 59 insertions(+), 3 deletions(-) (limited to 'Source/Core/VideoCommon/TextureCacheBase.cpp') diff --git a/Source/Core/VideoCommon/TextureCacheBase.cpp b/Source/Core/VideoCommon/TextureCacheBase.cpp index 9e8cb9387f..0bbc336a31 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/TextureCacheBase.cpp @@ -22,6 +22,7 @@ enum { TEXTURE_KILL_THRESHOLD = 200, + RENDER_TARGET_KILL_THRESHOLD = 3, }; TextureCache *g_texture_cache; @@ -30,6 +31,7 @@ GC_ALIGNED16(u8 *TextureCache::temp) = nullptr; unsigned int TextureCache::temp_size; TextureCache::TexCache TextureCache::textures; +TextureCache::RenderTargetPool TextureCache::render_target_pool; TextureCache::BackupConfig TextureCache::backup_config; @@ -67,6 +69,12 @@ void TextureCache::Invalidate() delete tex.second; } textures.clear(); + + for (auto& rt : render_target_pool) + { + delete rt; + } + render_target_pool.clear(); } TextureCache::~TextureCache() @@ -138,6 +146,22 @@ void TextureCache::Cleanup() ++iter; } } + + for (size_t i = 0; i < render_target_pool.size();) + { + auto rt = render_target_pool[i]; + + if (frameCount > RENDER_TARGET_KILL_THRESHOLD + rt->frameCount) + { + delete rt; + render_target_pool[i] = render_target_pool.back(); + render_target_pool.pop_back(); + } + else + { + ++i; + } + } } void TextureCache::InvalidateRange(u32 start_address, u32 size) @@ -868,8 +892,17 @@ void TextureCache::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFormat } else if (!(entry->type == TCET_EC_VRAM && entry->virtual_width == scaled_tex_w && entry->virtual_height == scaled_tex_h)) { - // remove it and recreate it as a render target - delete entry; + if (entry->type == TCET_EC_VRAM) + { + // try to re-use this render target later + FreeRenderTarget(entry); + } + else + { + // remove it and recreate it as a render target + delete entry; + } + entry = nullptr; } } @@ -877,7 +910,7 @@ void TextureCache::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFormat if (nullptr == entry) { // create the texture - textures[dstAddr] = entry = g_texture_cache->CreateRenderTargetTexture(scaled_tex_w, scaled_tex_h); + textures[dstAddr] = entry = AllocateRenderTarget(scaled_tex_w, scaled_tex_h); // TODO: Using the wrong dstFormat, dumb... entry->SetGeneralParameters(dstAddr, 0, dstFormat, 1); @@ -890,3 +923,26 @@ void TextureCache::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFormat entry->FromRenderTarget(dstAddr, dstFormat, srcFormat, srcRect, isIntensity, scaleByHalf, cbufid, colmat); } + +TextureCache::TCacheEntryBase* TextureCache::AllocateRenderTarget(unsigned int width, unsigned int height) +{ + for (size_t i = 0; i < render_target_pool.size(); ++i) + { + auto rt = render_target_pool[i]; + + if (rt->virtual_width != width || rt->virtual_height != height) + continue; + + render_target_pool[i] = render_target_pool.back(); + render_target_pool.pop_back(); + + return rt; + } + + return g_texture_cache->CreateRenderTargetTexture(width, height); +} + +void TextureCache::FreeRenderTarget(TCacheEntryBase* entry) +{ + render_target_pool.push_back(entry); +} -- cgit v1.2.3 From a8e591dc73fc3b35f888690879673ba0250bda68 Mon Sep 17 00:00:00 2001 From: "Jasper St. Pierre" Date: Sun, 10 Aug 2014 13:39:20 -0400 Subject: VideoCommon: Remove support for decoding to ARGB textures The D3D / OGL backends only ever used RGBA textures, and the Software backend uses its own custom code for sampling. The ARGB path seems to just be dead code. Since ARGB and RGBA formats are similar, I don't think this will make the code more difficult to read or unable to be used as reference. Somebody who wants to use this code to output ARGB can simply modify the MakeRGBA function to put the shift at the other end. --- Source/Core/VideoCommon/TextureCacheBase.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'Source/Core/VideoCommon/TextureCacheBase.cpp') diff --git a/Source/Core/VideoCommon/TextureCacheBase.cpp b/Source/Core/VideoCommon/TextureCacheBase.cpp index 0bbc336a31..ad414e36cc 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/TextureCacheBase.cpp @@ -490,8 +490,7 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int const stage, { if (!(texformat == GX_TF_RGBA8 && from_tmem)) { - pcfmt = TexDecoder_Decode(temp, src_data, expandedWidth, - expandedHeight, texformat, tlutaddr, tlutfmt, g_ActiveConfig.backend_info.bUseRGBATextures); + pcfmt = TexDecoder_Decode(temp, src_data, expandedWidth, expandedHeight, texformat, tlutaddr, tlutfmt); } else { @@ -567,7 +566,7 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int const stage, const u8*& mip_src_data = from_tmem ? ((level % 2) ? ptr_odd : ptr_even) : src_data; - TexDecoder_Decode(temp, mip_src_data, expanded_mip_width, expanded_mip_height, texformat, tlutaddr, tlutfmt, g_ActiveConfig.backend_info.bUseRGBATextures); + TexDecoder_Decode(temp, mip_src_data, expanded_mip_width, expanded_mip_height, texformat, tlutaddr, tlutfmt); mip_src_data += TexDecoder_GetTextureSizeInBytes(expanded_mip_width, expanded_mip_height, texformat); entry->Load(mip_width, mip_height, expanded_mip_width, level); -- cgit v1.2.3 From fcd4ecc94265cc95bf939e517f378447c47df703 Mon Sep 17 00:00:00 2001 From: "Jasper St. Pierre" Date: Sun, 10 Aug 2014 15:04:29 -0400 Subject: TextureDecoder: Add an enum for the TLUT formats Quick code cleanup. The enum names and values come from libogc. --- Source/Core/VideoCommon/TextureCacheBase.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'Source/Core/VideoCommon/TextureCacheBase.cpp') diff --git a/Source/Core/VideoCommon/TextureCacheBase.cpp b/Source/Core/VideoCommon/TextureCacheBase.cpp index ad414e36cc..cbfdb47d62 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/TextureCacheBase.cpp @@ -490,7 +490,7 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int const stage, { if (!(texformat == GX_TF_RGBA8 && from_tmem)) { - pcfmt = TexDecoder_Decode(temp, src_data, expandedWidth, expandedHeight, texformat, tlutaddr, tlutfmt); + pcfmt = TexDecoder_Decode(temp, src_data, expandedWidth, expandedHeight, texformat, tlutaddr, (TlutFormat) tlutfmt); } else { @@ -566,7 +566,7 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int const stage, const u8*& mip_src_data = from_tmem ? ((level % 2) ? ptr_odd : ptr_even) : src_data; - TexDecoder_Decode(temp, mip_src_data, expanded_mip_width, expanded_mip_height, texformat, tlutaddr, tlutfmt); + TexDecoder_Decode(temp, mip_src_data, expanded_mip_width, expanded_mip_height, texformat, tlutaddr, (TlutFormat) tlutfmt); mip_src_data += TexDecoder_GetTextureSizeInBytes(expanded_mip_width, expanded_mip_height, texformat); entry->Load(mip_width, mip_height, expanded_mip_width, level); -- cgit v1.2.3 From ea1245d19121d74b1f8398c4c8a0e66d2bb2f5c7 Mon Sep 17 00:00:00 2001 From: "Jasper St. Pierre" Date: Sun, 10 Aug 2014 15:28:42 -0400 Subject: TextureDecoder: Pass the TLUT address straight into the texture decoder This removes the requirement for the TextureDecoder to have access to global texture memory. --- Source/Core/VideoCommon/TextureCacheBase.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'Source/Core/VideoCommon/TextureCacheBase.cpp') diff --git a/Source/Core/VideoCommon/TextureCacheBase.cpp b/Source/Core/VideoCommon/TextureCacheBase.cpp index cbfdb47d62..c0b46d92b6 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/TextureCacheBase.cpp @@ -490,7 +490,8 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int const stage, { if (!(texformat == GX_TF_RGBA8 && from_tmem)) { - pcfmt = TexDecoder_Decode(temp, src_data, expandedWidth, expandedHeight, texformat, tlutaddr, (TlutFormat) tlutfmt); + const u8* tlut = &texMem[tlutaddr]; + pcfmt = TexDecoder_Decode(temp, src_data, expandedWidth, expandedHeight, texformat, tlut, (TlutFormat) tlutfmt); } else { @@ -566,7 +567,8 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int const stage, const u8*& mip_src_data = from_tmem ? ((level % 2) ? ptr_odd : ptr_even) : src_data; - TexDecoder_Decode(temp, mip_src_data, expanded_mip_width, expanded_mip_height, texformat, tlutaddr, (TlutFormat) tlutfmt); + const u8* tlut = &texMem[tlutaddr]; + TexDecoder_Decode(temp, mip_src_data, expanded_mip_width, expanded_mip_height, texformat, tlut, (TlutFormat) tlutfmt); mip_src_data += TexDecoder_GetTextureSizeInBytes(expanded_mip_width, expanded_mip_height, texformat); entry->Load(mip_width, mip_height, expanded_mip_width, level); -- cgit v1.2.3 From 7f6284c2fcea9d543b0eec44ea0f3ad36bd0c0aa Mon Sep 17 00:00:00 2001 From: comex Date: Thu, 2 Oct 2014 02:20:46 -0400 Subject: Change a bunch of reference function arguments to pointers. Per the coding style and sanity. --- Source/Core/VideoCommon/TextureCacheBase.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'Source/Core/VideoCommon/TextureCacheBase.cpp') diff --git a/Source/Core/VideoCommon/TextureCacheBase.cpp b/Source/Core/VideoCommon/TextureCacheBase.cpp index c0b46d92b6..df28184615 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/TextureCacheBase.cpp @@ -267,7 +267,7 @@ bool TextureCache::CheckForCustomTextureLODs(u64 tex_hash, int texformat, unsign return true; } -PC_TexFormat TextureCache::LoadCustomTexture(u64 tex_hash, int texformat, unsigned int level, unsigned int& width, unsigned int& height) +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; @@ -293,6 +293,7 @@ PC_TexFormat TextureCache::LoadCustomTexture(u64 tex_hash, int texformat, unsign 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) @@ -300,8 +301,8 @@ PC_TexFormat TextureCache::LoadCustomTexture(u64 tex_hash, int texformat, unsign 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); - width = newWidth; - height = newHeight; + *widthp = newWidth; + *heightp = newHeight; } return ret; } @@ -466,8 +467,7 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int const stage, if (g_ActiveConfig.bHiresTextures) { - // This function may modify width/height. - pcfmt = LoadCustomTexture(tex_hash, texformat, 0, width, height); + pcfmt = LoadCustomTexture(tex_hash, texformat, 0, &width, &height); if (pcfmt != PC_TEX_FMT_NONE) { if (expandedWidth != width || expandedHeight != height) @@ -584,7 +584,7 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int const stage, unsigned int mip_width = CalculateLevelSize(width, level); unsigned int mip_height = CalculateLevelSize(height, level); - LoadCustomTexture(tex_hash, texformat, level, mip_width, mip_height); + LoadCustomTexture(tex_hash, texformat, level, &mip_width, &mip_height); entry->Load(mip_width, mip_height, mip_width, level); } } -- cgit v1.2.3 From 733795891cad7894a9d51e23d125157fccd9e5a0 Mon Sep 17 00:00:00 2001 From: Fiora Date: Wed, 12 Nov 2014 21:42:34 -0800 Subject: D3D: fix issues with multi-level 1x1 textures on D3D Fixes NBA 2K11, maybe other things. --- Source/Core/VideoCommon/TextureCacheBase.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Source/Core/VideoCommon/TextureCacheBase.cpp') diff --git a/Source/Core/VideoCommon/TextureCacheBase.cpp b/Source/Core/VideoCommon/TextureCacheBase.cpp index df28184615..0618b3f1b9 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/TextureCacheBase.cpp @@ -410,7 +410,7 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int const stage, // D3D doesn't like when the specified mipmap count would require more than one 1x1-sized LOD in the mipmap chain // e.g. 64x64 with 7 LODs would have the mipmap chain 64x64,32x32,16x16,8x8,4x4,2x2,1x1,1x1, so we limit the mipmap count to 6 there - while (g_ActiveConfig.backend_info.bUseMinimalMipCount && std::max(expandedWidth, expandedHeight) >> maxlevel == 0) + while (g_ActiveConfig.backend_info.bUseMinimalMipCount && std::max(width, height) >> maxlevel == 0) --maxlevel; TCacheEntryBase *entry = textures[texID]; -- cgit v1.2.3 From 5944d15021e39f2356f7fbe1b6a935426bc0bb8a Mon Sep 17 00:00:00 2001 From: Jules Blok Date: Tue, 28 Oct 2014 14:47:13 +0100 Subject: TextureCache: Check the number of layers before reusing a texture. --- Source/Core/VideoCommon/TextureCacheBase.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'Source/Core/VideoCommon/TextureCacheBase.cpp') diff --git a/Source/Core/VideoCommon/TextureCacheBase.cpp b/Source/Core/VideoCommon/TextureCacheBase.cpp index 0618b3f1b9..d4296cc2aa 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/TextureCacheBase.cpp @@ -444,14 +444,15 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int const stage, // // TODO: Don't we need to force texture decoding to RGBA8 for dynamic EFB copies? // TODO: Actually, it should be enough if the internal texture format matches... - if ((entry->type == TCET_NORMAL && + if (((entry->type == TCET_NORMAL && width == entry->virtual_width && height == entry->virtual_height && full_format == entry->format && entry->num_mipmaps > maxlevel) || (entry->type == TCET_EC_DYNAMIC && entry->native_width == width && - entry->native_height == height)) + entry->native_height == height)) && + entry->num_layers == 1) { // reuse the texture } @@ -519,6 +520,7 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int const stage, // But that will currently make the above "existing entry" tests fail as "texLevels" is not calculated until after. // Currently, we might try to reuse a texture which appears to have more levels than actual, maybe.. entry->num_mipmaps = maxlevel + 1; + entry->num_layers = 1; entry->type = TCET_NORMAL; GFX_DEBUGGER_PAUSE_AT(NEXT_NEW_TEXTURE, true); -- cgit v1.2.3 From 4d9589b35f2629c558a9a7efdee3d66497fc0fc6 Mon Sep 17 00:00:00 2001 From: Jules Blok Date: Thu, 30 Oct 2014 15:13:31 +0100 Subject: Cosmetics. --- Source/Core/VideoCommon/TextureCacheBase.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Source/Core/VideoCommon/TextureCacheBase.cpp') diff --git a/Source/Core/VideoCommon/TextureCacheBase.cpp b/Source/Core/VideoCommon/TextureCacheBase.cpp index d4296cc2aa..4037a7470b 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/TextureCacheBase.cpp @@ -452,7 +452,7 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int const stage, (entry->type == TCET_EC_DYNAMIC && entry->native_width == width && entry->native_height == height)) && - entry->num_layers == 1) + entry->num_layers == 1) { // reuse the texture } -- cgit v1.2.3 From ee76c03160b72731facbce135be26d7ef8cebba5 Mon Sep 17 00:00:00 2001 From: Jules Blok Date: Tue, 4 Nov 2014 00:53:14 +0100 Subject: TextureCache: Recompile EFB2Tex shaders when stereo 3D is toggled. --- Source/Core/VideoCommon/TextureCacheBase.cpp | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'Source/Core/VideoCommon/TextureCacheBase.cpp') diff --git a/Source/Core/VideoCommon/TextureCacheBase.cpp b/Source/Core/VideoCommon/TextureCacheBase.cpp index 4037a7470b..651bb90708 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/TextureCacheBase.cpp @@ -115,6 +115,12 @@ void TextureCache::OnConfigChanged(VideoConfig& config) { g_texture_cache->ClearRenderTargets(); } + + if ((config.iStereoMode > 0) != backup_config.s_stereo_3d) + { + g_texture_cache->DeleteShaders(); + g_texture_cache->CompileShaders(); + } } backup_config.s_colorsamples = config.iSafeTextureCache_ColorSamples; @@ -126,6 +132,7 @@ void TextureCache::OnConfigChanged(VideoConfig& config) backup_config.s_texfmt_overlay_center = config.bTexFmtOverlayCenter; backup_config.s_hires_textures = config.bHiresTextures; backup_config.s_copy_cache_enable = config.bEFBCopyCacheEnable; + backup_config.s_stereo_3d = config.iStereoMode > 0; } void TextureCache::Cleanup() -- cgit v1.2.3 From 8210b9c915816cf8f778db1b633f2327897af005 Mon Sep 17 00:00:00 2001 From: Jules Blok Date: Thu, 6 Nov 2014 11:41:39 +0100 Subject: TextureCache: Ensure that all render target textures have as many layers as the frame buffer. Also fixes a case where the D3D code path did not initialize num_layers leading to undefined behaviour. --- Source/Core/VideoCommon/TextureCacheBase.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'Source/Core/VideoCommon/TextureCacheBase.cpp') diff --git a/Source/Core/VideoCommon/TextureCacheBase.cpp b/Source/Core/VideoCommon/TextureCacheBase.cpp index 651bb90708..e057b379ad 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/TextureCacheBase.cpp @@ -538,7 +538,7 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int const stage, entry->Load(width, height, expandedWidth, 0); } - entry->SetGeneralParameters(address, texture_size, full_format, entry->num_mipmaps); + entry->SetGeneralParameters(address, texture_size, full_format, entry->num_mipmaps, entry->num_layers); entry->SetDimensions(nativeW, nativeH, width, height); entry->hash = tex_hash; @@ -895,12 +895,12 @@ void TextureCache::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFormat TCacheEntryBase *entry = textures[dstAddr]; if (entry) { - if (entry->type == TCET_EC_DYNAMIC && entry->native_width == tex_w && entry->native_height == tex_h) + if (entry->type == TCET_EC_DYNAMIC && entry->native_width == tex_w && entry->native_height == tex_h && entry->num_layers == FramebufferManagerBase::GetEFBLayers()) { scaled_tex_w = tex_w; scaled_tex_h = tex_h; } - else if (!(entry->type == TCET_EC_VRAM && entry->virtual_width == scaled_tex_w && entry->virtual_height == scaled_tex_h)) + else if (!(entry->type == TCET_EC_VRAM && entry->virtual_width == scaled_tex_w && entry->virtual_height == scaled_tex_h && entry->num_layers == FramebufferManagerBase::GetEFBLayers())) { if (entry->type == TCET_EC_VRAM) { @@ -923,7 +923,7 @@ void TextureCache::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFormat textures[dstAddr] = entry = AllocateRenderTarget(scaled_tex_w, scaled_tex_h); // TODO: Using the wrong dstFormat, dumb... - entry->SetGeneralParameters(dstAddr, 0, dstFormat, 1); + entry->SetGeneralParameters(dstAddr, 0, dstFormat, 1, FramebufferManagerBase::GetEFBLayers()); entry->SetDimensions(tex_w, tex_h, scaled_tex_w, scaled_tex_h); entry->SetHashes(TEXHASH_INVALID); entry->type = TCET_EC_VRAM; -- cgit v1.2.3 From 0f63186371c4f0bcc784fa8506d18b9514075d29 Mon Sep 17 00:00:00 2001 From: Jules Blok Date: Sat, 8 Nov 2014 16:19:15 +0100 Subject: TextureCache: Add "Mono EFB Depth Copy" stereoscopy option. --- Source/Core/VideoCommon/TextureCacheBase.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'Source/Core/VideoCommon/TextureCacheBase.cpp') diff --git a/Source/Core/VideoCommon/TextureCacheBase.cpp b/Source/Core/VideoCommon/TextureCacheBase.cpp index e057b379ad..7fa540022d 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/TextureCacheBase.cpp @@ -116,7 +116,8 @@ void TextureCache::OnConfigChanged(VideoConfig& config) g_texture_cache->ClearRenderTargets(); } - if ((config.iStereoMode > 0) != backup_config.s_stereo_3d) + if ((config.iStereoMode > 0) != backup_config.s_stereo_3d || + config.bStereoMonoEFBDepth != backup_config.s_mono_efb_depth) { g_texture_cache->DeleteShaders(); g_texture_cache->CompileShaders(); @@ -133,6 +134,7 @@ void TextureCache::OnConfigChanged(VideoConfig& config) backup_config.s_hires_textures = config.bHiresTextures; backup_config.s_copy_cache_enable = config.bEFBCopyCacheEnable; backup_config.s_stereo_3d = config.iStereoMode > 0; + backup_config.s_mono_efb_depth = config.bStereoMonoEFBDepth; } void TextureCache::Cleanup() -- cgit v1.2.3 From 239eaf122a9b4bb1f2c1560a0d1f27115a869195 Mon Sep 17 00:00:00 2001 From: Rohit Nirmal Date: Sat, 29 Nov 2014 09:53:19 -0600 Subject: VideoCommon: Fix -Wsign-compare warnings. --- Source/Core/VideoCommon/TextureCacheBase.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'Source/Core/VideoCommon/TextureCacheBase.cpp') diff --git a/Source/Core/VideoCommon/TextureCacheBase.cpp b/Source/Core/VideoCommon/TextureCacheBase.cpp index 7fa540022d..e468dcca85 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/TextureCacheBase.cpp @@ -893,16 +893,17 @@ void TextureCache::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFormat unsigned int scaled_tex_w = g_ActiveConfig.bCopyEFBScaled ? Renderer::EFBToScaledX(tex_w) : tex_w; unsigned int scaled_tex_h = g_ActiveConfig.bCopyEFBScaled ? Renderer::EFBToScaledY(tex_h) : tex_h; + const unsigned int efb_layers = FramebufferManagerBase::GetEFBLayers(); TCacheEntryBase *entry = textures[dstAddr]; if (entry) { - if (entry->type == TCET_EC_DYNAMIC && entry->native_width == tex_w && entry->native_height == tex_h && entry->num_layers == FramebufferManagerBase::GetEFBLayers()) + if (entry->type == TCET_EC_DYNAMIC && entry->native_width == tex_w && entry->native_height == tex_h && entry->num_layers == efb_layers) { scaled_tex_w = tex_w; scaled_tex_h = tex_h; } - else if (!(entry->type == TCET_EC_VRAM && entry->virtual_width == scaled_tex_w && entry->virtual_height == scaled_tex_h && entry->num_layers == FramebufferManagerBase::GetEFBLayers())) + else if (!(entry->type == TCET_EC_VRAM && entry->virtual_width == scaled_tex_w && entry->virtual_height == scaled_tex_h && entry->num_layers == efb_layers)) { if (entry->type == TCET_EC_VRAM) { @@ -925,7 +926,7 @@ void TextureCache::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFormat textures[dstAddr] = entry = AllocateRenderTarget(scaled_tex_w, scaled_tex_h); // TODO: Using the wrong dstFormat, dumb... - entry->SetGeneralParameters(dstAddr, 0, dstFormat, 1, FramebufferManagerBase::GetEFBLayers()); + entry->SetGeneralParameters(dstAddr, 0, dstFormat, 1, efb_layers); entry->SetDimensions(tex_w, tex_h, scaled_tex_w, scaled_tex_h); entry->SetHashes(TEXHASH_INVALID); entry->type = TCET_EC_VRAM; -- cgit v1.2.3 From 31a55384b32990205c61f5ffb46484b2a2046d61 Mon Sep 17 00:00:00 2001 From: Jules Blok Date: Wed, 24 Dec 2014 23:06:44 +0100 Subject: VideoConfig: Rename "StereoMonoEFBDepth" to "StereoEFBMonoDepth" Makes a little bit more sense. --- Source/Core/VideoCommon/TextureCacheBase.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'Source/Core/VideoCommon/TextureCacheBase.cpp') diff --git a/Source/Core/VideoCommon/TextureCacheBase.cpp b/Source/Core/VideoCommon/TextureCacheBase.cpp index e468dcca85..a005da3754 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/TextureCacheBase.cpp @@ -117,7 +117,7 @@ void TextureCache::OnConfigChanged(VideoConfig& config) } if ((config.iStereoMode > 0) != backup_config.s_stereo_3d || - config.bStereoMonoEFBDepth != backup_config.s_mono_efb_depth) + config.bStereoEFBMonoDepth != backup_config.s_efb_mono_depth) { g_texture_cache->DeleteShaders(); g_texture_cache->CompileShaders(); @@ -134,7 +134,7 @@ void TextureCache::OnConfigChanged(VideoConfig& config) backup_config.s_hires_textures = config.bHiresTextures; backup_config.s_copy_cache_enable = config.bEFBCopyCacheEnable; backup_config.s_stereo_3d = config.iStereoMode > 0; - backup_config.s_mono_efb_depth = config.bStereoMonoEFBDepth; + backup_config.s_efb_mono_depth = config.bStereoEFBMonoDepth; } void TextureCache::Cleanup() -- cgit v1.2.3 From 51bfc4c52a49a01683192fafeeb5dd3506e838c9 Mon Sep 17 00:00:00 2001 From: degasus Date: Mon, 22 Dec 2014 12:53:03 +0100 Subject: VideoCommon: rewrite custom textures --- Source/Core/VideoCommon/TextureCacheBase.cpp | 123 +++++++++------------------ 1 file changed, 40 insertions(+), 83 deletions(-) (limited to 'Source/Core/VideoCommon/TextureCacheBase.cpp') diff --git a/Source/Core/VideoCommon/TextureCacheBase.cpp b/Source/Core/VideoCommon/TextureCacheBase.cpp index a005da3754..2674cb0c3d 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/TextureCacheBase.cpp @@ -28,7 +28,7 @@ enum TextureCache *g_texture_cache; GC_ALIGNED16(u8 *TextureCache::temp) = nullptr; -unsigned int TextureCache::temp_size; +size_t TextureCache::temp_size; TextureCache::TexCache TextureCache::textures; 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() { temp_size = 2048 * 2048 * 4; @@ -50,7 +60,7 @@ TextureCache::TextureCache() TexDecoder_SetTexFmtOverlayOptions(g_ActiveConfig.bTexFmtOverlayEnable, g_ActiveConfig.bTexFmtOverlayCenter); 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); @@ -98,7 +108,7 @@ void TextureCache::OnConfigChanged(VideoConfig& config) g_texture_cache->Invalidate(); 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); 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) { 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) tex_hash = GetHash64(src_data, texture_size, g_ActiveConfig.iSafeTextureCache_ColorSamples); + u32 palette_size = 0; 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); // 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 hires_tex; if (g_ActiveConfig.bHiresTextures) { - pcfmt = LoadCustomTexture(tex_hash, texformat, 0, &width, &height); - if (pcfmt != PC_TEX_FMT_NONE) + hires_tex.reset(HiresTexture::Search( + 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; - expandedHeight = height; + width = l.width; + height = l.height; // If we thought we could reuse the texture before, make sure to pool it now! if (entry) @@ -492,11 +446,15 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int const stage, 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)) { @@ -511,7 +469,7 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int const stage, } 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 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) @@ -549,7 +507,7 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int const stage, else entry->type = TCET_NORMAL; - if (g_ActiveConfig.bDumpTextures && !using_custom_texture) + if (g_ActiveConfig.bDumpTextures && !hires_tex) DumpTexture(entry, 0); u32 level = 1; @@ -592,11 +550,10 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int const stage, { for (; level != texLevels; ++level) { - unsigned int mip_width = CalculateLevelSize(width, level); - unsigned int mip_height = CalculateLevelSize(height, level); - - LoadCustomTexture(tex_hash, texformat, level, &mip_width, &mip_height); - entry->Load(mip_width, mip_height, mip_width, level); + auto& l = hires_tex->m_levels[level]; + CheckTempSize(l.data_size); + memcpy(temp, l.data, l.data_size); + entry->Load(l.width, l.height, l.width, level); } } } -- cgit v1.2.3 From f8184858dae55306b464b5d56c9cde8ecbfad8a1 Mon Sep 17 00:00:00 2001 From: degasus Date: Mon, 22 Dec 2014 22:33:38 +0100 Subject: VideoCommon: Merge code to generate texture names on dumping --- Source/Core/VideoCommon/TextureCacheBase.cpp | 31 ++++++++++++++-------------- 1 file changed, 15 insertions(+), 16 deletions(-) (limited to 'Source/Core/VideoCommon/TextureCacheBase.cpp') diff --git a/Source/Core/VideoCommon/TextureCacheBase.cpp b/Source/Core/VideoCommon/TextureCacheBase.cpp index 2674cb0c3d..3d9ea0c99d 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/TextureCacheBase.cpp @@ -263,9 +263,8 @@ void TextureCache::ClearRenderTargets() } } -void TextureCache::DumpTexture(TCacheEntryBase* entry, unsigned int level) +void TextureCache::DumpTexture(TCacheEntryBase* entry, std::string basename, unsigned int level) { - std::string filename; std::string szDir = File::GetUserPath(D_DUMPTEXTURES_IDX) + SConfig::GetInstance().m_LocalCoreStartupParameter.m_strUniqueID; @@ -273,20 +272,11 @@ void TextureCache::DumpTexture(TCacheEntryBase* entry, unsigned int level) if (!File::Exists(szDir) || !File::IsDirectory(szDir)) File::CreateDir(szDir); - // 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) + if (level > 0) { - filename = StringFromFormat("%s/%s_%08x_%i.png", szDir.c_str(), - SConfig::GetInstance().m_LocalCoreStartupParameter.m_strUniqueID.c_str(), - (u32)(entry->hash & 0x00000000FFFFFFFFLL), entry->format & 0xFFFF); - } - else - { - filename = StringFromFormat("%s/%s_%08x_%i_mip%i.png", szDir.c_str(), - SConfig::GetInstance().m_LocalCoreStartupParameter.m_strUniqueID.c_str(), - (u32) (entry->hash & 0x00000000FFFFFFFFLL), entry->format & 0xFFFF, level); + basename += StringFromFormat("_mip%i", level); } + std::string filename = szDir + "/" + basename + ".png"; if (!File::Exists(filename)) entry->Save(filename, level); @@ -507,8 +497,17 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int const stage, else entry->type = TCET_NORMAL; + std::string basename = ""; if (g_ActiveConfig.bDumpTextures && !hires_tex) - DumpTexture(entry, 0); + { + basename = HiresTexture::GenBaseName( + src_data, texture_size, + &texMem[tlutaddr], palette_size, + width, height, + texformat + ); + DumpTexture(entry, basename, 0); + } u32 level = 1; // load mips - TODO: Loading mipmaps from tmem is untested! @@ -543,7 +542,7 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int const stage, entry->Load(mip_width, mip_height, expanded_mip_width, level); if (g_ActiveConfig.bDumpTextures) - DumpTexture(entry, level); + DumpTexture(entry, basename, level); } } else if (using_custom_lods) -- cgit v1.2.3 From c6dd5044d6accb22441893afaa1338b0c93b769d Mon Sep 17 00:00:00 2001 From: degasus Date: Mon, 22 Dec 2014 22:35:08 +0100 Subject: VideoCommon: make hash independet from hires textures --- Source/Core/VideoCommon/TextureCacheBase.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'Source/Core/VideoCommon/TextureCacheBase.cpp') diff --git a/Source/Core/VideoCommon/TextureCacheBase.cpp b/Source/Core/VideoCommon/TextureCacheBase.cpp index 3d9ea0c99d..5654fb1fa9 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/TextureCacheBase.cpp @@ -62,7 +62,7 @@ TextureCache::TextureCache() if (g_ActiveConfig.bHiresTextures && !g_ActiveConfig.bDumpTextures) HiresTexture::Init(SConfig::GetInstance().m_LocalCoreStartupParameter.m_strUniqueID); - SetHash64Function(g_ActiveConfig.bHiresTextures || g_ActiveConfig.bDumpTextures); + SetHash64Function(); invalidate_texture_cache_requested = false; } @@ -110,7 +110,6 @@ void TextureCache::OnConfigChanged(VideoConfig& config) if (g_ActiveConfig.bHiresTextures) HiresTexture::Init(SConfig::GetInstance().m_LocalCoreStartupParameter.m_strUniqueID); - SetHash64Function(g_ActiveConfig.bHiresTextures || g_ActiveConfig.bDumpTextures); TexDecoder_SetTexFmtOverlayOptions(g_ActiveConfig.bTexFmtOverlayEnable, g_ActiveConfig.bTexFmtOverlayCenter); invalidate_texture_cache_requested = false; -- cgit v1.2.3 From 4d1face5407e7718f159b357a4da6bd0464df5d5 Mon Sep 17 00:00:00 2001 From: Tillmann Karras Date: Wed, 7 Jan 2015 21:48:59 +0100 Subject: Fix indentation --- Source/Core/VideoCommon/TextureCacheBase.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Source/Core/VideoCommon/TextureCacheBase.cpp') diff --git a/Source/Core/VideoCommon/TextureCacheBase.cpp b/Source/Core/VideoCommon/TextureCacheBase.cpp index a005da3754..76bd93e2ec 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/TextureCacheBase.cpp @@ -144,7 +144,7 @@ void TextureCache::Cleanup() while (iter != tcend) { if (frameCount > TEXTURE_KILL_THRESHOLD + iter->second->frameCount && - // EFB copies living on the host GPU are unrecoverable and thus shouldn't be deleted + // EFB copies living on the host GPU are unrecoverable and thus shouldn't be deleted !iter->second->IsEfbCopy()) { delete iter->second; -- cgit v1.2.3 From 614d058db14f4a282e27a8c21402f45cfaa5be88 Mon Sep 17 00:00:00 2001 From: degasus Date: Mon, 19 May 2014 22:35:53 +0200 Subject: TexCache: don't load tex level 0 on creation This reverts an optimization which isn't worth imo. Every texture uploads have to alloc vram and a staging buffer, so there is no need to do both in the same call. --- Source/Core/VideoCommon/TextureCacheBase.cpp | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'Source/Core/VideoCommon/TextureCacheBase.cpp') diff --git a/Source/Core/VideoCommon/TextureCacheBase.cpp b/Source/Core/VideoCommon/TextureCacheBase.cpp index 143a26cbd1..a539f561a3 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/TextureCacheBase.cpp @@ -481,16 +481,14 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int const stage, GFX_DEBUGGER_PAUSE_AT(NEXT_NEW_TEXTURE, true); } - else - { - // load texture (CreateTexture also loads level 0) - entry->Load(width, height, expandedWidth, 0); - } entry->SetGeneralParameters(address, texture_size, full_format, entry->num_mipmaps, entry->num_layers); entry->SetDimensions(nativeW, nativeH, width, height); entry->hash = tex_hash; + // load texture + entry->Load(width, height, expandedWidth, 0); + if (entry->IsEfbCopy() && !g_ActiveConfig.bCopyEFBToTexture) entry->type = TCET_EC_DYNAMIC; else -- cgit v1.2.3 From 38f42da55aa49d438fda123ccd7c7126e23714f4 Mon Sep 17 00:00:00 2001 From: degasus Date: Wed, 5 Nov 2014 22:09:39 +0100 Subject: TexCache: remove expanded_width This variable isn't use any more. --- Source/Core/VideoCommon/TextureCacheBase.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Source/Core/VideoCommon/TextureCacheBase.cpp') diff --git a/Source/Core/VideoCommon/TextureCacheBase.cpp b/Source/Core/VideoCommon/TextureCacheBase.cpp index a539f561a3..ce9b724b8f 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/TextureCacheBase.cpp @@ -466,7 +466,7 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int const stage, // create the entry/texture if (nullptr == entry) { - textures[texID] = entry = g_texture_cache->CreateTexture(width, height, expandedWidth, texLevels, pcfmt); + textures[texID] = entry = g_texture_cache->CreateTexture(width, height, texLevels, pcfmt); // Sometimes, we can get around recreating a texture if only the number of mip levels changes // e.g. if our texture cache entry got too many mipmap levels we can limit the number of used levels by setting the appropriate render states -- cgit v1.2.3 From dddcea5a9a38ae4832ccf9544d4b097e80df2e34 Mon Sep 17 00:00:00 2001 From: degasus Date: Fri, 16 May 2014 18:41:01 +0200 Subject: TexCache: don't invalidate efb copys because of config changes We'll loose data on invalidating them. So just keep them until a new copy is done. A wrong scaled copy is better than no copy if the game doesn't creates a new one. --- Source/Core/VideoCommon/TextureCacheBase.cpp | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) (limited to 'Source/Core/VideoCommon/TextureCacheBase.cpp') diff --git a/Source/Core/VideoCommon/TextureCacheBase.cpp b/Source/Core/VideoCommon/TextureCacheBase.cpp index ce9b724b8f..70e8f0433f 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/TextureCacheBase.cpp @@ -116,11 +116,7 @@ void TextureCache::OnConfigChanged(VideoConfig& config) } // TODO: Probably shouldn't clear all render targets here, just mark them dirty or something. - if (config.bEFBCopyCacheEnable != backup_config.s_copy_cache_enable || // TODO: not sure if this is needed? - config.bCopyEFBToTexture != backup_config.s_copy_efb_to_texture || - config.bCopyEFBScaled != backup_config.s_copy_efb_scaled || - config.bEFBCopyEnable != backup_config.s_copy_efb || - config.iEFBScale != backup_config.s_efb_scale) + if (config.bEFBCopyCacheEnable != backup_config.s_copy_cache_enable) // TODO: not sure if this is needed? { g_texture_cache->ClearRenderTargets(); } @@ -134,10 +130,6 @@ void TextureCache::OnConfigChanged(VideoConfig& config) } backup_config.s_colorsamples = config.iSafeTextureCache_ColorSamples; - backup_config.s_copy_efb_to_texture = config.bCopyEFBToTexture; - backup_config.s_copy_efb_scaled = config.bCopyEFBScaled; - backup_config.s_copy_efb = config.bEFBCopyEnable; - backup_config.s_efb_scale = config.iEFBScale; backup_config.s_texfmt_overlay = config.bTexFmtOverlayEnable; backup_config.s_texfmt_overlay_center = config.bTexFmtOverlayCenter; backup_config.s_hires_textures = config.bHiresTextures; -- cgit v1.2.3 From 774596dbed35c2d69d8b70d58c4190cb1b42d1ac Mon Sep 17 00:00:00 2001 From: degasus Date: Fri, 16 May 2014 21:57:14 +0200 Subject: TexCache: rename OverlapsMemoryRange --- Source/Core/VideoCommon/TextureCacheBase.cpp | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) (limited to 'Source/Core/VideoCommon/TextureCacheBase.cpp') diff --git a/Source/Core/VideoCommon/TextureCacheBase.cpp b/Source/Core/VideoCommon/TextureCacheBase.cpp index 70e8f0433f..94ac0d2848 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/TextureCacheBase.cpp @@ -181,8 +181,7 @@ void TextureCache::InvalidateRange(u32 start_address, u32 size) tcend = textures.end(); while (iter != tcend) { - const int rangePosition = iter->second->IntersectsMemoryRange(start_address, size); - if (0 == rangePosition) + if (iter->second->OverlapsMemoryRange(start_address, size)) { delete iter->second; textures.erase(iter++); @@ -205,8 +204,7 @@ void TextureCache::MakeRangeDynamic(u32 start_address, u32 size) for (; iter != tcend; ++iter) { - const int rangePosition = iter->second->IntersectsMemoryRange(start_address, size); - if (0 == rangePosition) + if (iter->second->OverlapsMemoryRange(start_address, size)) { iter->second->SetHashes(TEXHASH_INVALID); } @@ -223,15 +221,15 @@ bool TextureCache::Find(u32 start_address, u64 hash) return false; } -int TextureCache::TCacheEntryBase::IntersectsMemoryRange(u32 range_address, u32 range_size) const +bool TextureCache::TCacheEntryBase::OverlapsMemoryRange(u32 range_address, u32 range_size) const { if (addr + size_in_bytes < range_address) - return -1; + return false; if (addr >= range_address + range_size) - return 1; + return false; - return 0; + return true; } void TextureCache::ClearRenderTargets() -- cgit v1.2.3 From 6ba613fbd3e7ecca0357adaab2e7fac422480a54 Mon Sep 17 00:00:00 2001 From: degasus Date: Mon, 19 May 2014 18:27:59 +0200 Subject: TexCache: unify global variables --- Source/Core/VideoCommon/TextureCacheBase.cpp | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'Source/Core/VideoCommon/TextureCacheBase.cpp') diff --git a/Source/Core/VideoCommon/TextureCacheBase.cpp b/Source/Core/VideoCommon/TextureCacheBase.cpp index 94ac0d2848..870e79552b 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/TextureCacheBase.cpp @@ -19,11 +19,9 @@ #include "VideoCommon/TextureCacheBase.h" #include "VideoCommon/VideoConfig.h" -enum -{ - TEXTURE_KILL_THRESHOLD = 200, - RENDER_TARGET_KILL_THRESHOLD = 3, -}; +static const u64 TEXHASH_INVALID = 0; +static const int TEXTURE_KILL_THRESHOLD = 200; +static const int RENDER_TARGET_KILL_THRESHOLD = 3; TextureCache *g_texture_cache; -- cgit v1.2.3 From 1c98a43203263b73da32c19085492c94214a56cb Mon Sep 17 00:00:00 2001 From: degasus Date: Mon, 19 May 2014 18:31:38 +0200 Subject: TexCache: clean up frameCount handling --- Source/Core/VideoCommon/TextureCacheBase.cpp | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) (limited to 'Source/Core/VideoCommon/TextureCacheBase.cpp') diff --git a/Source/Core/VideoCommon/TextureCacheBase.cpp b/Source/Core/VideoCommon/TextureCacheBase.cpp index 870e79552b..d963727232 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/TextureCacheBase.cpp @@ -22,6 +22,7 @@ static const u64 TEXHASH_INVALID = 0; static const int TEXTURE_KILL_THRESHOLD = 200; static const int RENDER_TARGET_KILL_THRESHOLD = 3; +static const u64 FRAMECOUNT_INVALID = 0; TextureCache *g_texture_cache; @@ -136,13 +137,17 @@ void TextureCache::OnConfigChanged(VideoConfig& config) backup_config.s_efb_mono_depth = config.bStereoEFBMonoDepth; } -void TextureCache::Cleanup() +void TextureCache::Cleanup(int _frameCount) { TexCache::iterator iter = textures.begin(); TexCache::iterator tcend = textures.end(); while (iter != tcend) { - if (frameCount > TEXTURE_KILL_THRESHOLD + iter->second->frameCount && + if(iter->second->frameCount == FRAMECOUNT_INVALID) + { + iter->second->frameCount = _frameCount; + } + if (_frameCount > TEXTURE_KILL_THRESHOLD + iter->second->frameCount && // EFB copies living on the host GPU are unrecoverable and thus shouldn't be deleted !iter->second->IsEfbCopy()) { @@ -159,7 +164,7 @@ void TextureCache::Cleanup() { auto rt = render_target_pool[i]; - if (frameCount > RENDER_TARGET_KILL_THRESHOLD + rt->frameCount) + if (_frameCount > RENDER_TARGET_KILL_THRESHOLD + rt->frameCount) { delete rt; render_target_pool[i] = render_target_pool.back(); @@ -277,7 +282,7 @@ static u32 CalculateLevelSize(u32 level_0_size, u32 level) // Used by TextureCache::Load static TextureCache::TCacheEntryBase* ReturnEntry(unsigned int stage, TextureCache::TCacheEntryBase* entry) { - entry->frameCount = frameCount; + entry->frameCount = FRAMECOUNT_INVALID; entry->Bind(stage); GFX_DEBUGGER_PAUSE_AT(NEXT_TEXTURE_CHANGE, true); @@ -873,7 +878,7 @@ void TextureCache::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFormat entry->type = TCET_EC_VRAM; } - entry->frameCount = frameCount; + entry->frameCount = FRAMECOUNT_INVALID; entry->FromRenderTarget(dstAddr, dstFormat, srcFormat, srcRect, isIntensity, scaleByHalf, cbufid, colmat); } -- cgit v1.2.3 From 2b47df07b6e256e04f28e6b28faaa45b9fccf17c Mon Sep 17 00:00:00 2001 From: degasus Date: Sat, 31 May 2014 12:40:22 +0200 Subject: TexCache: use c++11 syntax for std::map::erase --- Source/Core/VideoCommon/TextureCacheBase.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Source/Core/VideoCommon/TextureCacheBase.cpp') diff --git a/Source/Core/VideoCommon/TextureCacheBase.cpp b/Source/Core/VideoCommon/TextureCacheBase.cpp index d963727232..88737a1e95 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/TextureCacheBase.cpp @@ -152,7 +152,7 @@ void TextureCache::Cleanup(int _frameCount) !iter->second->IsEfbCopy()) { delete iter->second; - textures.erase(iter++); + iter = textures.erase(iter); } else { -- cgit v1.2.3 From 1261f5f7f4f15fba126119eda0d0639568e2b101 Mon Sep 17 00:00:00 2001 From: degasus Date: Sun, 11 Jan 2015 12:48:04 +0100 Subject: TextureCache: inline arguments into texture cache --- Source/Core/VideoCommon/TextureCacheBase.cpp | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) (limited to 'Source/Core/VideoCommon/TextureCacheBase.cpp') diff --git a/Source/Core/VideoCommon/TextureCacheBase.cpp b/Source/Core/VideoCommon/TextureCacheBase.cpp index 88737a1e95..561c3e24ea 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/TextureCacheBase.cpp @@ -290,10 +290,20 @@ static TextureCache::TCacheEntryBase* ReturnEntry(unsigned int stage, TextureCac return entry; } -TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int const stage, - u32 const address, unsigned int width, unsigned int height, int const texformat, - unsigned int const tlutaddr, int const tlutfmt, bool const use_mipmaps, unsigned int maxlevel, bool const from_tmem) +TextureCache::TCacheEntryBase* TextureCache::Load(const u32 stage) { + const FourTexUnits &tex = bpmem.tex[stage >> 2]; + const u32 id = stage & 3; + const u32 address = (tex.texImage3[id].image_base/* & 0x1FFFFF*/) << 5; + u32 width = tex.texImage0[id].width + 1; + u32 height = tex.texImage0[id].height + 1; + const int texformat = tex.texImage0[id].format; + const u32 tlutaddr = tex.texTlut[id].tmem_offset << 9; + const u32 tlutfmt = tex.texTlut[id].tlut_format; + const bool use_mipmaps = (tex.texMode0[id].min_filter & 3) != 0; + u32 maxlevel = (tex.texMode1[id].max_lod + 0xf) / 0x10; + const bool from_tmem = tex.texImage1[id].image_type != 0; + if (0 == address) return nullptr; -- cgit v1.2.3 From d640453274099f2cead75df3f137f4b06522d92c Mon Sep 17 00:00:00 2001 From: degasus Date: Sun, 11 Jan 2015 12:58:27 +0100 Subject: TexCache: cleanup max texture level --- Source/Core/VideoCommon/TextureCacheBase.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'Source/Core/VideoCommon/TextureCacheBase.cpp') diff --git a/Source/Core/VideoCommon/TextureCacheBase.cpp b/Source/Core/VideoCommon/TextureCacheBase.cpp index 561c3e24ea..99bac2b519 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/TextureCacheBase.cpp @@ -301,7 +301,7 @@ TextureCache::TCacheEntryBase* TextureCache::Load(const u32 stage) const u32 tlutaddr = tex.texTlut[id].tmem_offset << 9; const u32 tlutfmt = tex.texTlut[id].tlut_format; const bool use_mipmaps = (tex.texMode0[id].min_filter & 3) != 0; - u32 maxlevel = (tex.texMode1[id].max_lod + 0xf) / 0x10; + u32 tex_levels = (tex.texMode1[id].max_lod + 0xf) / 0x10 + 1; const bool from_tmem = tex.texImage1[id].image_type != 0; if (0 == address) @@ -359,8 +359,8 @@ TextureCache::TCacheEntryBase* TextureCache::Load(const u32 stage) // D3D doesn't like when the specified mipmap count would require more than one 1x1-sized LOD in the mipmap chain // e.g. 64x64 with 7 LODs would have the mipmap chain 64x64,32x32,16x16,8x8,4x4,2x2,1x1,1x1, so we limit the mipmap count to 6 there - while (g_ActiveConfig.backend_info.bUseMinimalMipCount && std::max(width, height) >> maxlevel == 0) - --maxlevel; + while (g_ActiveConfig.backend_info.bUseMinimalMipCount && std::max(width, height) >> (tex_levels - 1) == 0) + --tex_levels; TCacheEntryBase *entry = textures[texID]; if (entry) @@ -383,7 +383,7 @@ TextureCache::TCacheEntryBase* TextureCache::Load(const u32 stage) // 2. b) For normal textures, all texture parameters need to match if (address == entry->addr && tex_hash == entry->hash && full_format == entry->format && - entry->num_mipmaps > maxlevel && entry->native_width == nativeW && entry->native_height == nativeH) + entry->tex_levels >= tex_levels && entry->native_width == nativeW && entry->native_height == nativeH) { return ReturnEntry(stage, entry); } @@ -397,7 +397,7 @@ TextureCache::TCacheEntryBase* TextureCache::Load(const u32 stage) width == entry->virtual_width && height == entry->virtual_height && full_format == entry->format && - entry->num_mipmaps > maxlevel) || + entry->tex_levels >= tex_levels) || (entry->type == TCET_EC_DYNAMIC && entry->native_width == width && entry->native_height == height)) && @@ -460,7 +460,7 @@ TextureCache::TCacheEntryBase* TextureCache::Load(const u32 stage) } } - u32 texLevels = use_mipmaps ? (maxlevel + 1) : 1; + u32 texLevels = use_mipmaps ? tex_levels : 1; 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 const bool use_native_mips = use_mipmaps && !using_custom_lods && (width == nativeW && height == nativeH); @@ -478,14 +478,14 @@ TextureCache::TCacheEntryBase* TextureCache::Load(const u32 stage) // TODO: This is the wrong value. We should be storing the number of levels our actual texture has. // But that will currently make the above "existing entry" tests fail as "texLevels" is not calculated until after. // Currently, we might try to reuse a texture which appears to have more levels than actual, maybe.. - entry->num_mipmaps = maxlevel + 1; + entry->tex_levels = tex_levels; entry->num_layers = 1; entry->type = TCET_NORMAL; GFX_DEBUGGER_PAUSE_AT(NEXT_NEW_TEXTURE, true); } - entry->SetGeneralParameters(address, texture_size, full_format, entry->num_mipmaps, entry->num_layers); + entry->SetGeneralParameters(address, texture_size, full_format, entry->tex_levels, entry->num_layers); entry->SetDimensions(nativeW, nativeH, width, height); entry->hash = tex_hash; -- cgit v1.2.3 From d95e5e2b6fdbdcc7af201a4fc1fa1389bbdf0ad5 Mon Sep 17 00:00:00 2001 From: degasus Date: Sun, 11 Jan 2015 15:03:41 +0100 Subject: TexCache: create a const Config struct --- Source/Core/VideoCommon/TextureCacheBase.cpp | 41 +++++++++++----------------- 1 file changed, 16 insertions(+), 25 deletions(-) (limited to 'Source/Core/VideoCommon/TextureCacheBase.cpp') diff --git a/Source/Core/VideoCommon/TextureCacheBase.cpp b/Source/Core/VideoCommon/TextureCacheBase.cpp index 99bac2b519..fd64f9b701 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/TextureCacheBase.cpp @@ -13,6 +13,7 @@ #include "Core/HW/Memmap.h" #include "VideoCommon/Debugger.h" +#include "VideoCommon/FramebufferManagerBase.h" #include "VideoCommon/HiresTextures.h" #include "VideoCommon/RenderBase.h" #include "VideoCommon/Statistics.h" @@ -383,7 +384,7 @@ TextureCache::TCacheEntryBase* TextureCache::Load(const u32 stage) // 2. b) For normal textures, all texture parameters need to match if (address == entry->addr && tex_hash == entry->hash && full_format == entry->format && - entry->tex_levels >= tex_levels && entry->native_width == nativeW && entry->native_height == nativeH) + entry->config.levels >= tex_levels && entry->native_width == nativeW && entry->native_height == nativeH) { return ReturnEntry(stage, entry); } @@ -394,14 +395,14 @@ TextureCache::TCacheEntryBase* TextureCache::Load(const u32 stage) // TODO: Don't we need to force texture decoding to RGBA8 for dynamic EFB copies? // TODO: Actually, it should be enough if the internal texture format matches... if (((entry->type == TCET_NORMAL && - width == entry->virtual_width && - height == entry->virtual_height && + width == entry->config.width && + height == entry->config.height && full_format == entry->format && - entry->tex_levels >= tex_levels) || + entry->config.levels >= tex_levels) || (entry->type == TCET_EC_DYNAMIC && entry->native_width == width && entry->native_height == height)) && - entry->num_layers == 1) + entry->config.layers == 1) { // reuse the texture } @@ -470,23 +471,13 @@ TextureCache::TCacheEntryBase* TextureCache::Load(const u32 stage) if (nullptr == entry) { textures[texID] = entry = g_texture_cache->CreateTexture(width, height, texLevels, pcfmt); - - // Sometimes, we can get around recreating a texture if only the number of mip levels changes - // e.g. if our texture cache entry got too many mipmap levels we can limit the number of used levels by setting the appropriate render states - // Thus, we don't update this member for every Load, but just whenever the texture gets recreated - - // TODO: This is the wrong value. We should be storing the number of levels our actual texture has. - // But that will currently make the above "existing entry" tests fail as "texLevels" is not calculated until after. - // Currently, we might try to reuse a texture which appears to have more levels than actual, maybe.. - entry->tex_levels = tex_levels; - entry->num_layers = 1; entry->type = TCET_NORMAL; GFX_DEBUGGER_PAUSE_AT(NEXT_NEW_TEXTURE, true); } - entry->SetGeneralParameters(address, texture_size, full_format, entry->tex_levels, entry->num_layers); - entry->SetDimensions(nativeW, nativeH, width, height); + entry->SetGeneralParameters(address, texture_size, full_format); + entry->SetDimensions(nativeW, nativeH); entry->hash = tex_hash; // load texture @@ -854,12 +845,12 @@ void TextureCache::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFormat TCacheEntryBase *entry = textures[dstAddr]; if (entry) { - if (entry->type == TCET_EC_DYNAMIC && entry->native_width == tex_w && entry->native_height == tex_h && entry->num_layers == efb_layers) + if (entry->type == TCET_EC_DYNAMIC && entry->native_width == tex_w && entry->native_height == tex_h && entry->config.layers == efb_layers) { scaled_tex_w = tex_w; scaled_tex_h = tex_h; } - else if (!(entry->type == TCET_EC_VRAM && entry->virtual_width == scaled_tex_w && entry->virtual_height == scaled_tex_h && entry->num_layers == efb_layers)) + else if (!(entry->type == TCET_EC_VRAM && entry->config.width == scaled_tex_w && entry->config.height == scaled_tex_h && entry->config.layers == efb_layers)) { if (entry->type == TCET_EC_VRAM) { @@ -879,11 +870,11 @@ void TextureCache::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFormat if (nullptr == entry) { // create the texture - textures[dstAddr] = entry = AllocateRenderTarget(scaled_tex_w, scaled_tex_h); + textures[dstAddr] = entry = AllocateRenderTarget(scaled_tex_w, scaled_tex_h, FramebufferManagerBase::GetEFBLayers()); // TODO: Using the wrong dstFormat, dumb... - entry->SetGeneralParameters(dstAddr, 0, dstFormat, 1, efb_layers); - entry->SetDimensions(tex_w, tex_h, scaled_tex_w, scaled_tex_h); + entry->SetGeneralParameters(dstAddr, 0, dstFormat); + entry->SetDimensions(tex_w, tex_h); entry->SetHashes(TEXHASH_INVALID); entry->type = TCET_EC_VRAM; } @@ -893,13 +884,13 @@ void TextureCache::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFormat entry->FromRenderTarget(dstAddr, dstFormat, srcFormat, srcRect, isIntensity, scaleByHalf, cbufid, colmat); } -TextureCache::TCacheEntryBase* TextureCache::AllocateRenderTarget(unsigned int width, unsigned int height) +TextureCache::TCacheEntryBase* TextureCache::AllocateRenderTarget(unsigned int width, unsigned int height, unsigned int layers) { for (size_t i = 0; i < render_target_pool.size(); ++i) { auto rt = render_target_pool[i]; - if (rt->virtual_width != width || rt->virtual_height != height) + if (rt->config.width != width || rt->config.height != height || rt->config.layers != layers) continue; render_target_pool[i] = render_target_pool.back(); @@ -908,7 +899,7 @@ TextureCache::TCacheEntryBase* TextureCache::AllocateRenderTarget(unsigned int w return rt; } - return g_texture_cache->CreateRenderTargetTexture(width, height); + return g_texture_cache->CreateRenderTargetTexture(width, height, layers); } void TextureCache::FreeRenderTarget(TCacheEntryBase* entry) -- cgit v1.2.3 From 744b1c162441b296e0af121d5ca6e95761587b6e Mon Sep 17 00:00:00 2001 From: degasus Date: Sun, 11 Jan 2015 15:15:14 +0100 Subject: TexCache: rewrite level calculation --- Source/Core/VideoCommon/TextureCacheBase.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'Source/Core/VideoCommon/TextureCacheBase.cpp') diff --git a/Source/Core/VideoCommon/TextureCacheBase.cpp b/Source/Core/VideoCommon/TextureCacheBase.cpp index fd64f9b701..885c78e9a9 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/TextureCacheBase.cpp @@ -358,10 +358,9 @@ TextureCache::TCacheEntryBase* TextureCache::Load(const u32 stage) tex_hash ^= tlut_hash; } - // D3D doesn't like when the specified mipmap count would require more than one 1x1-sized LOD in the mipmap chain - // e.g. 64x64 with 7 LODs would have the mipmap chain 64x64,32x32,16x16,8x8,4x4,2x2,1x1,1x1, so we limit the mipmap count to 6 there - while (g_ActiveConfig.backend_info.bUseMinimalMipCount && std::max(width, height) >> (tex_levels - 1) == 0) - --tex_levels; + // GPUs don't like when the specified mipmap count would require more than one 1x1-sized LOD in the mipmap chain + // e.g. 64x64 with 7 LODs would have the mipmap chain 64x64,32x32,16x16,8x8,4x4,2x2,1x1,0x0, so we limit the mipmap count to 6 there + tex_levels = std::min(IntLog2(std::max(width, height)) + 1, tex_levels); TCacheEntryBase *entry = textures[texID]; if (entry) -- cgit v1.2.3 From a9eb08b85da62944c1cde1594239a19af4559d02 Mon Sep 17 00:00:00 2001 From: degasus Date: Sun, 11 Jan 2015 22:41:04 +0100 Subject: TexCache: Choose texture based on mipmap count --- Source/Core/VideoCommon/TextureCacheBase.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'Source/Core/VideoCommon/TextureCacheBase.cpp') diff --git a/Source/Core/VideoCommon/TextureCacheBase.cpp b/Source/Core/VideoCommon/TextureCacheBase.cpp index 885c78e9a9..b5418069ca 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/TextureCacheBase.cpp @@ -383,7 +383,7 @@ TextureCache::TCacheEntryBase* TextureCache::Load(const u32 stage) // 2. b) For normal textures, all texture parameters need to match if (address == entry->addr && tex_hash == entry->hash && full_format == entry->format && - entry->config.levels >= tex_levels && entry->native_width == nativeW && entry->native_height == nativeH) + entry->native_levels >= tex_levels && entry->native_width == nativeW && entry->native_height == nativeH) { return ReturnEntry(stage, entry); } @@ -476,7 +476,7 @@ TextureCache::TCacheEntryBase* TextureCache::Load(const u32 stage) } entry->SetGeneralParameters(address, texture_size, full_format); - entry->SetDimensions(nativeW, nativeH); + entry->SetDimensions(nativeW, nativeH, tex_levels); entry->hash = tex_hash; // load texture @@ -873,7 +873,7 @@ void TextureCache::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFormat // TODO: Using the wrong dstFormat, dumb... entry->SetGeneralParameters(dstAddr, 0, dstFormat); - entry->SetDimensions(tex_w, tex_h); + entry->SetDimensions(tex_w, tex_h, 1); entry->SetHashes(TEXHASH_INVALID); entry->type = TCET_EC_VRAM; } -- cgit v1.2.3 From 22e06daf5c41c3d201edba8c22c85df5bafee63b Mon Sep 17 00:00:00 2001 From: degasus Date: Sun, 11 Jan 2015 23:11:04 +0100 Subject: TexCache: recreate the entry on level missmatch --- Source/Core/VideoCommon/TextureCacheBase.cpp | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'Source/Core/VideoCommon/TextureCacheBase.cpp') diff --git a/Source/Core/VideoCommon/TextureCacheBase.cpp b/Source/Core/VideoCommon/TextureCacheBase.cpp index b5418069ca..a2b32410f9 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/TextureCacheBase.cpp @@ -466,6 +466,13 @@ TextureCache::TCacheEntryBase* TextureCache::Load(const u32 stage) 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) + if (entry && entry->config.levels != texLevels) + { + // delete the texture and make a new one + delete entry; + entry = nullptr; + } + // create the entry/texture if (nullptr == entry) { -- cgit v1.2.3 From 96bcb09fb2a4e5146469bd09f1f4c24405169790 Mon Sep 17 00:00:00 2001 From: mimimi085181 Date: Sat, 17 Jan 2015 19:10:00 +0100 Subject: Fix another small bug with the efb2ram cache Textures that are directly next to each other were falsely detected as overlapping. --- Source/Core/VideoCommon/TextureCacheBase.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Source/Core/VideoCommon/TextureCacheBase.cpp') diff --git a/Source/Core/VideoCommon/TextureCacheBase.cpp b/Source/Core/VideoCommon/TextureCacheBase.cpp index a2b32410f9..38449ae5eb 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/TextureCacheBase.cpp @@ -227,7 +227,7 @@ bool TextureCache::Find(u32 start_address, u64 hash) bool TextureCache::TCacheEntryBase::OverlapsMemoryRange(u32 range_address, u32 range_size) const { - if (addr + size_in_bytes < range_address) + if (addr + size_in_bytes <= range_address) return false; if (addr >= range_address + range_size) -- cgit v1.2.3 From 615ae9f10626171fddbbbd0a23cd3e018fc960ef Mon Sep 17 00:00:00 2001 From: degasus Date: Sat, 17 Jan 2015 09:46:31 +0100 Subject: TexCache: remove PC_TexFormat We only support rgba32 for a while now, so there is no need to have everything in common configureable. --- Source/Core/VideoCommon/TextureCacheBase.cpp | 79 +++++++++++++--------------- 1 file changed, 37 insertions(+), 42 deletions(-) (limited to 'Source/Core/VideoCommon/TextureCacheBase.cpp') diff --git a/Source/Core/VideoCommon/TextureCacheBase.cpp b/Source/Core/VideoCommon/TextureCacheBase.cpp index 38449ae5eb..36f059181e 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/TextureCacheBase.cpp @@ -323,7 +323,6 @@ TextureCache::TCacheEntryBase* TextureCache::Load(const u32 stage) u64 tlut_hash = TEXHASH_INVALID; u32 full_format = texformat; - PC_TexFormat pcfmt = PC_TEX_FMT_NONE; const bool isPaletteTexture = (texformat == GX_TF_C4 || texformat == GX_TF_C8 || texformat == GX_TF_C14X2); if (isPaletteTexture) @@ -442,7 +441,6 @@ TextureCache::TCacheEntryBase* TextureCache::Load(const u32 stage) expandedHeight = l.height; CheckTempSize(l.data_size); memcpy(temp, l.data, l.data_size); - pcfmt = PC_TEX_FMT_RGBA32; } } @@ -451,12 +449,12 @@ TextureCache::TCacheEntryBase* TextureCache::Load(const u32 stage) if (!(texformat == GX_TF_RGBA8 && from_tmem)) { const u8* tlut = &texMem[tlutaddr]; - pcfmt = TexDecoder_Decode(temp, src_data, expandedWidth, expandedHeight, texformat, tlut, (TlutFormat) tlutfmt); + TexDecoder_Decode(temp, src_data, expandedWidth, expandedHeight, texformat, tlut, (TlutFormat) tlutfmt); } else { u8* src_data_gb = &texMem[bpmem.tex[stage/4].texImage2[stage%4].tmem_odd * TMEM_LINE_SIZE]; - pcfmt = TexDecoder_DecodeRGBA8FromTmem(temp, src_data, src_data_gb, expandedWidth, expandedHeight); + TexDecoder_DecodeRGBA8FromTmem(temp, src_data, src_data_gb, expandedWidth, expandedHeight); } } @@ -476,7 +474,7 @@ TextureCache::TCacheEntryBase* TextureCache::Load(const u32 stage) // create the entry/texture if (nullptr == entry) { - textures[texID] = entry = g_texture_cache->CreateTexture(width, height, texLevels, pcfmt); + textures[texID] = entry = g_texture_cache->CreateTexture(width, height, texLevels); entry->type = TCET_NORMAL; GFX_DEBUGGER_PAUSE_AT(NEXT_NEW_TEXTURE, true); @@ -508,49 +506,46 @@ TextureCache::TCacheEntryBase* TextureCache::Load(const u32 stage) u32 level = 1; // load mips - TODO: Loading mipmaps from tmem is untested! - if (pcfmt != PC_TEX_FMT_NONE) + if (use_native_mips) { - if (use_native_mips) + src_data += texture_size; + + const u8* ptr_even = nullptr; + const u8* ptr_odd = nullptr; + if (from_tmem) { - src_data += texture_size; + ptr_even = &texMem[bpmem.tex[stage/4].texImage1[stage%4].tmem_even * TMEM_LINE_SIZE + texture_size]; + ptr_odd = &texMem[bpmem.tex[stage/4].texImage2[stage%4].tmem_odd * TMEM_LINE_SIZE]; + } - const u8* ptr_even = nullptr; - const u8* ptr_odd = nullptr; - if (from_tmem) - { - ptr_even = &texMem[bpmem.tex[stage/4].texImage1[stage%4].tmem_even * TMEM_LINE_SIZE + texture_size]; - ptr_odd = &texMem[bpmem.tex[stage/4].texImage2[stage%4].tmem_odd * TMEM_LINE_SIZE]; - } + for (; level != texLevels; ++level) + { + const u32 mip_width = CalculateLevelSize(width, level); + const u32 mip_height = CalculateLevelSize(height, level); + const u32 expanded_mip_width = (mip_width + bsw) & (~bsw); + const u32 expanded_mip_height = (mip_height + bsh) & (~bsh); + + const u8*& mip_src_data = from_tmem + ? ((level % 2) ? ptr_odd : ptr_even) + : src_data; + const u8* tlut = &texMem[tlutaddr]; + TexDecoder_Decode(temp, mip_src_data, expanded_mip_width, expanded_mip_height, texformat, tlut, (TlutFormat) tlutfmt); + mip_src_data += TexDecoder_GetTextureSizeInBytes(expanded_mip_width, expanded_mip_height, texformat); - for (; level != texLevels; ++level) - { - const u32 mip_width = CalculateLevelSize(width, level); - const u32 mip_height = CalculateLevelSize(height, level); - const u32 expanded_mip_width = (mip_width + bsw) & (~bsw); - const u32 expanded_mip_height = (mip_height + bsh) & (~bsh); - - const u8*& mip_src_data = from_tmem - ? ((level % 2) ? ptr_odd : ptr_even) - : src_data; - const u8* tlut = &texMem[tlutaddr]; - TexDecoder_Decode(temp, mip_src_data, expanded_mip_width, expanded_mip_height, texformat, tlut, (TlutFormat) tlutfmt); - mip_src_data += TexDecoder_GetTextureSizeInBytes(expanded_mip_width, expanded_mip_height, texformat); - - entry->Load(mip_width, mip_height, expanded_mip_width, level); - - if (g_ActiveConfig.bDumpTextures) - DumpTexture(entry, basename, level); - } + entry->Load(mip_width, mip_height, expanded_mip_width, level); + + if (g_ActiveConfig.bDumpTextures) + DumpTexture(entry, basename, level); } - else if (using_custom_lods) + } + else if (using_custom_lods) + { + for (; level != texLevels; ++level) { - for (; level != texLevels; ++level) - { - auto& l = hires_tex->m_levels[level]; - CheckTempSize(l.data_size); - memcpy(temp, l.data, l.data_size); - entry->Load(l.width, l.height, l.width, level); - } + auto& l = hires_tex->m_levels[level]; + CheckTempSize(l.data_size); + memcpy(temp, l.data, l.data_size); + entry->Load(l.width, l.height, l.width, level); } } -- cgit v1.2.3 From 6cd6e6546f8a6481bd343fb9d1e22238491c2578 Mon Sep 17 00:00:00 2001 From: degasus Date: Sat, 17 Jan 2015 10:01:41 +0100 Subject: TexCache: merge texture and rendertarget factory function --- Source/Core/VideoCommon/TextureCacheBase.cpp | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) (limited to 'Source/Core/VideoCommon/TextureCacheBase.cpp') diff --git a/Source/Core/VideoCommon/TextureCacheBase.cpp b/Source/Core/VideoCommon/TextureCacheBase.cpp index 36f059181e..a30716f45c 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/TextureCacheBase.cpp @@ -474,7 +474,11 @@ TextureCache::TCacheEntryBase* TextureCache::Load(const u32 stage) // create the entry/texture if (nullptr == entry) { - textures[texID] = entry = g_texture_cache->CreateTexture(width, height, texLevels); + TCacheEntryConfig config; + config.width = width; + config.height = height; + config.levels = texLevels; + textures[texID] = entry = g_texture_cache->CreateTexture(config); entry->type = TCET_NORMAL; GFX_DEBUGGER_PAUSE_AT(NEXT_NEW_TEXTURE, true); @@ -900,7 +904,13 @@ TextureCache::TCacheEntryBase* TextureCache::AllocateRenderTarget(unsigned int w return rt; } - return g_texture_cache->CreateRenderTargetTexture(width, height, layers); + TCacheEntryConfig config; + config.rendertarget = true; + config.width = width; + config.height = height; + config.layers = layers; + + return g_texture_cache->CreateTexture(config); } void TextureCache::FreeRenderTarget(TCacheEntryBase* entry) -- cgit v1.2.3 From 4639d3b1bc3a882461645e0356c894c7d79a28f8 Mon Sep 17 00:00:00 2001 From: degasus Date: Sat, 17 Jan 2015 10:29:10 +0100 Subject: TexCache: also incude textures within the render target pool --- Source/Core/VideoCommon/TextureCacheBase.cpp | 84 +++++++++++++--------------- 1 file changed, 38 insertions(+), 46 deletions(-) (limited to 'Source/Core/VideoCommon/TextureCacheBase.cpp') diff --git a/Source/Core/VideoCommon/TextureCacheBase.cpp b/Source/Core/VideoCommon/TextureCacheBase.cpp index a30716f45c..f87b10aba9 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/TextureCacheBase.cpp @@ -22,7 +22,7 @@ static const u64 TEXHASH_INVALID = 0; static const int TEXTURE_KILL_THRESHOLD = 200; -static const int RENDER_TARGET_KILL_THRESHOLD = 3; +static const int TEXTURE_POOL_KILL_THRESHOLD = 3; static const u64 FRAMECOUNT_INVALID = 0; TextureCache *g_texture_cache; @@ -31,7 +31,7 @@ GC_ALIGNED16(u8 *TextureCache::temp) = nullptr; size_t TextureCache::temp_size; TextureCache::TexCache TextureCache::textures; -TextureCache::RenderTargetPool TextureCache::render_target_pool; +TextureCache::TexturePool TextureCache::texture_pool; TextureCache::BackupConfig TextureCache::backup_config; @@ -80,11 +80,11 @@ void TextureCache::Invalidate() } textures.clear(); - for (auto& rt : render_target_pool) + for (auto& rt : texture_pool) { delete rt; } - render_target_pool.clear(); + texture_pool.clear(); } TextureCache::~TextureCache() @@ -152,7 +152,7 @@ void TextureCache::Cleanup(int _frameCount) // EFB copies living on the host GPU are unrecoverable and thus shouldn't be deleted !iter->second->IsEfbCopy()) { - delete iter->second; + FreeTexture(iter->second); iter = textures.erase(iter); } else @@ -161,15 +161,15 @@ void TextureCache::Cleanup(int _frameCount) } } - for (size_t i = 0; i < render_target_pool.size();) + for (size_t i = 0; i < texture_pool.size();) { - auto rt = render_target_pool[i]; + auto rt = texture_pool[i]; - if (_frameCount > RENDER_TARGET_KILL_THRESHOLD + rt->frameCount) + if (_frameCount > TEXTURE_POOL_KILL_THRESHOLD + rt->frameCount) { delete rt; - render_target_pool[i] = render_target_pool.back(); - render_target_pool.pop_back(); + texture_pool[i] = texture_pool.back(); + texture_pool.pop_back(); } else { @@ -187,7 +187,7 @@ void TextureCache::InvalidateRange(u32 start_address, u32 size) { if (iter->second->OverlapsMemoryRange(start_address, size)) { - delete iter->second; + FreeTexture(iter->second); textures.erase(iter++); } else @@ -246,7 +246,7 @@ void TextureCache::ClearRenderTargets() { if (iter->second->type == TCET_EC_VRAM) { - delete iter->second; + FreeTexture(iter->second); textures.erase(iter++); } else @@ -407,7 +407,7 @@ TextureCache::TCacheEntryBase* TextureCache::Load(const u32 stage) else { // delete the texture and make a new one - delete entry; + FreeTexture(entry); entry = nullptr; } } @@ -433,7 +433,7 @@ TextureCache::TCacheEntryBase* TextureCache::Load(const u32 stage) // If we thought we could reuse the texture before, make sure to pool it now! if (entry) { - delete entry; + FreeTexture(entry); entry = nullptr; } } @@ -467,7 +467,7 @@ TextureCache::TCacheEntryBase* TextureCache::Load(const u32 stage) if (entry && entry->config.levels != texLevels) { // delete the texture and make a new one - delete entry; + FreeTexture(entry); entry = nullptr; } @@ -478,7 +478,7 @@ TextureCache::TCacheEntryBase* TextureCache::Load(const u32 stage) config.width = width; config.height = height; config.levels = texLevels; - textures[texID] = entry = g_texture_cache->CreateTexture(config); + textures[texID] = entry = AllocateTexture(config); entry->type = TCET_NORMAL; GFX_DEBUGGER_PAUSE_AT(NEXT_NEW_TEXTURE, true); @@ -553,7 +553,7 @@ TextureCache::TCacheEntryBase* TextureCache::Load(const u32 stage) } } - INCSTAT(stats.numTexturesCreated); + INCSTAT(stats.numTexturesUploaded); SETSTAT(stats.numTexturesAlive, textures.size()); return ReturnEntry(stage, entry); @@ -857,17 +857,8 @@ void TextureCache::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFormat } else if (!(entry->type == TCET_EC_VRAM && entry->config.width == scaled_tex_w && entry->config.height == scaled_tex_h && entry->config.layers == efb_layers)) { - if (entry->type == TCET_EC_VRAM) - { - // try to re-use this render target later - FreeRenderTarget(entry); - } - else - { - // remove it and recreate it as a render target - delete entry; - } - + // try to re-use this texture later + FreeTexture(entry); entry = nullptr; } } @@ -875,7 +866,13 @@ void TextureCache::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFormat if (nullptr == entry) { // create the texture - textures[dstAddr] = entry = AllocateRenderTarget(scaled_tex_w, scaled_tex_h, FramebufferManagerBase::GetEFBLayers()); + TCacheEntryConfig config; + config.rendertarget = true; + config.width = scaled_tex_w; + config.height = scaled_tex_h; + config.layers = FramebufferManagerBase::GetEFBLayers(); + + textures[dstAddr] = entry = AllocateTexture(config); // TODO: Using the wrong dstFormat, dumb... entry->SetGeneralParameters(dstAddr, 0, dstFormat); @@ -889,31 +886,26 @@ void TextureCache::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFormat entry->FromRenderTarget(dstAddr, dstFormat, srcFormat, srcRect, isIntensity, scaleByHalf, cbufid, colmat); } -TextureCache::TCacheEntryBase* TextureCache::AllocateRenderTarget(unsigned int width, unsigned int height, unsigned int layers) +TextureCache::TCacheEntryBase* TextureCache::AllocateTexture(const TCacheEntryConfig& config) { - for (size_t i = 0; i < render_target_pool.size(); ++i) + for (size_t i = 0; i < texture_pool.size(); ++i) { - auto rt = render_target_pool[i]; - - if (rt->config.width != width || rt->config.height != height || rt->config.layers != layers) - continue; + auto rt = texture_pool[i]; - render_target_pool[i] = render_target_pool.back(); - render_target_pool.pop_back(); + if (rt->config == config) + { + texture_pool[i] = texture_pool.back(); + texture_pool.pop_back(); - return rt; + return rt; + } } - TCacheEntryConfig config; - config.rendertarget = true; - config.width = width; - config.height = height; - config.layers = layers; - + INCSTAT(stats.numTexturesCreated); return g_texture_cache->CreateTexture(config); } -void TextureCache::FreeRenderTarget(TCacheEntryBase* entry) +void TextureCache::FreeTexture(TCacheEntryBase* entry) { - render_target_pool.push_back(entry); + texture_pool.push_back(entry); } -- cgit v1.2.3 From 8565f0269978cb0414ccddfc212312f132acc035 Mon Sep 17 00:00:00 2001 From: degasus Date: Sat, 17 Jan 2015 10:57:19 +0100 Subject: TexCache: use an unordered_multimap for the tex pool --- Source/Core/VideoCommon/TextureCacheBase.cpp | 41 ++++++++++++++-------------- 1 file changed, 20 insertions(+), 21 deletions(-) (limited to 'Source/Core/VideoCommon/TextureCacheBase.cpp') diff --git a/Source/Core/VideoCommon/TextureCacheBase.cpp b/Source/Core/VideoCommon/TextureCacheBase.cpp index f87b10aba9..f9f603e8e5 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/TextureCacheBase.cpp @@ -31,7 +31,7 @@ GC_ALIGNED16(u8 *TextureCache::temp) = nullptr; size_t TextureCache::temp_size; TextureCache::TexCache TextureCache::textures; -TextureCache::TexturePool TextureCache::texture_pool; +TextureCache::TexPool TextureCache::texture_pool; TextureCache::BackupConfig TextureCache::backup_config; @@ -82,7 +82,7 @@ void TextureCache::Invalidate() for (auto& rt : texture_pool) { - delete rt; + delete rt.second; } texture_pool.clear(); } @@ -161,19 +161,22 @@ void TextureCache::Cleanup(int _frameCount) } } - for (size_t i = 0; i < texture_pool.size();) + TexPool::iterator iter2 = texture_pool.begin(); + TexPool::iterator tcend2 = texture_pool.end(); + while (iter2 != tcend2) { - auto rt = texture_pool[i]; - - if (_frameCount > TEXTURE_POOL_KILL_THRESHOLD + rt->frameCount) + if(iter2->second->frameCount == FRAMECOUNT_INVALID) + { + iter2->second->frameCount = _frameCount; + } + if (_frameCount > TEXTURE_POOL_KILL_THRESHOLD + iter2->second->frameCount) { - delete rt; - texture_pool[i] = texture_pool.back(); - texture_pool.pop_back(); + delete iter2->second; + iter2 = texture_pool.erase(iter2); } else { - ++i; + ++iter2; } } } @@ -888,17 +891,12 @@ void TextureCache::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFormat TextureCache::TCacheEntryBase* TextureCache::AllocateTexture(const TCacheEntryConfig& config) { - for (size_t i = 0; i < texture_pool.size(); ++i) + TexPool::iterator iter = texture_pool.find(config); + if (iter != texture_pool.end()) { - auto rt = texture_pool[i]; - - if (rt->config == config) - { - texture_pool[i] = texture_pool.back(); - texture_pool.pop_back(); - - return rt; - } + TextureCache::TCacheEntryBase* entry = iter->second; + texture_pool.erase(iter); + return entry; } INCSTAT(stats.numTexturesCreated); @@ -907,5 +905,6 @@ TextureCache::TCacheEntryBase* TextureCache::AllocateTexture(const TCacheEntryCo void TextureCache::FreeTexture(TCacheEntryBase* entry) { - texture_pool.push_back(entry); + entry->frameCount = FRAMECOUNT_INVALID; + texture_pool.insert(TexPool::value_type(entry->config, entry)); } -- cgit v1.2.3 From 9f13a77799bc8d91e3022f334900ffb542bc1b43 Mon Sep 17 00:00:00 2001 From: degasus Date: Sat, 17 Jan 2015 11:18:57 +0100 Subject: TexCache: don't try to aggressive reuse the entry As we pool them now, freeing and reallocating them is quite fast. --- Source/Core/VideoCommon/TextureCacheBase.cpp | 108 +++++++-------------------- 1 file changed, 26 insertions(+), 82 deletions(-) (limited to 'Source/Core/VideoCommon/TextureCacheBase.cpp') diff --git a/Source/Core/VideoCommon/TextureCacheBase.cpp b/Source/Core/VideoCommon/TextureCacheBase.cpp index f9f603e8e5..8327812f01 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/TextureCacheBase.cpp @@ -364,7 +364,7 @@ TextureCache::TCacheEntryBase* TextureCache::Load(const u32 stage) // e.g. 64x64 with 7 LODs would have the mipmap chain 64x64,32x32,16x16,8x8,4x4,2x2,1x1,0x0, so we limit the mipmap count to 6 there tex_levels = std::min(IntLog2(std::max(width, height)) + 1, tex_levels); - TCacheEntryBase *entry = textures[texID]; + TCacheEntryBase*& entry = textures[texID]; if (entry) { // 1. Calculate reference hash: @@ -390,29 +390,8 @@ TextureCache::TCacheEntryBase* TextureCache::Load(const u32 stage) return ReturnEntry(stage, entry); } - // 3. If we reach this line, we'll have to upload the new texture data to VRAM. - // If we're lucky, the texture parameters didn't change and we can reuse the internal texture object instead of destroying and recreating it. - // - // TODO: Don't we need to force texture decoding to RGBA8 for dynamic EFB copies? - // TODO: Actually, it should be enough if the internal texture format matches... - if (((entry->type == TCET_NORMAL && - width == entry->config.width && - height == entry->config.height && - full_format == entry->format && - entry->config.levels >= tex_levels) || - (entry->type == TCET_EC_DYNAMIC && - entry->native_width == width && - entry->native_height == height)) && - entry->config.layers == 1) - { - // reuse the texture - } - else - { - // delete the texture and make a new one - FreeTexture(entry); - entry = nullptr; - } + // pool this texture and make a new one later + FreeTexture(entry); } std::unique_ptr hires_tex; @@ -432,13 +411,6 @@ TextureCache::TCacheEntryBase* TextureCache::Load(const u32 stage) { width = l.width; height = l.height; - - // If we thought we could reuse the texture before, make sure to pool it now! - if (entry) - { - FreeTexture(entry); - entry = nullptr; - } } expandedWidth = l.width; expandedHeight = l.height; @@ -467,25 +439,14 @@ TextureCache::TCacheEntryBase* TextureCache::Load(const u32 stage) 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) - if (entry && entry->config.levels != texLevels) - { - // delete the texture and make a new one - FreeTexture(entry); - entry = nullptr; - } - // create the entry/texture - if (nullptr == entry) - { - TCacheEntryConfig config; - config.width = width; - config.height = height; - config.levels = texLevels; - textures[texID] = entry = AllocateTexture(config); - entry->type = TCET_NORMAL; - - GFX_DEBUGGER_PAUSE_AT(NEXT_NEW_TEXTURE, true); - } + TCacheEntryConfig config; + config.width = width; + config.height = height; + config.levels = texLevels; + entry = AllocateTexture(config); + entry->type = TCET_NORMAL; + GFX_DEBUGGER_PAUSE_AT(NEXT_NEW_TEXTURE, true); entry->SetGeneralParameters(address, texture_size, full_format); entry->SetDimensions(nativeW, nativeH, tex_levels); @@ -848,41 +809,24 @@ void TextureCache::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFormat unsigned int scaled_tex_w = g_ActiveConfig.bCopyEFBScaled ? Renderer::EFBToScaledX(tex_w) : tex_w; unsigned int scaled_tex_h = g_ActiveConfig.bCopyEFBScaled ? Renderer::EFBToScaledY(tex_h) : tex_h; - const unsigned int efb_layers = FramebufferManagerBase::GetEFBLayers(); - - TCacheEntryBase *entry = textures[dstAddr]; + TCacheEntryBase*& entry = textures[dstAddr]; if (entry) - { - if (entry->type == TCET_EC_DYNAMIC && entry->native_width == tex_w && entry->native_height == tex_h && entry->config.layers == efb_layers) - { - scaled_tex_w = tex_w; - scaled_tex_h = tex_h; - } - else if (!(entry->type == TCET_EC_VRAM && entry->config.width == scaled_tex_w && entry->config.height == scaled_tex_h && entry->config.layers == efb_layers)) - { - // try to re-use this texture later - FreeTexture(entry); - entry = nullptr; - } - } + FreeTexture(entry); - if (nullptr == entry) - { - // create the texture - TCacheEntryConfig config; - config.rendertarget = true; - config.width = scaled_tex_w; - config.height = scaled_tex_h; - config.layers = FramebufferManagerBase::GetEFBLayers(); - - textures[dstAddr] = entry = AllocateTexture(config); - - // TODO: Using the wrong dstFormat, dumb... - entry->SetGeneralParameters(dstAddr, 0, dstFormat); - entry->SetDimensions(tex_w, tex_h, 1); - entry->SetHashes(TEXHASH_INVALID); - entry->type = TCET_EC_VRAM; - } + // create the texture + TCacheEntryConfig config; + config.rendertarget = true; + config.width = scaled_tex_w; + config.height = scaled_tex_h; + config.layers = FramebufferManagerBase::GetEFBLayers(); + + entry = AllocateTexture(config); + + // TODO: Using the wrong dstFormat, dumb... + entry->SetGeneralParameters(dstAddr, 0, dstFormat); + entry->SetDimensions(tex_w, tex_h, 1); + entry->SetHashes(TEXHASH_INVALID); + entry->type = TCET_EC_VRAM; entry->frameCount = FRAMECOUNT_INVALID; -- cgit v1.2.3 From 0d3343d093faa31f4884c51cb2e88254dbefc51b Mon Sep 17 00:00:00 2001 From: mimimi085181 Date: Mon, 19 Jan 2015 00:10:27 +0100 Subject: Make efb to texture less broken for paletted textures that are efb copies Don't change the texID depending on the tlut_hash for paletted textures that are efb copies and don't have an entry in the cache for texID ^ tlut_hash. This makes those textures less broken when using efb to texture. This is not really fixing those textures, but it's a step forward. The mini map in Twilight Princess for example is in grayscales with this and is more or less usable. --- Source/Core/VideoCommon/TextureCacheBase.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'Source/Core/VideoCommon/TextureCacheBase.cpp') diff --git a/Source/Core/VideoCommon/TextureCacheBase.cpp b/Source/Core/VideoCommon/TextureCacheBase.cpp index 38449ae5eb..b3ae7e125f 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/TextureCacheBase.cpp @@ -354,8 +354,17 @@ TextureCache::TCacheEntryBase* TextureCache::Load(const u32 stage) // we must make sure that a paletted texture gets assigned multiple IDs for each tlut used. // // TODO: Because texID isn't always the same as the address now, CopyRenderTargetToTexture might be broken now + u32 temp_texID = texID; texID ^= ((u32)tlut_hash) ^(u32)(tlut_hash >> 32); tex_hash ^= tlut_hash; + + // Don't change the texID depending on the tlut_hash for paletted textures that are efb copies and don't have + // an entry in the cache for texID ^ tlut_hash. This makes those textures less broken when using efb to texture. + // Examples are the mini map in Twilight Princess and objects on the targetting computer in Rogue Squadron 2(RS2). + // TODO: Convert those textures using the right palette, so they display correctly + auto iter = textures.find(temp_texID); + if (iter != textures.end() && iter->second->IsEfbCopy() && textures.find(texID) == textures.end()) + texID = temp_texID; } // GPUs don't like when the specified mipmap count would require more than one 1x1-sized LOD in the mipmap chain -- cgit v1.2.3 From ee9d05d67f4d8d2c1f754c0b40f7f54cfbd8d4fd Mon Sep 17 00:00:00 2001 From: degasus Date: Wed, 14 Jan 2015 21:25:33 +0100 Subject: CustomTexture: Use another file name with wildcards --- Source/Core/VideoCommon/TextureCacheBase.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Source/Core/VideoCommon/TextureCacheBase.cpp') diff --git a/Source/Core/VideoCommon/TextureCacheBase.cpp b/Source/Core/VideoCommon/TextureCacheBase.cpp index 684dc56b5e..1159159690 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/TextureCacheBase.cpp @@ -476,7 +476,7 @@ TextureCache::TCacheEntryBase* TextureCache::Load(const u32 stage) src_data, texture_size, &texMem[tlutaddr], palette_size, width, height, - texformat + texformat, true ); DumpTexture(entry, basename, 0); } -- cgit v1.2.3 From 62402efa6c2777c4e9829767c39fed71fe3de60a Mon Sep 17 00:00:00 2001 From: degasus Date: Thu, 15 Jan 2015 21:33:22 +0100 Subject: CustomTexture: Mark textures with mipmaps --- Source/Core/VideoCommon/TextureCacheBase.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'Source/Core/VideoCommon/TextureCacheBase.cpp') diff --git a/Source/Core/VideoCommon/TextureCacheBase.cpp b/Source/Core/VideoCommon/TextureCacheBase.cpp index 1159159690..3e61ea11f3 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/TextureCacheBase.cpp @@ -304,8 +304,8 @@ TextureCache::TCacheEntryBase* TextureCache::Load(const u32 stage) const int texformat = tex.texImage0[id].format; const u32 tlutaddr = tex.texTlut[id].tmem_offset << 9; const u32 tlutfmt = tex.texTlut[id].tlut_format; - const bool use_mipmaps = (tex.texMode0[id].min_filter & 3) != 0; u32 tex_levels = (tex.texMode1[id].max_lod + 0xf) / 0x10 + 1; + const bool use_mipmaps = (tex.texMode0[id].min_filter & 3) != 0 && tex_levels > 0; const bool from_tmem = tex.texImage1[id].image_type != 0; if (0 == address) @@ -410,7 +410,7 @@ TextureCache::TCacheEntryBase* TextureCache::Load(const u32 stage) src_data, texture_size, &texMem[tlutaddr], palette_size, width, height, - texformat + texformat, use_mipmaps )); if (hires_tex) @@ -476,7 +476,8 @@ TextureCache::TCacheEntryBase* TextureCache::Load(const u32 stage) src_data, texture_size, &texMem[tlutaddr], palette_size, width, height, - texformat, true + texformat, use_mipmaps, + true ); DumpTexture(entry, basename, 0); } -- cgit v1.2.3 From 6659c15bedd4add4bd536394900e74ab6b7d6648 Mon Sep 17 00:00:00 2001 From: magumagu Date: Wed, 21 Jan 2015 20:37:12 -0800 Subject: Remove EFB to RAM cache, and simplify code. --- Source/Core/VideoCommon/TextureCacheBase.cpp | 28 +--------------------------- 1 file changed, 1 insertion(+), 27 deletions(-) (limited to 'Source/Core/VideoCommon/TextureCacheBase.cpp') diff --git a/Source/Core/VideoCommon/TextureCacheBase.cpp b/Source/Core/VideoCommon/TextureCacheBase.cpp index 684dc56b5e..7b7c117a58 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/TextureCacheBase.cpp @@ -115,12 +115,6 @@ void TextureCache::OnConfigChanged(VideoConfig& config) invalidate_texture_cache_requested = false; } - // TODO: Probably shouldn't clear all render targets here, just mark them dirty or something. - if (config.bEFBCopyCacheEnable != backup_config.s_copy_cache_enable) // TODO: not sure if this is needed? - { - g_texture_cache->ClearRenderTargets(); - } - if ((config.iStereoMode > 0) != backup_config.s_stereo_3d || config.bStereoEFBMonoDepth != backup_config.s_efb_mono_depth) { @@ -133,7 +127,6 @@ void TextureCache::OnConfigChanged(VideoConfig& config) backup_config.s_texfmt_overlay = config.bTexFmtOverlayEnable; backup_config.s_texfmt_overlay_center = config.bTexFmtOverlayCenter; backup_config.s_hires_textures = config.bHiresTextures; - backup_config.s_copy_cache_enable = config.bEFBCopyCacheEnable; backup_config.s_stereo_3d = config.iStereoMode > 0; backup_config.s_efb_mono_depth = config.bStereoEFBMonoDepth; } @@ -218,16 +211,6 @@ void TextureCache::MakeRangeDynamic(u32 start_address, u32 size) } } -bool TextureCache::Find(u32 start_address, u64 hash) -{ - TexCache::iterator iter = textures.lower_bound(start_address); - - if (iter->second->hash == hash) - return true; - - return false; -} - bool TextureCache::TCacheEntryBase::OverlapsMemoryRange(u32 range_address, u32 range_size) const { if (addr + size_in_bytes <= range_address) @@ -247,7 +230,7 @@ void TextureCache::ClearRenderTargets() while (iter != tcend) { - if (iter->second->type == TCET_EC_VRAM) + if (iter->second->IsEfbCopy()) { FreeTexture(iter->second); textures.erase(iter++); @@ -384,8 +367,6 @@ TextureCache::TCacheEntryBase* TextureCache::Load(const u32 stage) // 2. a) For EFB copies, only the hash and the texture address need to match if (entry->IsEfbCopy() && tex_hash == entry->hash && address == entry->addr) { - entry->type = TCET_EC_VRAM; - // TODO: Print a warning if the format changes! In this case, // we could reinterpret the internal texture object data to the new pixel format // (similar to what is already being done in Renderer::ReinterpretPixelFormat()) @@ -454,7 +435,6 @@ TextureCache::TCacheEntryBase* TextureCache::Load(const u32 stage) config.height = height; config.levels = texLevels; entry = AllocateTexture(config); - entry->type = TCET_NORMAL; GFX_DEBUGGER_PAUSE_AT(NEXT_NEW_TEXTURE, true); entry->SetGeneralParameters(address, texture_size, full_format); @@ -464,11 +444,6 @@ TextureCache::TCacheEntryBase* TextureCache::Load(const u32 stage) // load texture entry->Load(width, height, expandedWidth, 0); - if (entry->IsEfbCopy() && !g_ActiveConfig.bCopyEFBToTexture) - entry->type = TCET_EC_DYNAMIC; - else - entry->type = TCET_NORMAL; - std::string basename = ""; if (g_ActiveConfig.bDumpTextures && !hires_tex) { @@ -835,7 +810,6 @@ void TextureCache::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFormat entry->SetGeneralParameters(dstAddr, 0, dstFormat); entry->SetDimensions(tex_w, tex_h, 1); entry->SetHashes(TEXHASH_INVALID); - entry->type = TCET_EC_VRAM; entry->frameCount = FRAMECOUNT_INVALID; -- cgit v1.2.3 From 51990fcdfaae1983ca232d3bc9e28e1230931d74 Mon Sep 17 00:00:00 2001 From: degasus Date: Sat, 24 Jan 2015 13:07:26 +0100 Subject: TexCache: Rewrite the texID generation for paletted textures This changes the behavior if both texture are available. The old code did try to load the modfied texID, the new code tries the unmodified texID first. --- Source/Core/VideoCommon/TextureCacheBase.cpp | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) (limited to 'Source/Core/VideoCommon/TextureCacheBase.cpp') diff --git a/Source/Core/VideoCommon/TextureCacheBase.cpp b/Source/Core/VideoCommon/TextureCacheBase.cpp index 3e61ea11f3..ea830c24fc 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/TextureCacheBase.cpp @@ -323,7 +323,6 @@ TextureCache::TCacheEntryBase* TextureCache::Load(const u32 stage) u32 texID = address; // Hash assigned to texcache entry (also used to generate filenames used for texture dumping and custom texture lookup) u64 tex_hash = TEXHASH_INVALID; - u64 tlut_hash = TEXHASH_INVALID; u32 full_format = texformat; @@ -345,7 +344,10 @@ TextureCache::TCacheEntryBase* TextureCache::Load(const u32 stage) if (isPaletteTexture) { palette_size = TexDecoder_GetPaletteSize(texformat); - tlut_hash = GetHash64(&texMem[tlutaddr], palette_size, g_ActiveConfig.iSafeTextureCache_ColorSamples); + u64 tlut_hash = GetHash64(&texMem[tlutaddr], palette_size, g_ActiveConfig.iSafeTextureCache_ColorSamples); + + // Mix the tlut hash into the texture hash. So we only have to compare it one. + tex_hash ^= tlut_hash; // NOTE: For non-paletted textures, texID is equal to the texture address. // A paletted texture, however, may have multiple texIDs assigned though depending on the currently used tlut. @@ -355,18 +357,13 @@ TextureCache::TCacheEntryBase* TextureCache::Load(const u32 stage) // visible or invisible. Thus, unless we want to recreate the textures for every drawn character, // we must make sure that a paletted texture gets assigned multiple IDs for each tlut used. // - // TODO: Because texID isn't always the same as the address now, CopyRenderTargetToTexture might be broken now - u32 temp_texID = texID; - texID ^= ((u32)tlut_hash) ^(u32)(tlut_hash >> 32); - tex_hash ^= tlut_hash; - - // Don't change the texID depending on the tlut_hash for paletted textures that are efb copies and don't have - // an entry in the cache for texID ^ tlut_hash. This makes those textures less broken when using efb to texture. - // Examples are the mini map in Twilight Princess and objects on the targetting computer in Rogue Squadron 2(RS2). + // EFB copys however didn't know anything about the tlut, so don't change the texID if there + // already is an efb copy at this source. This makes those textures less broken when using efb to texture. + // Examples are the mini map in Twilight Princess and objects on the targetting computer in Rogue Squadron 2(RS2). // TODO: Convert those textures using the right palette, so they display correctly - auto iter = textures.find(temp_texID); - if (iter != textures.end() && iter->second->IsEfbCopy() && textures.find(texID) == textures.end()) - texID = temp_texID; + auto iter = textures.find(texID); + if (iter == textures.end() || !iter->second->IsEfbCopy()) + texID ^= ((u32)tlut_hash) ^(u32)(tlut_hash >> 32); } // GPUs don't like when the specified mipmap count would require more than one 1x1-sized LOD in the mipmap chain -- cgit v1.2.3 From 2f8e0c9bb9e27077b5203ee2c2d62945f347394a Mon Sep 17 00:00:00 2001 From: mimimi085181 Date: Sun, 1 Feb 2015 15:36:19 +0100 Subject: Allow multiple texture cache entries for textures at the same address This is the same trick which is used for Metroid's fonts/texts, but for all textures. If 2 different textures at the same address are loaded during the same frame, create a 2nd entry instead of overwriting the existing one. If the entry was overwritten in this case, there wouldn't be any caching, which results in a big performance drop. The restriction to textures, which are loaded during the same frame, prevents creating lots of textures when textures are used in the regular way. This restriction is new. Overwriting textures, instead of creating new ones is faster, if the old ones are unlikely to be used again. Since this would break efb copies, don't do it for efb copies. Castlevania 3 goes from 80 fps to 115 fps for me. There might be games that need a higher texture cache accuracy with this, but those games should also see a performance boost from this PR. Some games, which use paletted textures, which are not efb copies, might be faster now. And also not require a higher texture cache accuracy anymore. (similar sitation as PR https://github.com/dolphin-emu/dolphin/pull/1916) --- Source/Core/VideoCommon/TextureCacheBase.cpp | 123 ++++++++++++++++++--------- 1 file changed, 83 insertions(+), 40 deletions(-) (limited to 'Source/Core/VideoCommon/TextureCacheBase.cpp') diff --git a/Source/Core/VideoCommon/TextureCacheBase.cpp b/Source/Core/VideoCommon/TextureCacheBase.cpp index b40f9d0882..ac47e1929f 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/TextureCacheBase.cpp @@ -21,7 +21,7 @@ #include "VideoCommon/VideoConfig.h" static const u64 TEXHASH_INVALID = 0; -static const int TEXTURE_KILL_THRESHOLD = 200; +static const int TEXTURE_KILL_THRESHOLD = 10; static const int TEXTURE_POOL_KILL_THRESHOLD = 3; static const u64 FRAMECOUNT_INVALID = 0; @@ -303,7 +303,6 @@ TextureCache::TCacheEntryBase* TextureCache::Load(const u32 stage) const unsigned int nativeW = width; const unsigned int nativeH = height; - u32 texID = address; // Hash assigned to texcache entry (also used to generate filenames used for texture dumping and custom texture lookup) u64 tex_hash = TEXHASH_INVALID; @@ -329,56 +328,90 @@ TextureCache::TCacheEntryBase* TextureCache::Load(const u32 stage) palette_size = TexDecoder_GetPaletteSize(texformat); u64 tlut_hash = GetHash64(&texMem[tlutaddr], palette_size, g_ActiveConfig.iSafeTextureCache_ColorSamples); - // Mix the tlut hash into the texture hash. So we only have to compare it one. + // Mix the tlut hash into the texture hash. So we only have to compare it once. tex_hash ^= tlut_hash; - - // NOTE: For non-paletted textures, texID is equal to the texture address. - // A paletted texture, however, may have multiple texIDs assigned though depending on the currently used tlut. - // This (changing texID depending on the tlut_hash) is a trick to get around - // an issue with Metroid Prime's fonts (it has multiple sets of fonts on each other - // stored in a single texture and uses the palette to make different characters - // visible or invisible. Thus, unless we want to recreate the textures for every drawn character, - // we must make sure that a paletted texture gets assigned multiple IDs for each tlut used. - // - // EFB copys however didn't know anything about the tlut, so don't change the texID if there - // already is an efb copy at this source. This makes those textures less broken when using efb to texture. - // Examples are the mini map in Twilight Princess and objects on the targetting computer in Rogue Squadron 2(RS2). - // TODO: Convert those textures using the right palette, so they display correctly - auto iter = textures.find(texID); - if (iter == textures.end() || !iter->second->IsEfbCopy()) - texID ^= ((u32)tlut_hash) ^(u32)(tlut_hash >> 32); } // GPUs don't like when the specified mipmap count would require more than one 1x1-sized LOD in the mipmap chain // e.g. 64x64 with 7 LODs would have the mipmap chain 64x64,32x32,16x16,8x8,4x4,2x2,1x1,0x0, so we limit the mipmap count to 6 there tex_levels = std::min(IntLog2(std::max(width, height)) + 1, tex_levels); - TCacheEntryBase*& entry = textures[texID]; - if (entry) + // Find all texture cache entries for the current texture address, and decide whether to use one of + // them, or to create a new one + // + // In most cases, the fastest way is to use only one texture cache entry for the same address. Usually, + // when a texture changes, the old version of the texture is unlikely to be used again. If there were + // new cache entries created for normal texture updates, there would be a slowdown due to a huge amount + // of unused cache entries. Also thanks to texture pooling, overwriting an existing cache entry is + // faster than creating a new one from scratch. + // + // Some games use the same address for different textures though. If the same cache entry was used in + // this case, it would be constantly overwritten, and effectively there wouldn't be any caching for + // those textures. Examples for this are Metroid Prime and Castlevania 3. Metroid Prime has multiple + // sets of fonts on each other stored in a single texture and uses the palette to make different + // characters visible or invisible. In Castlevania 3 some textures are used for 2 different things or + // at least in 2 different ways(size 1024x1024 vs 1024x256). + // + // To determine whether to use multiple cache entries or a single entry, use the following heuristic: + // If the same texture address is used several times during the same frame, assume the address is used + // for different purposes and allow creating an additional cache entry. If there's at least one entry + // that hasn't been used for the same frame, then overwrite it, in order to keep the cache as small as + // possible. If the current texture is found in the cache, use that entry. + // + // For efb copies, the entry created in CopyRenderTargetToTexture always has to be used, or else it was + // done in vain. + std::pair iter_range = textures.equal_range(address); + TexCache::iterator iter = iter_range.first; + TexCache::iterator oldest_entry = iter; + int temp_frameCount = 0x7fffffff; + + while (iter != iter_range.second) { - // 1. Calculate reference hash: - // calculated from RAM texture data for normal textures. Hashes for paletted textures are modified by tlut_hash. 0 for virtual EFB copies. - if (g_ActiveConfig.bCopyEFBToTexture && entry->IsEfbCopy()) - tex_hash = TEXHASH_INVALID; + TCacheEntryBase* entry = iter->second; + if (entry->IsEfbCopy()) + { + // For EFB copies, only the hash and the texture address need to match. Ignore the hash when + // using EFB to texture, because there's no hash in this case + if (g_ActiveConfig.bCopyEFBToTexture || entry->hash == tex_hash) + { + // TODO: Print a warning if the format changes! In this case, + // we could reinterpret the internal texture object data to the new pixel format + // (similar to what is already being done in Renderer::ReinterpretPixelFormat()) + // TODO: Convert paletted textures, which are efb copies, using the right palette, so they display correctly + return ReturnEntry(stage, entry); + } + else + { + // Keeping an unused entry for an efb copy in the cache is pointless, because a new entry + // will be created in CopyRenderTargetToTexture + FreeTexture(entry); + iter = textures.erase(iter); + continue; + } + } - // 2. a) For EFB copies, only the hash and the texture address need to match - if (entry->IsEfbCopy() && tex_hash == entry->hash && address == entry->addr) + // For normal textures, all texture parameters need to match + if (entry->hash == tex_hash && entry->format == full_format && entry->native_levels >= tex_levels && + entry->native_width == nativeW && entry->native_height == nativeH) { - // TODO: Print a warning if the format changes! In this case, - // we could reinterpret the internal texture object data to the new pixel format - // (similar to what is already being done in Renderer::ReinterpretPixelFormat()) return ReturnEntry(stage, entry); } - // 2. b) For normal textures, all texture parameters need to match - if (address == entry->addr && tex_hash == entry->hash && full_format == entry->format && - entry->native_levels >= tex_levels && entry->native_width == nativeW && entry->native_height == nativeH) + // Find the entry which hasn't been used for the longest time + if (entry->frameCount != FRAMECOUNT_INVALID && entry->frameCount < temp_frameCount) { - return ReturnEntry(stage, entry); + temp_frameCount = entry->frameCount; + oldest_entry = iter; } + ++iter; + } + // If at least one entry was not used for the same frame, overwrite the oldest one + if (temp_frameCount != 0x7fffffff) + { // pool this texture and make a new one later - FreeTexture(entry); + FreeTexture(oldest_entry->second); + textures.erase(oldest_entry); } std::unique_ptr hires_tex; @@ -431,9 +464,12 @@ TextureCache::TCacheEntryBase* TextureCache::Load(const u32 stage) config.width = width; config.height = height; config.levels = texLevels; - entry = AllocateTexture(config); + + TCacheEntryBase* entry = AllocateTexture(config); GFX_DEBUGGER_PAUSE_AT(NEXT_NEW_TEXTURE, true); + textures.insert(TexCache::value_type(address, entry)); + entry->SetGeneralParameters(address, texture_size, full_format); entry->SetDimensions(nativeW, nativeH, tex_levels); entry->hash = tex_hash; @@ -791,9 +827,14 @@ void TextureCache::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFormat unsigned int scaled_tex_w = g_ActiveConfig.bCopyEFBScaled ? Renderer::EFBToScaledX(tex_w) : tex_w; unsigned int scaled_tex_h = g_ActiveConfig.bCopyEFBScaled ? Renderer::EFBToScaledY(tex_h) : tex_h; - TCacheEntryBase*& entry = textures[dstAddr]; - if (entry) - FreeTexture(entry); + // remove all texture cache entries at dstAddr + std::pair iter_range = textures.equal_range(dstAddr); + TexCache::iterator iter = iter_range.first; + while (iter != iter_range.second) + { + FreeTexture(iter->second); + iter = textures.erase(iter); + } // create the texture TCacheEntryConfig config; @@ -802,7 +843,7 @@ void TextureCache::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFormat config.height = scaled_tex_h; config.layers = FramebufferManagerBase::GetEFBLayers(); - entry = AllocateTexture(config); + TCacheEntryBase* entry = AllocateTexture(config); // TODO: Using the wrong dstFormat, dumb... entry->SetGeneralParameters(dstAddr, 0, dstFormat); @@ -812,6 +853,8 @@ void TextureCache::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFormat entry->frameCount = FRAMECOUNT_INVALID; entry->FromRenderTarget(dstAddr, dstFormat, srcFormat, srcRect, isIntensity, scaleByHalf, cbufid, colmat); + + textures.insert(TexCache::value_type(dstAddr, entry)); } TextureCache::TCacheEntryBase* TextureCache::AllocateTexture(const TCacheEntryConfig& config) -- cgit v1.2.3 From c0a4760f0efbb99274c33f30154a7f43aab70494 Mon Sep 17 00:00:00 2001 From: magumagu Date: Mon, 26 Jan 2015 15:33:23 -0800 Subject: Decode EFB copies used as paletted textures. A number of games make an EFB copy in I4/I8 format, then use it as a texture in C4/C8 format. Detect when this happens, and decode the copy on the GPU using the specified palette. This has a few advantages: it allows using EFB2Tex for a few more games, it, it preserves the resolution of scaled EFB copies, and it's probably a bit faster. D3D only at the moment, but porting to OpenGL should be straightforward.. --- Source/Core/VideoCommon/TextureCacheBase.cpp | 187 +++++++++++++++++---------- 1 file changed, 116 insertions(+), 71 deletions(-) (limited to 'Source/Core/VideoCommon/TextureCacheBase.cpp') diff --git a/Source/Core/VideoCommon/TextureCacheBase.cpp b/Source/Core/VideoCommon/TextureCacheBase.cpp index ac47e1929f..6ab9705c4c 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/TextureCacheBase.cpp @@ -32,6 +32,7 @@ size_t TextureCache::temp_size; TextureCache::TexCache TextureCache::textures; TextureCache::TexPool TextureCache::texture_pool; +TextureCache::TCacheEntryBase* TextureCache::bound_textures[8]; TextureCache::BackupConfig TextureCache::backup_config; @@ -74,6 +75,8 @@ void TextureCache::RequestInvalidateTextureCache() void TextureCache::Invalidate() { + UnbindTextures(); + for (auto& tex : textures) { delete tex.second; @@ -143,7 +146,7 @@ void TextureCache::Cleanup(int _frameCount) } if (_frameCount > TEXTURE_KILL_THRESHOLD + iter->second->frameCount && // EFB copies living on the host GPU are unrecoverable and thus shouldn't be deleted - !iter->second->IsEfbCopy()) + !iter->second->IsUnrecoverable()) { FreeTexture(iter->second); iter = textures.erase(iter); @@ -174,17 +177,17 @@ void TextureCache::Cleanup(int _frameCount) } } -void TextureCache::InvalidateRange(u32 start_address, u32 size) +void TextureCache::MakeRangeDynamic(u32 start_address, u32 size) { TexCache::iterator - iter = textures.begin(), - tcend = textures.end(); - while (iter != tcend) + iter = textures.begin(); + + while (iter != textures.end()) { if (iter->second->OverlapsMemoryRange(start_address, size)) { FreeTexture(iter->second); - textures.erase(iter++); + iter = textures.erase(iter); } else { @@ -193,53 +196,19 @@ void TextureCache::InvalidateRange(u32 start_address, u32 size) } } -void TextureCache::MakeRangeDynamic(u32 start_address, u32 size) -{ - TexCache::iterator - iter = textures.lower_bound(start_address), - tcend = textures.upper_bound(start_address + size); - - if (iter != textures.begin()) - --iter; - - for (; iter != tcend; ++iter) - { - if (iter->second->OverlapsMemoryRange(start_address, size)) - { - iter->second->SetHashes(TEXHASH_INVALID); - } - } -} - bool TextureCache::TCacheEntryBase::OverlapsMemoryRange(u32 range_address, u32 range_size) const { - if (addr + size_in_bytes <= range_address) + if (!addr.HasMemAddress()) return false; - if (addr >= range_address + range_size) + u32 memaddr = addr.GetMemAddress(); + if (memaddr + size_in_bytes <= range_address) return false; - return true; -} - -void TextureCache::ClearRenderTargets() -{ - TexCache::iterator - iter = textures.begin(), - tcend = textures.end(); + if (memaddr >= range_address + range_size) + return false; - while (iter != tcend) - { - if (iter->second->IsEfbCopy()) - { - FreeTexture(iter->second); - textures.erase(iter++); - } - else - { - ++iter; - } - } + return true; } void TextureCache::DumpTexture(TCacheEntryBase* entry, std::string basename, unsigned int level) @@ -267,16 +236,30 @@ static u32 CalculateLevelSize(u32 level_0_size, u32 level) } // Used by TextureCache::Load -static TextureCache::TCacheEntryBase* ReturnEntry(unsigned int stage, TextureCache::TCacheEntryBase* entry) +TextureCache::TCacheEntryBase* TextureCache::ReturnEntry(unsigned int stage, TCacheEntryBase* entry) { entry->frameCount = FRAMECOUNT_INVALID; - entry->Bind(stage); + bound_textures[stage] = entry; GFX_DEBUGGER_PAUSE_AT(NEXT_TEXTURE_CHANGE, true); return entry; } +void TextureCache::BindTextures() +{ + for (int i = 0; i < 8; ++i) + { + if (bound_textures[i]) + bound_textures[i]->Bind(i); + } +} + +void TextureCache::UnbindTextures() +{ + std::fill(std::begin(bound_textures), std::end(bound_textures), nullptr); +} + TextureCache::TCacheEntryBase* TextureCache::Load(const u32 stage) { const FourTexUnits &tex = bpmem.tex[stage >> 2]; @@ -309,6 +292,11 @@ TextureCache::TCacheEntryBase* TextureCache::Load(const u32 stage) u32 full_format = texformat; const bool isPaletteTexture = (texformat == GX_TF_C4 || texformat == GX_TF_C8 || texformat == GX_TF_C14X2); + + // Reject invalid tlut format. + if (isPaletteTexture && tlutfmt > GX_TL_RGB5A3) + return nullptr; + if (isPaletteTexture) full_format = texformat | (tlutfmt << 16); @@ -323,19 +311,43 @@ TextureCache::TCacheEntryBase* TextureCache::Load(const u32 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) tex_hash = GetHash64(src_data, texture_size, g_ActiveConfig.iSafeTextureCache_ColorSamples); u32 palette_size = 0; + u64 tlut_hash = 0; if (isPaletteTexture) { palette_size = TexDecoder_GetPaletteSize(texformat); - u64 tlut_hash = GetHash64(&texMem[tlutaddr], palette_size, g_ActiveConfig.iSafeTextureCache_ColorSamples); - - // Mix the tlut hash into the texture hash. So we only have to compare it once. - tex_hash ^= tlut_hash; + tlut_hash = GetHash64(&texMem[tlutaddr], palette_size, g_ActiveConfig.iSafeTextureCache_ColorSamples); } // GPUs don't like when the specified mipmap count would require more than one 1x1-sized LOD in the mipmap chain // e.g. 64x64 with 7 LODs would have the mipmap chain 64x64,32x32,16x16,8x8,4x4,2x2,1x1,0x0, so we limit the mipmap count to 6 there tex_levels = std::min(IntLog2(std::max(width, height)) + 1, tex_levels); + // Compute a texture ID; this isn't everything about a texture, rather just + // enough to group together textures with related memory addresses. + TextureAddress texID; + TextureAddress paletteDecodedID; + if (from_tmem) + { + u32 tmem_addr = bpmem.tex[stage / 4].texImage1[stage % 4].tmem_even * TMEM_LINE_SIZE; + if (texformat == GX_TF_RGBA8 && from_tmem) + { + u32 tmem_odd_addr = bpmem.tex[stage / 4].texImage2[stage % 4].tmem_odd * TMEM_LINE_SIZE; + texID = TextureAddress::TMemRGBA8(tmem_addr, tmem_odd_addr); + } + else + { + texID = TextureAddress::TMem(tmem_addr); + if (isPaletteTexture) + paletteDecodedID = TextureAddress::TMemPalette(tmem_addr, tlutaddr); + } + } + else + { + texID = TextureAddress::Mem(address); + if (isPaletteTexture) + paletteDecodedID = TextureAddress::MemPalette(address, tlutaddr); + } + // Find all texture cache entries for the current texture address, and decide whether to use one of // them, or to create a new one // @@ -360,7 +372,13 @@ TextureCache::TCacheEntryBase* TextureCache::Load(const u32 stage) // // For efb copies, the entry created in CopyRenderTargetToTexture always has to be used, or else it was // done in vain. - std::pair iter_range = textures.equal_range(address); + std::pair iter_range = textures.equal_range(texID); + bool palette_decoded_entry = false; + if (isPaletteTexture && iter_range.first == iter_range.second) + { + iter_range = textures.equal_range(paletteDecodedID); + palette_decoded_entry = true; + } TexCache::iterator iter = iter_range.first; TexCache::iterator oldest_entry = iter; int temp_frameCount = 0x7fffffff; @@ -370,14 +388,39 @@ TextureCache::TCacheEntryBase* TextureCache::Load(const u32 stage) TCacheEntryBase* entry = iter->second; if (entry->IsEfbCopy()) { - // For EFB copies, only the hash and the texture address need to match. Ignore the hash when - // using EFB to texture, because there's no hash in this case - if (g_ActiveConfig.bCopyEFBToTexture || entry->hash == tex_hash) + // EFB copies have slightly different rules: the hash doesn't need to match + // in EFB2Tex mode, and EFB copy formats have different meanings from texture + // formats. + if (g_ActiveConfig.bCopyEFBToTexture || + (tex_hash == entry->hash && (!isPaletteTexture || g_Config.backend_info.bSupportsPaletteConversion))) { - // TODO: Print a warning if the format changes! In this case, - // we could reinterpret the internal texture object data to the new pixel format - // (similar to what is already being done in Renderer::ReinterpretPixelFormat()) - // TODO: Convert paletted textures, which are efb copies, using the right palette, so they display correctly + // TODO: We should check format/width/height/levels for EFB copies. Checking + // format is complicated because EFB copy formats don't exactly match + // texture formats. I'm not sure what effect checking width/height/levels + // would have. + if (!palette_decoded_entry && isPaletteTexture && g_Config.backend_info.bSupportsPaletteConversion) + { + // Perform palette decoding. + // TODO: Skip decoding if we find a match. + std::pair decoded_iter_range = textures.equal_range(paletteDecodedID); + while (decoded_iter_range.first != decoded_iter_range.second) + { + // Pool this texture and make a new one later. + FreeTexture(decoded_iter_range.first->second); + decoded_iter_range.first = textures.erase(decoded_iter_range.first); + } + + TCacheEntryBase *decoded_entry = AllocateTexture(entry->config); + + decoded_entry->SetGeneralParameters(paletteDecodedID, texture_size, full_format); + decoded_entry->SetDimensions(entry->native_width, entry->native_height, 1); + decoded_entry->SetHashes(TEXHASH_INVALID); + decoded_entry->frameCount = FRAMECOUNT_INVALID; + + g_texture_cache->ConvertTexture(decoded_entry, entry, &texMem[tlutaddr], (TlutFormat)tlutfmt); + textures.insert(TexCache::value_type(paletteDecodedID, decoded_entry)); + entry = decoded_entry; + } return ReturnEntry(stage, entry); } else @@ -389,12 +432,14 @@ TextureCache::TCacheEntryBase* TextureCache::Load(const u32 stage) continue; } } - - // For normal textures, all texture parameters need to match - if (entry->hash == tex_hash && entry->format == full_format && entry->native_levels >= tex_levels && - entry->native_width == nativeW && entry->native_height == nativeH) + else { - return ReturnEntry(stage, entry); + // For normal textures, all texture parameters need to match + if (entry->hash == (tex_hash ^ tlut_hash) && entry->format == full_format && entry->native_levels >= tex_levels && + entry->native_width == nativeW && entry->native_height == nativeH) + { + return ReturnEntry(stage, entry); + } } // Find the entry which hasn't been used for the longest time @@ -468,11 +513,11 @@ TextureCache::TCacheEntryBase* TextureCache::Load(const u32 stage) TCacheEntryBase* entry = AllocateTexture(config); GFX_DEBUGGER_PAUSE_AT(NEXT_NEW_TEXTURE, true); - textures.insert(TexCache::value_type(address, entry)); + textures.insert(TexCache::value_type(isPaletteTexture ? paletteDecodedID : texID, entry)); - entry->SetGeneralParameters(address, texture_size, full_format); + entry->SetGeneralParameters(isPaletteTexture ? paletteDecodedID : texID, texture_size, full_format); entry->SetDimensions(nativeW, nativeH, tex_levels); - entry->hash = tex_hash; + entry->hash = tex_hash ^ tlut_hash; // load texture entry->Load(width, height, expandedWidth, 0); @@ -828,7 +873,7 @@ void TextureCache::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFormat unsigned int scaled_tex_h = g_ActiveConfig.bCopyEFBScaled ? Renderer::EFBToScaledY(tex_h) : tex_h; // remove all texture cache entries at dstAddr - std::pair iter_range = textures.equal_range(dstAddr); + std::pair iter_range = textures.equal_range(TextureAddress::Mem(dstAddr)); TexCache::iterator iter = iter_range.first; while (iter != iter_range.second) { @@ -846,7 +891,7 @@ void TextureCache::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFormat TCacheEntryBase* entry = AllocateTexture(config); // TODO: Using the wrong dstFormat, dumb... - entry->SetGeneralParameters(dstAddr, 0, dstFormat); + entry->SetGeneralParameters(TextureAddress::Mem(dstAddr), 0, dstFormat); entry->SetDimensions(tex_w, tex_h, 1); entry->SetHashes(TEXHASH_INVALID); @@ -854,7 +899,7 @@ void TextureCache::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFormat entry->FromRenderTarget(dstAddr, dstFormat, srcFormat, srcRect, isIntensity, scaleByHalf, cbufid, colmat); - textures.insert(TexCache::value_type(dstAddr, entry)); + textures.insert(TexCache::value_type(TextureAddress::Mem(dstAddr), entry)); } TextureCache::TCacheEntryBase* TextureCache::AllocateTexture(const TCacheEntryConfig& config) -- cgit v1.2.3 From ddc815dd7a77d70e42a18d18443732ec2f6f782a Mon Sep 17 00:00:00 2001 From: magumagu Date: Thu, 19 Feb 2015 15:19:31 -0800 Subject: Remove TextureAddress struct. --- Source/Core/VideoCommon/TextureCacheBase.cpp | 112 ++++++++++----------------- 1 file changed, 41 insertions(+), 71 deletions(-) (limited to 'Source/Core/VideoCommon/TextureCacheBase.cpp') diff --git a/Source/Core/VideoCommon/TextureCacheBase.cpp b/Source/Core/VideoCommon/TextureCacheBase.cpp index 6ab9705c4c..736ab57428 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/TextureCacheBase.cpp @@ -146,7 +146,7 @@ void TextureCache::Cleanup(int _frameCount) } if (_frameCount > TEXTURE_KILL_THRESHOLD + iter->second->frameCount && // EFB copies living on the host GPU are unrecoverable and thus shouldn't be deleted - !iter->second->IsUnrecoverable()) + !iter->second->IsEfbCopy()) { FreeTexture(iter->second); iter = textures.erase(iter); @@ -198,14 +198,10 @@ void TextureCache::MakeRangeDynamic(u32 start_address, u32 size) bool TextureCache::TCacheEntryBase::OverlapsMemoryRange(u32 range_address, u32 range_size) const { - if (!addr.HasMemAddress()) + if (addr + size_in_bytes <= range_address) return false; - u32 memaddr = addr.GetMemAddress(); - if (memaddr + size_in_bytes <= range_address) - return false; - - if (memaddr >= range_address + range_size) + if (addr >= range_address + range_size) return false; return true; @@ -322,32 +318,6 @@ TextureCache::TCacheEntryBase* TextureCache::Load(const u32 stage) // e.g. 64x64 with 7 LODs would have the mipmap chain 64x64,32x32,16x16,8x8,4x4,2x2,1x1,0x0, so we limit the mipmap count to 6 there tex_levels = std::min(IntLog2(std::max(width, height)) + 1, tex_levels); - // Compute a texture ID; this isn't everything about a texture, rather just - // enough to group together textures with related memory addresses. - TextureAddress texID; - TextureAddress paletteDecodedID; - if (from_tmem) - { - u32 tmem_addr = bpmem.tex[stage / 4].texImage1[stage % 4].tmem_even * TMEM_LINE_SIZE; - if (texformat == GX_TF_RGBA8 && from_tmem) - { - u32 tmem_odd_addr = bpmem.tex[stage / 4].texImage2[stage % 4].tmem_odd * TMEM_LINE_SIZE; - texID = TextureAddress::TMemRGBA8(tmem_addr, tmem_odd_addr); - } - else - { - texID = TextureAddress::TMem(tmem_addr); - if (isPaletteTexture) - paletteDecodedID = TextureAddress::TMemPalette(tmem_addr, tlutaddr); - } - } - else - { - texID = TextureAddress::Mem(address); - if (isPaletteTexture) - paletteDecodedID = TextureAddress::MemPalette(address, tlutaddr); - } - // Find all texture cache entries for the current texture address, and decide whether to use one of // them, or to create a new one // @@ -372,16 +342,11 @@ TextureCache::TCacheEntryBase* TextureCache::Load(const u32 stage) // // For efb copies, the entry created in CopyRenderTargetToTexture always has to be used, or else it was // done in vain. - std::pair iter_range = textures.equal_range(texID); - bool palette_decoded_entry = false; - if (isPaletteTexture && iter_range.first == iter_range.second) - { - iter_range = textures.equal_range(paletteDecodedID); - palette_decoded_entry = true; - } + std::pair iter_range = textures.equal_range(address); TexCache::iterator iter = iter_range.first; TexCache::iterator oldest_entry = iter; int temp_frameCount = 0x7fffffff; + TexCache::iterator unconverted_copy = textures.end(); while (iter != iter_range.second) { @@ -398,35 +363,21 @@ TextureCache::TCacheEntryBase* TextureCache::Load(const u32 stage) // format is complicated because EFB copy formats don't exactly match // texture formats. I'm not sure what effect checking width/height/levels // would have. - if (!palette_decoded_entry && isPaletteTexture && g_Config.backend_info.bSupportsPaletteConversion) - { - // Perform palette decoding. - // TODO: Skip decoding if we find a match. - std::pair decoded_iter_range = textures.equal_range(paletteDecodedID); - while (decoded_iter_range.first != decoded_iter_range.second) - { - // Pool this texture and make a new one later. - FreeTexture(decoded_iter_range.first->second); - decoded_iter_range.first = textures.erase(decoded_iter_range.first); - } - - TCacheEntryBase *decoded_entry = AllocateTexture(entry->config); - - decoded_entry->SetGeneralParameters(paletteDecodedID, texture_size, full_format); - decoded_entry->SetDimensions(entry->native_width, entry->native_height, 1); - decoded_entry->SetHashes(TEXHASH_INVALID); - decoded_entry->frameCount = FRAMECOUNT_INVALID; - - g_texture_cache->ConvertTexture(decoded_entry, entry, &texMem[tlutaddr], (TlutFormat)tlutfmt); - textures.insert(TexCache::value_type(paletteDecodedID, decoded_entry)); - entry = decoded_entry; - } - return ReturnEntry(stage, entry); + if (!isPaletteTexture || !g_Config.backend_info.bSupportsPaletteConversion) + return ReturnEntry(stage, entry); + + // Note that we found an unconverted EFB copy, then continue. We'll + // perform the conversion later. Currently, we only convert EFB copies to + // palette textures; we could do other conversions if it proved to be + // beneficial. + unconverted_copy = iter; } else { - // Keeping an unused entry for an efb copy in the cache is pointless, because a new entry - // will be created in CopyRenderTargetToTexture + // Aggressively prune EFB copies: if it isn't useful here, it will probably + // never be useful again. It's theoretically possible for a game to do + // something weird where the copy could become useful in the future, but in + // practice it doesn't happen. FreeTexture(entry); iter = textures.erase(iter); continue; @@ -451,6 +402,23 @@ TextureCache::TCacheEntryBase* TextureCache::Load(const u32 stage) ++iter; } + if (unconverted_copy != textures.end()) + { + // Perform palette decoding. + TCacheEntryBase *entry = unconverted_copy->second; + TCacheEntryBase *decoded_entry = AllocateTexture(entry->config); + + decoded_entry->SetGeneralParameters(address, texture_size, full_format); + decoded_entry->SetDimensions(entry->native_width, entry->native_height, 1); + decoded_entry->SetHashes(tex_hash ^ tlut_hash); + decoded_entry->frameCount = FRAMECOUNT_INVALID; + decoded_entry->is_efb_copy = false; + + g_texture_cache->ConvertTexture(decoded_entry, entry, &texMem[tlutaddr], (TlutFormat)tlutfmt); + textures.insert(TexCache::value_type(address, decoded_entry)); + return ReturnEntry(stage, decoded_entry); + } + // If at least one entry was not used for the same frame, overwrite the oldest one if (temp_frameCount != 0x7fffffff) { @@ -513,11 +481,12 @@ TextureCache::TCacheEntryBase* TextureCache::Load(const u32 stage) TCacheEntryBase* entry = AllocateTexture(config); GFX_DEBUGGER_PAUSE_AT(NEXT_NEW_TEXTURE, true); - textures.insert(TexCache::value_type(isPaletteTexture ? paletteDecodedID : texID, entry)); + textures.insert(TexCache::value_type(address, entry)); - entry->SetGeneralParameters(isPaletteTexture ? paletteDecodedID : texID, texture_size, full_format); + entry->SetGeneralParameters(address, texture_size, full_format); entry->SetDimensions(nativeW, nativeH, tex_levels); entry->hash = tex_hash ^ tlut_hash; + entry->is_efb_copy = false; // load texture entry->Load(width, height, expandedWidth, 0); @@ -873,7 +842,7 @@ void TextureCache::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFormat unsigned int scaled_tex_h = g_ActiveConfig.bCopyEFBScaled ? Renderer::EFBToScaledY(tex_h) : tex_h; // remove all texture cache entries at dstAddr - std::pair iter_range = textures.equal_range(TextureAddress::Mem(dstAddr)); + std::pair iter_range = textures.equal_range(dstAddr); TexCache::iterator iter = iter_range.first; while (iter != iter_range.second) { @@ -891,15 +860,16 @@ void TextureCache::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFormat TCacheEntryBase* entry = AllocateTexture(config); // TODO: Using the wrong dstFormat, dumb... - entry->SetGeneralParameters(TextureAddress::Mem(dstAddr), 0, dstFormat); + entry->SetGeneralParameters(dstAddr, 0, dstFormat); entry->SetDimensions(tex_w, tex_h, 1); entry->SetHashes(TEXHASH_INVALID); entry->frameCount = FRAMECOUNT_INVALID; + entry->is_efb_copy = true; entry->FromRenderTarget(dstAddr, dstFormat, srcFormat, srcRect, isIntensity, scaleByHalf, cbufid, colmat); - textures.insert(TexCache::value_type(TextureAddress::Mem(dstAddr), entry)); + textures.insert(TexCache::value_type(dstAddr, entry)); } TextureCache::TCacheEntryBase* TextureCache::AllocateTexture(const TCacheEntryConfig& config) -- cgit v1.2.3 From 074397c12dd95b6c5119054ed6674043fb4641cc Mon Sep 17 00:00:00 2001 From: magumagu Date: Thu, 19 Feb 2015 15:53:52 -0800 Subject: Explicitly set up AllocateTexture configuration for palette conversion. No functional change. --- Source/Core/VideoCommon/TextureCacheBase.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'Source/Core/VideoCommon/TextureCacheBase.cpp') diff --git a/Source/Core/VideoCommon/TextureCacheBase.cpp b/Source/Core/VideoCommon/TextureCacheBase.cpp index 736ab57428..62fdfa80d2 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/TextureCacheBase.cpp @@ -406,7 +406,13 @@ TextureCache::TCacheEntryBase* TextureCache::Load(const u32 stage) { // Perform palette decoding. TCacheEntryBase *entry = unconverted_copy->second; - TCacheEntryBase *decoded_entry = AllocateTexture(entry->config); + + TCacheEntryConfig config; + config.rendertarget = true; + config.width = entry->config.width; + config.height = entry->config.height; + config.layers = FramebufferManagerBase::GetEFBLayers(); + TCacheEntryBase *decoded_entry = AllocateTexture(config); decoded_entry->SetGeneralParameters(address, texture_size, full_format); decoded_entry->SetDimensions(entry->native_width, entry->native_height, 1); -- cgit v1.2.3 From e2fec13ab6d02617a2f17c2ae892ef3384a222d6 Mon Sep 17 00:00:00 2001 From: Tillmann Karras Date: Tue, 24 Feb 2015 01:40:48 +0100 Subject: Fix some -Wsign-compare warnings --- Source/Core/VideoCommon/TextureCacheBase.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Source/Core/VideoCommon/TextureCacheBase.cpp') diff --git a/Source/Core/VideoCommon/TextureCacheBase.cpp b/Source/Core/VideoCommon/TextureCacheBase.cpp index 62fdfa80d2..7bd5a6b570 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/TextureCacheBase.cpp @@ -23,7 +23,7 @@ static const u64 TEXHASH_INVALID = 0; static const int TEXTURE_KILL_THRESHOLD = 10; static const int TEXTURE_POOL_KILL_THRESHOLD = 3; -static const u64 FRAMECOUNT_INVALID = 0; +static const int FRAMECOUNT_INVALID = 0; TextureCache *g_texture_cache; -- cgit v1.2.3 From 967eaad8df52197dad69891c25cbc69f8e52e6b8 Mon Sep 17 00:00:00 2001 From: degasus Date: Sat, 21 Feb 2015 12:08:47 +0100 Subject: VideoCommon: rename efb2tex and efb2ram --- Source/Core/VideoCommon/TextureCacheBase.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Source/Core/VideoCommon/TextureCacheBase.cpp') diff --git a/Source/Core/VideoCommon/TextureCacheBase.cpp b/Source/Core/VideoCommon/TextureCacheBase.cpp index 7bd5a6b570..8b6e819fed 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/TextureCacheBase.cpp @@ -356,7 +356,7 @@ TextureCache::TCacheEntryBase* TextureCache::Load(const u32 stage) // EFB copies have slightly different rules: the hash doesn't need to match // in EFB2Tex mode, and EFB copy formats have different meanings from texture // formats. - if (g_ActiveConfig.bCopyEFBToTexture || + if (g_ActiveConfig.bSkipEFBCopyToRam || (tex_hash == entry->hash && (!isPaletteTexture || g_Config.backend_info.bSupportsPaletteConversion))) { // TODO: We should check format/width/height/levels for EFB copies. Checking -- cgit v1.2.3 From 93b16a4a2d5f3e6d467d1315c461aff12852b26c Mon Sep 17 00:00:00 2001 From: Stevoisiak Date: Sun, 15 Feb 2015 14:43:31 -0500 Subject: Formatting/Whitespace Cleanup Various fixes to formatting and whitespace --- Source/Core/VideoCommon/TextureCacheBase.cpp | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'Source/Core/VideoCommon/TextureCacheBase.cpp') diff --git a/Source/Core/VideoCommon/TextureCacheBase.cpp b/Source/Core/VideoCommon/TextureCacheBase.cpp index 62fdfa80d2..603d1a4500 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/TextureCacheBase.cpp @@ -140,7 +140,7 @@ void TextureCache::Cleanup(int _frameCount) TexCache::iterator tcend = textures.end(); while (iter != tcend) { - if(iter->second->frameCount == FRAMECOUNT_INVALID) + if (iter->second->frameCount == FRAMECOUNT_INVALID) { iter->second->frameCount = _frameCount; } @@ -161,7 +161,7 @@ void TextureCache::Cleanup(int _frameCount) TexPool::iterator tcend2 = texture_pool.end(); while (iter2 != tcend2) { - if(iter2->second->frameCount == FRAMECOUNT_INVALID) + if (iter2->second->frameCount == FRAMECOUNT_INVALID) { iter2->second->frameCount = _frameCount; } @@ -467,7 +467,7 @@ TextureCache::TCacheEntryBase* TextureCache::Load(const u32 stage) } else { - u8* src_data_gb = &texMem[bpmem.tex[stage/4].texImage2[stage%4].tmem_odd * TMEM_LINE_SIZE]; + u8* src_data_gb = &texMem[bpmem.tex[stage / 4].texImage2[stage % 4].tmem_odd * TMEM_LINE_SIZE]; TexDecoder_DecodeRGBA8FromTmem(temp, src_data, src_data_gb, expandedWidth, expandedHeight); } } @@ -520,8 +520,8 @@ TextureCache::TCacheEntryBase* TextureCache::Load(const u32 stage) const u8* ptr_odd = nullptr; if (from_tmem) { - ptr_even = &texMem[bpmem.tex[stage/4].texImage1[stage%4].tmem_even * TMEM_LINE_SIZE + texture_size]; - ptr_odd = &texMem[bpmem.tex[stage/4].texImage2[stage%4].tmem_odd * TMEM_LINE_SIZE]; + ptr_even = &texMem[bpmem.tex[stage / 4].texImage1[stage % 4].tmem_even * TMEM_LINE_SIZE + texture_size]; + ptr_odd = &texMem[bpmem.tex[stage / 4].texImage2[stage % 4].tmem_odd * TMEM_LINE_SIZE]; } for (; level != texLevels; ++level) @@ -535,7 +535,7 @@ TextureCache::TCacheEntryBase* TextureCache::Load(const u32 stage) ? ((level % 2) ? ptr_odd : ptr_even) : src_data; const u8* tlut = &texMem[tlutaddr]; - TexDecoder_Decode(temp, mip_src_data, expanded_mip_width, expanded_mip_height, texformat, tlut, (TlutFormat) tlutfmt); + TexDecoder_Decode(temp, mip_src_data, expanded_mip_width, expanded_mip_height, texformat, tlut, (TlutFormat)tlutfmt); mip_src_data += TexDecoder_GetTextureSizeInBytes(expanded_mip_width, expanded_mip_height, texformat); entry->Load(mip_width, mip_height, expanded_mip_width, level); @@ -669,7 +669,7 @@ void TextureCache::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFormat } else if (isIntensity) { - fConstAdd[0] = fConstAdd[1] = fConstAdd[2] = 16.0f/255.0f; + fConstAdd[0] = fConstAdd[1] = fConstAdd[2] = 16.0f / 255.0f; switch (dstFormat) { case 0: // I4 @@ -685,7 +685,7 @@ void TextureCache::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFormat if (dstFormat < 2 || dstFormat == 8) { colmat[12] = 0.257f; colmat[13] = 0.504f; colmat[14] = 0.098f; - fConstAdd[3] = 16.0f/255.0f; + fConstAdd[3] = 16.0f / 255.0f; if (dstFormat == 0) { ColorMask[0] = ColorMask[1] = ColorMask[2] = 15.0f; @@ -841,8 +841,8 @@ void TextureCache::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFormat } } - const unsigned int tex_w = scaleByHalf ? srcRect.GetWidth()/2 : srcRect.GetWidth(); - const unsigned int tex_h = scaleByHalf ? srcRect.GetHeight()/2 : srcRect.GetHeight(); + const unsigned int tex_w = scaleByHalf ? srcRect.GetWidth() / 2 : srcRect.GetWidth(); + const unsigned int tex_h = scaleByHalf ? srcRect.GetHeight() / 2 : srcRect.GetHeight(); unsigned int scaled_tex_w = g_ActiveConfig.bCopyEFBScaled ? Renderer::EFBToScaledX(tex_w) : tex_w; unsigned int scaled_tex_h = g_ActiveConfig.bCopyEFBScaled ? Renderer::EFBToScaledY(tex_h) : tex_h; -- cgit v1.2.3 From 7ca24f90d169dbca36f96eb7bc89bbe89f06febd Mon Sep 17 00:00:00 2001 From: degasus Date: Sun, 1 Mar 2015 12:19:33 +0100 Subject: TexCache: increase TEXTURE_KILL_THRESHOLD Xenoblade uses more than 40 textures alternately per frame for eg water effects. So don't try to drop them as aggressive. --- Source/Core/VideoCommon/TextureCacheBase.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Source/Core/VideoCommon/TextureCacheBase.cpp') diff --git a/Source/Core/VideoCommon/TextureCacheBase.cpp b/Source/Core/VideoCommon/TextureCacheBase.cpp index e27c3b7224..e35a94424b 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/TextureCacheBase.cpp @@ -21,7 +21,7 @@ #include "VideoCommon/VideoConfig.h" static const u64 TEXHASH_INVALID = 0; -static const int TEXTURE_KILL_THRESHOLD = 10; +static const int TEXTURE_KILL_THRESHOLD = 60; static const int TEXTURE_POOL_KILL_THRESHOLD = 3; static const int FRAMECOUNT_INVALID = 0; -- cgit v1.2.3 From 35373c5185d586602a44c51544f85fb6acde10f1 Mon Sep 17 00:00:00 2001 From: degasus Date: Sun, 1 Mar 2015 13:04:48 +0100 Subject: TextureCache: load all mipmap levels from custom textures This drops the "feature" to load level 0 from the custom texture and all other levels from the native one if the size matches. But in my opinion, when a custom texture only provide one level, no more should be used at all. --- Source/Core/VideoCommon/TextureCacheBase.cpp | 40 +++++++++++++--------------- 1 file changed, 19 insertions(+), 21 deletions(-) (limited to 'Source/Core/VideoCommon/TextureCacheBase.cpp') diff --git a/Source/Core/VideoCommon/TextureCacheBase.cpp b/Source/Core/VideoCommon/TextureCacheBase.cpp index e35a94424b..53168f45e7 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/TextureCacheBase.cpp @@ -266,8 +266,8 @@ TextureCache::TCacheEntryBase* TextureCache::Load(const u32 stage) const int texformat = tex.texImage0[id].format; const u32 tlutaddr = tex.texTlut[id].tmem_offset << 9; const u32 tlutfmt = tex.texTlut[id].tlut_format; - u32 tex_levels = (tex.texMode1[id].max_lod + 0xf) / 0x10 + 1; - const bool use_mipmaps = (tex.texMode0[id].min_filter & 3) != 0 && tex_levels > 0; + const bool use_mipmaps = (tex.texMode0[id].min_filter & 3) != 0; + u32 tex_levels = use_mipmaps ? ((tex.texMode1[id].max_lod + 0xf) / 0x10 + 1) : 1; const bool from_tmem = tex.texImage1[id].image_type != 0; if (0 == address) @@ -472,11 +472,8 @@ TextureCache::TCacheEntryBase* TextureCache::Load(const u32 stage) } } - u32 texLevels = use_mipmaps ? tex_levels : 1; - 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 - 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) + // how many levels the allocated texture shall have + const u32 texLevels = hires_tex ? (u32)hires_tex->m_levels.size() : tex_levels; // create the entry/texture TCacheEntryConfig config; @@ -493,6 +490,7 @@ TextureCache::TCacheEntryBase* TextureCache::Load(const u32 stage) entry->SetDimensions(nativeW, nativeH, tex_levels); entry->hash = tex_hash ^ tlut_hash; entry->is_efb_copy = false; + entry->is_custom_tex = hires_tex != nullptr; // load texture entry->Load(width, height, expandedWidth, 0); @@ -510,10 +508,19 @@ TextureCache::TCacheEntryBase* TextureCache::Load(const u32 stage) DumpTexture(entry, basename, 0); } - u32 level = 1; - // load mips - TODO: Loading mipmaps from tmem is untested! - if (use_native_mips) + if (hires_tex) { + for (u32 level = 1; level != texLevels; ++level) + { + auto& l = hires_tex->m_levels[level]; + CheckTempSize(l.data_size); + memcpy(temp, l.data, l.data_size); + entry->Load(l.width, l.height, l.width, level); + } + } + else + { + // load mips - TODO: Loading mipmaps from tmem is untested! src_data += texture_size; const u8* ptr_even = nullptr; @@ -524,7 +531,7 @@ TextureCache::TCacheEntryBase* TextureCache::Load(const u32 stage) ptr_odd = &texMem[bpmem.tex[stage / 4].texImage2[stage % 4].tmem_odd * TMEM_LINE_SIZE]; } - for (; level != texLevels; ++level) + for (u32 level = 1; level != texLevels; ++level) { const u32 mip_width = CalculateLevelSize(width, level); const u32 mip_height = CalculateLevelSize(height, level); @@ -544,16 +551,6 @@ TextureCache::TCacheEntryBase* TextureCache::Load(const u32 stage) DumpTexture(entry, basename, level); } } - else if (using_custom_lods) - { - for (; level != texLevels; ++level) - { - auto& l = hires_tex->m_levels[level]; - CheckTempSize(l.data_size); - memcpy(temp, l.data, l.data_size); - entry->Load(l.width, l.height, l.width, level); - } - } INCSTAT(stats.numTexturesUploaded); SETSTAT(stats.numTexturesAlive, textures.size()); @@ -872,6 +869,7 @@ void TextureCache::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFormat entry->frameCount = FRAMECOUNT_INVALID; entry->is_efb_copy = true; + entry->is_custom_tex = false; entry->FromRenderTarget(dstAddr, dstFormat, srcFormat, srcRect, isIntensity, scaleByHalf, cbufid, colmat); -- cgit v1.2.3 From 54f44439715975d5b6e6e15ad7bad5c20ae625ef Mon Sep 17 00:00:00 2001 From: Jules Blok Date: Sat, 2 May 2015 12:10:40 +0200 Subject: VideoCommon: Implement EFB dumping for both backends. --- Source/Core/VideoCommon/TextureCacheBase.cpp | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'Source/Core/VideoCommon/TextureCacheBase.cpp') diff --git a/Source/Core/VideoCommon/TextureCacheBase.cpp b/Source/Core/VideoCommon/TextureCacheBase.cpp index 53168f45e7..251ee54783 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/TextureCacheBase.cpp @@ -873,6 +873,13 @@ void TextureCache::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFormat entry->FromRenderTarget(dstAddr, dstFormat, srcFormat, srcRect, isIntensity, scaleByHalf, cbufid, colmat); + if (g_ActiveConfig.bDumpEFBTarget) + { + static int count = 0; + entry->Save(StringFromFormat("%sefb_frame_%i.png", File::GetUserPath(D_DUMPTEXTURES_IDX).c_str(), + count++), 0); + } + textures.insert(TexCache::value_type(dstAddr, entry)); } -- cgit v1.2.3 From 242f7d964d30c37f8547a0763484f68d2bdcaef1 Mon Sep 17 00:00:00 2001 From: degasus Date: Sun, 1 Mar 2015 23:53:15 +0100 Subject: CustomTexture: prefetch all available textures --- Source/Core/VideoCommon/TextureCacheBase.cpp | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) (limited to 'Source/Core/VideoCommon/TextureCacheBase.cpp') diff --git a/Source/Core/VideoCommon/TextureCacheBase.cpp b/Source/Core/VideoCommon/TextureCacheBase.cpp index 251ee54783..f06043883d 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/TextureCacheBase.cpp @@ -60,8 +60,7 @@ TextureCache::TextureCache() TexDecoder_SetTexFmtOverlayOptions(g_ActiveConfig.bTexFmtOverlayEnable, g_ActiveConfig.bTexFmtOverlayCenter); - if (g_ActiveConfig.bHiresTextures && !g_ActiveConfig.bDumpTextures) - HiresTexture::Init(SConfig::GetInstance().m_LocalCoreStartupParameter.m_strUniqueID); + HiresTexture::Init(); SetHash64Function(); @@ -92,6 +91,7 @@ void TextureCache::Invalidate() TextureCache::~TextureCache() { + HiresTexture::Shutdown(); Invalidate(); FreeAlignedMemory(temp); temp = nullptr; @@ -101,6 +101,12 @@ void TextureCache::OnConfigChanged(VideoConfig& config) { if (g_texture_cache) { + if (config.bHiresTextures != backup_config.s_hires_textures || + config.bCacheHiresTextures != backup_config.s_cache_hires_textures) + { + HiresTexture::Update(); + } + // TODO: Invalidating texcache is really stupid in some of these cases if (config.iSafeTextureCache_ColorSamples != backup_config.s_colorsamples || config.bTexFmtOverlayEnable != backup_config.s_texfmt_overlay || @@ -110,9 +116,6 @@ void TextureCache::OnConfigChanged(VideoConfig& config) { g_texture_cache->Invalidate(); - if (g_ActiveConfig.bHiresTextures) - HiresTexture::Init(SConfig::GetInstance().m_LocalCoreStartupParameter.m_strUniqueID); - TexDecoder_SetTexFmtOverlayOptions(g_ActiveConfig.bTexFmtOverlayEnable, g_ActiveConfig.bTexFmtOverlayCenter); invalidate_texture_cache_requested = false; @@ -130,6 +133,7 @@ void TextureCache::OnConfigChanged(VideoConfig& config) backup_config.s_texfmt_overlay = config.bTexFmtOverlayEnable; backup_config.s_texfmt_overlay_center = config.bTexFmtOverlayCenter; backup_config.s_hires_textures = config.bHiresTextures; + backup_config.s_cache_hires_textures = config.bCacheHiresTextures; backup_config.s_stereo_3d = config.iStereoMode > 0; backup_config.s_efb_mono_depth = config.bStereoEFBMonoDepth; } @@ -433,15 +437,15 @@ TextureCache::TCacheEntryBase* TextureCache::Load(const u32 stage) textures.erase(oldest_entry); } - std::unique_ptr hires_tex; + std::shared_ptr hires_tex; if (g_ActiveConfig.bHiresTextures) { - hires_tex.reset(HiresTexture::Search( + hires_tex = HiresTexture::Search( src_data, texture_size, &texMem[tlutaddr], palette_size, width, height, texformat, use_mipmaps - )); + ); if (hires_tex) { -- cgit v1.2.3 From cefcb0ace9d363b3679b4e93bcc9ec05f1e5f4f8 Mon Sep 17 00:00:00 2001 From: Tillmann Karras Date: Mon, 18 May 2015 01:08:10 +0200 Subject: Update license headers to GPLv2+ --- Source/Core/VideoCommon/TextureCacheBase.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Source/Core/VideoCommon/TextureCacheBase.cpp') diff --git a/Source/Core/VideoCommon/TextureCacheBase.cpp b/Source/Core/VideoCommon/TextureCacheBase.cpp index 251ee54783..98aa101b28 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/TextureCacheBase.cpp @@ -1,5 +1,5 @@ // Copyright 2013 Dolphin Emulator Project -// Licensed under GPLv2 +// Licensed under GPLv2+ // Refer to the license.txt file included. #include -- cgit v1.2.3 From 30ebb2459eb97ba544547183854775df8460b475 Mon Sep 17 00:00:00 2001 From: Tillmann Karras Date: Sun, 24 May 2015 06:55:12 +0200 Subject: Set copyright year to when a file was created --- Source/Core/VideoCommon/TextureCacheBase.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Source/Core/VideoCommon/TextureCacheBase.cpp') diff --git a/Source/Core/VideoCommon/TextureCacheBase.cpp b/Source/Core/VideoCommon/TextureCacheBase.cpp index 98aa101b28..bce936661e 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/TextureCacheBase.cpp @@ -1,4 +1,4 @@ -// Copyright 2013 Dolphin Emulator Project +// Copyright 2010 Dolphin Emulator Project // Licensed under GPLv2+ // Refer to the license.txt file included. -- cgit v1.2.3 From 3b9020dc9bd164f53a022a276a3369f3e5a97135 Mon Sep 17 00:00:00 2001 From: mimimi085181 Date: Sun, 22 Feb 2015 18:42:19 +0100 Subject: Search the texture cache for small textures by address and hash This fixes issue 6563: https://code.google.com/p/dolphin-emu/issues/detail?id=6563 This PR adds a 2nd map to texture cache, which uses the hash as key. Cache entries from this new map are used only if the address matches or if the texture was fully hashed. This restriction avoids false positive cache hits. This results in a possible situation where safe texture cache accuracy could be faster than the fast one. Small textures means up to 1KB for fast texture cache accuracy, 4KB for medium, and all textures for safe accuracy. Since this adds a small overhead to all texture cache handling, some regression testing would be nice. Games, which use a lot of textures the same time, should be affected the most. --- Source/Core/VideoCommon/TextureCacheBase.cpp | 114 +++++++++++++++++++-------- 1 file changed, 81 insertions(+), 33 deletions(-) (limited to 'Source/Core/VideoCommon/TextureCacheBase.cpp') diff --git a/Source/Core/VideoCommon/TextureCacheBase.cpp b/Source/Core/VideoCommon/TextureCacheBase.cpp index ac882ec3df..6ca71d037c 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/TextureCacheBase.cpp @@ -30,7 +30,8 @@ TextureCache *g_texture_cache; GC_ALIGNED16(u8 *TextureCache::temp) = nullptr; size_t TextureCache::temp_size; -TextureCache::TexCache TextureCache::textures; +TextureCache::TexCache TextureCache::textures_by_address; +TextureCache::TexCache TextureCache::textures_by_hash; TextureCache::TexPool TextureCache::texture_pool; TextureCache::TCacheEntryBase* TextureCache::bound_textures[8]; @@ -76,11 +77,12 @@ void TextureCache::Invalidate() { UnbindTextures(); - for (auto& tex : textures) + for (auto& tex : textures_by_address) { delete tex.second; } - textures.clear(); + textures_by_address.clear(); + textures_by_hash.clear(); for (auto& rt : texture_pool) { @@ -140,8 +142,8 @@ void TextureCache::OnConfigChanged(VideoConfig& config) void TextureCache::Cleanup(int _frameCount) { - TexCache::iterator iter = textures.begin(); - TexCache::iterator tcend = textures.end(); + TexCache::iterator iter = textures_by_address.begin(); + TexCache::iterator tcend = textures_by_address.end(); while (iter != tcend) { if (iter->second->frameCount == FRAMECOUNT_INVALID) @@ -152,8 +154,7 @@ void TextureCache::Cleanup(int _frameCount) // EFB copies living on the host GPU are unrecoverable and thus shouldn't be deleted !iter->second->IsEfbCopy()) { - FreeTexture(iter->second); - iter = textures.erase(iter); + iter = RemoveTextureFromCache(iter); } else { @@ -184,14 +185,13 @@ void TextureCache::Cleanup(int _frameCount) void TextureCache::MakeRangeDynamic(u32 start_address, u32 size) { TexCache::iterator - iter = textures.begin(); + iter = textures_by_address.begin(); - while (iter != textures.end()) + while (iter != textures_by_address.end()) { if (iter->second->OverlapsMemoryRange(start_address, size)) { - FreeTexture(iter->second); - iter = textures.erase(iter); + iter = RemoveTextureFromCache(iter); } else { @@ -288,6 +288,7 @@ TextureCache::TCacheEntryBase* TextureCache::Load(const u32 stage) // Hash assigned to texcache entry (also used to generate filenames used for texture dumping and custom texture lookup) u64 tex_hash = TEXHASH_INVALID; + u64 full_hash = TEXHASH_INVALID; u32 full_format = texformat; @@ -311,17 +312,22 @@ TextureCache::TCacheEntryBase* TextureCache::Load(const u32 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) tex_hash = GetHash64(src_data, texture_size, g_ActiveConfig.iSafeTextureCache_ColorSamples); u32 palette_size = 0; - u64 tlut_hash = 0; if (isPaletteTexture) { palette_size = TexDecoder_GetPaletteSize(texformat); - tlut_hash = GetHash64(&texMem[tlutaddr], palette_size, g_ActiveConfig.iSafeTextureCache_ColorSamples); + full_hash = tex_hash ^ GetHash64(&texMem[tlutaddr], palette_size, g_ActiveConfig.iSafeTextureCache_ColorSamples); + } + else + { + full_hash = tex_hash; } // GPUs don't like when the specified mipmap count would require more than one 1x1-sized LOD in the mipmap chain // e.g. 64x64 with 7 LODs would have the mipmap chain 64x64,32x32,16x16,8x8,4x4,2x2,1x1,0x0, so we limit the mipmap count to 6 there tex_levels = std::min(IntLog2(std::max(width, height)) + 1, tex_levels); + // Search the texture cache for textures by address + // // Find all texture cache entries for the current texture address, and decide whether to use one of // them, or to create a new one // @@ -346,11 +352,11 @@ TextureCache::TCacheEntryBase* TextureCache::Load(const u32 stage) // // For efb copies, the entry created in CopyRenderTargetToTexture always has to be used, or else it was // done in vain. - std::pair iter_range = textures.equal_range(address); + std::pair iter_range = textures_by_address.equal_range((u64)address); TexCache::iterator iter = iter_range.first; TexCache::iterator oldest_entry = iter; int temp_frameCount = 0x7fffffff; - TexCache::iterator unconverted_copy = textures.end(); + TexCache::iterator unconverted_copy = textures_by_address.end(); while (iter != iter_range.second) { @@ -383,14 +389,14 @@ TextureCache::TCacheEntryBase* TextureCache::Load(const u32 stage) // something weird where the copy could become useful in the future, but in // practice it doesn't happen. FreeTexture(entry); - iter = textures.erase(iter); + iter = textures_by_address.erase(iter); continue; } } else { // For normal textures, all texture parameters need to match - if (entry->hash == (tex_hash ^ tlut_hash) && entry->format == full_format && entry->native_levels >= tex_levels && + if (entry->hash == full_hash && entry->format == full_format && entry->native_levels >= tex_levels && entry->native_width == nativeW && entry->native_height == nativeH) { return ReturnEntry(stage, entry); @@ -406,7 +412,7 @@ TextureCache::TCacheEntryBase* TextureCache::Load(const u32 stage) ++iter; } - if (unconverted_copy != textures.end()) + if (unconverted_copy != textures_by_address.end()) { // Perform palette decoding. TCacheEntryBase *entry = unconverted_copy->second; @@ -420,21 +426,42 @@ TextureCache::TCacheEntryBase* TextureCache::Load(const u32 stage) decoded_entry->SetGeneralParameters(address, texture_size, full_format); decoded_entry->SetDimensions(entry->native_width, entry->native_height, 1); - decoded_entry->SetHashes(tex_hash ^ tlut_hash); + decoded_entry->SetHashes(full_hash); decoded_entry->frameCount = FRAMECOUNT_INVALID; decoded_entry->is_efb_copy = false; g_texture_cache->ConvertTexture(decoded_entry, entry, &texMem[tlutaddr], (TlutFormat)tlutfmt); - textures.insert(TexCache::value_type(address, decoded_entry)); + textures_by_address.insert(TexCache::value_type((u64)address, decoded_entry)); return ReturnEntry(stage, decoded_entry); } + // Search the texture cache for normal textures by hash + // + // If the texture was fully hashed, the address does not need to match. Identical duplicate textures cause unnecessary slowdowns + // Example: Tales of Symphonia (GC) uses over 500 small textures in menus, but only around 70 different ones + if (g_ActiveConfig.iSafeTextureCache_ColorSamples == 0 || + std::max(texture_size, palette_size) <= (u32)g_ActiveConfig.iSafeTextureCache_ColorSamples * 8) + { + iter_range = textures_by_hash.equal_range(full_hash); + iter = iter_range.first; + while (iter != iter_range.second) + { + TCacheEntryBase* entry = iter->second; + // All parameters, except the address, need to match here + if (entry->format == full_format && entry->native_levels >= tex_levels && + entry->native_width == nativeW && entry->native_height == nativeH) + { + return ReturnEntry(stage, entry); + } + ++iter; + } + } + // If at least one entry was not used for the same frame, overwrite the oldest one if (temp_frameCount != 0x7fffffff) { // pool this texture and make a new one later - FreeTexture(oldest_entry->second); - textures.erase(oldest_entry); + RemoveTextureFromCache(oldest_entry); } std::shared_ptr hires_tex; @@ -488,11 +515,16 @@ TextureCache::TCacheEntryBase* TextureCache::Load(const u32 stage) TCacheEntryBase* entry = AllocateTexture(config); GFX_DEBUGGER_PAUSE_AT(NEXT_NEW_TEXTURE, true); - textures.insert(TexCache::value_type(address, entry)); + textures_by_address.insert(TexCache::value_type((u64)address, entry)); + if (g_ActiveConfig.iSafeTextureCache_ColorSamples == 0 || + std::max(texture_size, palette_size) <= (u32)g_ActiveConfig.iSafeTextureCache_ColorSamples * 8) + { + entry->textures_by_hash_iter = textures_by_hash.insert(TexCache::value_type(full_hash, entry)); + } entry->SetGeneralParameters(address, texture_size, full_format); entry->SetDimensions(nativeW, nativeH, tex_levels); - entry->hash = tex_hash ^ tlut_hash; + entry->hash = full_hash; entry->is_efb_copy = false; entry->is_custom_tex = hires_tex != nullptr; @@ -557,7 +589,7 @@ TextureCache::TCacheEntryBase* TextureCache::Load(const u32 stage) } INCSTAT(stats.numTexturesUploaded); - SETSTAT(stats.numTexturesAlive, textures.size()); + SETSTAT(stats.numTexturesAlive, textures_by_address.size()); return ReturnEntry(stage, entry); } @@ -849,12 +881,11 @@ void TextureCache::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFormat unsigned int scaled_tex_h = g_ActiveConfig.bCopyEFBScaled ? Renderer::EFBToScaledY(tex_h) : tex_h; // remove all texture cache entries at dstAddr - std::pair iter_range = textures.equal_range(dstAddr); + std::pair iter_range = textures_by_address.equal_range((u64)dstAddr); TexCache::iterator iter = iter_range.first; while (iter != iter_range.second) { - FreeTexture(iter->second); - iter = textures.erase(iter); + iter = RemoveTextureFromCache(iter); } // create the texture @@ -884,21 +915,38 @@ void TextureCache::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFormat count++), 0); } - textures.insert(TexCache::value_type(dstAddr, entry)); + textures_by_address.insert(TexCache::value_type((u64)dstAddr, entry)); } TextureCache::TCacheEntryBase* TextureCache::AllocateTexture(const TCacheEntryConfig& config) { TexPool::iterator iter = texture_pool.find(config); + TextureCache::TCacheEntryBase* entry; if (iter != texture_pool.end()) { - TextureCache::TCacheEntryBase* entry = iter->second; + entry = iter->second; texture_pool.erase(iter); - return entry; + } + else + { + entry = g_texture_cache->CreateTexture(config); + INCSTAT(stats.numTexturesCreated); + } + + entry->textures_by_hash_iter = textures_by_address.end(); + return entry; +} + +TextureCache::TexCache::iterator TextureCache::RemoveTextureFromCache(TexCache::iterator iter) +{ + if (iter->second->textures_by_hash_iter != textures_by_address.end()) + { + textures_by_hash.erase(iter->second->textures_by_hash_iter); + iter->second->textures_by_hash_iter = textures_by_address.end(); } - INCSTAT(stats.numTexturesCreated); - return g_texture_cache->CreateTexture(config); + FreeTexture(iter->second); + return textures_by_address.erase(iter); } void TextureCache::FreeTexture(TCacheEntryBase* entry) -- cgit v1.2.3