Remove the last remains of the idea that textures can be efficiently updated instead of recreated. Accidentally fixes #10697 somehow.

Also this is good for terminology, no more confusion with the texture
replacement facility :)
This commit is contained in:
Henrik Rydgård 2018-03-25 10:49:28 +02:00
parent b0a22fb5c7
commit f967e206b8
10 changed files with 45 additions and 98 deletions

View File

@ -574,23 +574,15 @@ void TextureCacheCommon::DecimateVideos() {
}
}
bool TextureCacheCommon::HandleTextureChange(TexCacheEntry *const entry, const char *reason, bool initialMatch, bool doDelete) {
bool replaceImages = false;
void TextureCacheCommon::HandleTextureChange(TexCacheEntry *const entry, const char *reason, bool initialMatch, bool doDelete) {
cacheSizeEstimate_ -= EstimateTexMemoryUsage(entry);
entry->numInvalidated++;
gpuStats.numTextureInvalidations++;
DEBUG_LOG(G3D, "Texture different or overwritten, reloading at %08x: %s", entry->addr, reason);
if (doDelete) {
if (initialMatch && standardScaleFactor_ == 1 && (entry->status & TexCacheEntry::STATUS_IS_SCALED) == 0) {
// Actually, if size and number of levels match, let's try to avoid deleting and recreating.
// Instead, let's use glTexSubImage to replace the images.
replaceImages = true;
} else {
InvalidateLastTexture();
ReleaseTexture(entry, true);
entry->status &= ~TexCacheEntry::STATUS_IS_SCALED;
}
InvalidateLastTexture();
ReleaseTexture(entry, true);
entry->status &= ~TexCacheEntry::STATUS_IS_SCALED;
}
// Clear the reliable bit if set.
if (entry->GetHashStatus() == TexCacheEntry::STATUS_RELIABLE) {
@ -617,8 +609,6 @@ bool TextureCacheCommon::HandleTextureChange(TexCacheEntry *const entry, const c
}
}
entry->numFrames = 0;
return replaceImages;
}
void TextureCacheCommon::NotifyFramebuffer(u32 address, VirtualFramebuffer *framebuffer, FramebufferNotification msg) {
@ -1487,7 +1477,6 @@ void TextureCacheCommon::ApplyTexture() {
UpdateMaxSeenV(entry, gstate.isModeThrough());
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.
@ -1508,14 +1497,14 @@ void TextureCacheCommon::ApplyTexture() {
}
if (nextNeedsChange_) {
// This texture existed previously, let's handle the change.
replaceImages = HandleTextureChange(entry, nextChangeReason_, false, true);
HandleTextureChange(entry, nextChangeReason_, false, true);
}
// We actually build afterward (shared with rehash rebuild.)
} else if (nextNeedsRehash_) {
// Okay, this matched and didn't change - but let's check the hash. Maybe it will change.
bool doDelete = true;
if (!CheckFullHash(entry, doDelete)) {
replaceImages = HandleTextureChange(entry, "hash fail", true, doDelete);
HandleTextureChange(entry, "hash fail", true, doDelete);
nextNeedsRebuild_ = true;
} else if (nextTexture_ != nullptr) {
// The secondary cache may choose an entry from its storage by setting nextTexture_.
@ -1528,7 +1517,8 @@ void TextureCacheCommon::ApplyTexture() {
// Okay, now actually rebuild the texture if needed.
if (nextNeedsRebuild_) {
BuildTexture(entry, replaceImages);
_assert_(!entry->texturePtr);
BuildTexture(entry);
}
entry->lastFrame = gpuStats.numFlips;

View File

@ -224,8 +224,8 @@ protected:
void Decimate();
virtual void ApplyTextureFramebuffer(TexCacheEntry *entry, VirtualFramebuffer *framebuffer) = 0;
bool HandleTextureChange(TexCacheEntry *const entry, const char *reason, bool initialMatch, bool doDelete);
virtual void BuildTexture(TexCacheEntry *const entry, bool replaceImages) = 0;
void HandleTextureChange(TexCacheEntry *const entry, const char *reason, bool initialMatch, bool doDelete);
virtual void BuildTexture(TexCacheEntry *const entry) = 0;
virtual void UpdateCurrentClut(GEPaletteFormat clutFormat, u32 clutBase, bool clutIndexIsSimple) = 0;
bool CheckFullHash(TexCacheEntry *entry, bool &doDelete);

View File

@ -427,7 +427,7 @@ void TextureCacheD3D11::ApplyTextureFramebuffer(TexCacheEntry *entry, VirtualFra
}
void TextureCacheD3D11::BuildTexture(TexCacheEntry *const entry, bool replaceImages) {
void TextureCacheD3D11::BuildTexture(TexCacheEntry *const entry) {
entry->status &= ~TexCacheEntry::STATUS_ALPHA_MASK;
// For the estimate, we assume cluts always point to 8888 for simplicity.
@ -487,11 +487,6 @@ void TextureCacheD3D11::BuildTexture(TexCacheEntry *const entry, bool replaceIma
int h = gstate.getTextureHeight(0);
ReplacedTexture &replaced = replacer_.FindReplacement(cachekey, entry->fullhash, w, h);
if (replaced.GetSize(0, w, h)) {
if (replaceImages) {
// Since we're replacing the texture, we can't replace the image inside.
ReleaseTexture(entry, true);
replaceImages = false;
}
// We're replacing, so we won't scale.
scaleFactor = 1;
entry->status |= TexCacheEntry::STATUS_IS_SCALED;
@ -519,12 +514,6 @@ void TextureCacheD3D11::BuildTexture(TexCacheEntry *const entry, bool replaceIma
}
}
if (replaceImages) {
// Make sure it's not currently set.
ID3D11ShaderResourceView *srv = nullptr;
context_->PSSetShaderResources(0, 1, &srv);
}
// Seems to cause problems in Tactics Ogre.
if (badMipSizes) {
maxLevel = 0;
@ -535,10 +524,11 @@ void TextureCacheD3D11::BuildTexture(TexCacheEntry *const entry, bool replaceIma
if (IsFakeMipmapChange()) {
// NOTE: Since the level is not part of the cache key, we assume it never changes.
u8 level = std::max(0, gstate.getTexLevelOffset16() / 16);
LoadTextureLevel(*entry, replaced, level, maxLevel, replaceImages, scaleFactor, dstFmt);
LoadTextureLevel(*entry, replaced, level, maxLevel, scaleFactor, dstFmt);
} else {
LoadTextureLevel(*entry, replaced, 0, maxLevel, replaceImages, scaleFactor, dstFmt);
LoadTextureLevel(*entry, replaced, 0, maxLevel, scaleFactor, dstFmt);
}
ID3D11ShaderResourceView *textureView = DxView(entry);
if (!textureView) {
return;
@ -547,7 +537,7 @@ void TextureCacheD3D11::BuildTexture(TexCacheEntry *const entry, bool replaceIma
// Mipmapping is only enabled when texture scaling is disabled.
if (maxLevel > 0 && scaleFactor == 1) {
for (int i = 1; i <= maxLevel; i++) {
LoadTextureLevel(*entry, replaced, i, maxLevel, replaceImages, scaleFactor, dstFmt);
LoadTextureLevel(*entry, replaced, i, maxLevel, scaleFactor, dstFmt);
}
}
@ -641,12 +631,12 @@ DXGI_FORMAT ToDXGIFormat(ReplacedTextureFormat fmt) {
}
}
void TextureCacheD3D11::LoadTextureLevel(TexCacheEntry &entry, ReplacedTexture &replaced, int level, int maxLevel, bool replaceImages, int scaleFactor, DXGI_FORMAT dstFmt) {
void TextureCacheD3D11::LoadTextureLevel(TexCacheEntry &entry, ReplacedTexture &replaced, int level, int maxLevel, int scaleFactor, DXGI_FORMAT dstFmt) {
int w = gstate.getTextureWidth(level);
int h = gstate.getTextureHeight(level);
ID3D11Texture2D *texture = DxTex(&entry);
if ((level == 0 || IsFakeMipmapChange()) && (!replaceImages || texture == nullptr)) {
if ((level == 0 || IsFakeMipmapChange()) && texture == nullptr) {
// Create texture
int levels = scaleFactor == 1 ? maxLevel + 1 : 1;
int tw = w, th = h;

View File

@ -69,19 +69,19 @@ protected:
void ReleaseTexture(TexCacheEntry *entry, bool delete_them) override;
private:
void LoadTextureLevel(TexCacheEntry &entry, ReplacedTexture &replaced, int level, int maxLevel, bool replaceImages, int scaleFactor, DXGI_FORMAT dstFmt);
void LoadTextureLevel(TexCacheEntry &entry, ReplacedTexture &replaced, int level, int maxLevel, int scaleFactor, DXGI_FORMAT dstFmt);
DXGI_FORMAT GetDestFormat(GETextureFormat format, GEPaletteFormat clutFormat) const;
TexCacheEntry::TexStatus CheckAlpha(const u32 *pixelData, u32 dstFmt, int stride, int w, int h);
void UpdateCurrentClut(GEPaletteFormat clutFormat, u32 clutBase, bool clutIndexIsSimple) override;
void ApplyTextureFramebuffer(TexCacheEntry *entry, VirtualFramebuffer *framebuffer) override;
void BuildTexture(TexCacheEntry *const entry, bool replaceImages) override;
void BuildTexture(TexCacheEntry *const entry) override;
ID3D11Device *device_;
ID3D11DeviceContext *context_;
ID3D11Texture2D *DxTex(TexCacheEntry *entry) {
return (ID3D11Texture2D *)entry->texturePtr;
ID3D11Texture2D *&DxTex(TexCacheEntry *entry) {
return (ID3D11Texture2D *&)entry->texturePtr;
}
ID3D11ShaderResourceView *DxView(TexCacheEntry *entry) {
return (ID3D11ShaderResourceView *)entry->textureView;

View File

@ -469,7 +469,7 @@ void TextureCacheDX9::ApplyTextureFramebuffer(TexCacheEntry *entry, VirtualFrame
InvalidateLastTexture();
}
void TextureCacheDX9::BuildTexture(TexCacheEntry *const entry, bool replaceImages) {
void TextureCacheDX9::BuildTexture(TexCacheEntry *const entry) {
entry->status &= ~TexCacheEntry::STATUS_ALPHA_MASK;
// For the estimate, we assume cluts always point to 8888 for simplicity.
@ -532,11 +532,6 @@ void TextureCacheDX9::BuildTexture(TexCacheEntry *const entry, bool replaceImage
int h = gstate.getTextureHeight(0);
ReplacedTexture &replaced = replacer_.FindReplacement(cachekey, entry->fullhash, w, h);
if (replaced.GetSize(0, w, h)) {
if (replaceImages) {
// Since we're replacing the texture, we can't replace the image inside.
ReleaseTexture(entry, true);
replaceImages = false;
}
// We're replacing, so we won't scale.
scaleFactor = 1;
entry->status |= TexCacheEntry::STATUS_IS_SCALED;
@ -564,10 +559,6 @@ void TextureCacheDX9::BuildTexture(TexCacheEntry *const entry, bool replaceImage
}
}
if (replaceImages) {
// Make sure it's not currently set.
device_->SetTexture(0, NULL);
}
// Seems to cause problems in Tactics Ogre.
if (badMipSizes) {
maxLevel = 0;
@ -576,9 +567,9 @@ void TextureCacheDX9::BuildTexture(TexCacheEntry *const entry, bool replaceImage
if (IsFakeMipmapChange()) {
// NOTE: Since the level is not part of the cache key, we assume it never changes.
u8 level = std::max(0, gstate.getTexLevelOffset16() / 16);
LoadTextureLevel(*entry, replaced, level, maxLevel, replaceImages, scaleFactor, dstFmt);
LoadTextureLevel(*entry, replaced, level, maxLevel, scaleFactor, dstFmt);
} else {
LoadTextureLevel(*entry, replaced, 0, maxLevel, replaceImages, scaleFactor, dstFmt);
LoadTextureLevel(*entry, replaced, 0, maxLevel, scaleFactor, dstFmt);
}
LPDIRECT3DTEXTURE9 &texture = DxTex(entry);
if (!texture) {
@ -588,7 +579,7 @@ void TextureCacheDX9::BuildTexture(TexCacheEntry *const entry, bool replaceImage
// Mipmapping is only enabled when texture scaling is disabled.
if (maxLevel > 0 && scaleFactor == 1) {
for (int i = 1; i <= maxLevel; i++) {
LoadTextureLevel(*entry, replaced, i, maxLevel, replaceImages, scaleFactor, dstFmt);
LoadTextureLevel(*entry, replaced, i, maxLevel, scaleFactor, dstFmt);
}
}
@ -663,12 +654,12 @@ D3DFORMAT ToD3D9Format(ReplacedTextureFormat fmt) {
}
}
void TextureCacheDX9::LoadTextureLevel(TexCacheEntry &entry, ReplacedTexture &replaced, int level, int maxLevel, bool replaceImages, int scaleFactor, u32 dstFmt) {
void TextureCacheDX9::LoadTextureLevel(TexCacheEntry &entry, ReplacedTexture &replaced, int level, int maxLevel, int scaleFactor, u32 dstFmt) {
int w = gstate.getTextureWidth(level);
int h = gstate.getTextureHeight(level);
LPDIRECT3DTEXTURE9 &texture = DxTex(&entry);
if ((level == 0 || IsFakeMipmapChange()) && (!replaceImages || texture == nullptr)) {
if ((level == 0 || IsFakeMipmapChange()) && texture == nullptr) {
// Create texture
D3DPOOL pool = D3DPOOL_MANAGED;
int usage = 0;

View File

@ -63,13 +63,13 @@ protected:
private:
void UpdateSamplingParams(TexCacheEntry &entry, bool force);
void LoadTextureLevel(TexCacheEntry &entry, ReplacedTexture &replaced, int level, int maxLevel, bool replaceImages, int scaleFactor, u32 dstFmt);
void LoadTextureLevel(TexCacheEntry &entry, ReplacedTexture &replaced, int level, int maxLevel, int scaleFactor, u32 dstFmt);
D3DFORMAT GetDestFormat(GETextureFormat format, GEPaletteFormat clutFormat) const;
TexCacheEntry::TexStatus CheckAlpha(const u32 *pixelData, u32 dstFmt, int stride, int w, int h);
void UpdateCurrentClut(GEPaletteFormat clutFormat, u32 clutBase, bool clutIndexIsSimple) override;
void ApplyTextureFramebuffer(TexCacheEntry *entry, VirtualFramebuffer *framebuffer) override;
void BuildTexture(TexCacheEntry *const entry, bool replaceImages) override;
void BuildTexture(TexCacheEntry *const entry) override;
LPDIRECT3DTEXTURE9 &DxTex(TexCacheEntry *entry) {
return *(LPDIRECT3DTEXTURE9 *)&entry->texturePtr;

View File

@ -496,13 +496,9 @@ GLenum ToGLESFormat(ReplacedTextureFormat fmt) {
}
}
void TextureCacheGLES::BuildTexture(TexCacheEntry *const entry, bool replaceImages) {
void TextureCacheGLES::BuildTexture(TexCacheEntry *const entry) {
entry->status &= ~TexCacheEntry::STATUS_ALPHA_MASK;
// Never replace images in-place - there's no such thing, drivers have to fake it anyway, at least if
// the image has been in use within the last frame or two.
replaceImages = false;
// For the estimate, we assume cluts always point to 8888 for simplicity.
cacheSizeEstimate_ += EstimateTexMemoryUsage(entry);
@ -512,10 +508,8 @@ void TextureCacheGLES::BuildTexture(TexCacheEntry *const entry, bool replaceImag
}
// Always generate a texture name unless it's a framebuffer, we might need it if the texture is replaced later.
if (!replaceImages) {
if (!entry->textureName) {
entry->textureName = render_->CreateTexture(GL_TEXTURE_2D);
}
if (!entry->textureName) {
entry->textureName = render_->CreateTexture(GL_TEXTURE_2D);
}
if ((entry->bufw == 0 || (gstate.texbufwidth[0] & 0xf800) != 0) && entry->addr >= PSP_GetKernelMemoryEnd()) {
@ -576,13 +570,6 @@ void TextureCacheGLES::BuildTexture(TexCacheEntry *const entry, bool replaceImag
int h = gstate.getTextureHeight(0);
ReplacedTexture &replaced = replacer_.FindReplacement(cachekey, entry->fullhash, w, h);
if (replaced.GetSize(0, w, h)) {
if (replaceImages) {
// Since we're replacing the texture, we can't replace the image inside.
render_->DeleteTexture(entry->textureName);
entry->textureName = render_->CreateTexture(GL_TEXTURE_2D);
replaceImages = false;
}
// We're replacing, so we won't scale.
scaleFactor = 1;
entry->status |= TexCacheEntry::STATUS_IS_SCALED;
@ -623,9 +610,9 @@ void TextureCacheGLES::BuildTexture(TexCacheEntry *const entry, bool replaceImag
if (IsFakeMipmapChange()) {
// NOTE: Since the level is not part of the cache key, we assume it never changes.
u8 level = std::max(0, gstate.getTexLevelOffset16() / 16);
LoadTextureLevel(*entry, replaced, level, replaceImages, scaleFactor, dstFmt);
LoadTextureLevel(*entry, replaced, level, scaleFactor, dstFmt);
} else
LoadTextureLevel(*entry, replaced, 0, replaceImages, scaleFactor, dstFmt);
LoadTextureLevel(*entry, replaced, 0, scaleFactor, dstFmt);
// Mipmapping only enable when texture scaling disable
int texMaxLevel = 0;
@ -642,7 +629,7 @@ void TextureCacheGLES::BuildTexture(TexCacheEntry *const entry, bool replaceImag
}
} else {
for (int i = 1; i <= maxLevel; i++) {
LoadTextureLevel(*entry, replaced, i, replaceImages, scaleFactor, dstFmt);
LoadTextureLevel(*entry, replaced, i, scaleFactor, dstFmt);
}
texMaxLevel = maxLevel;
}
@ -719,7 +706,7 @@ TexCacheEntry::TexStatus TextureCacheGLES::CheckAlpha(const uint8_t *pixelData,
return (TexCacheEntry::TexStatus)res;
}
void TextureCacheGLES::LoadTextureLevel(TexCacheEntry &entry, ReplacedTexture &replaced, int level, bool replaceImages, int scaleFactor, GLenum dstFmt) {
void TextureCacheGLES::LoadTextureLevel(TexCacheEntry &entry, ReplacedTexture &replaced, int level, int scaleFactor, GLenum dstFmt) {
int w = gstate.getTextureWidth(level);
int h = gstate.getTextureHeight(level);
bool useUnpack = false;
@ -791,17 +778,11 @@ void TextureCacheGLES::LoadTextureLevel(TexCacheEntry &entry, ReplacedTexture &r
GLuint components2 = components;
if (replaceImages) {
PROFILE_THIS_SCOPE("repltex");
Crash();
// glTexSubImage2D(GL_TEXTURE_2D, level, 0, 0, w, h, components2, dstFmt, pixelData);
} else {
PROFILE_THIS_SCOPE("loadtex");
if (IsFakeMipmapChange())
render_->TextureImage(entry.textureName, 0, w, h, components, components2, dstFmt, pixelData, GLRAllocType::ALIGNED);
else
render_->TextureImage(entry.textureName, level, w, h, components, components2, dstFmt, pixelData, GLRAllocType::ALIGNED);
}
PROFILE_THIS_SCOPE("loadtex");
if (IsFakeMipmapChange())
render_->TextureImage(entry.textureName, 0, w, h, components, components2, dstFmt, pixelData, GLRAllocType::ALIGNED);
else
render_->TextureImage(entry.textureName, level, w, h, components, components2, dstFmt, pixelData, GLRAllocType::ALIGNED);
}
bool TextureCacheGLES::GetCurrentTextureDebug(GPUDebugBuffer &buffer, int level) {

View File

@ -75,14 +75,14 @@ protected:
private:
void UpdateSamplingParams(TexCacheEntry &entry, bool force);
void LoadTextureLevel(TexCacheEntry &entry, ReplacedTexture &replaced, int level, bool replaceImages, int scaleFactor, GLenum dstFmt);
void LoadTextureLevel(TexCacheEntry &entry, ReplacedTexture &replaced, int level, int scaleFactor, GLenum dstFmt);
GLenum GetDestFormat(GETextureFormat format, GEPaletteFormat clutFormat) const;
TexCacheEntry::TexStatus CheckAlpha(const uint8_t *pixelData, GLenum dstFmt, int stride, int w, int h);
void UpdateCurrentClut(GEPaletteFormat clutFormat, u32 clutBase, bool clutIndexIsSimple) override;
void ApplyTextureFramebuffer(TexCacheEntry *entry, VirtualFramebuffer *framebuffer) override;
void BuildTexture(TexCacheEntry *const entry, bool replaceImages) override;
void BuildTexture(TexCacheEntry *const entry) override;
GLRenderManager *render_;

View File

@ -459,7 +459,7 @@ VkFormat ToVulkanFormat(ReplacedTextureFormat fmt) {
}
}
void TextureCacheVulkan::BuildTexture(TexCacheEntry *const entry, bool replaceImages) {
void TextureCacheVulkan::BuildTexture(TexCacheEntry *const entry) {
entry->status &= ~TexCacheEntry::STATUS_ALPHA_MASK;
VkCommandBuffer cmdInit = (VkCommandBuffer)draw_->GetNativeObject(Draw::NativeObject::INIT_COMMANDBUFFER);
@ -525,11 +525,6 @@ void TextureCacheVulkan::BuildTexture(TexCacheEntry *const entry, bool replaceIm
int h = gstate.getTextureHeight(0);
ReplacedTexture &replaced = replacer_.FindReplacement(cachekey, entry->fullhash, w, h);
if (replaced.GetSize(0, w, h)) {
if (replaceImages) {
// Since we're replacing the texture, we can't replace the image inside.
ReleaseTexture(entry, true);
replaceImages = false;
}
// We're replacing, so we won't scale.
scaleFactor = 1;
entry->status |= TexCacheEntry::STATUS_IS_SCALED;

View File

@ -129,7 +129,7 @@ private:
void UpdateCurrentClut(GEPaletteFormat clutFormat, u32 clutBase, bool clutIndexIsSimple) override;
void ApplyTextureFramebuffer(TexCacheEntry *entry, VirtualFramebuffer *framebuffer) override;
void BuildTexture(TexCacheEntry *const entry, bool replaceImages) override;
void BuildTexture(TexCacheEntry *const entry) override;
VulkanContext *vulkan_ = nullptr;
VulkanDeviceAllocator *allocator_ = nullptr;