diff --git a/src/video_core/renderer_opengl/gl_resource_manager.h b/src/video_core/renderer_opengl/gl_resource_manager.h index 68fc1e6d3..65034d40d 100644 --- a/src/video_core/renderer_opengl/gl_resource_manager.h +++ b/src/video_core/renderer_opengl/gl_resource_manager.h @@ -37,6 +37,30 @@ public: GLuint handle = 0; }; +class OGLSampler : private NonCopyable { +public: + OGLSampler() = default; + OGLSampler(OGLSampler&& o) { std::swap(handle, o.handle); } + ~OGLSampler() { Release(); } + OGLSampler& operator=(OGLSampler&& o) { std::swap(handle, o.handle); return *this; } + + /// Creates a new internal OpenGL resource and stores the handle + void Create() { + if (handle != 0) return; + glGenSamplers(1, &handle); + } + + /// Deletes the internal OpenGL resource + void Release() { + if (handle == 0) return; + glDeleteSamplers(1, &handle); + OpenGLState::ResetSampler(handle); + handle = 0; + } + + GLuint handle = 0; +}; + class OGLShader : private NonCopyable { public: OGLShader() = default; diff --git a/src/video_core/renderer_opengl/gl_state.cpp b/src/video_core/renderer_opengl/gl_state.cpp index ba47ce8b8..e02c27fbf 100644 --- a/src/video_core/renderer_opengl/gl_state.cpp +++ b/src/video_core/renderer_opengl/gl_state.cpp @@ -44,6 +44,7 @@ OpenGLState::OpenGLState() { for (auto& texture_unit : texture_units) { texture_unit.texture_2d = 0; + texture_unit.sampler = 0; } draw.framebuffer = 0; @@ -154,10 +155,13 @@ void OpenGLState::Apply() { } // Textures - for (unsigned texture_index = 0; texture_index < ARRAY_SIZE(texture_units); ++texture_index) { - if (texture_units[texture_index].texture_2d != cur_state.texture_units[texture_index].texture_2d) { - glActiveTexture(GL_TEXTURE0 + texture_index); - glBindTexture(GL_TEXTURE_2D, texture_units[texture_index].texture_2d); + for (unsigned i = 0; i < ARRAY_SIZE(texture_units); ++i) { + if (texture_units[i].texture_2d != cur_state.texture_units[i].texture_2d) { + glActiveTexture(GL_TEXTURE0 + i); + glBindTexture(GL_TEXTURE_2D, texture_units[i].texture_2d); + } + if (texture_units[i].sampler != cur_state.texture_units[i].sampler) { + glBindSampler(i, texture_units[i].sampler); } } @@ -192,6 +196,14 @@ void OpenGLState::ResetTexture(GLuint id) { } } +void OpenGLState::ResetSampler(GLuint id) { + for (auto& unit : cur_state.texture_units) { + if (unit.sampler == id) { + unit.sampler = 0; + } + } +} + void OpenGLState::ResetProgram(GLuint id) { if (cur_state.draw.shader_program == id) { cur_state.draw.shader_program = 0; diff --git a/src/video_core/renderer_opengl/gl_state.h b/src/video_core/renderer_opengl/gl_state.h index 43aa29a81..6ecbedbb4 100644 --- a/src/video_core/renderer_opengl/gl_state.h +++ b/src/video_core/renderer_opengl/gl_state.h @@ -57,6 +57,7 @@ public: // 3 texture units - one for each that is used in PICA fragment shader emulation struct { GLuint texture_2d; // GL_TEXTURE_BINDING_2D + GLuint sampler; // GL_SAMPLER_BINDING } texture_units[3]; struct { @@ -77,6 +78,7 @@ public: void Apply(); static void ResetTexture(GLuint id); + static void ResetSampler(GLuint id); static void ResetProgram(GLuint id); static void ResetBuffer(GLuint id); static void ResetVertexArray(GLuint id);