mirror of
https://github.com/libretro/ppsspp.git
synced 2025-01-27 03:35:14 +00:00
Merge pull request #9447 from unknownbrackets/texcache
Always mark videos as frequently changing
This commit is contained in:
commit
de72005b77
@ -28,13 +28,12 @@ enum ScreenshotType {
|
||||
// What's being show on screen (e.g. including FPS, etc.)
|
||||
SCREENSHOT_OUTPUT,
|
||||
// What the game rendered (e.g. at render resolution) to the display.
|
||||
// Can only be used while in game.
|
||||
SCREENSHOT_DISPLAY,
|
||||
// What the game is in-progress rendering now.
|
||||
// Can only be used while in game.
|
||||
SCREENSHOT_RENDER,
|
||||
};
|
||||
|
||||
const u8 *ConvertBufferTo888RGB(const GPUDebugBuffer &buf, u8 *&temp, u32 &w, u32 &h);
|
||||
|
||||
// Can only be used while in game.
|
||||
bool TakeGameScreenshot(const char *filename, ScreenshotFormat fmt, ScreenshotType type, int *width = nullptr, int *height = nullptr, int maxRes = -1);
|
||||
|
@ -210,7 +210,7 @@ bool TranslateShader(std::string *dest, ShaderLanguage destLang, TranslatedShade
|
||||
// Can't fail, parsing worked, "linking" worked.
|
||||
glslang::GlslangToSpv(*program.getIntermediate(shaderStage), spirv);
|
||||
|
||||
// Alright, step 1 done. Now let's takes this SPIR-V shader and output in our desired format.
|
||||
// Alright, step 1 done. Now let's take this SPIR-V shader and output in our desired format.
|
||||
|
||||
switch (destLang) {
|
||||
case GLSL_VULKAN:
|
||||
@ -276,4 +276,4 @@ bool TranslateShader(std::string *dest, ShaderLanguage destLang, TranslatedShade
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
@ -34,7 +34,7 @@
|
||||
#include <emmintrin.h>
|
||||
#endif
|
||||
|
||||
// Videos should be updated every few frames, so we forge quickly.
|
||||
// Videos should be updated every few frames, so we forget quickly.
|
||||
#define VIDEO_DECIMATE_AGE 4
|
||||
|
||||
// If a texture hasn't been seen for this many frames, get rid of it.
|
||||
@ -349,11 +349,12 @@ void TextureCacheCommon::SetTexture(bool force) {
|
||||
nextTexture_ = entry;
|
||||
nextNeedsRehash_ = rehash;
|
||||
nextNeedsChange_ = false;
|
||||
// Might need a rebuild if the hash fails.
|
||||
// Might need a rebuild if the hash fails, but that will be set later.
|
||||
nextNeedsRebuild_ = false;
|
||||
VERBOSE_LOG(G3D, "Texture at %08x Found in Cache, applying", texaddr);
|
||||
return; //Done!
|
||||
} else {
|
||||
// Wasn't a match, we will rebuild.
|
||||
nextChangeReason_ = reason;
|
||||
nextNeedsChange_ = true;
|
||||
}
|
||||
@ -502,6 +503,16 @@ bool TextureCacheCommon::HandleTextureChange(TexCacheEntry *const entry, const c
|
||||
}
|
||||
}
|
||||
|
||||
entry->status |= TexCacheEntry::STATUS_UNRELIABLE;
|
||||
if (entry->numFrames < TEXCACHE_FRAME_CHANGE_FREQUENT) {
|
||||
if (entry->status & TexCacheEntry::STATUS_FREE_CHANGE) {
|
||||
entry->status &= ~TexCacheEntry::STATUS_FREE_CHANGE;
|
||||
} else {
|
||||
entry->status |= TexCacheEntry::STATUS_CHANGE_FREQUENT;
|
||||
}
|
||||
}
|
||||
entry->numFrames = 0;
|
||||
|
||||
return replaceImages;
|
||||
}
|
||||
|
||||
@ -1356,7 +1367,6 @@ void TextureCacheCommon::ReadIndexedTex(u8 *out, int outPitch, int level, const
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void TextureCacheCommon::ApplyTexture() {
|
||||
TexCacheEntry *entry = nextTexture_;
|
||||
if (entry == nullptr) {
|
||||
@ -1368,6 +1378,13 @@ void TextureCacheCommon::ApplyTexture() {
|
||||
|
||||
bool replaceImages = false;
|
||||
if (nextNeedsRebuild_) {
|
||||
// Regardless of hash fails or otherwise, if this is a video, mark it frequently changing.
|
||||
// This prevents temporary scaling perf hits on the first second of video.
|
||||
bool isVideo = videos_.find(entry->addr & 0x3FFFFFFF) != videos_.end();
|
||||
if (isVideo) {
|
||||
entry->status |= TexCacheEntry::STATUS_CHANGE_FREQUENT;
|
||||
}
|
||||
|
||||
if (nextNeedsRehash_) {
|
||||
// Update the hash on the texture.
|
||||
int w = gstate.getTextureWidth(0);
|
||||
@ -1438,13 +1455,11 @@ void TextureCacheCommon::DeleteTexture(TexCache::iterator it) {
|
||||
}
|
||||
|
||||
bool TextureCacheCommon::CheckFullHash(TexCacheEntry *entry, bool &doDelete) {
|
||||
bool hashFail = false;
|
||||
int w = gstate.getTextureWidth(0);
|
||||
int h = gstate.getTextureHeight(0);
|
||||
u32 fullhash = QuickTexHash(replacer_, entry->addr, entry->bufw, w, h, GETextureFormat(entry->format), entry);
|
||||
if (fullhash != entry->fullhash) {
|
||||
hashFail = true;
|
||||
} else {
|
||||
|
||||
if (fullhash == entry->fullhash) {
|
||||
if (g_Config.bTextureBackoffCache) {
|
||||
if (entry->GetHashStatus() != TexCacheEntry::STATUS_HASHING && entry->numFrames > TexCacheEntry::FRAMES_REGAIN_TRUST) {
|
||||
// Reset to STATUS_HASHING.
|
||||
@ -1454,51 +1469,42 @@ bool TextureCacheCommon::CheckFullHash(TexCacheEntry *entry, bool &doDelete) {
|
||||
} else if (entry->numFrames > TEXCACHE_FRAME_CHANGE_FREQUENT_REGAIN_TRUST) {
|
||||
entry->status &= ~TexCacheEntry::STATUS_CHANGE_FREQUENT;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
if (hashFail) {
|
||||
// Don't give up just yet. Let's try the secondary cache if it's been invalidated before.
|
||||
// If it's failed a bunch of times, then the second cache is just wasting time and VRAM.
|
||||
if (g_Config.bTextureSecondaryCache) {
|
||||
// Don't forget this one was unreliable (in case we match a secondary entry.)
|
||||
entry->status |= TexCacheEntry::STATUS_UNRELIABLE;
|
||||
if (entry->numFrames < TEXCACHE_FRAME_CHANGE_FREQUENT) {
|
||||
if (entry->status & TexCacheEntry::STATUS_FREE_CHANGE) {
|
||||
entry->status &= ~TexCacheEntry::STATUS_FREE_CHANGE;
|
||||
} else {
|
||||
entry->status |= TexCacheEntry::STATUS_CHANGE_FREQUENT;
|
||||
}
|
||||
}
|
||||
entry->numFrames = 0;
|
||||
|
||||
// Don't give up just yet. Let's try the secondary cache if it's been invalidated before.
|
||||
// If it's failed a bunch of times, then the second cache is just wasting time and VRAM.
|
||||
if (g_Config.bTextureSecondaryCache) {
|
||||
if (entry->numInvalidated > 2 && entry->numInvalidated < 128 && !lowMemoryMode_) {
|
||||
u64 secondKey = fullhash | (u64)entry->cluthash << 32;
|
||||
TexCache::iterator secondIter = secondCache_.find(secondKey);
|
||||
if (secondIter != secondCache_.end()) {
|
||||
TexCacheEntry *secondEntry = secondIter->second.get();
|
||||
if (secondEntry->Matches(entry->dim, entry->format, entry->maxLevel)) {
|
||||
// Reset the numInvalidated value lower, we got a match.
|
||||
if (entry->numInvalidated > 8) {
|
||||
--entry->numInvalidated;
|
||||
}
|
||||
nextTexture_ = secondEntry;
|
||||
return true;
|
||||
if (entry->numInvalidated > 2 && entry->numInvalidated < 128 && !lowMemoryMode_) {
|
||||
u64 secondKey = fullhash | (u64)entry->cluthash << 32;
|
||||
TexCache::iterator secondIter = secondCache_.find(secondKey);
|
||||
if (secondIter != secondCache_.end()) {
|
||||
TexCacheEntry *secondEntry = secondIter->second.get();
|
||||
if (secondEntry->Matches(entry->dim, entry->format, entry->maxLevel)) {
|
||||
// Reset the numInvalidated value lower, we got a match.
|
||||
if (entry->numInvalidated > 8) {
|
||||
--entry->numInvalidated;
|
||||
}
|
||||
} else {
|
||||
secondKey = entry->fullhash | ((u64)entry->cluthash << 32);
|
||||
secondCacheSizeEstimate_ += EstimateTexMemoryUsage(entry);
|
||||
// Is this wise? We simply copy the entry.
|
||||
secondCache_[secondKey].reset(new TexCacheEntry(*entry));
|
||||
doDelete = false;
|
||||
nextTexture_ = secondEntry;
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
secondKey = entry->fullhash | ((u64)entry->cluthash << 32);
|
||||
secondCacheSizeEstimate_ += EstimateTexMemoryUsage(entry);
|
||||
// Is this wise? We simply copy the entry.
|
||||
secondCache_[secondKey].reset(new TexCacheEntry(*entry));
|
||||
doDelete = false;
|
||||
}
|
||||
}
|
||||
|
||||
// We know it failed, so update the full hash right away.
|
||||
entry->fullhash = fullhash;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
// We know it failed, so update the full hash right away.
|
||||
entry->fullhash = fullhash;
|
||||
return false;
|
||||
}
|
||||
|
||||
void TextureCacheCommon::Invalidate(u32 addr, int size, GPUInvalidationType type) {
|
||||
|
@ -104,6 +104,9 @@ struct TexCacheEntry {
|
||||
STATUS_DEPALETTIZE = 0x40, // Needs to go through a depalettize pass.
|
||||
STATUS_TO_SCALE = 0x80, // Pending texture scaling in a later frame.
|
||||
STATUS_IS_SCALED = 0x100, // Has been scaled (can't be replaceImages'd.)
|
||||
// When hashing large textures, we optimize 512x512 down to 512x272 by default, since this
|
||||
// is commonly the only part accessed. If access is made above 272, we hash the entire
|
||||
// texture, and set this flag to allow scaling the texture just once for the new hash.
|
||||
STATUS_FREE_CHANGE = 0x200, // Allow one change before marking "frequent".
|
||||
};
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user