From c4fc141ced900bfa73b06155e5e566df131e2f67 Mon Sep 17 00:00:00 2001 From: degasus Date: Fri, 29 May 2015 00:53:07 +0200 Subject: [PATCH] OGL: Always use sampler objects. We are used to use the texture parameter for all util draw calls, but AMD seems to have a bug where they use the sampler parameter of stage 0 if no sampler is bound to the used stage. So as workaround (and a bit as nicer code), we now use sampler objects everywhere. --- .../VideoBackends/OGL/FramebufferManager.cpp | 12 ++-------- .../Core/VideoBackends/OGL/PostProcessing.cpp | 4 ++-- .../Core/VideoBackends/OGL/SamplerCache.cpp | 23 ++++++++++++++++++- Source/Core/VideoBackends/OGL/SamplerCache.h | 3 +++ .../Core/VideoBackends/OGL/TextureCache.cpp | 8 ++++++- .../VideoBackends/OGL/TextureConverter.cpp | 12 ++++------ 6 files changed, 40 insertions(+), 22 deletions(-) diff --git a/Source/Core/VideoBackends/OGL/FramebufferManager.cpp b/Source/Core/VideoBackends/OGL/FramebufferManager.cpp index 784e424c29..839f91ad39 100644 --- a/Source/Core/VideoBackends/OGL/FramebufferManager.cpp +++ b/Source/Core/VideoBackends/OGL/FramebufferManager.cpp @@ -7,6 +7,7 @@ #include "VideoBackends/OGL/FramebufferManager.h" #include "VideoBackends/OGL/Render.h" +#include "VideoBackends/OGL/SamplerCache.h" #include "VideoBackends/OGL/TextureConverter.h" #include "VideoCommon/DriverDetails.h" @@ -85,20 +86,14 @@ FramebufferManager::FramebufferManager(int targetWidth, int targetHeight, int ms glBindTexture(m_textureType, m_efbColor); glTexParameteri(m_textureType, GL_TEXTURE_MAX_LEVEL, 0); - glTexParameteri(m_textureType, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(m_textureType, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexImage3D(m_textureType, 0, GL_RGBA, m_targetWidth, m_targetHeight, m_EFBLayers, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); glBindTexture(m_textureType, m_efbDepth); glTexParameteri(m_textureType, GL_TEXTURE_MAX_LEVEL, 0); - glTexParameteri(m_textureType, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(m_textureType, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexImage3D(m_textureType, 0, GL_DEPTH_COMPONENT24, m_targetWidth, m_targetHeight, m_EFBLayers, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, nullptr); glBindTexture(m_textureType, m_efbColorSwap); glTexParameteri(m_textureType, GL_TEXTURE_MAX_LEVEL, 0); - glTexParameteri(m_textureType, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(m_textureType, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexImage3D(m_textureType, 0, GL_RGBA, m_targetWidth, m_targetHeight, m_EFBLayers, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); } else @@ -146,14 +141,10 @@ FramebufferManager::FramebufferManager(int targetWidth, int targetHeight, int ms glBindTexture(resolvedType, m_resolvedColorTexture); glTexParameteri(resolvedType, GL_TEXTURE_MAX_LEVEL, 0); - glTexParameteri(resolvedType, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(resolvedType, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexImage3D(resolvedType, 0, GL_RGBA, m_targetWidth, m_targetHeight, m_EFBLayers, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); glBindTexture(resolvedType, m_resolvedDepthTexture); glTexParameteri(resolvedType, GL_TEXTURE_MAX_LEVEL, 0); - glTexParameteri(resolvedType, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(resolvedType, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexImage3D(resolvedType, 0, GL_DEPTH_COMPONENT24, m_targetWidth, m_targetHeight, m_EFBLayers, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, nullptr); // Bind resolved textures to resolved framebuffer. @@ -542,6 +533,7 @@ void FramebufferManager::ReinterpretPixelData(unsigned int convtype) glViewport(0,0, m_targetWidth, m_targetHeight); glActiveTexture(GL_TEXTURE9); glBindTexture(m_textureType, src_texture); + g_sampler_cache->BindNearestSampler(9); m_pixel_format_shaders[convtype ? 1 : 0].Bind(); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); diff --git a/Source/Core/VideoBackends/OGL/PostProcessing.cpp b/Source/Core/VideoBackends/OGL/PostProcessing.cpp index 92ca734398..b6715ff0ff 100644 --- a/Source/Core/VideoBackends/OGL/PostProcessing.cpp +++ b/Source/Core/VideoBackends/OGL/PostProcessing.cpp @@ -10,6 +10,7 @@ #include "VideoBackends/OGL/GLUtil.h" #include "VideoBackends/OGL/PostProcessing.h" #include "VideoBackends/OGL/ProgramShaderCache.h" +#include "VideoBackends/OGL/SamplerCache.h" #include "VideoCommon/DriverDetails.h" #include "VideoCommon/VideoCommon.h" @@ -154,8 +155,7 @@ void OpenGLPostProcessing::BlitFromTexture(TargetRectangle src, TargetRectangle glActiveTexture(GL_TEXTURE9); glBindTexture(GL_TEXTURE_2D_ARRAY, src_texture); - glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + g_sampler_cache->BindLinearSampler(9); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); } diff --git a/Source/Core/VideoBackends/OGL/SamplerCache.cpp b/Source/Core/VideoBackends/OGL/SamplerCache.cpp index 16c4ea8d48..3fad7f04b0 100644 --- a/Source/Core/VideoBackends/OGL/SamplerCache.cpp +++ b/Source/Core/VideoBackends/OGL/SamplerCache.cpp @@ -13,11 +13,32 @@ SamplerCache *g_sampler_cache; SamplerCache::SamplerCache() : m_last_max_anisotropy() -{} +{ + glGenSamplers(2, m_sampler_id); + glSamplerParameteri(m_sampler_id[0], GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glSamplerParameteri(m_sampler_id[0], GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glSamplerParameteri(m_sampler_id[0], GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glSamplerParameteri(m_sampler_id[0], GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glSamplerParameteri(m_sampler_id[1], GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glSamplerParameteri(m_sampler_id[1], GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glSamplerParameteri(m_sampler_id[1], GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glSamplerParameteri(m_sampler_id[1], GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); +} SamplerCache::~SamplerCache() { Clear(); + glDeleteSamplers(2, m_sampler_id); +} + +void SamplerCache::BindNearestSampler(int stage) +{ + glBindSampler(stage, m_sampler_id[0]); +} + +void SamplerCache::BindLinearSampler(int stage) +{ + glBindSampler(stage, m_sampler_id[1]); } void SamplerCache::SetSamplerState(int stage, const TexMode0& tm0, const TexMode1& tm1, bool custom_tex) diff --git a/Source/Core/VideoBackends/OGL/SamplerCache.h b/Source/Core/VideoBackends/OGL/SamplerCache.h index a970fff8f8..ec469a81da 100644 --- a/Source/Core/VideoBackends/OGL/SamplerCache.h +++ b/Source/Core/VideoBackends/OGL/SamplerCache.h @@ -20,6 +20,8 @@ public: void SetSamplerState(int stage, const TexMode0& tm0, const TexMode1& tm1, bool custom_tex); void Clear(); + void BindNearestSampler(int stage); + void BindLinearSampler(int stage); private: struct Params @@ -73,6 +75,7 @@ private: std::pair m_active_samplers[8]; int m_last_max_anisotropy; + u32 m_sampler_id[2]; }; extern SamplerCache *g_sampler_cache; diff --git a/Source/Core/VideoBackends/OGL/TextureCache.cpp b/Source/Core/VideoBackends/OGL/TextureCache.cpp index fd55258838..0256b303e7 100644 --- a/Source/Core/VideoBackends/OGL/TextureCache.cpp +++ b/Source/Core/VideoBackends/OGL/TextureCache.cpp @@ -18,6 +18,7 @@ #include "VideoBackends/OGL/GLInterfaceBase.h" #include "VideoBackends/OGL/ProgramShaderCache.h" #include "VideoBackends/OGL/Render.h" +#include "VideoBackends/OGL/SamplerCache.h" #include "VideoBackends/OGL/StreamBuffer.h" #include "VideoBackends/OGL/TextureCache.h" #include "VideoBackends/OGL/TextureConverter.h" @@ -61,7 +62,6 @@ bool SaveTexture(const std::string& filename, u32 textarget, u32 tex, int virtua glActiveTexture(GL_TEXTURE9); glBindTexture(textarget, tex); glGetTexImage(textarget, level, GL_RGBA, GL_UNSIGNED_BYTE, data.data()); - glBindTexture(textarget, 0); TextureCache::SetStage(); return TextureToPng(data.data(), width * 4, filename, width, height, true); @@ -178,6 +178,10 @@ void TextureCache::TCacheEntry::FromRenderTarget(u32 dstAddr, unsigned int dstFo glActiveTexture(GL_TEXTURE9); glBindTexture(GL_TEXTURE_2D_ARRAY, read_texture); + if (scaleByHalf) + g_sampler_cache->BindLinearSampler(9); + else + g_sampler_cache->BindNearestSampler(9); glViewport(0, 0, config.width, config.height); @@ -489,6 +493,7 @@ void TextureCache::ConvertTexture(TCacheEntryBase* _entry, TCacheEntryBase* _unc glActiveTexture(GL_TEXTURE9); glBindTexture(GL_TEXTURE_2D_ARRAY, unconverted->texture); + g_sampler_cache->BindNearestSampler(9); FramebufferManager::SetFramebuffer(entry->framebuffer); glViewport(0, 0, entry->config.width, entry->config.height); @@ -504,6 +509,7 @@ void TextureCache::ConvertTexture(TCacheEntryBase* _entry, TCacheEntryBase* _unc glActiveTexture(GL_TEXTURE10); glBindTexture(GL_TEXTURE_BUFFER, s_palette_resolv_texture); + g_sampler_cache->BindNearestSampler(10); OpenGL_BindAttributelessVAO(); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); diff --git a/Source/Core/VideoBackends/OGL/TextureConverter.cpp b/Source/Core/VideoBackends/OGL/TextureConverter.cpp index 62c74e7b95..c696ccf687 100644 --- a/Source/Core/VideoBackends/OGL/TextureConverter.cpp +++ b/Source/Core/VideoBackends/OGL/TextureConverter.cpp @@ -14,6 +14,7 @@ #include "VideoBackends/OGL/FramebufferManager.h" #include "VideoBackends/OGL/ProgramShaderCache.h" #include "VideoBackends/OGL/Render.h" +#include "VideoBackends/OGL/SamplerCache.h" #include "VideoBackends/OGL/TextureCache.h" #include "VideoBackends/OGL/TextureConverter.h" @@ -229,15 +230,9 @@ static void EncodeToRamUsingShader(GLuint srcTexture, glBindTexture(GL_TEXTURE_2D_ARRAY, srcTexture); if (linearFilter) - { - glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - } + g_sampler_cache->BindLinearSampler(9); else - { - glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - } + g_sampler_cache->BindNearestSampler(9); glViewport(0, 0, (GLsizei)dstWidth, (GLsizei)dstHeight); @@ -377,6 +372,7 @@ void DecodeToTexture(u32 xfbAddr, int srcWidth, int srcHeight, GLuint destTextur glActiveTexture(GL_TEXTURE9); glBindTexture(GL_TEXTURE_2D, s_srcTexture); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, srcWidth / 2, srcHeight, 0, GL_BGRA, GL_UNSIGNED_BYTE, srcAddr); + g_sampler_cache->BindNearestSampler(9); glViewport(0, 0, srcWidth, srcHeight); s_yuyvToRgbProgram.Bind();