diff --git a/GPU/Common/FramebufferCommon.cpp b/GPU/Common/FramebufferCommon.cpp index bb161849b3..c0d747802f 100644 --- a/GPU/Common/FramebufferCommon.cpp +++ b/GPU/Common/FramebufferCommon.cpp @@ -1965,6 +1965,8 @@ bool FramebufferManagerCommon::GetDepthbuffer(u32 fb_address, int fb_stride, u32 } // No need to free on failure, that's the caller's job (it likely will reuse a buffer.) bool retval = draw_->CopyFramebufferToMemorySync(vfb->fbo, Draw::FB_DEPTH_BIT, 0, 0, w, h, Draw::DataFormat::D32F, buffer.GetData(), w); + // After a readback we'll have flushed and started over, need to dirty a bunch of things to be safe. + gstate_c.Dirty(DIRTY_VIEWPORTSCISSOR_STATE | DIRTY_BLEND_STATE | DIRTY_DEPTHSTENCIL_STATE | DIRTY_RASTER_STATE | DIRTY_TEXTURE_IMAGE | DIRTY_TEXTURE_PARAMS); // That may have unbound the framebuffer, rebind to avoid crashes when debugging. RebindFramebuffer(); return retval; diff --git a/GPU/Common/TextureCacheCommon.h b/GPU/Common/TextureCacheCommon.h index aa69f123a5..1bc16a2541 100644 --- a/GPU/Common/TextureCacheCommon.h +++ b/GPU/Common/TextureCacheCommon.h @@ -148,16 +148,8 @@ struct TexCacheEntry { u32 framesUntilNextFullHash; u32 fullhash; u32 cluthash; - float lodBias; u16 maxSeenV; - // Cache the current filter settings so we can avoid setting it again. - // (OpenGL ES 2.0 madness where filter settings are attached to each texture. Unused in other backends). - u8 magFilt; - u8 minFilt; - bool sClamp; - bool tClamp; - TexStatus GetHashStatus() { return TexStatus(status & STATUS_MASK); } diff --git a/GPU/Directx9/TextureCacheDX9.cpp b/GPU/Directx9/TextureCacheDX9.cpp index 123eebd0ff..53e69baa56 100644 --- a/GPU/Directx9/TextureCacheDX9.cpp +++ b/GPU/Directx9/TextureCacheDX9.cpp @@ -171,7 +171,6 @@ void TextureCacheDX9::UpdateSamplingParams(TexCacheEntry &entry, bool force) { dxstate.texMaxMipLevel.set(0); dxstate.texMipLodBias.set(0.0f); } - entry.lodBias = lodBias; } else { dxstate.texMaxMipLevel.set(0); dxstate.texMipLodBias.set(0.0f); diff --git a/GPU/GLES/TextureCacheGLES.cpp b/GPU/GLES/TextureCacheGLES.cpp index 3ff8704bca..8560438e04 100644 --- a/GPU/GLES/TextureCacheGLES.cpp +++ b/GPU/GLES/TextureCacheGLES.cpp @@ -130,7 +130,7 @@ void TextureCacheGLES::UpdateSamplingParams(TexCacheEntry &entry, bool force) { float maxLod = 0.0f; if (maxLevel != 0) { // TODO: What about a swap of autoMip mode? - if (force || entry.lodBias != lodBias) { + if (true) { if (mode == GE_TEXLEVEL_MODE_AUTO) { minLod = 0.0f; maxLod = (float)maxLevel; @@ -147,7 +147,6 @@ void TextureCacheGLES::UpdateSamplingParams(TexCacheEntry &entry, bool force) { minLod = 0.0f; maxLod = (float)maxLevel; } - entry.lodBias = lodBias; } } else { minLod = 0.0f; @@ -156,14 +155,8 @@ void TextureCacheGLES::UpdateSamplingParams(TexCacheEntry &entry, bool force) { render_->SetTextureLod(minLod, maxLod, lodBias); } - if (force || entry.minFilt != minFilt || entry.magFilt != magFilt || entry.sClamp != sClamp || entry.tClamp != tClamp) { - float aniso = 0.0f; - render_->SetTextureSampler(sClamp ? GL_CLAMP_TO_EDGE : GL_REPEAT, tClamp ? GL_CLAMP_TO_EDGE : GL_REPEAT, MagFiltGL[magFilt], MinFiltGL[minFilt], aniso); - entry.minFilt = minFilt; - entry.magFilt = magFilt; - entry.sClamp = sClamp; - entry.tClamp = tClamp; - } + float aniso = 0.0f; + render_->SetTextureSampler(sClamp ? GL_CLAMP_TO_EDGE : GL_REPEAT, tClamp ? GL_CLAMP_TO_EDGE : GL_REPEAT, MagFiltGL[magFilt], MinFiltGL[minFilt], aniso); CHECK_GL_ERROR_IF_DEBUG(); } diff --git a/ext/native/thin3d/GLQueueRunner.cpp b/ext/native/thin3d/GLQueueRunner.cpp index 8e02ffe1bd..872d7b03dd 100644 --- a/ext/native/thin3d/GLQueueRunner.cpp +++ b/ext/native/thin3d/GLQueueRunner.cpp @@ -409,8 +409,8 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step) { GLRFramebuffer *fb = step.render.framebuffer; GLRProgram *curProgram = nullptr; - int activeTexture = 0; - glActiveTexture(GL_TEXTURE0 + activeTexture); + int activeSlot = 0; + glActiveTexture(GL_TEXTURE0 + activeSlot); // State filtering tracking. int attrMask = 0; @@ -426,6 +426,8 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step) { GLuint blendEqColor = (GLuint)-1; GLuint blendEqAlpha = (GLuint)-1; + GLRTexture *curTex[8]{}; + auto &commands = step.commands; for (const auto &c : commands) { switch (c.cmd) { @@ -604,23 +606,27 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step) { case GLRRenderCommand::BINDTEXTURE: { GLint slot = c.texture.slot; - if (slot != activeTexture) { + if (slot != activeSlot) { glActiveTexture(GL_TEXTURE0 + slot); - activeTexture = slot; + activeSlot = slot; } if (c.texture.texture) { - glBindTexture(c.texture.texture->target, c.texture.texture->texture); + if (curTex[slot] != c.texture.texture) { + glBindTexture(c.texture.texture->target, c.texture.texture->texture); + curTex[slot] = c.texture.texture; + } } else { glBindTexture(GL_TEXTURE_2D, 0); // Which target? Well we only use this one anyway... + curTex[slot] = nullptr; } break; } case GLRRenderCommand::BIND_FB_TEXTURE: { GLint slot = c.bind_fb_texture.slot; - if (slot != activeTexture) { + if (slot != activeSlot) { glActiveTexture(GL_TEXTURE0 + slot); - activeTexture = slot; + activeSlot = slot; } if (c.bind_fb_texture.aspect == GL_COLOR_BUFFER_BIT) { glBindTexture(GL_TEXTURE_2D, c.bind_fb_texture.framebuffer->color_texture); @@ -695,21 +701,55 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step) { } break; case GLRRenderCommand::TEXTURESAMPLER: - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, c.textureSampler.wrapS); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, c.textureSampler.wrapT); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, c.textureSampler.magFilter); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, c.textureSampler.minFilter); - if (c.textureSampler.anisotropy != 0.0f) { + { + GLRTexture *tex = curTex[activeSlot]; + if (!tex) { + break; + } + if (tex->wrapS != c.textureSampler.wrapS) { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, c.textureSampler.wrapS); + tex->wrapS = c.textureSampler.wrapS; + } + if (tex->wrapT != c.textureSampler.wrapT) { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, c.textureSampler.wrapT); + tex->wrapT = c.textureSampler.wrapT; + } + if (tex->magFilter != c.textureSampler.magFilter) { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, c.textureSampler.magFilter); + tex->magFilter = c.textureSampler.magFilter; + } + if (tex->minFilter != c.textureSampler.minFilter) { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, c.textureSampler.minFilter); + tex->minFilter = c.textureSampler.minFilter; + } + if (tex->anisotropy != c.textureSampler.anisotropy) { glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, c.textureSampler.anisotropy); + tex->anisotropy = c.textureSampler.anisotropy; } break; + } case GLRRenderCommand::TEXTURELOD: - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_LOD, c.textureLod.minLod); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, c.textureLod.maxLod); + { + GLRTexture *tex = curTex[activeSlot]; + if (!tex) { + break; + } #ifndef USING_GLES2 - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_LOD_BIAS, c.textureLod.lodBias); + if (tex->lodBias != c.textureLod.lodBias) { + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_LOD_BIAS, c.textureLod.lodBias); + tex->lodBias = c.textureLod.lodBias; + } #endif + if (tex->minLod != c.textureLod.minLod) { + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_LOD, c.textureLod.minLod); + tex->minLod = c.textureLod.minLod; + } + if (tex->maxLod != c.textureLod.maxLod) { + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, c.textureLod.maxLod); + tex->maxLod = c.textureLod.maxLod; + } break; + } case GLRRenderCommand::RASTER: if (c.raster.cullEnable) { if (!cullEnabled) { @@ -744,7 +784,7 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step) { } } - if (activeTexture != 0) + if (activeSlot != 0) glActiveTexture(GL_TEXTURE0); // Wipe out the current state. diff --git a/ext/native/thin3d/GLRenderManager.h b/ext/native/thin3d/GLRenderManager.h index e712482ddf..6d0e44f0ca 100644 --- a/ext/native/thin3d/GLRenderManager.h +++ b/ext/native/thin3d/GLRenderManager.h @@ -111,9 +111,17 @@ public: glDeleteTextures(1, &texture); } } - GLuint texture; - GLenum target; - // TODO: Move sampler params here so we can move the dirty-tracking from TextureCacheGLES to here. + GLuint texture = 0; + // Could also trust OpenGL defaults I guess.. + GLenum target = 0xFFFF; + GLenum wrapS = 0xFFFF; + GLenum wrapT = 0xFFFF; + GLenum magFilter = 0xFFFF; + GLenum minFilter = 0xFFFF; + float anisotropy = -100000.0f; + float minLod = -100000.0f; + float maxLod = 100000.0f; + float lodBias = 0.0f; }; class GLRBuffer {