From c7e6f051e429f3d8db17626556dd59ee943d585e Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 15 Mar 2015 19:10:33 -0700 Subject: [PATCH] Split the texture application into two stages. The latter simply applies the texture. This makes our IsAlphaTestTriviallyTrue() check correct. --- GPU/Common/TextureCacheCommon.cpp | 1 - GPU/GLES/ShaderManager.cpp | 1 + GPU/GLES/StateMapping.cpp | 2 + GPU/GLES/TextureCache.cpp | 156 ++++++++++++++++++------------ GPU/GLES/TextureCache.h | 5 + 5 files changed, 101 insertions(+), 64 deletions(-) diff --git a/GPU/Common/TextureCacheCommon.cpp b/GPU/Common/TextureCacheCommon.cpp index 60a799f685..d6098933c6 100644 --- a/GPU/Common/TextureCacheCommon.cpp +++ b/GPU/Common/TextureCacheCommon.cpp @@ -51,7 +51,6 @@ void TextureCacheCommon::GetSamplingParams(int &minFilt, int &magFilt, bool &sCl minFilt |= 1; } if (g_Config.iTexFiltering == TEX_FILTER_LINEAR && (!gstate.isColorTestEnabled() || IsColorTestTriviallyTrue())) { - // TODO: IsAlphaTestTriviallyTrue() is unsafe here. vertexFullAlpha is not calculated yet. if (!gstate.isAlphaTestEnabled() || IsAlphaTestTriviallyTrue()) { magFilt |= 1; minFilt |= 1; diff --git a/GPU/GLES/ShaderManager.cpp b/GPU/GLES/ShaderManager.cpp index c305d5a079..a310e67713 100644 --- a/GPU/GLES/ShaderManager.cpp +++ b/GPU/GLES/ShaderManager.cpp @@ -747,6 +747,7 @@ void ShaderManager::DirtyLastShader() { // disables vertex arrays if (lastShader_) lastShader_->stop(); lastShader_ = 0; + lastVShaderSame_ = false; } // This is to be used when debugging why incompatible shaders are being linked, like is diff --git a/GPU/GLES/StateMapping.cpp b/GPU/GLES/StateMapping.cpp index 2a0bd9f6b3..8ff8d7980b 100644 --- a/GPU/GLES/StateMapping.cpp +++ b/GPU/GLES/StateMapping.cpp @@ -901,6 +901,8 @@ void TransformDrawEngine::ApplyDrawStateLate() { fragmentTestCache_->BindTestTexture(GL_TEXTURE2); } + textureCache_->ApplyTexture(); + if (fboTexNeedBind_) { framebufferManager_->BindFramebufferColor(GL_TEXTURE1, gstate.getFrameBufRawAddress(), nullptr); glActiveTexture(GL_TEXTURE1); diff --git a/GPU/GLES/TextureCache.cpp b/GPU/GLES/TextureCache.cpp index 146cc2c989..e26ef834b2 100644 --- a/GPU/GLES/TextureCache.cpp +++ b/GPU/GLES/TextureCache.cpp @@ -88,6 +88,8 @@ TextureCache::TextureCache() : cacheSizeEstimate_(0), secondCacheSizeEstimate_(0 glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &maxAnisotropyLevel); SetupTextureDecoder(); + + nextTexture_ = nullptr; } TextureCache::~TextureCache() { @@ -938,61 +940,7 @@ void TextureCache::SetTextureFramebuffer(TexCacheEntry *entry, VirtualFramebuffe depal = depalShaderCache_->GetDepalettizeShader(clutFormat, framebuffer->drawnFormat); } if (depal) { - GLuint clutTexture = depalShaderCache_->GetClutTexture(clutFormat, clutHash_, clutBuf_); - FBO *depalFBO = framebufferManager_->GetTempFBO(framebuffer->renderWidth, framebuffer->renderHeight, FBO_8888); - fbo_bind_as_render_target(depalFBO); - static const float pos[12] = { - -1, -1, -1, - 1, -1, -1, - 1, 1, -1, - -1, 1, -1 - }; - static const float uv[8] = { - 0, 0, - 1, 0, - 1, 1, - 0, 1, - }; - static const GLubyte indices[4] = { 0, 1, 3, 2 }; - - shaderManager_->DirtyLastShader(); - - glUseProgram(depal->program); - - glstate.arrayBuffer.unbind(); - glstate.elementArrayBuffer.unbind(); - glEnableVertexAttribArray(depal->a_position); - glEnableVertexAttribArray(depal->a_texcoord0); - - glActiveTexture(GL_TEXTURE3); - glBindTexture(GL_TEXTURE_2D, clutTexture); - glActiveTexture(GL_TEXTURE0); - - framebufferManager_->BindFramebufferColor(GL_TEXTURE0, gstate.getFrameBufRawAddress(), framebuffer, true); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - - glDisable(GL_BLEND); - glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); - glDisable(GL_SCISSOR_TEST); - glDisable(GL_CULL_FACE); - glDisable(GL_DEPTH_TEST); - glDisable(GL_STENCIL_TEST); -#if !defined(USING_GLES2) - glDisable(GL_LOGIC_OP); -#endif - glViewport(0, 0, framebuffer->renderWidth, framebuffer->renderHeight); - - glVertexAttribPointer(depal->a_position, 3, GL_FLOAT, GL_FALSE, 12, pos); - glVertexAttribPointer(depal->a_texcoord0, 2, GL_FLOAT, GL_FALSE, 8, uv); - glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_BYTE, indices); - glDisableVertexAttribArray(depal->a_position); - glDisableVertexAttribArray(depal->a_texcoord0); - - fbo_bind_color_as_texture(depalFBO, 0); - glstate.Restore(); - framebufferManager_->RebindFramebuffer(); - + const GEPaletteFormat clutFormat = gstate.getClutPaletteFormat(); const u32 bytesPerColor = clutFormat == GE_CMODE_32BIT_ABGR8888 ? sizeof(u32) : sizeof(u16); const u32 clutTotalColors = clutMaxBytes_ / bytesPerColor; @@ -1001,7 +949,6 @@ void TextureCache::SetTextureFramebuffer(TexCacheEntry *entry, VirtualFramebuffe gstate_c.textureSimpleAlpha = alphaStatus == TexCacheEntry::STATUS_ALPHA_SIMPLE; } else { entry->status &= ~TexCacheEntry::STATUS_DEPALETTIZE; - framebufferManager_->BindFramebufferColor(GL_TEXTURE0, gstate.getFrameBufRawAddress(), framebuffer); gstate_c.textureFullAlpha = gstate.getTextureFormat() == GE_TFMT_5650; gstate_c.textureSimpleAlpha = gstate_c.textureFullAlpha; @@ -1020,7 +967,8 @@ void TextureCache::SetTextureFramebuffer(TexCacheEntry *entry, VirtualFramebuffe if (gstate_c.curTextureXOffset != 0 || gstate_c.curTextureYOffset != 0) { gstate_c.needShaderTexClamp = true; } - SetFramebufferSamplingParams(framebuffer->bufferWidth, framebuffer->bufferHeight); + + nextTexture_ = entry; } else { if (framebuffer->fbo) { fbo_destroy(framebuffer->fbo); @@ -1031,6 +979,92 @@ void TextureCache::SetTextureFramebuffer(TexCacheEntry *entry, VirtualFramebuffe } } +void TextureCache::ApplyTexture() { + if (nextTexture_ == nullptr) { + return; + } + + if (nextTexture_->framebuffer) { + ApplyTextureFramebuffer(nextTexture_, nextTexture_->framebuffer); + } else { + glBindTexture(GL_TEXTURE_2D, nextTexture_->textureName); + lastBoundTexture = nextTexture_->textureName; + UpdateSamplingParams(*nextTexture_, false); + } + + nextTexture_ = nullptr; +} + +void TextureCache::ApplyTextureFramebuffer(TexCacheEntry *entry, VirtualFramebuffer *framebuffer) { + DepalShader *depal = nullptr; + const GEPaletteFormat clutFormat = gstate.getClutPaletteFormat(); + if ((entry->status & TexCacheEntry::STATUS_DEPALETTIZE) && !g_Config.bDisableSlowFramebufEffects) { + depal = depalShaderCache_->GetDepalettizeShader(clutFormat, framebuffer->drawnFormat); + } + if (depal) { + GLuint clutTexture = depalShaderCache_->GetClutTexture(clutFormat, clutHash_, clutBuf_); + FBO *depalFBO = framebufferManager_->GetTempFBO(framebuffer->renderWidth, framebuffer->renderHeight, FBO_8888); + fbo_bind_as_render_target(depalFBO); + static const float pos[12] = { + -1, -1, -1, + 1, -1, -1, + 1, 1, -1, + -1, 1, -1 + }; + static const float uv[8] = { + 0, 0, + 1, 0, + 1, 1, + 0, 1, + }; + static const GLubyte indices[4] = { 0, 1, 3, 2 }; + + shaderManager_->DirtyLastShader(); + + glUseProgram(depal->program); + + glstate.arrayBuffer.unbind(); + glstate.elementArrayBuffer.unbind(); + glEnableVertexAttribArray(depal->a_position); + glEnableVertexAttribArray(depal->a_texcoord0); + + glActiveTexture(GL_TEXTURE3); + glBindTexture(GL_TEXTURE_2D, clutTexture); + glActiveTexture(GL_TEXTURE0); + + framebufferManager_->BindFramebufferColor(GL_TEXTURE0, gstate.getFrameBufRawAddress(), framebuffer, true); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + + glDisable(GL_BLEND); + glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); + glDisable(GL_SCISSOR_TEST); + glDisable(GL_CULL_FACE); + glDisable(GL_DEPTH_TEST); + glDisable(GL_STENCIL_TEST); +#if !defined(USING_GLES2) + glDisable(GL_LOGIC_OP); +#endif + glViewport(0, 0, framebuffer->renderWidth, framebuffer->renderHeight); + + glVertexAttribPointer(depal->a_position, 3, GL_FLOAT, GL_FALSE, 12, pos); + glVertexAttribPointer(depal->a_texcoord0, 2, GL_FLOAT, GL_FALSE, 8, uv); + glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_BYTE, indices); + glDisableVertexAttribArray(depal->a_position); + glDisableVertexAttribArray(depal->a_texcoord0); + + fbo_bind_color_as_texture(depalFBO, 0); + glstate.Restore(); + framebufferManager_->RebindFramebuffer(); + } else { + framebufferManager_->BindFramebufferColor(GL_TEXTURE0, gstate.getFrameBufRawAddress(), framebuffer); + } + + SetFramebufferSamplingParams(framebuffer->bufferWidth, framebuffer->bufferHeight); + + lastBoundTexture = -1; +} + bool TextureCache::SetOffsetTexture(u32 offset) { if (g_Config.iRenderingMode != FB_BUFFERED_MODE) { return false; @@ -1057,8 +1091,8 @@ bool TextureCache::SetOffsetTexture(u32 offset) { } if (success && entry->framebuffer) { + // This will not apply the texture immediately. SetTextureFramebuffer(entry, entry->framebuffer); - lastBoundTexture = -1; entry->lastFrame = gpuStats.numFlips; return true; } @@ -1136,7 +1170,6 @@ void TextureCache::SetTexture(bool force) { if (entry->framebuffer) { if (match) { SetTextureFramebuffer(entry, entry->framebuffer); - lastBoundTexture = -1; entry->lastFrame = gpuStats.numFlips; return; } else { @@ -1254,12 +1287,10 @@ void TextureCache::SetTexture(bool force) { //got one! entry->lastFrame = gpuStats.numFlips; if (entry->textureName != lastBoundTexture) { - glBindTexture(GL_TEXTURE_2D, entry->textureName); - lastBoundTexture = entry->textureName; + nextTexture_ = entry; gstate_c.textureFullAlpha = entry->GetAlphaStatus() == TexCacheEntry::STATUS_ALPHA_FULL; gstate_c.textureSimpleAlpha = entry->GetAlphaStatus() != TexCacheEntry::STATUS_ALPHA_UNKNOWN; } - UpdateSamplingParams(*entry, false); VERBOSE_LOG(G3D, "Texture at %08x Found in Cache, applying", texaddr); return; //Done! } else { @@ -1353,7 +1384,6 @@ void TextureCache::SetTexture(bool force) { // If we ended up with a framebuffer, attach it - no texture decoding needed. if (entry->framebuffer) { SetTextureFramebuffer(entry, entry->framebuffer); - lastBoundTexture = -1; entry->lastFrame = gpuStats.numFlips; return; } diff --git a/GPU/GLES/TextureCache.h b/GPU/GLES/TextureCache.h index 6c47ba0019..ab0321bdee 100644 --- a/GPU/GLES/TextureCache.h +++ b/GPU/GLES/TextureCache.h @@ -92,6 +92,8 @@ public: void SetFramebufferSamplingParams(u16 bufferWidth, u16 bufferHeight); + void ApplyTexture(); + private: // Can't be unordered_map, we use lower_bound ... although for some reason that compiles on MSVC. typedef std::map TexCache; @@ -112,6 +114,7 @@ private: bool AttachFramebuffer(TexCacheEntry *entry, u32 address, VirtualFramebuffer *framebuffer, u32 texaddrOffset = 0); void DetachFramebuffer(TexCacheEntry *entry, u32 address, VirtualFramebuffer *framebuffer); void SetTextureFramebuffer(TexCacheEntry *entry, VirtualFramebuffer *framebuffer); + void ApplyTextureFramebuffer(TexCacheEntry *entry, VirtualFramebuffer *framebuffer); TexCache cache; TexCache secondCache; @@ -150,6 +153,8 @@ private: bool clutAlphaLinear_; u16 clutAlphaLinearColor_; + TexCacheEntry *nextTexture_; + u32 lastBoundTexture; float maxAnisotropyLevel;