diff options
Diffstat (limited to 'src/video_core/renderer_opengl/gl_shader_manager.h')
-rw-r--r-- | src/video_core/renderer_opengl/gl_shader_manager.h | 73 |
1 files changed, 33 insertions, 40 deletions
diff --git a/src/video_core/renderer_opengl/gl_shader_manager.h b/src/video_core/renderer_opengl/gl_shader_manager.h index 4970aafed..cec18a832 100644 --- a/src/video_core/renderer_opengl/gl_shader_manager.h +++ b/src/video_core/renderer_opengl/gl_shader_manager.h @@ -4,6 +4,8 @@ #pragma once +#include <cstddef> + #include <glad/glad.h> #include "video_core/renderer_opengl/gl_resource_manager.h" @@ -12,14 +14,13 @@ namespace OpenGL::GLShader { -using Tegra::Engines::Maxwell3D; - /// Uniform structure for the Uniform Buffer Object, all vectors must be 16-byte aligned -// NOTE: Always keep a vec4 at the end. The GL spec is not clear whether the alignment at -// the end of a uniform block is included in UNIFORM_BLOCK_DATA_SIZE or not. -// Not following that rule will cause problems on some AMD drivers. +/// @note Always keep a vec4 at the end. The GL spec is not clear whether the alignment at +/// the end of a uniform block is included in UNIFORM_BLOCK_DATA_SIZE or not. +/// Not following that rule will cause problems on some AMD drivers. struct MaxwellUniformData { - void SetFromRegs(const Maxwell3D::State::ShaderStageInfo& shader_stage); + void SetFromRegs(const Tegra::Engines::Maxwell3D& maxwell, std::size_t shader_stage); + alignas(16) GLvec4 viewport_flip; struct alignas(16) { GLuint instance_id; @@ -39,56 +40,48 @@ static_assert(sizeof(MaxwellUniformData) < 16384, class ProgramManager { public: - ProgramManager() { - pipeline.Create(); - } + explicit ProgramManager(); + ~ProgramManager(); + + void ApplyTo(OpenGLState& state); void UseProgrammableVertexShader(GLuint program) { - vs = program; + current_state.vertex_shader = program; } void UseProgrammableGeometryShader(GLuint program) { - gs = program; + current_state.geometry_shader = program; } void UseProgrammableFragmentShader(GLuint program) { - fs = program; + current_state.fragment_shader = program; } void UseTrivialGeometryShader() { - gs = 0; - } - - void ApplyTo(OpenGLState& state) { - UpdatePipeline(); - state.draw.shader_program = 0; - state.draw.program_pipeline = pipeline.handle; - state.geometry_shaders.enabled = (gs != 0); + current_state.geometry_shader = 0; } private: - void UpdatePipeline() { - // Avoid updating the pipeline when values have no changed - if (old_vs == vs && old_fs == fs && old_gs == gs) - return; - // Workaround for AMD bug - glUseProgramStages(pipeline.handle, - GL_VERTEX_SHADER_BIT | GL_GEOMETRY_SHADER_BIT | GL_FRAGMENT_SHADER_BIT, - 0); - - glUseProgramStages(pipeline.handle, GL_VERTEX_SHADER_BIT, vs); - glUseProgramStages(pipeline.handle, GL_GEOMETRY_SHADER_BIT, gs); - glUseProgramStages(pipeline.handle, GL_FRAGMENT_SHADER_BIT, fs); - - // Update the old values - old_vs = vs; - old_fs = fs; - old_gs = gs; - } + struct PipelineState { + bool operator==(const PipelineState& rhs) const { + return vertex_shader == rhs.vertex_shader && fragment_shader == rhs.fragment_shader && + geometry_shader == rhs.geometry_shader; + } + + bool operator!=(const PipelineState& rhs) const { + return !operator==(rhs); + } + + GLuint vertex_shader{}; + GLuint fragment_shader{}; + GLuint geometry_shader{}; + }; + + void UpdatePipeline(); OGLPipeline pipeline; - GLuint vs{}, fs{}, gs{}; - GLuint old_vs{}, old_fs{}, old_gs{}; + PipelineState current_state; + PipelineState old_state; }; } // namespace OpenGL::GLShader |