mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-10-20 17:59:08 +02:00
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:
1 parent
9687873417
commit
b6375638f5
5 files changed
+59
-19
No files matched your search
@@ -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.
|
||||
|
||||
@@ -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()));
|
||||
}
|
||||
|
||||
@@ -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()));
|
||||
}
|
||||
|
||||
@@ -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()));
|
||||
}
|
||||
|
||||
@@ -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()));
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user