Merge pull request #1023 from yuriks/gl-state-bugs
OpenGL: Fix state tracking in situations with reused object handles
This commit is contained in:
		| @@ -99,7 +99,6 @@ void RasterizerOpenGL::InitObjects() { | |||||||
|     fb_color_texture.texture.Create(); |     fb_color_texture.texture.Create(); | ||||||
|     ReconfigureColorTexture(fb_color_texture, Pica::Regs::ColorFormat::RGBA8, 1, 1); |     ReconfigureColorTexture(fb_color_texture, Pica::Regs::ColorFormat::RGBA8, 1, 1); | ||||||
|  |  | ||||||
|     state.texture_units[0].enabled_2d = true; |  | ||||||
|     state.texture_units[0].texture_2d = fb_color_texture.texture.handle; |     state.texture_units[0].texture_2d = fb_color_texture.texture.handle; | ||||||
|     state.Apply(); |     state.Apply(); | ||||||
|  |  | ||||||
| @@ -115,7 +114,6 @@ void RasterizerOpenGL::InitObjects() { | |||||||
|     fb_depth_texture.texture.Create(); |     fb_depth_texture.texture.Create(); | ||||||
|     ReconfigureDepthTexture(fb_depth_texture, Pica::Regs::DepthFormat::D16, 1, 1); |     ReconfigureDepthTexture(fb_depth_texture, Pica::Regs::DepthFormat::D16, 1, 1); | ||||||
|  |  | ||||||
|     state.texture_units[0].enabled_2d = true; |  | ||||||
|     state.texture_units[0].texture_2d = fb_depth_texture.texture.handle; |     state.texture_units[0].texture_2d = fb_depth_texture.texture.handle; | ||||||
|     state.Apply(); |     state.Apply(); | ||||||
|  |  | ||||||
| @@ -493,7 +491,6 @@ void RasterizerOpenGL::ReconfigureColorTexture(TextureInfo& texture, Pica::Regs: | |||||||
|         break; |         break; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     state.texture_units[0].enabled_2d = true; |  | ||||||
|     state.texture_units[0].texture_2d = texture.texture.handle; |     state.texture_units[0].texture_2d = texture.texture.handle; | ||||||
|     state.Apply(); |     state.Apply(); | ||||||
|  |  | ||||||
| @@ -537,7 +534,6 @@ void RasterizerOpenGL::ReconfigureDepthTexture(DepthTextureInfo& texture, Pica:: | |||||||
|         break; |         break; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     state.texture_units[0].enabled_2d = true; |  | ||||||
|     state.texture_units[0].texture_2d = texture.texture.handle; |     state.texture_units[0].texture_2d = texture.texture.handle; | ||||||
|     state.Apply(); |     state.Apply(); | ||||||
|  |  | ||||||
| @@ -766,10 +762,9 @@ void RasterizerOpenGL::SyncDrawState() { | |||||||
|         const auto& texture = pica_textures[texture_index]; |         const auto& texture = pica_textures[texture_index]; | ||||||
|  |  | ||||||
|         if (texture.enabled) { |         if (texture.enabled) { | ||||||
|             state.texture_units[texture_index].enabled_2d = true; |  | ||||||
|             res_cache.LoadAndBindTexture(state, texture_index, texture); |             res_cache.LoadAndBindTexture(state, texture_index, texture); | ||||||
|         } else { |         } else { | ||||||
|             state.texture_units[texture_index].enabled_2d = false; |             state.texture_units[texture_index].texture_2d = 0; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -804,7 +799,6 @@ void RasterizerOpenGL::ReloadColorBuffer() { | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     state.texture_units[0].enabled_2d = true; |  | ||||||
|     state.texture_units[0].texture_2d = fb_color_texture.texture.handle; |     state.texture_units[0].texture_2d = fb_color_texture.texture.handle; | ||||||
|     state.Apply(); |     state.Apply(); | ||||||
|  |  | ||||||
| @@ -862,7 +856,6 @@ void RasterizerOpenGL::ReloadDepthBuffer() { | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     state.texture_units[0].enabled_2d = true; |  | ||||||
|     state.texture_units[0].texture_2d = fb_depth_texture.texture.handle; |     state.texture_units[0].texture_2d = fb_depth_texture.texture.handle; | ||||||
|     state.Apply(); |     state.Apply(); | ||||||
|  |  | ||||||
| @@ -887,7 +880,6 @@ void RasterizerOpenGL::CommitColorBuffer() { | |||||||
|  |  | ||||||
|             std::unique_ptr<u8[]> temp_gl_color_buffer(new u8[fb_color_texture.width * fb_color_texture.height * bytes_per_pixel]); |             std::unique_ptr<u8[]> temp_gl_color_buffer(new u8[fb_color_texture.width * fb_color_texture.height * bytes_per_pixel]); | ||||||
|  |  | ||||||
|             state.texture_units[0].enabled_2d = true; |  | ||||||
|             state.texture_units[0].texture_2d = fb_color_texture.texture.handle; |             state.texture_units[0].texture_2d = fb_color_texture.texture.handle; | ||||||
|             state.Apply(); |             state.Apply(); | ||||||
|  |  | ||||||
| @@ -927,7 +919,6 @@ void RasterizerOpenGL::CommitDepthBuffer() { | |||||||
|  |  | ||||||
|             std::unique_ptr<u8[]> temp_gl_depth_buffer(new u8[fb_depth_texture.width * fb_depth_texture.height * gl_bpp]); |             std::unique_ptr<u8[]> temp_gl_depth_buffer(new u8[fb_depth_texture.width * fb_depth_texture.height * gl_bpp]); | ||||||
|  |  | ||||||
|             state.texture_units[0].enabled_2d = true; |  | ||||||
|             state.texture_units[0].texture_2d = fb_depth_texture.texture.handle; |             state.texture_units[0].texture_2d = fb_depth_texture.texture.handle; | ||||||
|             state.Apply(); |             state.Apply(); | ||||||
|  |  | ||||||
|   | |||||||
| @@ -30,6 +30,7 @@ void RasterizerCacheOpenGL::LoadAndBindTexture(OpenGLState &state, unsigned text | |||||||
|         new_texture->texture.Create(); |         new_texture->texture.Create(); | ||||||
|         state.texture_units[texture_unit].texture_2d = new_texture->texture.handle; |         state.texture_units[texture_unit].texture_2d = new_texture->texture.handle; | ||||||
|         state.Apply(); |         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_MAG_FILTER, PicaToGL::TextureFilterMode(config.config.mag_filter)); | ||||||
|         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, PicaToGL::TextureFilterMode(config.config.min_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/generated/gl_3_2_core.h" | ||||||
| #include "video_core/renderer_opengl/gl_shader_util.h" | #include "video_core/renderer_opengl/gl_shader_util.h" | ||||||
|  | #include "video_core/renderer_opengl/gl_state.h" | ||||||
|  |  | ||||||
| class OGLTexture : private NonCopyable { | class OGLTexture : private NonCopyable { | ||||||
| public: | public: | ||||||
| @@ -28,6 +29,7 @@ public: | |||||||
|     void Release() { |     void Release() { | ||||||
|         if (handle == 0) return; |         if (handle == 0) return; | ||||||
|         glDeleteTextures(1, &handle); |         glDeleteTextures(1, &handle); | ||||||
|  |         OpenGLState::ResetTexture(handle); | ||||||
|         handle = 0; |         handle = 0; | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -51,6 +53,7 @@ public: | |||||||
|     void Release() { |     void Release() { | ||||||
|         if (handle == 0) return; |         if (handle == 0) return; | ||||||
|         glDeleteProgram(handle); |         glDeleteProgram(handle); | ||||||
|  |         OpenGLState::ResetProgram(handle); | ||||||
|         handle = 0; |         handle = 0; | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -74,6 +77,7 @@ public: | |||||||
|     void Release() { |     void Release() { | ||||||
|         if (handle == 0) return; |         if (handle == 0) return; | ||||||
|         glDeleteBuffers(1, &handle); |         glDeleteBuffers(1, &handle); | ||||||
|  |         OpenGLState::ResetBuffer(handle); | ||||||
|         handle = 0; |         handle = 0; | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -97,6 +101,7 @@ public: | |||||||
|     void Release() { |     void Release() { | ||||||
|         if (handle == 0) return; |         if (handle == 0) return; | ||||||
|         glDeleteVertexArrays(1, &handle); |         glDeleteVertexArrays(1, &handle); | ||||||
|  |         OpenGLState::ResetVertexArray(handle); | ||||||
|         handle = 0; |         handle = 0; | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -120,6 +125,7 @@ public: | |||||||
|     void Release() { |     void Release() { | ||||||
|         if (handle == 0) return; |         if (handle == 0) return; | ||||||
|         glDeleteFramebuffers(1, &handle); |         glDeleteFramebuffers(1, &handle); | ||||||
|  |         OpenGLState::ResetFramebuffer(handle); | ||||||
|         handle = 0; |         handle = 0; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -40,7 +40,6 @@ OpenGLState::OpenGLState() { | |||||||
|     logic_op = GL_COPY; |     logic_op = GL_COPY; | ||||||
|  |  | ||||||
|     for (auto& texture_unit : texture_units) { |     for (auto& texture_unit : texture_units) { | ||||||
|         texture_unit.enabled_2d = false; |  | ||||||
|         texture_unit.texture_2d = 0; |         texture_unit.texture_2d = 0; | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -147,16 +146,9 @@ void OpenGLState::Apply() { | |||||||
|  |  | ||||||
|     // Textures |     // Textures | ||||||
|     for (unsigned texture_index = 0; texture_index < ARRAY_SIZE(texture_units); ++texture_index) { |     for (unsigned texture_index = 0; texture_index < ARRAY_SIZE(texture_units); ++texture_index) { | ||||||
|         if (texture_units[texture_index].enabled_2d != cur_state.texture_units[texture_index].enabled_2d || |         if (texture_units[texture_index].texture_2d != cur_state.texture_units[texture_index].texture_2d) { | ||||||
|             texture_units[texture_index].texture_2d != cur_state.texture_units[texture_index].texture_2d) { |  | ||||||
|  |  | ||||||
|             glActiveTexture(GL_TEXTURE0 + texture_index); |             glActiveTexture(GL_TEXTURE0 + texture_index); | ||||||
|  |             glBindTexture(GL_TEXTURE_2D, texture_units[texture_index].texture_2d); | ||||||
|             if (texture_units[texture_index].enabled_2d) { |  | ||||||
|                 glBindTexture(GL_TEXTURE_2D, texture_units[texture_index].texture_2d); |  | ||||||
|             } else { |  | ||||||
|                 glBindTexture(GL_TEXTURE_2D, 0); |  | ||||||
|             } |  | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -182,3 +174,35 @@ void OpenGLState::Apply() { | |||||||
|  |  | ||||||
|     cur_state = *this; |     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; | ||||||
|  |     } | ||||||
|  | } | ||||||
|   | |||||||
| @@ -53,7 +53,6 @@ public: | |||||||
|  |  | ||||||
|     // 3 texture units - one for each that is used in PICA fragment shader emulation |     // 3 texture units - one for each that is used in PICA fragment shader emulation | ||||||
|     struct { |     struct { | ||||||
|         bool enabled_2d; // GL_TEXTURE_2D |  | ||||||
|         GLuint texture_2d; // GL_TEXTURE_BINDING_2D |         GLuint texture_2d; // GL_TEXTURE_BINDING_2D | ||||||
|     } texture_units[3]; |     } texture_units[3]; | ||||||
|  |  | ||||||
| @@ -74,6 +73,12 @@ public: | |||||||
|     /// Apply this state as the current OpenGL state |     /// Apply this state as the current OpenGL state | ||||||
|     void Apply(); |     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: | private: | ||||||
|     static OpenGLState cur_state; |     static OpenGLState cur_state; | ||||||
| }; | }; | ||||||
|   | |||||||
| @@ -163,7 +163,6 @@ void RendererOpenGL::LoadFBToActiveGLTexture(const GPU::Regs::FramebufferConfig& | |||||||
|     // only allows rows to have a memory alignement of 4. |     // only allows rows to have a memory alignement of 4. | ||||||
|     ASSERT(pixel_stride % 4 == 0); |     ASSERT(pixel_stride % 4 == 0); | ||||||
|  |  | ||||||
|     state.texture_units[0].enabled_2d = true; |  | ||||||
|     state.texture_units[0].texture_2d = texture.handle; |     state.texture_units[0].texture_2d = texture.handle; | ||||||
|     state.Apply(); |     state.Apply(); | ||||||
|  |  | ||||||
| @@ -191,7 +190,6 @@ void RendererOpenGL::LoadFBToActiveGLTexture(const GPU::Regs::FramebufferConfig& | |||||||
|  */ |  */ | ||||||
| void RendererOpenGL::LoadColorToActiveGLTexture(u8 color_r, u8 color_g, u8 color_b, | void RendererOpenGL::LoadColorToActiveGLTexture(u8 color_r, u8 color_g, u8 color_b, | ||||||
|                                                 const TextureInfo& texture) { |                                                 const TextureInfo& texture) { | ||||||
|     state.texture_units[0].enabled_2d = true; |  | ||||||
|     state.texture_units[0].texture_2d = texture.handle; |     state.texture_units[0].texture_2d = texture.handle; | ||||||
|     state.Apply(); |     state.Apply(); | ||||||
|  |  | ||||||
| @@ -239,7 +237,6 @@ void RendererOpenGL::InitOpenGLObjects() { | |||||||
|         // Allocation of storage is deferred until the first frame, when we |         // Allocation of storage is deferred until the first frame, when we | ||||||
|         // know the framebuffer size. |         // know the framebuffer size. | ||||||
|  |  | ||||||
|         state.texture_units[0].enabled_2d = true; |  | ||||||
|         state.texture_units[0].texture_2d = texture.handle; |         state.texture_units[0].texture_2d = texture.handle; | ||||||
|         state.Apply(); |         state.Apply(); | ||||||
|  |  | ||||||
| @@ -305,7 +302,6 @@ void RendererOpenGL::ConfigureFramebufferTexture(TextureInfo& texture, | |||||||
|         UNIMPLEMENTED(); |         UNIMPLEMENTED(); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     state.texture_units[0].enabled_2d = true; |  | ||||||
|     state.texture_units[0].texture_2d = texture.handle; |     state.texture_units[0].texture_2d = texture.handle; | ||||||
|     state.Apply(); |     state.Apply(); | ||||||
|  |  | ||||||
| @@ -325,7 +321,6 @@ void RendererOpenGL::DrawSingleScreenRotated(const TextureInfo& texture, float x | |||||||
|         ScreenRectVertex(x+w, y+h, 0.f, 1.f), |         ScreenRectVertex(x+w, y+h, 0.f, 1.f), | ||||||
|     }; |     }; | ||||||
|  |  | ||||||
|     state.texture_units[0].enabled_2d = true; |  | ||||||
|     state.texture_units[0].texture_2d = texture.handle; |     state.texture_units[0].texture_2d = texture.handle; | ||||||
|     state.Apply(); |     state.Apply(); | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user