Merge pull request #3494 from ReinUsesLisp/fix-cs-pipeline
gl_shader_manager: Fix interaction between graphics and compute
This commit is contained in:
		| @@ -565,7 +565,7 @@ void RasterizerOpenGL::Draw(bool is_indexed, bool is_instanced) { | |||||||
|     bind_ubo_pushbuffer.Bind(); |     bind_ubo_pushbuffer.Bind(); | ||||||
|     bind_ssbo_pushbuffer.Bind(); |     bind_ssbo_pushbuffer.Bind(); | ||||||
|  |  | ||||||
|     program_manager.Update(); |     program_manager.BindGraphicsPipeline(); | ||||||
|  |  | ||||||
|     if (texture_cache.TextureBarrier()) { |     if (texture_cache.TextureBarrier()) { | ||||||
|         glTextureBarrier(); |         glTextureBarrier(); | ||||||
| @@ -627,8 +627,7 @@ void RasterizerOpenGL::DispatchCompute(GPUVAddr code_addr) { | |||||||
|     const ProgramVariant variant(launch_desc.block_dim_x, launch_desc.block_dim_y, |     const ProgramVariant variant(launch_desc.block_dim_x, launch_desc.block_dim_y, | ||||||
|                                  launch_desc.block_dim_z, launch_desc.shared_alloc, |                                  launch_desc.block_dim_z, launch_desc.shared_alloc, | ||||||
|                                  launch_desc.local_pos_alloc); |                                  launch_desc.local_pos_alloc); | ||||||
|     glUseProgramStages(program_manager.GetHandle(), GL_COMPUTE_SHADER_BIT, |     program_manager.BindComputeShader(kernel->GetHandle(variant)); | ||||||
|                        kernel->GetHandle(variant)); |  | ||||||
|  |  | ||||||
|     const std::size_t buffer_size = |     const std::size_t buffer_size = | ||||||
|         Tegra::Engines::KeplerCompute::NumConstBuffers * |         Tegra::Engines::KeplerCompute::NumConstBuffers * | ||||||
|   | |||||||
| @@ -2,21 +2,29 @@ | |||||||
| // Licensed under GPLv2 or any later version | // Licensed under GPLv2 or any later version | ||||||
| // Refer to the license.txt file included. | // Refer to the license.txt file included. | ||||||
|  |  | ||||||
|  | #include <glad/glad.h> | ||||||
|  |  | ||||||
| #include "common/common_types.h" | #include "common/common_types.h" | ||||||
| #include "video_core/engines/maxwell_3d.h" | #include "video_core/engines/maxwell_3d.h" | ||||||
| #include "video_core/renderer_opengl/gl_shader_manager.h" | #include "video_core/renderer_opengl/gl_shader_manager.h" | ||||||
|  |  | ||||||
| namespace OpenGL::GLShader { | namespace OpenGL::GLShader { | ||||||
|  |  | ||||||
| using Tegra::Engines::Maxwell3D; | ProgramManager::ProgramManager() = default; | ||||||
|  |  | ||||||
| ProgramManager::~ProgramManager() = default; | ProgramManager::~ProgramManager() = default; | ||||||
|  |  | ||||||
| void ProgramManager::Create() { | 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 |     // Avoid updating the pipeline when values have no changed | ||||||
|     if (old_state == current_state) { |     if (old_state == current_state) { | ||||||
|         return; |         return; | ||||||
| @@ -25,16 +33,21 @@ void ProgramManager::Update() { | |||||||
|     // Workaround for AMD bug |     // Workaround for AMD bug | ||||||
|     static constexpr GLenum all_used_stages{GL_VERTEX_SHADER_BIT | GL_GEOMETRY_SHADER_BIT | |     static constexpr GLenum all_used_stages{GL_VERTEX_SHADER_BIT | GL_GEOMETRY_SHADER_BIT | | ||||||
|                                             GL_FRAGMENT_SHADER_BIT}; |                                             GL_FRAGMENT_SHADER_BIT}; | ||||||
|     glUseProgramStages(pipeline.handle, all_used_stages, 0); |     const GLuint handle = graphics_pipeline.handle; | ||||||
|  |     glUseProgramStages(handle, all_used_stages, 0); | ||||||
|     glUseProgramStages(pipeline.handle, GL_VERTEX_SHADER_BIT, current_state.vertex_shader); |     glUseProgramStages(handle, GL_VERTEX_SHADER_BIT, current_state.vertex_shader); | ||||||
|     glUseProgramStages(pipeline.handle, GL_GEOMETRY_SHADER_BIT, current_state.geometry_shader); |     glUseProgramStages(handle, GL_GEOMETRY_SHADER_BIT, current_state.geometry_shader); | ||||||
|     glUseProgramStages(pipeline.handle, GL_FRAGMENT_SHADER_BIT, current_state.fragment_shader); |     glUseProgramStages(handle, GL_FRAGMENT_SHADER_BIT, current_state.fragment_shader); | ||||||
|  |  | ||||||
|     old_state = current_state; |     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; |     const auto& regs = maxwell.regs; | ||||||
|  |  | ||||||
|     // Y_NEGATE controls what value S2R returns for the Y_DIRECTION system value. |     // Y_NEGATE controls what value S2R returns for the Y_DIRECTION system value. | ||||||
|   | |||||||
| @@ -28,11 +28,16 @@ static_assert(sizeof(MaxwellUniformData) < 16384, | |||||||
|  |  | ||||||
| class ProgramManager { | class ProgramManager { | ||||||
| public: | public: | ||||||
|  |     explicit ProgramManager(); | ||||||
|     ~ProgramManager(); |     ~ProgramManager(); | ||||||
|  |  | ||||||
|     void Create(); |     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) { |     void UseVertexShader(GLuint program) { | ||||||
|         current_state.vertex_shader = program; |         current_state.vertex_shader = program; | ||||||
| @@ -46,33 +51,27 @@ public: | |||||||
|         current_state.fragment_shader = program; |         current_state.fragment_shader = program; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     GLuint GetHandle() const { |  | ||||||
|         return pipeline.handle; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     void UseTrivialFragmentShader() { |  | ||||||
|         current_state.fragment_shader = 0; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
| private: | private: | ||||||
|     struct PipelineState { |     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 && |             return vertex_shader == rhs.vertex_shader && fragment_shader == rhs.fragment_shader && | ||||||
|                    geometry_shader == rhs.geometry_shader; |                    geometry_shader == rhs.geometry_shader; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         bool operator!=(const PipelineState& rhs) const { |         bool operator!=(const PipelineState& rhs) const noexcept { | ||||||
|             return !operator==(rhs); |             return !operator==(rhs); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         GLuint vertex_shader{}; |         GLuint vertex_shader = 0; | ||||||
|         GLuint fragment_shader{}; |         GLuint fragment_shader = 0; | ||||||
|         GLuint geometry_shader{}; |         GLuint geometry_shader = 0; | ||||||
|     }; |     }; | ||||||
|  |  | ||||||
|     OGLPipeline pipeline; |     OGLPipeline graphics_pipeline; | ||||||
|  |     OGLPipeline compute_pipeline; | ||||||
|     PipelineState current_state; |     PipelineState current_state; | ||||||
|     PipelineState old_state; |     PipelineState old_state; | ||||||
|  |     bool is_graphics_bound = true; | ||||||
| }; | }; | ||||||
|  |  | ||||||
| } // namespace OpenGL::GLShader | } // namespace OpenGL::GLShader | ||||||
|   | |||||||
| @@ -443,7 +443,6 @@ void RendererOpenGL::InitOpenGLObjects() { | |||||||
|  |  | ||||||
|     // Create program pipeline |     // Create program pipeline | ||||||
|     program_manager.Create(); |     program_manager.Create(); | ||||||
|     glBindProgramPipeline(program_manager.GetHandle()); |  | ||||||
|  |  | ||||||
|     // Generate VBO handle for drawing |     // Generate VBO handle for drawing | ||||||
|     vertex_buffer.Create(); |     vertex_buffer.Create(); | ||||||
| @@ -596,7 +595,7 @@ void RendererOpenGL::DrawScreen(const Layout::FramebufferLayout& layout) { | |||||||
|     program_manager.UseVertexShader(vertex_program.handle); |     program_manager.UseVertexShader(vertex_program.handle); | ||||||
|     program_manager.UseGeometryShader(0); |     program_manager.UseGeometryShader(0); | ||||||
|     program_manager.UseFragmentShader(fragment_program.handle); |     program_manager.UseFragmentShader(fragment_program.handle); | ||||||
|     program_manager.Update(); |     program_manager.BindGraphicsPipeline(); | ||||||
|  |  | ||||||
|     glEnable(GL_CULL_FACE); |     glEnable(GL_CULL_FACE); | ||||||
|     if (screen_info.display_srgb) { |     if (screen_info.display_srgb) { | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user