mirror of
https://github.com/libretro/ppsspp.git
synced 2024-11-29 11:20:40 +00:00
Merge pull request #6336 from unknownbrackets/texcache
Separate framebuffer sampling params from tex
This commit is contained in:
commit
43bddd8067
@ -163,6 +163,49 @@ static inline bool blendColorSimilar(const Vec3f &a, const Vec3f &b, float margi
|
||||
return false;
|
||||
}
|
||||
|
||||
bool TransformDrawEngine::ApplyShaderBlending() {
|
||||
bool skipBlit = false;
|
||||
if (gl_extensions.NV_shader_framebuffer_fetch) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static const int MAX_REASONABLE_BLITS_PER_FRAME = 24;
|
||||
|
||||
static int lastFrameBlit = -1;
|
||||
static int blitsThisFrame = 0;
|
||||
if (lastFrameBlit != gpuStats.numFlips) {
|
||||
if (blitsThisFrame > MAX_REASONABLE_BLITS_PER_FRAME) {
|
||||
WARN_LOG_REPORT_ONCE(blendingBlit, G3D, "Lots of blits needed for obscure blending: %d per frame, blend %d/%d/%d", blitsThisFrame, gstate.getBlendFuncA(), gstate.getBlendFuncB(), gstate.getBlendEq());
|
||||
}
|
||||
blitsThisFrame = 0;
|
||||
lastFrameBlit = gpuStats.numFlips;
|
||||
}
|
||||
++blitsThisFrame;
|
||||
if (blitsThisFrame > MAX_REASONABLE_BLITS_PER_FRAME * 2) {
|
||||
WARN_LOG_ONCE(blendingBlit2, G3D, "Skipping additional blits needed for obscure blending: %d per frame, blend %d/%d/%d", blitsThisFrame, gstate.getBlendFuncA(), gstate.getBlendFuncB(), gstate.getBlendEq());
|
||||
ResetShaderBlending();
|
||||
return false;
|
||||
}
|
||||
|
||||
glActiveTexture(GL_TEXTURE1);
|
||||
framebufferManager_->BindFramebufferColor(NULL);
|
||||
// If we are rendering at a higher resolution, linear is probably best for the dest color.
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
fboTexBound_ = true;
|
||||
|
||||
shaderManager_->DirtyUniform(DIRTY_SHADERBLEND);
|
||||
return true;
|
||||
}
|
||||
|
||||
void TransformDrawEngine::ResetShaderBlending() {
|
||||
glActiveTexture(GL_TEXTURE1);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
fboTexBound_ = false;
|
||||
}
|
||||
|
||||
void TransformDrawEngine::ApplyDrawState(int prim) {
|
||||
// TODO: All this setup is soon so expensive that we'll need dirty flags, or simply do it in the command writes where we detect dirty by xoring. Silly to do all this work on every drawcall.
|
||||
|
||||
@ -179,37 +222,12 @@ void TransformDrawEngine::ApplyDrawState(int prim) {
|
||||
// Set blend - unless we need to do it in the shader.
|
||||
bool wantBlend = !gstate.isModeClear() && gstate.isAlphaBlendEnabled();
|
||||
if (wantBlend && ShouldUseShaderBlending()) {
|
||||
if (!gl_extensions.NV_shader_framebuffer_fetch) {
|
||||
static const int MAX_REASONABLE_BLITS_PER_FRAME = 24;
|
||||
|
||||
static int lastFrameBlit = -1;
|
||||
static int blitsThisFrame = 0;
|
||||
if (lastFrameBlit != gpuStats.numFlips) {
|
||||
if (blitsThisFrame > MAX_REASONABLE_BLITS_PER_FRAME) {
|
||||
WARN_LOG_REPORT_ONCE(blendingBlit, G3D, "Lots of blits needed for obscure blending: %d per frame, blend %d/%d/%d", blitsThisFrame, gstate.getBlendFuncA(), gstate.getBlendFuncB(), gstate.getBlendEq());
|
||||
}
|
||||
blitsThisFrame = 0;
|
||||
lastFrameBlit = gpuStats.numFlips;
|
||||
}
|
||||
++blitsThisFrame;
|
||||
|
||||
glActiveTexture(GL_TEXTURE1);
|
||||
framebufferManager_->BindFramebufferColor(NULL);
|
||||
// If we are rendering at a higher resolution, linear is probably best for the dest color.
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
fboTexBound_ = true;
|
||||
|
||||
shaderManager_->DirtyUniform(DIRTY_SHADERBLEND);
|
||||
if (ApplyShaderBlending()) {
|
||||
// None of the below logic is interesting, we're gonna do it entirely in the shader.
|
||||
wantBlend = false;
|
||||
}
|
||||
// None of the below logic is interesting, we're gonna do it entirely in the shader.
|
||||
wantBlend = false;
|
||||
} else if (fboTexBound_) {
|
||||
glActiveTexture(GL_TEXTURE1);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
fboTexBound_ = false;
|
||||
ResetShaderBlending();
|
||||
}
|
||||
|
||||
glstate.blend.set(wantBlend);
|
||||
|
@ -584,46 +584,24 @@ static const GLuint MagFiltGL[2] = {
|
||||
GL_LINEAR
|
||||
};
|
||||
|
||||
// This should not have to be done per texture! OpenGL is silly yo
|
||||
void TextureCache::UpdateSamplingParams(TexCacheEntry &entry, bool force) {
|
||||
int minFilt = gstate.texfilter & 0x7;
|
||||
int magFilt = (gstate.texfilter>>8) & 1;
|
||||
bool sClamp = gstate.isTexCoordClampedS();
|
||||
bool tClamp = gstate.isTexCoordClampedT();
|
||||
|
||||
if (entry.status & TexCacheEntry::STATUS_TEXPARAM_DIRTY) {
|
||||
entry.status &= ~TexCacheEntry::STATUS_TEXPARAM_DIRTY;
|
||||
force = true;
|
||||
}
|
||||
void TextureCache::GetSamplingParams(int &minFilt, int &magFilt, bool &sClamp, bool &tClamp, float &lodBias, int maxLevel) {
|
||||
minFilt = gstate.texfilter & 0x7;
|
||||
magFilt = (gstate.texfilter>>8) & 1;
|
||||
sClamp = gstate.isTexCoordClampedS();
|
||||
tClamp = gstate.isTexCoordClampedT();
|
||||
|
||||
bool noMip = (gstate.texlevel & 0xFFFFFF) == 0x000001 || (gstate.texlevel & 0xFFFFFF) == 0x100001 ; // Fix texlevel at 0
|
||||
|
||||
if (entry.maxLevel == 0) {
|
||||
if (maxLevel == 0) {
|
||||
// Enforce no mip filtering, for safety.
|
||||
minFilt &= 1; // no mipmaps yet
|
||||
lodBias = 0.0f;
|
||||
} else {
|
||||
// Texture lod bias should be signed.
|
||||
float lodBias = (float)(int)(s8)((gstate.texlevel >> 16) & 0xFF) / 16.0f;
|
||||
if (force || entry.lodBias != lodBias) {
|
||||
#ifndef USING_GLES2
|
||||
GETexLevelMode mode = gstate.getTexLevelMode();
|
||||
switch (mode) {
|
||||
case GE_TEXLEVEL_MODE_AUTO:
|
||||
// TODO
|
||||
break;
|
||||
case GE_TEXLEVEL_MODE_CONST:
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_LOD_BIAS, lodBias);
|
||||
break;
|
||||
case GE_TEXLEVEL_MODE_SLOPE:
|
||||
// TODO
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
entry.lodBias = lodBias;
|
||||
}
|
||||
lodBias = (float)(int)(s8)((gstate.texlevel >> 16) & 0xFF) / 16.0f;
|
||||
}
|
||||
|
||||
if (g_Config.iTexFiltering == LINEARFMV && g_iNumVideos > 0 && (entry.dim & 0xF) >= 9) {
|
||||
if (g_Config.iTexFiltering == LINEARFMV && g_iNumVideos > 0 && (gstate.getTextureDimension(0) & 0xF) >= 9) {
|
||||
magFilt |= 1;
|
||||
minFilt |= 1;
|
||||
}
|
||||
@ -650,6 +628,36 @@ void TextureCache::UpdateSamplingParams(TexCacheEntry &entry, bool force) {
|
||||
if (!g_Config.bMipMap || noMip) {
|
||||
minFilt &= 1;
|
||||
}
|
||||
}
|
||||
|
||||
// This should not have to be done per texture! OpenGL is silly yo
|
||||
void TextureCache::UpdateSamplingParams(TexCacheEntry &entry, bool force) {
|
||||
int minFilt;
|
||||
int magFilt;
|
||||
bool sClamp;
|
||||
bool tClamp;
|
||||
float lodBias;
|
||||
GetSamplingParams(minFilt, magFilt, sClamp, tClamp, lodBias, entry.maxLevel);
|
||||
|
||||
if (entry.maxLevel != 0) {
|
||||
if (force || entry.lodBias != lodBias) {
|
||||
#ifndef USING_GLES2
|
||||
GETexLevelMode mode = gstate.getTexLevelMode();
|
||||
switch (mode) {
|
||||
case GE_TEXLEVEL_MODE_AUTO:
|
||||
// TODO
|
||||
break;
|
||||
case GE_TEXLEVEL_MODE_CONST:
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_LOD_BIAS, lodBias);
|
||||
break;
|
||||
case GE_TEXLEVEL_MODE_SLOPE:
|
||||
// TODO
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
entry.lodBias = lodBias;
|
||||
}
|
||||
}
|
||||
|
||||
if (force || entry.minFilt != minFilt) {
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, MinFiltGL[minFilt]);
|
||||
@ -660,16 +668,8 @@ void TextureCache::UpdateSamplingParams(TexCacheEntry &entry, bool force) {
|
||||
entry.magFilt = magFilt;
|
||||
}
|
||||
|
||||
// Platforms without non-pow-2 extensions can't wrap non-pow-2 textures.
|
||||
// Only framebuffer textures can be non-pow-2.
|
||||
if (!gl_extensions.OES_texture_npot && entry.framebuffer) {
|
||||
// Check if it matches the size, in which case we can still enable wrapping.
|
||||
int w = gstate.getTextureWidth(0);
|
||||
int h = gstate.getTextureHeight(0);
|
||||
if (w != entry.framebuffer->bufferWidth || h != entry.framebuffer->bufferHeight) {
|
||||
// We'll do it in the shader.
|
||||
return;
|
||||
}
|
||||
if (entry.framebuffer) {
|
||||
WARN_LOG_REPORT_ONCE(wrongFramebufAttach, G3D, "Framebuffer still attached in UpdateSamplingParams()?");
|
||||
}
|
||||
|
||||
if (force || entry.sClamp != sClamp) {
|
||||
@ -682,6 +682,29 @@ void TextureCache::UpdateSamplingParams(TexCacheEntry &entry, bool force) {
|
||||
}
|
||||
}
|
||||
|
||||
void TextureCache::SetFramebufferSamplingParams(u16 bufferWidth, u16 bufferHeight) {
|
||||
int minFilt;
|
||||
int magFilt;
|
||||
bool sClamp;
|
||||
bool tClamp;
|
||||
float lodBias;
|
||||
GetSamplingParams(minFilt, magFilt, sClamp, tClamp, lodBias, 0);
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, MinFiltGL[minFilt]);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, MagFiltGL[magFilt]);
|
||||
|
||||
// Often the framebuffer will not match the texture size. We'll wrap/clamp in the shader in that case.
|
||||
// This happens whether we have OES_texture_npot or not.
|
||||
int w = gstate.getTextureWidth(0);
|
||||
int h = gstate.getTextureHeight(0);
|
||||
if (w != bufferWidth || h != bufferHeight) {
|
||||
return;
|
||||
}
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, sClamp ? GL_CLAMP_TO_EDGE : GL_REPEAT);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, tClamp ? GL_CLAMP_TO_EDGE : GL_REPEAT);
|
||||
}
|
||||
|
||||
static void ConvertColors(void *dstBuf, const void *srcBuf, GLuint dstFmt, int numPixels) {
|
||||
const u32 *src = (const u32 *)srcBuf;
|
||||
u32 *dst = (u32 *)dstBuf;
|
||||
@ -1013,7 +1036,6 @@ void TextureCache::SetTextureFramebuffer(TexCacheEntry *entry, VirtualFramebuffe
|
||||
framebufferManager_->BindFramebufferColor(framebuffer, true);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
entry->status |= TexCacheEntry::STATUS_TEXPARAM_DIRTY;
|
||||
|
||||
glDisable(GL_BLEND);
|
||||
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
|
||||
@ -1065,7 +1087,7 @@ void TextureCache::SetTextureFramebuffer(TexCacheEntry *entry, VirtualFramebuffe
|
||||
if (gstate_c.curTextureXOffset != 0 || gstate_c.curTextureYOffset != 0) {
|
||||
gstate_c.needShaderTexClamp = true;
|
||||
}
|
||||
UpdateSamplingParams(*entry, true);
|
||||
SetFramebufferSamplingParams(framebuffer->bufferWidth, framebuffer->bufferHeight);
|
||||
} else {
|
||||
if (framebuffer->fbo)
|
||||
framebuffer->fbo = 0;
|
||||
|
@ -113,11 +113,8 @@ public:
|
||||
|
||||
STATUS_CHANGE_FREQUENT = 0x10, // Changes often (less than 15 frames in between.)
|
||||
STATUS_CLUT_RECHECK = 0x20, // Another texture with same addr had a hashfail.
|
||||
STATUS_DEPALETTIZE = 0x40,
|
||||
STATUS_DEPALETTIZE_DIRTY = 0x80,
|
||||
STATUS_TEXPARAM_DIRTY = 0x100,
|
||||
|
||||
STATUS_TO_SCALE = 0x200,
|
||||
STATUS_DEPALETTIZE = 0x40, // Needs to go through a depalettize pass.
|
||||
STATUS_TO_SCALE = 0x80, // Pending texture scaling in a later frame.
|
||||
};
|
||||
|
||||
// Status, but int so we can zero initialize.
|
||||
@ -170,6 +167,8 @@ public:
|
||||
bool Matches(u16 dim2, u8 format2, int maxLevel2);
|
||||
};
|
||||
|
||||
void SetFramebufferSamplingParams(u16 bufferWidth, u16 bufferHeight);
|
||||
|
||||
private:
|
||||
typedef std::map<u64, TexCacheEntry> TexCache;
|
||||
|
||||
@ -177,6 +176,7 @@ private:
|
||||
void DeleteTexture(TexCache::iterator it);
|
||||
void *UnswizzleFromMem(const u8 *texptr, u32 bufw, u32 bytesPerPixel, u32 level);
|
||||
void *ReadIndexedTex(int level, const u8 *texptr, int bytesPerIndex, GLuint dstFmt, int bufw);
|
||||
void GetSamplingParams(int &minFilt, int &magFilt, bool &sClamp, bool &tClamp, float &lodBias, int maxLevel);
|
||||
void UpdateSamplingParams(TexCacheEntry &entry, bool force);
|
||||
void LoadTextureLevel(TexCacheEntry &entry, int level, bool replaceImages, int scaleFactor, GLenum dstFmt);
|
||||
GLenum GetDestFormat(GETextureFormat format, GEPaletteFormat clutFormat) const;
|
||||
|
@ -174,6 +174,8 @@ private:
|
||||
void DoFlush();
|
||||
void SoftwareTransformAndDraw(int prim, u8 *decoded, LinkedShader *program, int vertexCount, u32 vertexType, void *inds, int indexType, const DecVtxFormat &decVtxFormat, int maxIndex);
|
||||
void ApplyDrawState(int prim);
|
||||
bool ApplyShaderBlending();
|
||||
void ResetShaderBlending();
|
||||
bool IsReallyAClear(int numVerts) const;
|
||||
GLuint AllocateBuffer();
|
||||
void FreeBuffer(GLuint buf);
|
||||
|
Loading…
Reference in New Issue
Block a user