Merge pull request #3494 from ReinUsesLisp/fix-cs-pipeline

gl_shader_manager: Fix interaction between graphics and compute
This commit is contained in:
bunnei 2020-03-11 13:51:54 -04:00 committed by GitHub
commit fce33adcf1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 39 additions and 29 deletions

View file

@ -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 *

View file

@ -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::BindGraphicsPipeline() {
if (!is_graphics_bound) {
is_graphics_bound = true;
glUseProgram(0);
}
void ProgramManager::Update() {
// 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.

View file

@ -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

View file

@ -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) {