diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/video_core/renderer_opengl/gl_shader_manager.cpp | 34 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_shader_manager.h | 61 |
2 files changed, 61 insertions, 34 deletions
diff --git a/src/video_core/renderer_opengl/gl_shader_manager.cpp b/src/video_core/renderer_opengl/gl_shader_manager.cpp index eaf3e03a0..05ab01dcb 100644 --- a/src/video_core/renderer_opengl/gl_shader_manager.cpp +++ b/src/video_core/renderer_opengl/gl_shader_manager.cpp | |||
| @@ -2,12 +2,44 @@ | |||
| 2 | // Licensed under GPLv2 or any later version | 2 | // Licensed under GPLv2 or any later version |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include "common/common_types.h" | ||
| 6 | #include "video_core/engines/maxwell_3d.h" | ||
| 5 | #include "video_core/renderer_opengl/gl_shader_manager.h" | 7 | #include "video_core/renderer_opengl/gl_shader_manager.h" |
| 6 | 8 | ||
| 7 | namespace OpenGL::GLShader { | 9 | namespace OpenGL::GLShader { |
| 8 | 10 | ||
| 9 | using Tegra::Engines::Maxwell3D; | 11 | using Tegra::Engines::Maxwell3D; |
| 10 | 12 | ||
| 13 | ProgramManager::ProgramManager() { | ||
| 14 | pipeline.Create(); | ||
| 15 | } | ||
| 16 | |||
| 17 | ProgramManager::~ProgramManager() = default; | ||
| 18 | |||
| 19 | void ProgramManager::ApplyTo(OpenGLState& state) { | ||
| 20 | UpdatePipeline(); | ||
| 21 | state.draw.shader_program = 0; | ||
| 22 | state.draw.program_pipeline = pipeline.handle; | ||
| 23 | } | ||
| 24 | |||
| 25 | void ProgramManager::UpdatePipeline() { | ||
| 26 | // Avoid updating the pipeline when values have no changed | ||
| 27 | if (old_state == current_state) { | ||
| 28 | return; | ||
| 29 | } | ||
| 30 | |||
| 31 | // Workaround for AMD bug | ||
| 32 | constexpr GLenum all_used_stages{GL_VERTEX_SHADER_BIT | GL_GEOMETRY_SHADER_BIT | | ||
| 33 | GL_FRAGMENT_SHADER_BIT}; | ||
| 34 | glUseProgramStages(pipeline.handle, all_used_stages, 0); | ||
| 35 | |||
| 36 | glUseProgramStages(pipeline.handle, GL_VERTEX_SHADER_BIT, current_state.vertex_shader); | ||
| 37 | glUseProgramStages(pipeline.handle, GL_GEOMETRY_SHADER_BIT, current_state.geometry_shader); | ||
| 38 | glUseProgramStages(pipeline.handle, GL_FRAGMENT_SHADER_BIT, current_state.fragment_shader); | ||
| 39 | |||
| 40 | old_state = current_state; | ||
| 41 | } | ||
| 42 | |||
| 11 | void MaxwellUniformData::SetFromRegs(const Maxwell3D& maxwell, std::size_t shader_stage) { | 43 | void MaxwellUniformData::SetFromRegs(const Maxwell3D& maxwell, std::size_t shader_stage) { |
| 12 | const auto& regs = maxwell.regs; | 44 | const auto& regs = maxwell.regs; |
| 13 | const auto& state = maxwell.state; | 45 | const auto& state = maxwell.state; |
| @@ -16,7 +48,7 @@ void MaxwellUniformData::SetFromRegs(const Maxwell3D& maxwell, std::size_t shade | |||
| 16 | viewport_flip[0] = regs.viewport_transform[0].scale_x < 0.0 ? -1.0f : 1.0f; | 48 | viewport_flip[0] = regs.viewport_transform[0].scale_x < 0.0 ? -1.0f : 1.0f; |
| 17 | viewport_flip[1] = regs.viewport_transform[0].scale_y < 0.0 ? -1.0f : 1.0f; | 49 | viewport_flip[1] = regs.viewport_transform[0].scale_y < 0.0 ? -1.0f : 1.0f; |
| 18 | 50 | ||
| 19 | u32 func = static_cast<u32>(regs.alpha_test_func); | 51 | auto func{static_cast<u32>(regs.alpha_test_func)}; |
| 20 | // Normalize the gl variants of opCompare to be the same as the normal variants | 52 | // Normalize the gl variants of opCompare to be the same as the normal variants |
| 21 | const u32 op_gl_variant_base = static_cast<u32>(Maxwell3D::Regs::ComparisonOp::Never); | 53 | const u32 op_gl_variant_base = static_cast<u32>(Maxwell3D::Regs::ComparisonOp::Never); |
| 22 | if (func >= op_gl_variant_base) { | 54 | if (func >= op_gl_variant_base) { |
diff --git a/src/video_core/renderer_opengl/gl_shader_manager.h b/src/video_core/renderer_opengl/gl_shader_manager.h index 37dcfefdb..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 @@ | |||
| 4 | 4 | ||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | #include <cstddef> | ||
| 8 | |||
| 7 | #include <glad/glad.h> | 9 | #include <glad/glad.h> |
| 8 | 10 | ||
| 9 | #include "video_core/renderer_opengl/gl_resource_manager.h" | 11 | #include "video_core/renderer_opengl/gl_resource_manager.h" |
| @@ -38,55 +40,48 @@ static_assert(sizeof(MaxwellUniformData) < 16384, | |||
| 38 | 40 | ||
| 39 | class ProgramManager { | 41 | class ProgramManager { |
| 40 | public: | 42 | public: |
| 41 | ProgramManager() { | 43 | explicit ProgramManager(); |
| 42 | pipeline.Create(); | 44 | ~ProgramManager(); |
| 43 | } | 45 | |
| 46 | void ApplyTo(OpenGLState& state); | ||
| 44 | 47 | ||
| 45 | void UseProgrammableVertexShader(GLuint program) { | 48 | void UseProgrammableVertexShader(GLuint program) { |
| 46 | vs = program; | 49 | current_state.vertex_shader = program; |
| 47 | } | 50 | } |
| 48 | 51 | ||
| 49 | void UseProgrammableGeometryShader(GLuint program) { | 52 | void UseProgrammableGeometryShader(GLuint program) { |
| 50 | gs = program; | 53 | current_state.geometry_shader = program; |
| 51 | } | 54 | } |
| 52 | 55 | ||
| 53 | void UseProgrammableFragmentShader(GLuint program) { | 56 | void UseProgrammableFragmentShader(GLuint program) { |
| 54 | fs = program; | 57 | current_state.fragment_shader = program; |
| 55 | } | 58 | } |
| 56 | 59 | ||
| 57 | void UseTrivialGeometryShader() { | 60 | void UseTrivialGeometryShader() { |
| 58 | gs = 0; | 61 | current_state.geometry_shader = 0; |
| 59 | } | ||
| 60 | |||
| 61 | void ApplyTo(OpenGLState& state) { | ||
| 62 | UpdatePipeline(); | ||
| 63 | state.draw.shader_program = 0; | ||
| 64 | state.draw.program_pipeline = pipeline.handle; | ||
| 65 | } | 62 | } |
| 66 | 63 | ||
| 67 | private: | 64 | private: |
| 68 | void UpdatePipeline() { | 65 | struct PipelineState { |
| 69 | // Avoid updating the pipeline when values have no changed | 66 | bool operator==(const PipelineState& rhs) const { |
| 70 | if (old_vs == vs && old_fs == fs && old_gs == gs) | 67 | return vertex_shader == rhs.vertex_shader && fragment_shader == rhs.fragment_shader && |
| 71 | return; | 68 | geometry_shader == rhs.geometry_shader; |
| 72 | // Workaround for AMD bug | 69 | } |
| 73 | glUseProgramStages(pipeline.handle, | 70 | |
| 74 | GL_VERTEX_SHADER_BIT | GL_GEOMETRY_SHADER_BIT | GL_FRAGMENT_SHADER_BIT, | 71 | bool operator!=(const PipelineState& rhs) const { |
| 75 | 0); | 72 | return !operator==(rhs); |
| 76 | 73 | } | |
| 77 | glUseProgramStages(pipeline.handle, GL_VERTEX_SHADER_BIT, vs); | 74 | |
| 78 | glUseProgramStages(pipeline.handle, GL_GEOMETRY_SHADER_BIT, gs); | 75 | GLuint vertex_shader{}; |
| 79 | glUseProgramStages(pipeline.handle, GL_FRAGMENT_SHADER_BIT, fs); | 76 | GLuint fragment_shader{}; |
| 80 | 77 | GLuint geometry_shader{}; | |
| 81 | // Update the old values | 78 | }; |
| 82 | old_vs = vs; | 79 | |
| 83 | old_fs = fs; | 80 | void UpdatePipeline(); |
| 84 | old_gs = gs; | ||
| 85 | } | ||
| 86 | 81 | ||
| 87 | OGLPipeline pipeline; | 82 | OGLPipeline pipeline; |
| 88 | GLuint vs{}, fs{}, gs{}; | 83 | PipelineState current_state; |
| 89 | GLuint old_vs{}, old_fs{}, old_gs{}; | 84 | PipelineState old_state; |
| 90 | }; | 85 | }; |
| 91 | 86 | ||
| 92 | } // namespace OpenGL::GLShader | 87 | } // namespace OpenGL::GLShader |