diff options
4 files changed, 39 insertions, 29 deletions
| diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index 55324e6d5..4e4138573 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp @@ -565,7 +565,7 @@ void RasterizerOpenGL::Draw(bool is_indexed, bool is_instanced) {      bind_ubo_pushbuffer.Bind();      bind_ssbo_pushbuffer.Bind(); -    program_manager.Update(); +    program_manager.BindGraphicsPipeline();      if (texture_cache.TextureBarrier()) {          glTextureBarrier(); @@ -627,8 +627,7 @@ void RasterizerOpenGL::DispatchCompute(GPUVAddr code_addr) {      const ProgramVariant variant(launch_desc.block_dim_x, launch_desc.block_dim_y,                                   launch_desc.block_dim_z, launch_desc.shared_alloc,                                   launch_desc.local_pos_alloc); -    glUseProgramStages(program_manager.GetHandle(), GL_COMPUTE_SHADER_BIT, -                       kernel->GetHandle(variant)); +    program_manager.BindComputeShader(kernel->GetHandle(variant));      const std::size_t buffer_size =          Tegra::Engines::KeplerCompute::NumConstBuffers * diff --git a/src/video_core/renderer_opengl/gl_shader_manager.cpp b/src/video_core/renderer_opengl/gl_shader_manager.cpp index 15f3cd066..9c7b0adbd 100644 --- a/src/video_core/renderer_opengl/gl_shader_manager.cpp +++ b/src/video_core/renderer_opengl/gl_shader_manager.cpp @@ -2,21 +2,29 @@  // Licensed under GPLv2 or any later version  // Refer to the license.txt file included. +#include <glad/glad.h> +  #include "common/common_types.h"  #include "video_core/engines/maxwell_3d.h"  #include "video_core/renderer_opengl/gl_shader_manager.h"  namespace OpenGL::GLShader { -using Tegra::Engines::Maxwell3D; +ProgramManager::ProgramManager() = default;  ProgramManager::~ProgramManager() = default;  void ProgramManager::Create() { -    pipeline.Create(); +    graphics_pipeline.Create(); +    glBindProgramPipeline(graphics_pipeline.handle);  } -void ProgramManager::Update() { +void ProgramManager::BindGraphicsPipeline() { +    if (!is_graphics_bound) { +        is_graphics_bound = true; +        glUseProgram(0); +    } +      // Avoid updating the pipeline when values have no changed      if (old_state == current_state) {          return; @@ -25,16 +33,21 @@ void ProgramManager::Update() {      // Workaround for AMD bug      static constexpr GLenum all_used_stages{GL_VERTEX_SHADER_BIT | GL_GEOMETRY_SHADER_BIT |                                              GL_FRAGMENT_SHADER_BIT}; -    glUseProgramStages(pipeline.handle, all_used_stages, 0); - -    glUseProgramStages(pipeline.handle, GL_VERTEX_SHADER_BIT, current_state.vertex_shader); -    glUseProgramStages(pipeline.handle, GL_GEOMETRY_SHADER_BIT, current_state.geometry_shader); -    glUseProgramStages(pipeline.handle, GL_FRAGMENT_SHADER_BIT, current_state.fragment_shader); +    const GLuint handle = graphics_pipeline.handle; +    glUseProgramStages(handle, all_used_stages, 0); +    glUseProgramStages(handle, GL_VERTEX_SHADER_BIT, current_state.vertex_shader); +    glUseProgramStages(handle, GL_GEOMETRY_SHADER_BIT, current_state.geometry_shader); +    glUseProgramStages(handle, GL_FRAGMENT_SHADER_BIT, current_state.fragment_shader);      old_state = current_state;  } -void MaxwellUniformData::SetFromRegs(const Maxwell3D& maxwell) { +void ProgramManager::BindComputeShader(GLuint program) { +    is_graphics_bound = false; +    glUseProgram(program); +} + +void MaxwellUniformData::SetFromRegs(const Tegra::Engines::Maxwell3D& maxwell) {      const auto& regs = maxwell.regs;      // Y_NEGATE controls what value S2R returns for the Y_DIRECTION system value. diff --git a/src/video_core/renderer_opengl/gl_shader_manager.h b/src/video_core/renderer_opengl/gl_shader_manager.h index e94cd75aa..d2e47f2a9 100644 --- a/src/video_core/renderer_opengl/gl_shader_manager.h +++ b/src/video_core/renderer_opengl/gl_shader_manager.h @@ -28,11 +28,16 @@ static_assert(sizeof(MaxwellUniformData) < 16384,  class ProgramManager {  public: +    explicit ProgramManager();      ~ProgramManager();      void Create(); -    void Update(); +    /// Updates the graphics pipeline and binds it. +    void BindGraphicsPipeline(); + +    /// Binds a compute shader. +    void BindComputeShader(GLuint program);      void UseVertexShader(GLuint program) {          current_state.vertex_shader = program; @@ -46,33 +51,27 @@ public:          current_state.fragment_shader = program;      } -    GLuint GetHandle() const { -        return pipeline.handle; -    } - -    void UseTrivialFragmentShader() { -        current_state.fragment_shader = 0; -    } -  private:      struct PipelineState { -        bool operator==(const PipelineState& rhs) const { +        bool operator==(const PipelineState& rhs) const noexcept {              return vertex_shader == rhs.vertex_shader && fragment_shader == rhs.fragment_shader &&                     geometry_shader == rhs.geometry_shader;          } -        bool operator!=(const PipelineState& rhs) const { +        bool operator!=(const PipelineState& rhs) const noexcept {              return !operator==(rhs);          } -        GLuint vertex_shader{}; -        GLuint fragment_shader{}; -        GLuint geometry_shader{}; +        GLuint vertex_shader = 0; +        GLuint fragment_shader = 0; +        GLuint geometry_shader = 0;      }; -    OGLPipeline pipeline; +    OGLPipeline graphics_pipeline; +    OGLPipeline compute_pipeline;      PipelineState current_state;      PipelineState old_state; +    bool is_graphics_bound = true;  };  } // namespace OpenGL::GLShader diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp index a51410660..c05677cd9 100644 --- a/src/video_core/renderer_opengl/renderer_opengl.cpp +++ b/src/video_core/renderer_opengl/renderer_opengl.cpp @@ -443,7 +443,6 @@ void RendererOpenGL::InitOpenGLObjects() {      // Create program pipeline      program_manager.Create(); -    glBindProgramPipeline(program_manager.GetHandle());      // Generate VBO handle for drawing      vertex_buffer.Create(); @@ -596,7 +595,7 @@ void RendererOpenGL::DrawScreen(const Layout::FramebufferLayout& layout) {      program_manager.UseVertexShader(vertex_program.handle);      program_manager.UseGeometryShader(0);      program_manager.UseFragmentShader(fragment_program.handle); -    program_manager.Update(); +    program_manager.BindGraphicsPipeline();      glEnable(GL_CULL_FACE);      if (screen_info.display_srgb) { | 
