GPU: Block mipmap autogen for matching size.

If the mips don't get smaller, we can't autogen - the bias in that case is
used to select a different texture.  Fixes #9731.

This also may improve a minor performance issue on PowerVR in some games.
This commit is contained in:
Unknown W. Brackets committed 2017-05-31 21:23:20 -07:00
1 parent 9687873417
commit b6375638f5
5 files changed
+59 -19

No files matched your search

+2
View File
@@ -111,6 +111,8 @@ struct TexCacheEntry {
// 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".
STATUS_BAD_MIPS = 0x400, // Has bad or unusable mipmap levels.
};
// Status, but int so we can zero initialize.
+8 -2
View File
@@ -177,7 +177,8 @@ void TextureCacheD3D11::UpdateSamplingParams(TexCacheEntry &entry, SamplerCacheK
bool tClamp;
float lodBias;
bool autoMip;
GetSamplingParams(minFilt, magFilt, sClamp, tClamp, lodBias, entry.maxLevel, entry.addr, autoMip);
u8 maxLevel = (entry.status & TexCacheEntry::STATUS_BAD_MIPS) ? 0 : entry.maxLevel;
GetSamplingParams(minFilt, magFilt, sClamp, tClamp, lodBias, maxLevel, entry.addr, autoMip);
key.minFilt = minFilt & 1;
key.mipEnable = (minFilt >> 2) & 1;
key.mipFilt = (minFilt >> 1) & 1;
@@ -186,7 +187,7 @@ void TextureCacheD3D11::UpdateSamplingParams(TexCacheEntry &entry, SamplerCacheK
key.tClamp = tClamp;
// Don't clamp to maxLevel - this may bias magnify levels.
key.lodBias = (int)(lodBias * 256.0f);
key.maxLevel = entry.maxLevel;
key.maxLevel = maxLevel;
key.lodAuto = autoMip;
if (entry.framebuffer) {
@@ -587,6 +588,11 @@ void TextureCacheD3D11::BuildTexture(TexCacheEntry *const entry, bool replaceIma
}
}
if (maxLevel == 0) {
entry->status |= TexCacheEntry::STATUS_BAD_MIPS;
} else {
entry->status &= ~TexCacheEntry::STATUS_BAD_MIPS;
}
if (replaced.Valid()) {
entry->SetAlphaStatus(TexCacheEntry::Status(replaced.AlphaStatus()));
}
+9 -3
View File
@@ -155,16 +155,17 @@ void TextureCacheDX9::UpdateSamplingParams(TexCacheEntry &entry, bool force) {
bool tClamp;
float lodBias;
bool autoMip;
GetSamplingParams(minFilt, magFilt, sClamp, tClamp, lodBias, entry.maxLevel, entry.addr, autoMip);
u8 maxLevel = (entry.status & TexCacheEntry::STATUS_BAD_MIPS) ? 0 : entry.maxLevel;
GetSamplingParams(minFilt, magFilt, sClamp, tClamp, lodBias, maxLevel, entry.addr, autoMip);
if (entry.maxLevel != 0) {
if (maxLevel != 0) {
if (autoMip) {
dxstate.texMaxMipLevel.set(0);
dxstate.texMipLodBias.set(lodBias);
} else {
// TODO: This is just an approximation - texMaxMipLevel sets the lowest numbered mip to use.
// Unfortunately, this doesn't support a const 1.5 or etc.
dxstate.texMaxMipLevel.set(std::max(0, std::min((int)entry.maxLevel, (int)lodBias)));
dxstate.texMaxMipLevel.set(std::max(0, std::min((int)maxLevel, (int)lodBias)));
dxstate.texMipLodBias.set(-1000.0f);
}
entry.lodBias = lodBias;
@@ -590,6 +591,11 @@ void TextureCacheDX9::BuildTexture(TexCacheEntry *const entry, bool replaceImage
}
}
if (maxLevel == 0) {
entry->status |= TexCacheEntry::STATUS_BAD_MIPS;
} else {
entry->status &= ~TexCacheEntry::STATUS_BAD_MIPS;
}
if (replaced.Valid()) {
entry->SetAlphaStatus(TexCacheEntry::Status(replaced.AlphaStatus()));
}
+33 -13
View File
@@ -129,10 +129,11 @@ void TextureCacheGLES::UpdateSamplingParams(TexCacheEntry &entry, bool force) {
bool tClamp;
float lodBias;
bool autoMip;
GetSamplingParams(minFilt, magFilt, sClamp, tClamp, lodBias, entry.maxLevel, entry.addr, autoMip);
u8 maxLevel = (entry.status & TexCacheEntry::STATUS_BAD_MIPS) ? 0 : entry.maxLevel;
GetSamplingParams(minFilt, magFilt, sClamp, tClamp, lodBias, maxLevel, entry.addr, autoMip);
if (gstate_c.Supports(GPU_SUPPORTS_TEXTURE_LOD_CONTROL)) {
if (entry.maxLevel != 0) {
if (maxLevel != 0) {
// TODO: What about a swap of autoMip mode?
if (force || entry.lodBias != lodBias) {
if (autoMip) {
@@ -141,10 +142,10 @@ void TextureCacheGLES::UpdateSamplingParams(TexCacheEntry &entry, bool force) {
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_LOD_BIAS, lodBias);
#endif
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_LOD, 0);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, (float)entry.maxLevel);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, (float)maxLevel);
} else {
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_LOD, std::max(0.0f, std::min((float)entry.maxLevel, lodBias)));
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, std::max(0.0f, std::min((float)entry.maxLevel, lodBias)));
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_LOD, std::max(0.0f, std::min((float)maxLevel, lodBias)));
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, std::max(0.0f, std::min((float)maxLevel, lodBias)));
}
entry.lodBias = lodBias;
}
@@ -570,6 +571,7 @@ void TextureCacheGLES::BuildTexture(TexCacheEntry *const entry, bool replaceImag
// Adjust maxLevel to actually present levels..
bool badMipSizes = false;
bool canAutoGen = false;
int maxLevel = entry->maxLevel;
for (int i = 0; i <= maxLevel; i++) {
// If encountering levels pointing to nothing, adjust max level.
@@ -587,11 +589,19 @@ void TextureCacheGLES::BuildTexture(TexCacheEntry *const entry, bool replaceImag
break;
}
if (i > 0 && gstate_c.Supports(GPU_SUPPORTS_TEXTURE_LOD_CONTROL)) {
if (tw != 1 && tw != (gstate.getTextureWidth(i - 1) >> 1))
badMipSizes = true;
else if (th != 1 && th != (gstate.getTextureHeight(i - 1) >> 1))
badMipSizes = true;
if (i > 0) {
int lastW = gstate.getTextureWidth(i - 1);
int lastH = gstate.getTextureHeight(i - 1);
if (gstate_c.Supports(GPU_SUPPORTS_TEXTURE_LOD_CONTROL)) {
if (tw != 1 && tw != (lastW >> 1))
badMipSizes = true;
else if (th != 1 && th != (lastH >> 1))
badMipSizes = true;
}
if (lastW > tw || lastH > th)
canAutoGen = true;
}
}
@@ -688,7 +698,12 @@ void TextureCacheGLES::BuildTexture(TexCacheEntry *const entry, bool replaceImag
if (gstate_c.Supports(GPU_SUPPORTS_TEXTURE_LOD_CONTROL)) {
if (badMipSizes) {
// WARN_LOG(G3D, "Bad mipmap for texture sized %dx%dx%d - autogenerating", w, h, (int)format);
glGenerateMipmap(GL_TEXTURE_2D);
if (canAutoGen) {
glGenerateMipmap(GL_TEXTURE_2D);
} else {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
maxLevel = 0;
}
} else {
for (int i = 1; i <= maxLevel; i++) {
LoadTextureLevel(*entry, replaced, i, replaceImages, scaleFactor, dstFmt);
@@ -697,17 +712,22 @@ void TextureCacheGLES::BuildTexture(TexCacheEntry *const entry, bool replaceImag
}
} else {
// Avoid PowerVR driver bug
if (w > 1 && h > 1 && !(h > w && (gl_extensions.bugs & BUG_PVR_GENMIPMAP_HEIGHT_GREATER))) { // Really! only seems to fail if height > width
if (canAutoGen && w > 1 && h > 1 && !(h > w && (gl_extensions.bugs & BUG_PVR_GENMIPMAP_HEIGHT_GREATER))) { // Really! only seems to fail if height > width
// NOTICE_LOG(G3D, "Generating mipmap for texture sized %dx%d%d", w, h, (int)format);
glGenerateMipmap(GL_TEXTURE_2D);
} else {
entry->maxLevel = 0;
maxLevel = 0;
}
}
} else if (gstate_c.Supports(GPU_SUPPORTS_TEXTURE_LOD_CONTROL)) {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
}
if (maxLevel == 0) {
entry->status |= TexCacheEntry::STATUS_BAD_MIPS;
} else {
entry->status &= ~TexCacheEntry::STATUS_BAD_MIPS;
}
if (replaced.Valid()) {
entry->SetAlphaStatus(TexCacheEntry::Status(replaced.AlphaStatus()));
}
+7 -1
View File
@@ -212,7 +212,8 @@ void TextureCacheVulkan::UpdateSamplingParams(TexCacheEntry &entry, SamplerCache
bool tClamp;
float lodBias;
bool autoMip;
GetSamplingParams(minFilt, magFilt, sClamp, tClamp, lodBias, entry.maxLevel, entry.addr, autoMip);
u8 maxLevel = (entry.status & TexCacheEntry::STATUS_BAD_MIPS) ? 0 : entry.maxLevel;
GetSamplingParams(minFilt, magFilt, sClamp, tClamp, lodBias, maxLevel, entry.addr, autoMip);
key.minFilt = minFilt & 1;
key.mipEnable = (minFilt >> 2) & 1;
key.mipFilt = (minFilt >> 1) & 1;
@@ -661,6 +662,11 @@ void TextureCacheVulkan::BuildTexture(TexCacheEntry *const entry, bool replaceIm
entry->vkTex->texture_->UploadMip(i, mipWidth, mipHeight, texBuf, bufferOffset, stride / bpp);
}
if (maxLevel == 0) {
entry->status |= TexCacheEntry::STATUS_BAD_MIPS;
} else {
entry->status &= ~TexCacheEntry::STATUS_BAD_MIPS;
}
if (replaced.Valid()) {
entry->SetAlphaStatus(TexCacheEntry::Status(replaced.AlphaStatus()));
}