Merge pull request #3494 from ReinUsesLisp/fix-cs-pipeline
gl_shader_manager: Fix interaction between graphics and compute
This commit is contained in:
commit
fce33adcf1
|
@ -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