diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index c8eed05f2..2d471f3de 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp @@ -91,7 +91,7 @@ RasterizerOpenGL::RasterizerOpenGL() : shader_dirty(true) { for (size_t i = 0; i < lighting_luts.size(); ++i) { lighting_luts[i].Create(); state.SetActiveTextureUnit(GL_TEXTURE3 + i); - state.SetLUTTexture1D(lighting_luts[i].handle); + state.SetTexture1D(lighting_luts[i].handle); glTexImage1D(GL_TEXTURE_1D, 0, GL_RGBA32F, 256, 0, GL_RGBA, GL_FLOAT, nullptr); glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); @@ -166,7 +166,7 @@ void RasterizerOpenGL::DrawTriangles() { bool has_stencil = regs.framebuffer.depth_format == Pica::Regs::DepthFormat::D24S8; glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_TEXTURE_2D, (has_stencil && depth_surface != nullptr) ? depth_surface->texture.handle : 0, 0); - if (OpenGLState::CheckFBStatus(GL_DRAW_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { + if (OpenGLState::CheckBoundFBStatus(GL_DRAW_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { return; } @@ -616,13 +616,12 @@ bool RasterizerOpenGL::AccelerateFill(const GPU::Regs::MemoryFillConfig& config) utility_state.MakeCurrent(); utility_state.SetDrawFramebuffer(framebuffer.handle); - // TODO: When scissor test is implemented, need to disable scissor test in the state here so Clear call isn't affected if (dst_type == SurfaceType::Color || dst_type == SurfaceType::Texture) { glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, dst_surface->texture.handle, 0); glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, 0, 0); - if (OpenGLState::CheckFBStatus(GL_DRAW_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { + if (OpenGLState::CheckBoundFBStatus(GL_DRAW_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { old_state->MakeCurrent(); return false; } @@ -707,7 +706,7 @@ bool RasterizerOpenGL::AccelerateFill(const GPU::Regs::MemoryFillConfig& config) glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, dst_surface->texture.handle, 0); glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_TEXTURE_2D, 0, 0); - if (OpenGLState::CheckFBStatus(GL_DRAW_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { + if (OpenGLState::CheckBoundFBStatus(GL_DRAW_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { old_state->MakeCurrent(); return false; } @@ -725,7 +724,7 @@ bool RasterizerOpenGL::AccelerateFill(const GPU::Regs::MemoryFillConfig& config) glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0); glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, dst_surface->texture.handle, 0); - if (OpenGLState::CheckFBStatus(GL_DRAW_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { + if (OpenGLState::CheckBoundFBStatus(GL_DRAW_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { old_state->MakeCurrent(); return false; } diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp index 536a5b6d7..5f2c79844 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp @@ -145,12 +145,12 @@ bool RasterizerCacheOpenGL::BlitTextures(GLuint src_tex, GLuint dst_tex, CachedS buffers = GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT; } - if (OpenGLState::CheckFBStatus(GL_READ_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { + if (OpenGLState::CheckBoundFBStatus(GL_READ_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { old_state->MakeCurrent(); return false; } - if (OpenGLState::CheckFBStatus(GL_DRAW_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { + if (OpenGLState::CheckBoundFBStatus(GL_DRAW_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { old_state->MakeCurrent(); return false; } diff --git a/src/video_core/renderer_opengl/gl_state.cpp b/src/video_core/renderer_opengl/gl_state.cpp index 653467a9f..b706d5669 100644 --- a/src/video_core/renderer_opengl/gl_state.cpp +++ b/src/video_core/renderer_opengl/gl_state.cpp @@ -49,14 +49,11 @@ OpenGLState::OpenGLState() { logic_op = GL_COPY; for (auto& texture_unit : texture_units) { + texture_unit.texture_1d = 0; texture_unit.texture_2d = 0; texture_unit.sampler = 0; } - for (auto& lut : lighting_luts) { - lut.texture_1d = 0; - } - active_texture_unit = GL_TEXTURE0; draw.read_framebuffer = 0; @@ -71,6 +68,51 @@ OpenGLState* OpenGLState::GetCurrentState() { return cur_state; } +void OpenGLState::MakeCurrent() { + if (cur_state == this) { + return; + } + + SetCullEnabled(cull.enabled); + SetCullMode(cull.mode); + SetCullFrontFace(cull.front_face); + + SetDepthTestEnabled(depth.test_enabled); + SetDepthFunc(depth.test_func); + SetDepthWriteMask(depth.write_mask); + + SetColorMask(color_mask.red_enabled, color_mask.green_enabled, color_mask.blue_enabled, color_mask.alpha_enabled); + + SetStencilTestEnabled(stencil.test_enabled); + SetStencilFunc(stencil.test_func, stencil.test_ref, stencil.test_mask); + SetStencilOp(stencil.action_stencil_fail, stencil.action_depth_fail, stencil.action_depth_pass); + SetStencilWriteMask(stencil.write_mask); + + SetBlendEnabled(blend.enabled); + SetBlendFunc(blend.src_rgb_func, blend.dst_rgb_func, blend.src_a_func, blend.dst_a_func); + SetBlendColor(blend.color.red, blend.color.green, blend.color.blue, blend.color.alpha); + + SetLogicOp(logic_op); + + for (unsigned i = 0; i < ARRAY_SIZE(texture_units); ++i) { + SetActiveTextureUnit(GL_TEXTURE0 + i); + SetTexture1D(texture_units[i].texture_1d); + SetTexture2D(texture_units[i].texture_2d); + SetSampler(texture_units[i].sampler); + } + + SetActiveTextureUnit(active_texture_unit); + + SetReadFramebuffer(draw.read_framebuffer); + SetDrawFramebuffer(draw.draw_framebuffer); + SetVertexArray(draw.vertex_array); + SetVertexBuffer(draw.vertex_buffer); + SetUniformBuffer(draw.uniform_buffer); + SetShaderProgram(draw.shader_program); + + cur_state = this; +} + void OpenGLState::SetCullEnabled(bool n_enabled) { if (n_enabled != cur_state->cull.enabled) { if (n_enabled) { @@ -158,14 +200,14 @@ void OpenGLState::SetStencilFunc(GLenum n_test_func, GLint n_test_ref, GLuint n_ } void OpenGLState::SetStencilOp(GLenum n_action_stencil_fail, GLenum n_action_depth_fail, GLenum n_action_depth_pass) { - if (n_action_stencil_fail != cur_state->stencil.action_depth_fail || - n_action_depth_fail != cur_state->stencil.action_depth_pass || - n_action_depth_pass != cur_state->stencil.action_stencil_fail) { + if (n_action_stencil_fail != cur_state->stencil.action_stencil_fail || + n_action_depth_fail != cur_state->stencil.action_depth_fail || + n_action_depth_pass != cur_state->stencil.action_depth_pass) { glStencilOp(n_action_stencil_fail, n_action_depth_fail, n_action_depth_pass); } - stencil.action_depth_fail = n_action_stencil_fail; - stencil.action_depth_pass = n_action_depth_fail; - stencil.action_stencil_fail = n_action_depth_pass; + stencil.action_stencil_fail = n_action_stencil_fail; + stencil.action_depth_fail = n_action_depth_fail; + stencil.action_depth_pass = n_action_depth_pass; } void OpenGLState::SetStencilWriteMask(GLuint n_write_mask) { @@ -225,6 +267,16 @@ void OpenGLState::SetLogicOp(GLenum n_logic_op) { logic_op = n_logic_op; } +void OpenGLState::SetTexture1D(GLuint n_texture_1d) { + unsigned unit_index = active_texture_unit - GL_TEXTURE0; + ASSERT(unit_index < ARRAY_SIZE(texture_units)); + + if (n_texture_1d != cur_state->texture_units[unit_index].texture_1d) { + glBindTexture(GL_TEXTURE_1D, n_texture_1d); + } + texture_units[unit_index].texture_1d = n_texture_1d; +} + void OpenGLState::SetTexture2D(GLuint n_texture_2d) { unsigned unit_index = active_texture_unit - GL_TEXTURE0; ASSERT(unit_index < ARRAY_SIZE(texture_units)); @@ -245,16 +297,6 @@ void OpenGLState::SetSampler(GLuint n_sampler) { texture_units[unit_index].sampler = n_sampler; } -void OpenGLState::SetLUTTexture1D(GLuint n_texture_1d) { - unsigned unit_index = active_texture_unit - GL_TEXTURE3; - ASSERT(unit_index < ARRAY_SIZE(lighting_luts)); - - if (n_texture_1d != cur_state->lighting_luts[unit_index].texture_1d) { - glBindTexture(GL_TEXTURE_1D, n_texture_1d); - } - lighting_luts[unit_index].texture_1d = n_texture_1d; -} - void OpenGLState::SetActiveTextureUnit(GLenum n_active_texture_unit) { if (n_active_texture_unit != cur_state->active_texture_unit) { glActiveTexture(n_active_texture_unit); @@ -304,85 +346,31 @@ void OpenGLState::SetShaderProgram(GLuint n_shader_program) { draw.shader_program = n_shader_program; } -void OpenGLState::MakeCurrent() { - if (cur_state == this) { - return; - } - - SetCullEnabled(cull.enabled); - SetCullMode(cull.mode); - SetCullFrontFace(cull.front_face); - - SetDepthTestEnabled(depth.test_enabled); - SetDepthFunc(depth.test_func); - SetDepthWriteMask(depth.write_mask); - - SetColorMask(color_mask.red_enabled, color_mask.green_enabled, color_mask.blue_enabled, color_mask.alpha_enabled); - - SetStencilTestEnabled(stencil.test_enabled); - SetStencilFunc(stencil.test_func, stencil.test_ref, stencil.test_mask); - SetStencilOp(stencil.action_stencil_fail, stencil.action_depth_fail, stencil.action_depth_pass); - SetStencilWriteMask(stencil.write_mask); - - SetBlendEnabled(blend.enabled); - SetBlendFunc(blend.src_rgb_func, blend.dst_rgb_func, blend.src_a_func, blend.dst_a_func); - SetBlendColor(blend.color.red, blend.color.green, blend.color.blue, blend.color.alpha); - - SetLogicOp(logic_op); - - for (unsigned i = 0; i < ARRAY_SIZE(texture_units); ++i) { - SetActiveTextureUnit(GL_TEXTURE0 + i); - SetTexture2D(texture_units[i].texture_2d); - SetSampler(texture_units[i].sampler); - } - - for (unsigned i = 0; i < ARRAY_SIZE(lighting_luts); ++i) { - SetActiveTextureUnit(GL_TEXTURE3 + i); - SetLUTTexture1D(lighting_luts[i].texture_1d); - } - - SetActiveTextureUnit(active_texture_unit); - - SetReadFramebuffer(draw.read_framebuffer); - SetDrawFramebuffer(draw.draw_framebuffer); - SetVertexArray(draw.vertex_array); - SetVertexBuffer(draw.vertex_buffer); - SetUniformBuffer(draw.uniform_buffer); - SetShaderProgram(draw.shader_program); - - cur_state = this; -} - -GLenum OpenGLState::CheckFBStatus(GLenum target) { - GLenum fb_status = glCheckFramebufferStatus(target); - if (fb_status != GL_FRAMEBUFFER_COMPLETE) { - const char* fb_description = (target == GL_READ_FRAMEBUFFER ? "READ" : (target == GL_DRAW_FRAMEBUFFER ? "DRAW" : "UNK")); - LOG_CRITICAL(Render_OpenGL, "OpenGL %s framebuffer check failed, status %X", fb_description, fb_status); - } - - return fb_status; -} - void OpenGLState::ResetTexture(GLuint handle) { for (unsigned i = 0; i < ARRAY_SIZE(texture_units); ++i) { + if (cur_state->texture_units[i].texture_1d == handle) { + GLenum prev_active_texture_unit = cur_state->active_texture_unit; + cur_state->SetActiveTextureUnit(GL_TEXTURE0 + i); + cur_state->SetTexture1D(0); + cur_state->SetActiveTextureUnit(prev_active_texture_unit); + } + if (cur_state->texture_units[i].texture_2d == handle) { + GLenum prev_active_texture_unit = cur_state->active_texture_unit; cur_state->SetActiveTextureUnit(GL_TEXTURE0 + i); cur_state->SetTexture2D(0); - } - } - for (unsigned i = 0; i < ARRAY_SIZE(lighting_luts); ++i) { - if (cur_state->lighting_luts[i].texture_1d == handle) { - cur_state->SetActiveTextureUnit(GL_TEXTURE3 + i); - cur_state->SetLUTTexture1D(0); + cur_state->SetActiveTextureUnit(prev_active_texture_unit); } } } void OpenGLState::ResetSampler(GLuint handle) { for (unsigned i = 0; i < ARRAY_SIZE(texture_units); ++i) { - if (cur_state->texture_units[i].texture_2d == handle) { + if (cur_state->texture_units[i].sampler == handle) { + GLenum prev_active_texture_unit = cur_state->active_texture_unit; cur_state->SetActiveTextureUnit(GL_TEXTURE0 + i); cur_state->SetSampler(0); + cur_state->SetActiveTextureUnit(prev_active_texture_unit); } } } @@ -416,3 +404,13 @@ void OpenGLState::ResetFramebuffer(GLuint handle) { cur_state->SetDrawFramebuffer(0); } } + +GLenum OpenGLState::CheckBoundFBStatus(GLenum target) { + GLenum fb_status = glCheckFramebufferStatus(target); + if (fb_status != GL_FRAMEBUFFER_COMPLETE) { + const char* fb_description = (target == GL_READ_FRAMEBUFFER ? "READ" : (target == GL_DRAW_FRAMEBUFFER ? "DRAW" : "UNK")); + LOG_CRITICAL(Render_OpenGL, "OpenGL %s framebuffer check failed, status %X", fb_description, fb_status); + } + + return fb_status; +} diff --git a/src/video_core/renderer_opengl/gl_state.h b/src/video_core/renderer_opengl/gl_state.h index 9b5aa5e70..46c1d9189 100644 --- a/src/video_core/renderer_opengl/gl_state.h +++ b/src/video_core/renderer_opengl/gl_state.h @@ -10,22 +10,13 @@ class OpenGLState { public: OpenGLState(); + /// Get a pointer to the currently bound state tracker object static OpenGLState* GetCurrentState(); /// Apply this state as the current OpenGL state void MakeCurrent(); - /// Check the status of the current OpenGL read or draw framebuffer configuration - static GLenum CheckFBStatus(GLenum target); - - /// Resets and unbinds any references to the given resource in the current OpenGL state - static void ResetTexture(GLuint handle); - static void ResetSampler(GLuint handle); - static void ResetProgram(GLuint handle); - static void ResetBuffer(GLuint handle); - static void ResetVertexArray(GLuint handle); - static void ResetFramebuffer(GLuint handle); - + /// Setter functions for OpenGL state void SetCullEnabled(bool n_enabled); void SetCullMode(GLenum n_mode); void SetCullFrontFace(GLenum n_front_face); @@ -47,11 +38,10 @@ public: void SetLogicOp(GLenum n_logic_op); + void SetTexture1D(GLuint n_texture_1d); void SetTexture2D(GLuint n_texture_2d); void SetSampler(GLuint n_sampler); - void SetLUTTexture1D(GLuint n_texture_1d); - void SetActiveTextureUnit(GLenum n_active_texture_unit); void SetReadFramebuffer(GLuint n_read_framebuffer); @@ -61,6 +51,17 @@ public: void SetUniformBuffer(GLuint n_uniform_buffer); void SetShaderProgram(GLuint n_shader_program); + /// Resets and unbinds any references to the given resource in the current OpenGL state + static void ResetTexture(GLuint handle); + static void ResetSampler(GLuint handle); + static void ResetProgram(GLuint handle); + static void ResetBuffer(GLuint handle); + static void ResetVertexArray(GLuint handle); + static void ResetFramebuffer(GLuint handle); + + /// Check the status of the currently bound OpenGL read or draw framebuffer configuration + static GLenum CheckBoundFBStatus(GLenum target); + private: struct { bool enabled; // GL_CULL_FACE @@ -111,13 +112,10 @@ private: // 3 texture units - one for each that is used in PICA fragment shader emulation struct { + GLuint texture_1d; // GL_TEXTURE_BINDING_1D GLuint texture_2d; // GL_TEXTURE_BINDING_2D GLuint sampler; // GL_SAMPLER_BINDING - } texture_units[3]; - - struct { - GLuint texture_1d; // GL_TEXTURE_BINDING_1D - } lighting_luts[6]; + } texture_units[9]; GLenum active_texture_unit; // GL_ACTIVE_TEXTURE