diff options
| author | Rodolfo Bogado <rodolfoosvaldobogado@gmail.com> | 2015-06-29 22:19:19 -0300 |
|---|---|---|
| committer | Rodolfo Bogado <rodolfoosvaldobogado@gmail.com> | 2015-07-02 08:53:40 -0300 |
| commit | d8cd2c3252ab6f2ce6c1656b5eb194863e834f52 (patch) | |
| tree | bfefa30392b15403d1792f83cd5ea8cd709a397e /Source/Core/VideoCommon/TextureCacheBase.cpp | |
| parent | 8d69c2b4b722e2c4f9f0496b9ff1912c1a10d9e1 (diff) | |
Implement scaled partial texture updates
Diffstat (limited to 'Source/Core/VideoCommon/TextureCacheBase.cpp')
| -rw-r--r-- | Source/Core/VideoCommon/TextureCacheBase.cpp | 100 |
1 files changed, 76 insertions, 24 deletions
diff --git a/Source/Core/VideoCommon/TextureCacheBase.cpp b/Source/Core/VideoCommon/TextureCacheBase.cpp index 6baca12326..7d49e698da 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/TextureCacheBase.cpp @@ -211,46 +211,98 @@ bool TextureCache::TCacheEntryBase::OverlapsMemoryRange(u32 range_address, u32 r return true; } -void TextureCache::TCacheEntryBase::DoPartialTextureUpdates() +TextureCache::TCacheEntryBase* TextureCache::DoPartialTextureUpdates(TexCache::iterator iter_t) { - const bool isPaletteTexture = (format== GX_TF_C4 || format == GX_TF_C8 || format == GX_TF_C14X2 || format >= 0x10000); + TCacheEntryBase* entry_to_update = iter_t->second; + const bool isPaletteTexture = (entry_to_update->format == GX_TF_C4 + || entry_to_update->format == GX_TF_C8 + || entry_to_update->format == GX_TF_C14X2 + || entry_to_update->format >= 0x10000); // Efb copies and paletted textures are excluded from these updates, until there's an example where a game would // benefit from this. Both would require more work to be done. // TODO: Implement upscaling support for normal textures, and then remove the efb to ram and the scaled efb restrictions - if (!g_ActiveConfig.backend_info.bSupportsCopySubImage || !g_ActiveConfig.bSkipEFBCopyToRam || IsEfbCopy() - || isPaletteTexture || (g_ActiveConfig.bCopyEFBScaled && g_ActiveConfig.iEFBScale != SCALE_1X)) - return; - - u32 block_width = TexDecoder_GetBlockWidthInTexels(format); - u32 block_height = TexDecoder_GetBlockHeightInTexels(format); - u32 block_size = block_width * block_height * TexDecoder_GetTexelSizeInNibbles(format) / 2; + if (entry_to_update->IsEfbCopy() + || isPaletteTexture) + return entry_to_update; - u32 numBlocksX = (native_width + block_width - 1) / block_width; + u32 block_width = TexDecoder_GetBlockWidthInTexels(entry_to_update->format); + u32 block_height = TexDecoder_GetBlockHeightInTexels(entry_to_update->format); + u32 block_size = block_width * block_height * TexDecoder_GetTexelSizeInNibbles(entry_to_update->format) / 2; - TexCache::iterator iter = textures_by_address.lower_bound(addr); - TexCache::iterator iterend = textures_by_address.upper_bound(addr + size_in_bytes); + u32 numBlocksX = (entry_to_update->native_width + block_width - 1) / block_width; + TexCache::iterator iter = textures_by_address.lower_bound(entry_to_update->addr); + TexCache::iterator iterend = textures_by_address.upper_bound(entry_to_update->addr + entry_to_update->size_in_bytes); + bool entry_need_scaling = true; while (iter != iterend) { TCacheEntryBase* entry = iter->second; - if (entry->IsEfbCopy() && addr <= entry->addr && entry->addr + entry->size_in_bytes <= addr + size_in_bytes - && entry->frameCount == FRAMECOUNT_INVALID && entry->copyMipMapStrideChannels * 32 == numBlocksX * block_size) + if (entry != entry_to_update + && entry->IsEfbCopy() + && entry_to_update->addr <= entry->addr + && entry->addr + entry->size_in_bytes <= entry_to_update->addr + entry_to_update->size_in_bytes + && entry->frameCount == FRAMECOUNT_INVALID + && entry->copyMipMapStrideChannels * 32 == numBlocksX * block_size) { - u32 block_offset = (entry->addr - addr) / block_size; + u32 block_offset = (entry->addr - entry_to_update->addr) / block_size; u32 block_x = block_offset % numBlocksX; u32 block_y = block_offset / numBlocksX; u32 x = block_x * block_width; u32 y = block_y * block_height; - - DoPartialTextureUpdate(entry, x, y); - + MathUtil::Rectangle<int> srcrect, dstrect; + srcrect.left = 0; + srcrect.top = 0; + dstrect.left = 0; + dstrect.top = 0; + if (entry_need_scaling) + { + entry_need_scaling = false; + u32 w = entry_to_update->native_width * entry->config.width / entry->native_width; + u32 h = entry_to_update->native_height * entry->config.height / entry->native_height; + u32 max = g_renderer->GetMaxTextureSize(); + if (max < w || max < h) + { + iter++; + continue; + } + if (entry_to_update->config.width != w || entry_to_update->config.height != h) + { + TextureCache::TCacheEntryConfig newconfig; + newconfig.width = w; + newconfig.height = h; + newconfig.rendertarget = true; + TCacheEntryBase* newentry = AllocateTexture(newconfig); + newentry->SetGeneralParameters(entry_to_update->addr, entry_to_update->size_in_bytes, entry_to_update->format); + newentry->SetDimensions(entry_to_update->native_width, entry_to_update->native_height, 1); + newentry->SetHashes(entry_to_update->hash); + newentry->frameCount = frameCount; + newentry->is_efb_copy = false; + srcrect.right = entry_to_update->config.width; + srcrect.bottom = entry_to_update->config.height; + dstrect.right = w; + dstrect.bottom = h; + newentry->CopyRectangleFromTexture(entry_to_update, srcrect, dstrect); + entry_to_update = newentry; + u64 key = iter_t->first; + iter_t = FreeTexture(iter_t); + textures_by_address.emplace(key, entry_to_update); + } + } + srcrect.right = entry->config.width; + srcrect.bottom = entry->config.height; + dstrect.left = x * entry_to_update->config.width / entry_to_update->native_width; + dstrect.top = y * entry_to_update->config.height / entry_to_update->native_height; + dstrect.right = (x + entry->native_width) * entry_to_update->config.width / entry_to_update->native_width; + dstrect.bottom = (y + entry->native_height) * entry_to_update->config.height / entry_to_update->native_height; + entry_to_update->CopyRectangleFromTexture(entry, srcrect, dstrect); // Mark the texture update as used, so it isn't applied more than once entry->frameCount = frameCount; } ++iter; } + return entry_to_update; } void TextureCache::DumpTexture(TCacheEntryBase* entry, std::string basename, unsigned int level) @@ -323,7 +375,7 @@ TextureCache::TCacheEntryBase* TextureCache::Load(const u32 stage) const unsigned int bsw = TexDecoder_GetBlockWidthInTexels(texformat) - 1; const unsigned int bsh = TexDecoder_GetBlockHeightInTexels(texformat) - 1; - unsigned int expandedWidth = (width + bsw) & (~bsw); + unsigned int expandedWidth = (width + bsw) & (~bsw); unsigned int expandedHeight = (height + bsh) & (~bsh); const unsigned int nativeW = width; const unsigned int nativeH = height; @@ -440,7 +492,7 @@ TextureCache::TCacheEntryBase* TextureCache::Load(const u32 stage) if (entry->hash == full_hash && entry->format == full_format && entry->native_levels >= tex_levels && entry->native_width == nativeW && entry->native_height == nativeH) { - entry->DoPartialTextureUpdates(); + entry = DoPartialTextureUpdates(iter); return ReturnEntry(stage, entry); } @@ -494,7 +546,7 @@ TextureCache::TCacheEntryBase* TextureCache::Load(const u32 stage) if (entry->format == full_format && entry->native_levels >= tex_levels && entry->native_width == nativeW && entry->native_height == nativeH) { - entry->DoPartialTextureUpdates(); + entry = DoPartialTextureUpdates(iter); return ReturnEntry(stage, entry); } @@ -539,7 +591,7 @@ TextureCache::TCacheEntryBase* TextureCache::Load(const u32 stage) if (!(texformat == GX_TF_RGBA8 && from_tmem)) { const u8* tlut = &texMem[tlutaddr]; - TexDecoder_Decode(temp, src_data, expandedWidth, expandedHeight, texformat, tlut, (TlutFormat) tlutfmt); + TexDecoder_Decode(temp, src_data, expandedWidth, expandedHeight, texformat, tlut, (TlutFormat)tlutfmt); } else { @@ -560,7 +612,7 @@ TextureCache::TCacheEntryBase* TextureCache::Load(const u32 stage) TCacheEntryBase* entry = AllocateTexture(config); GFX_DEBUGGER_PAUSE_AT(NEXT_NEW_TEXTURE, true); - textures_by_address.emplace((u64)address, entry); + iter = textures_by_address.emplace((u64)address, entry); if (g_ActiveConfig.iSafeTextureCache_ColorSamples == 0 || std::max(texture_size, palette_size) <= (u32)g_ActiveConfig.iSafeTextureCache_ColorSamples * 8) { @@ -636,7 +688,7 @@ TextureCache::TCacheEntryBase* TextureCache::Load(const u32 stage) INCSTAT(stats.numTexturesUploaded); SETSTAT(stats.numTexturesAlive, textures_by_address.size()); - entry->DoPartialTextureUpdates(); + entry = DoPartialTextureUpdates(iter); return ReturnEntry(stage, entry); } |
