Skip to content

Commit

Permalink
Merge pull request #9447 from unknownbrackets/texcache
Browse files Browse the repository at this point in the history
Always mark videos as frequently changing
  • Loading branch information
hrydgard authored Mar 18, 2017
2 parents 24cfb73 + b21c081 commit de72005
Show file tree
Hide file tree
Showing 4 changed files with 55 additions and 47 deletions.
3 changes: 1 addition & 2 deletions Core/Screenshot.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
4 changes: 2 additions & 2 deletions GPU/Common/ShaderTranslation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -276,4 +276,4 @@ bool TranslateShader(std::string *dest, ShaderLanguage destLang, TranslatedShade
}
}

#endif
#endif
92 changes: 49 additions & 43 deletions GPU/Common/TextureCacheCommon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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;
}

Expand Down Expand Up @@ -1356,7 +1367,6 @@ void TextureCacheCommon::ReadIndexedTex(u8 *out, int outPitch, int level, const
}
}


void TextureCacheCommon::ApplyTexture() {
TexCacheEntry *entry = nextTexture_;
if (entry == nullptr) {
Expand All @@ -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);
Expand Down Expand Up @@ -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.
Expand All @@ -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) {
Expand Down
3 changes: 3 additions & 0 deletions GPU/Common/TextureCacheCommon.h
Original file line number Diff line number Diff line change
Expand Up @@ -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".
};

Expand Down

0 comments on commit de72005

Please sign in to comment.