mirror of
https://github.com/hrydgard/ppsspp.git
synced 2025-03-03 19:47:59 +00:00
Merge pull request #9678 from unknownbrackets/mipmaps
Make const mipmaps more consistent
This commit is contained in:
commit
8cff9f8bc9
@ -124,23 +124,43 @@ int TextureCacheCommon::AttachedDrawingHeight() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void TextureCacheCommon::GetSamplingParams(int &minFilt, int &magFilt, bool &sClamp, bool &tClamp, float &lodBias, u8 maxLevel, u32 addr) {
|
||||
// Produces a signed 1.23.8 value.
|
||||
static int TexLog2(float delta) {
|
||||
union FloatBits {
|
||||
float f;
|
||||
u32 u;
|
||||
};
|
||||
FloatBits f;
|
||||
f.f = delta;
|
||||
// Use the exponent as the tex level, and the top mantissa bits for a frac.
|
||||
// We can't support more than 8 bits of frac, so truncate.
|
||||
int useful = (f.u >> 15) & 0xFFFF;
|
||||
// Now offset so the exponent aligns with log2f (exp=127 is 0.)
|
||||
return useful - 127 * 256;
|
||||
}
|
||||
|
||||
void TextureCacheCommon::GetSamplingParams(int &minFilt, int &magFilt, bool &sClamp, bool &tClamp, float &lodBias, u8 maxLevel, u32 addr, bool &autoMip) {
|
||||
minFilt = gstate.texfilter & 0x7;
|
||||
magFilt = (gstate.texfilter >> 8) & 1;
|
||||
sClamp = gstate.isTexCoordClampedS();
|
||||
tClamp = gstate.isTexCoordClampedT();
|
||||
|
||||
bool noMip = (gstate.texlevel & 0xFFFFFF) == 0x000001; // Fix texlevel at 0
|
||||
if (IsFakeMipmapChange())
|
||||
noMip = gstate.getTexLevelMode() == GE_TEXLEVEL_MODE_CONST;
|
||||
GETexLevelMode mipMode = gstate.getTexLevelMode();
|
||||
autoMip = mipMode == GE_TEXLEVEL_MODE_AUTO;
|
||||
lodBias = (float)(int)(s8)((gstate.texlevel >> 16) & 0xFF) * (1.0f / 16.0f);
|
||||
if (mipMode == GE_TEXLEVEL_MODE_SLOPE) {
|
||||
lodBias += 1.0f + TexLog2(gstate.getTextureLodSlope()) * (1.0f / 256.0f);
|
||||
}
|
||||
|
||||
if (maxLevel == 0) {
|
||||
// If mip level is forced to zero, disable mipmapping.
|
||||
bool noMip = !g_Config.bMipMap || maxLevel == 0 || (!autoMip && lodBias <= 0.0f);
|
||||
if (IsFakeMipmapChange())
|
||||
noMip = noMip || !autoMip;
|
||||
|
||||
if (noMip) {
|
||||
// Enforce no mip filtering, for safety.
|
||||
minFilt &= 1; // no mipmaps yet
|
||||
lodBias = 0.0f;
|
||||
} else {
|
||||
// Texture lod bias should be signed.
|
||||
lodBias = (float)(int)(s8)((gstate.texlevel >> 16) & 0xFF) / 16.0f;
|
||||
}
|
||||
|
||||
if (g_Config.iTexFiltering == TEX_FILTER_LINEAR_VIDEO) {
|
||||
@ -169,10 +189,6 @@ void TextureCacheCommon::GetSamplingParams(int &minFilt, int &magFilt, bool &sCl
|
||||
magFilt &= ~1;
|
||||
minFilt &= ~1;
|
||||
}
|
||||
|
||||
if (!g_Config.bMipMap || noMip) {
|
||||
minFilt &= 1;
|
||||
}
|
||||
}
|
||||
|
||||
void TextureCacheCommon::UpdateMaxSeenV(TexCacheEntry *entry, bool throughMode) {
|
||||
|
@ -71,8 +71,9 @@ struct SamplerCacheKey {
|
||||
bool tClamp : 1;
|
||||
bool lodAuto : 1;
|
||||
bool : 1;
|
||||
int8_t lodBias : 8;
|
||||
int8_t maxLevel : 4;
|
||||
int8_t : 4;
|
||||
int16_t lodBias : 16;
|
||||
};
|
||||
};
|
||||
|
||||
@ -242,7 +243,7 @@ protected:
|
||||
}
|
||||
|
||||
u32 EstimateTexMemoryUsage(const TexCacheEntry *entry);
|
||||
void GetSamplingParams(int &minFilt, int &magFilt, bool &sClamp, bool &tClamp, float &lodBias, u8 maxLevel, u32 addr);
|
||||
void GetSamplingParams(int &minFilt, int &magFilt, bool &sClamp, bool &tClamp, float &lodBias, u8 maxLevel, u32 addr, bool &autoMip);
|
||||
void UpdateMaxSeenV(TexCacheEntry *entry, bool throughMode);
|
||||
|
||||
bool AttachFramebuffer(TexCacheEntry *entry, u32 address, VirtualFramebuffer *framebuffer, u32 texaddrOffset = 0);
|
||||
|
@ -99,11 +99,11 @@ ID3D11SamplerState *SamplerCacheD3D11::GetOrCreateSampler(ID3D11Device *device,
|
||||
// Auto selected mip + bias.
|
||||
samp.MaxLOD = key.maxLevel;
|
||||
samp.MinLOD = 0.0f;
|
||||
samp.MipLODBias = (float)key.lodBias / 16.0f;
|
||||
samp.MipLODBias = (float)key.lodBias / 256.0f;
|
||||
} else {
|
||||
// Constant mip at bias.
|
||||
samp.MaxLOD = (float)key.lodBias / 16.0f;
|
||||
samp.MinLOD = (float)key.lodBias / 16.0f;
|
||||
samp.MaxLOD = std::max(0.0f, std::min((float)key.maxLevel, (float)key.lodBias / 256.0f));
|
||||
samp.MinLOD = std::max(0.0f, std::min((float)key.maxLevel, (float)key.lodBias / 256.0f));
|
||||
samp.MipLODBias = 0.0f;
|
||||
}
|
||||
#endif
|
||||
@ -176,20 +176,18 @@ void TextureCacheD3D11::UpdateSamplingParams(TexCacheEntry &entry, SamplerCacheK
|
||||
bool sClamp;
|
||||
bool tClamp;
|
||||
float lodBias;
|
||||
GetSamplingParams(minFilt, magFilt, sClamp, tClamp, lodBias, entry.maxLevel, entry.addr);
|
||||
bool autoMip;
|
||||
GetSamplingParams(minFilt, magFilt, sClamp, tClamp, lodBias, entry.maxLevel, entry.addr, autoMip);
|
||||
key.minFilt = minFilt & 1;
|
||||
key.mipEnable = (minFilt >> 2) & 1;
|
||||
key.mipFilt = (minFilt >> 1) & 1;
|
||||
key.magFilt = magFilt & 1;
|
||||
key.sClamp = sClamp;
|
||||
key.tClamp = tClamp;
|
||||
key.lodBias = (s8)((gstate.texlevel >> 16) & 0xFF);
|
||||
if (key.lodBias > entry.maxLevel * 16) {
|
||||
key.lodBias = entry.maxLevel * 16;
|
||||
}
|
||||
// Don't clamp to maxLevel - this may bias magnify levels.
|
||||
key.lodBias = (int)(lodBias * 256.0f);
|
||||
key.maxLevel = entry.maxLevel;
|
||||
key.lodAuto = gstate.getTexLevelMode() == GE_TEXLEVEL_MODE_AUTO;
|
||||
// TODO: GE_TEXLEVEL_MODE_SLOPE
|
||||
key.lodAuto = autoMip;
|
||||
|
||||
if (entry.framebuffer) {
|
||||
WARN_LOG_REPORT_ONCE(wrongFramebufAttach, G3D, "Framebuffer still attached in UpdateSamplingParams()?");
|
||||
@ -202,7 +200,8 @@ void TextureCacheD3D11::SetFramebufferSamplingParams(u16 bufferWidth, u16 buffer
|
||||
bool sClamp;
|
||||
bool tClamp;
|
||||
float lodBias;
|
||||
GetSamplingParams(minFilt, magFilt, sClamp, tClamp, lodBias, 0, 0);
|
||||
bool autoMip;
|
||||
GetSamplingParams(minFilt, magFilt, sClamp, tClamp, lodBias, 0, 0, autoMip);
|
||||
|
||||
key.minFilt = minFilt & 1;
|
||||
key.mipFilt = 0;
|
||||
|
@ -154,27 +154,18 @@ void TextureCacheDX9::UpdateSamplingParams(TexCacheEntry &entry, bool force) {
|
||||
bool sClamp;
|
||||
bool tClamp;
|
||||
float lodBias;
|
||||
GetSamplingParams(minFilt, magFilt, sClamp, tClamp, lodBias, entry.maxLevel, entry.addr);
|
||||
bool autoMip;
|
||||
GetSamplingParams(minFilt, magFilt, sClamp, tClamp, lodBias, entry.maxLevel, entry.addr, autoMip);
|
||||
|
||||
if (entry.maxLevel != 0) {
|
||||
GETexLevelMode mode = gstate.getTexLevelMode();
|
||||
switch (mode) {
|
||||
case GE_TEXLEVEL_MODE_AUTO:
|
||||
if (autoMip) {
|
||||
dxstate.texMaxMipLevel.set(0);
|
||||
dxstate.texMipLodBias.set(lodBias);
|
||||
break;
|
||||
case GE_TEXLEVEL_MODE_CONST:
|
||||
} 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((int)lodBias);
|
||||
dxstate.texMaxMipLevel.set(std::max(0, std::min((int)entry.maxLevel, (int)lodBias)));
|
||||
dxstate.texMipLodBias.set(-1000.0f);
|
||||
break;
|
||||
case GE_TEXLEVEL_MODE_SLOPE:
|
||||
WARN_LOG_REPORT_ONCE(texSlope, G3D, "Unsupported texture lod slope: %f + %f", gstate.getTextureLodSlope(), lodBias);
|
||||
// TODO: This behavior isn't correct.
|
||||
dxstate.texMaxMipLevel.set(0);
|
||||
dxstate.texMipLodBias.set(lodBias);
|
||||
break;
|
||||
}
|
||||
entry.lodBias = lodBias;
|
||||
} else {
|
||||
@ -203,7 +194,8 @@ void TextureCacheDX9::SetFramebufferSamplingParams(u16 bufferWidth, u16 bufferHe
|
||||
bool sClamp;
|
||||
bool tClamp;
|
||||
float lodBias;
|
||||
GetSamplingParams(minFilt, magFilt, sClamp, tClamp, lodBias, 0, 0);
|
||||
bool autoMip;
|
||||
GetSamplingParams(minFilt, magFilt, sClamp, tClamp, lodBias, 0, 0, autoMip);
|
||||
|
||||
dxstate.texMinFilter.set(MinFilt[minFilt]);
|
||||
dxstate.texMipFilter.set(MipFilt[minFilt]);
|
||||
|
@ -128,42 +128,31 @@ void TextureCacheGLES::UpdateSamplingParams(TexCacheEntry &entry, bool force) {
|
||||
bool sClamp;
|
||||
bool tClamp;
|
||||
float lodBias;
|
||||
GetSamplingParams(minFilt, magFilt, sClamp, tClamp, lodBias, entry.maxLevel, entry.addr);
|
||||
bool autoMip;
|
||||
GetSamplingParams(minFilt, magFilt, sClamp, tClamp, lodBias, entry.maxLevel, entry.addr, autoMip);
|
||||
|
||||
if (entry.maxLevel != 0) {
|
||||
if (force || entry.lodBias != lodBias) {
|
||||
if (gstate_c.Supports(GPU_SUPPORTS_TEXTURE_LOD_CONTROL)) {
|
||||
GETexLevelMode mode = gstate.getTexLevelMode();
|
||||
switch (mode) {
|
||||
case GE_TEXLEVEL_MODE_AUTO:
|
||||
if (entry.maxLevel != 0) {
|
||||
// TODO: What about a swap of autoMip mode?
|
||||
if (force || entry.lodBias != lodBias) {
|
||||
if (autoMip) {
|
||||
#ifndef USING_GLES2
|
||||
// Sigh, LOD_BIAS is not even in ES 3.0.. but we could do it in the shader via texture()...
|
||||
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);
|
||||
break;
|
||||
case GE_TEXLEVEL_MODE_CONST:
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_LOD, lodBias);
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, lodBias);
|
||||
break;
|
||||
case GE_TEXLEVEL_MODE_SLOPE:
|
||||
WARN_LOG_REPORT_ONCE(texSlope, G3D, "Unsupported texture lod slope: %f + %f", gstate.getTextureLodSlope(), lodBias);
|
||||
// TODO: This behavior isn't correct.
|
||||
#ifndef USING_GLES2
|
||||
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);
|
||||
break;
|
||||
}
|
||||
} 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)));
|
||||
}
|
||||
entry.lodBias = lodBias;
|
||||
}
|
||||
} else if (gstate_c.Supports(GPU_SUPPORTS_TEXTURE_LOD_CONTROL)) {
|
||||
} else {
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_LOD, 0.0f);
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, 0.0f);
|
||||
}
|
||||
}
|
||||
|
||||
if (force || entry.minFilt != minFilt) {
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, MinFiltGL[minFilt]);
|
||||
@ -195,7 +184,8 @@ void TextureCacheGLES::SetFramebufferSamplingParams(u16 bufferWidth, u16 bufferH
|
||||
bool sClamp;
|
||||
bool tClamp;
|
||||
float lodBias;
|
||||
GetSamplingParams(minFilt, magFilt, sClamp, tClamp, lodBias, 0, 0);
|
||||
bool autoMip;
|
||||
GetSamplingParams(minFilt, magFilt, sClamp, tClamp, lodBias, 0, 0, autoMip);
|
||||
|
||||
minFilt &= 1; // framebuffers can't mipmap.
|
||||
|
||||
|
@ -124,6 +124,7 @@ const CommonCommandTableEntry commonCommandTable[] = {
|
||||
{ GE_CMD_TEXSIZE7, FLAG_FLUSHBEFOREONCHANGE, DIRTY_TEXTURE_PARAMS },
|
||||
{ GE_CMD_TEXFORMAT, FLAG_FLUSHBEFOREONCHANGE, DIRTY_TEXTURE_IMAGE },
|
||||
{ GE_CMD_TEXLEVEL, FLAG_EXECUTEONCHANGE, DIRTY_TEXTURE_PARAMS, &GPUCommon::Execute_TexLevel },
|
||||
{ GE_CMD_TEXLODSLOPE, FLAG_FLUSHBEFOREONCHANGE, DIRTY_TEXTURE_PARAMS },
|
||||
{ GE_CMD_TEXADDR0, FLAG_FLUSHBEFOREONCHANGE, DIRTY_TEXTURE_IMAGE | DIRTY_UVSCALEOFFSET },
|
||||
{ GE_CMD_TEXADDR1, FLAG_FLUSHBEFOREONCHANGE, DIRTY_TEXTURE_PARAMS },
|
||||
{ GE_CMD_TEXADDR2, FLAG_FLUSHBEFOREONCHANGE, DIRTY_TEXTURE_PARAMS },
|
||||
@ -265,7 +266,6 @@ const CommonCommandTableEntry commonCommandTable[] = {
|
||||
|
||||
// Ignored commands
|
||||
{ GE_CMD_TEXFLUSH, 0 },
|
||||
{ GE_CMD_TEXLODSLOPE, 0 },
|
||||
{ GE_CMD_TEXSYNC, 0 },
|
||||
|
||||
// These are just nop or part of other later commands.
|
||||
@ -1416,7 +1416,7 @@ void GPUCommon::Execute_TexLevel(u32 op, u32 diff) {
|
||||
if (diff == 0xFFFFFFFF) return;
|
||||
|
||||
gstate.texlevel ^= diff;
|
||||
if (gstate.getTexLevelMode() == GE_TEXLEVEL_MODE_CONST && (0x00FF0000 & gstate.texlevel) != 0) {
|
||||
if (gstate.getTexLevelMode() != GE_TEXLEVEL_MODE_AUTO && (0x00FF0000 & gstate.texlevel) != 0) {
|
||||
Flush();
|
||||
}
|
||||
gstate.texlevel ^= diff;
|
||||
|
@ -1226,7 +1226,7 @@ static inline void ApplyTexturing(Vec4<int> *prim_color, const Vec4<float> &s, c
|
||||
break;
|
||||
case GE_TEXLEVEL_MODE_CONST:
|
||||
default:
|
||||
// TODO: Verify what 3 does.
|
||||
// Unused value 3 operates the same as CONST.
|
||||
detail = 0;
|
||||
break;
|
||||
}
|
||||
|
@ -211,7 +211,8 @@ void TextureCacheVulkan::UpdateSamplingParams(TexCacheEntry &entry, SamplerCache
|
||||
bool sClamp;
|
||||
bool tClamp;
|
||||
float lodBias;
|
||||
GetSamplingParams(minFilt, magFilt, sClamp, tClamp, lodBias, entry.maxLevel, entry.addr);
|
||||
bool autoMip;
|
||||
GetSamplingParams(minFilt, magFilt, sClamp, tClamp, lodBias, entry.maxLevel, entry.addr, autoMip);
|
||||
key.minFilt = minFilt & 1;
|
||||
key.mipEnable = (minFilt >> 2) & 1;
|
||||
key.mipFilt = (minFilt >> 1) & 1;
|
||||
@ -223,17 +224,10 @@ void TextureCacheVulkan::UpdateSamplingParams(TexCacheEntry &entry, SamplerCache
|
||||
if (entry.maxLevel != 0) {
|
||||
if (force || entry.lodBias != lodBias) {
|
||||
if (gstate_c.Supports(GPU_SUPPORTS_TEXTURE_LOD_CONTROL)) {
|
||||
GETexLevelMode mode = gstate.getTexLevelMode();
|
||||
switch (mode) {
|
||||
case GE_TEXLEVEL_MODE_AUTO:
|
||||
if (autoMip) {
|
||||
// TODO
|
||||
break;
|
||||
case GE_TEXLEVEL_MODE_CONST:
|
||||
// Sigh, LOD_BIAS is not even in ES 3.0..
|
||||
break;
|
||||
case GE_TEXLEVEL_MODE_SLOPE:
|
||||
} else {
|
||||
// TODO
|
||||
break;
|
||||
}
|
||||
}
|
||||
entry.lodBias = lodBias;
|
||||
@ -252,7 +246,8 @@ void TextureCacheVulkan::SetFramebufferSamplingParams(u16 bufferWidth, u16 buffe
|
||||
bool sClamp;
|
||||
bool tClamp;
|
||||
float lodBias;
|
||||
GetSamplingParams(minFilt, magFilt, sClamp, tClamp, lodBias, 0, 0);
|
||||
bool autoMip;
|
||||
GetSamplingParams(minFilt, magFilt, sClamp, tClamp, lodBias, 0, 0, autoMip);
|
||||
|
||||
key.minFilt = minFilt & 1;
|
||||
key.mipFilt = 0;
|
||||
|
Loading…
x
Reference in New Issue
Block a user