OpenGL: Fix state tracking in situations with reused object handles
If an OpenGL object is created, bound to a binding using the state tracker, and then destroyed, a newly created object can be assigned the same numeric handle by OpenGL. However, even though it is a new object, and thus needs to be bound to the binding again, the state tracker compared the current and previous handles and concluded that no change needed to be made, leading to failure to bind objects in certain cases. This manifested as broken text in VVVVVV, which this commit fixes along with similar texturing problems in other games.
This commit is contained in:
parent
ff68db61bc
commit
254582aa35
|
@ -30,6 +30,7 @@ void RasterizerCacheOpenGL::LoadAndBindTexture(OpenGLState &state, unsigned text
|
|||
new_texture->texture.Create();
|
||||
state.texture_units[texture_unit].texture_2d = new_texture->texture.handle;
|
||||
state.Apply();
|
||||
glActiveTexture(GL_TEXTURE0 + texture_unit);
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, PicaToGL::TextureFilterMode(config.config.mag_filter));
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, PicaToGL::TextureFilterMode(config.config.min_filter));
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
|
||||
#include "video_core/renderer_opengl/generated/gl_3_2_core.h"
|
||||
#include "video_core/renderer_opengl/gl_shader_util.h"
|
||||
#include "video_core/renderer_opengl/gl_state.h"
|
||||
|
||||
class OGLTexture : private NonCopyable {
|
||||
public:
|
||||
|
@ -28,6 +29,7 @@ public:
|
|||
void Release() {
|
||||
if (handle == 0) return;
|
||||
glDeleteTextures(1, &handle);
|
||||
OpenGLState::ResetTexture(handle);
|
||||
handle = 0;
|
||||
}
|
||||
|
||||
|
@ -51,6 +53,7 @@ public:
|
|||
void Release() {
|
||||
if (handle == 0) return;
|
||||
glDeleteProgram(handle);
|
||||
OpenGLState::ResetProgram(handle);
|
||||
handle = 0;
|
||||
}
|
||||
|
||||
|
@ -74,6 +77,7 @@ public:
|
|||
void Release() {
|
||||
if (handle == 0) return;
|
||||
glDeleteBuffers(1, &handle);
|
||||
OpenGLState::ResetBuffer(handle);
|
||||
handle = 0;
|
||||
}
|
||||
|
||||
|
@ -97,6 +101,7 @@ public:
|
|||
void Release() {
|
||||
if (handle == 0) return;
|
||||
glDeleteVertexArrays(1, &handle);
|
||||
OpenGLState::ResetVertexArray(handle);
|
||||
handle = 0;
|
||||
}
|
||||
|
||||
|
@ -120,6 +125,7 @@ public:
|
|||
void Release() {
|
||||
if (handle == 0) return;
|
||||
glDeleteFramebuffers(1, &handle);
|
||||
OpenGLState::ResetFramebuffer(handle);
|
||||
handle = 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -174,3 +174,35 @@ void OpenGLState::Apply() {
|
|||
|
||||
cur_state = *this;
|
||||
}
|
||||
|
||||
void OpenGLState::ResetTexture(GLuint id) {
|
||||
for (auto& unit : cur_state.texture_units) {
|
||||
if (unit.texture_2d == id) {
|
||||
unit.texture_2d = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void OpenGLState::ResetProgram(GLuint id) {
|
||||
if (cur_state.draw.shader_program == id) {
|
||||
cur_state.draw.shader_program = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void OpenGLState::ResetBuffer(GLuint id) {
|
||||
if (cur_state.draw.vertex_buffer == id) {
|
||||
cur_state.draw.vertex_buffer = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void OpenGLState::ResetVertexArray(GLuint id) {
|
||||
if (cur_state.draw.vertex_array == id) {
|
||||
cur_state.draw.vertex_array = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void OpenGLState::ResetFramebuffer(GLuint id) {
|
||||
if (cur_state.draw.framebuffer == id) {
|
||||
cur_state.draw.framebuffer = 0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -73,6 +73,12 @@ public:
|
|||
/// Apply this state as the current OpenGL state
|
||||
void Apply();
|
||||
|
||||
static void ResetTexture(GLuint id);
|
||||
static void ResetProgram(GLuint id);
|
||||
static void ResetBuffer(GLuint id);
|
||||
static void ResetVertexArray(GLuint id);
|
||||
static void ResetFramebuffer(GLuint id);
|
||||
|
||||
private:
|
||||
static OpenGLState cur_state;
|
||||
};
|
||||
|
|
Reference in New Issue