diff options
Diffstat (limited to '')
-rw-r--r-- | src/video_core/renderer_opengl/gl_shader_manager.h | 126 |
1 files changed, 10 insertions, 116 deletions
diff --git a/src/video_core/renderer_opengl/gl_shader_manager.h b/src/video_core/renderer_opengl/gl_shader_manager.h index 0e7085776..533e42caa 100644 --- a/src/video_core/renderer_opengl/gl_shader_manager.h +++ b/src/video_core/renderer_opengl/gl_shader_manager.h @@ -4,12 +4,9 @@ #pragma once -#include <tuple> -#include <unordered_map> -#include <boost/functional/hash.hpp> #include <glad/glad.h> + #include "video_core/renderer_opengl/gl_resource_manager.h" -#include "video_core/renderer_opengl/gl_shader_gen.h" #include "video_core/renderer_opengl/maxwell_to_gl.h" namespace OpenGL::GLShader { @@ -19,10 +16,6 @@ static constexpr size_t NumTextureSamplers = 32; using Tegra::Engines::Maxwell3D; -namespace Impl { -void SetShaderUniformBlockBindings(GLuint shader); -} // namespace Impl - /// 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. @@ -36,102 +29,22 @@ static_assert(sizeof(MaxwellUniformData) == 32, "MaxwellUniformData structure si static_assert(sizeof(MaxwellUniformData) < 16384, "MaxwellUniformData structure must be less than 16kb as per the OpenGL spec"); -class OGLShaderStage { -public: - OGLShaderStage() = default; - - void Create(const ProgramResult& program_result, GLenum type) { - OGLShader shader; - shader.Create(program_result.first.c_str(), type); - program.Create(true, shader.handle); - Impl::SetShaderUniformBlockBindings(program.handle); - entries = program_result.second; - } - GLuint GetHandle() const { - return program.handle; - } - - ShaderEntries GetEntries() const { - return entries; - } - -private: - OGLProgram program; - ShaderEntries entries; -}; - -// TODO(wwylele): beautify this doc -// This is a shader cache designed for translating PICA shader to GLSL shader. -// The double cache is needed because diffent KeyConfigType, which includes a hash of the code -// region (including its leftover unused code) can generate the same GLSL code. -template <typename KeyConfigType, - ProgramResult (*CodeGenerator)(const ShaderSetup&, const KeyConfigType&), - GLenum ShaderType> -class ShaderCache { -public: - ShaderCache() = default; - - using Result = std::pair<GLuint, ShaderEntries>; - - Result Get(const KeyConfigType& key, const ShaderSetup& setup) { - auto map_it = shader_map.find(key); - if (map_it == shader_map.end()) { - ProgramResult program = CodeGenerator(setup, key); - - auto [iter, new_shader] = shader_cache.emplace(program.first, OGLShaderStage{}); - OGLShaderStage& cached_shader = iter->second; - if (new_shader) { - cached_shader.Create(program, ShaderType); - } - shader_map[key] = &cached_shader; - return {cached_shader.GetHandle(), program.second}; - } else { - return {map_it->second->GetHandle(), map_it->second->GetEntries()}; - } - } - -private: - std::unordered_map<KeyConfigType, OGLShaderStage*> shader_map; - std::unordered_map<std::string, OGLShaderStage> shader_cache; -}; - -using VertexShaders = ShaderCache<MaxwellVSConfig, &GenerateVertexShader, GL_VERTEX_SHADER>; - -using FragmentShaders = ShaderCache<MaxwellFSConfig, &GenerateFragmentShader, GL_FRAGMENT_SHADER>; - class ProgramManager { public: ProgramManager() { pipeline.Create(); } - ShaderEntries UseProgrammableVertexShader(const MaxwellVSConfig& config, - const ShaderSetup& setup) { - ShaderEntries result; - std::tie(current.vs, result) = vertex_shaders.Get(config, setup); - return result; - } - - ShaderEntries UseProgrammableFragmentShader(const MaxwellFSConfig& config, - const ShaderSetup& setup) { - ShaderEntries result; - std::tie(current.fs, result) = fragment_shaders.Get(config, setup); - return result; + void UseProgrammableVertexShader(GLuint program) { + vs = program; } - GLuint GetCurrentProgramStage(Maxwell3D::Regs::ShaderStage stage) const { - switch (stage) { - case Maxwell3D::Regs::ShaderStage::Vertex: - return current.vs; - case Maxwell3D::Regs::ShaderStage::Fragment: - return current.fs; - } - - UNREACHABLE(); + void UseProgrammableFragmentShader(GLuint program) { + fs = program; } void UseTrivialGeometryShader() { - current.gs = 0; + gs = 0; } void ApplyTo(OpenGLState& state) { @@ -140,35 +53,16 @@ public: GL_VERTEX_SHADER_BIT | GL_GEOMETRY_SHADER_BIT | GL_FRAGMENT_SHADER_BIT, 0); - glUseProgramStages(pipeline.handle, GL_VERTEX_SHADER_BIT, current.vs); - glUseProgramStages(pipeline.handle, GL_GEOMETRY_SHADER_BIT, current.gs); - glUseProgramStages(pipeline.handle, GL_FRAGMENT_SHADER_BIT, current.fs); + glUseProgramStages(pipeline.handle, GL_VERTEX_SHADER_BIT, vs); + glUseProgramStages(pipeline.handle, GL_GEOMETRY_SHADER_BIT, gs); + glUseProgramStages(pipeline.handle, GL_FRAGMENT_SHADER_BIT, fs); state.draw.shader_program = 0; state.draw.program_pipeline = pipeline.handle; } private: - struct ShaderTuple { - GLuint vs = 0, gs = 0, fs = 0; - bool operator==(const ShaderTuple& rhs) const { - return std::tie(vs, gs, fs) == std::tie(rhs.vs, rhs.gs, rhs.fs); - } - struct Hash { - std::size_t operator()(const ShaderTuple& tuple) const { - std::size_t hash = 0; - boost::hash_combine(hash, tuple.vs); - boost::hash_combine(hash, tuple.gs); - boost::hash_combine(hash, tuple.fs); - return hash; - } - }; - }; - ShaderTuple current; - VertexShaders vertex_shaders; - FragmentShaders fragment_shaders; - - std::unordered_map<ShaderTuple, OGLProgram, ShaderTuple::Hash> program_cache; OGLPipeline pipeline; + GLuint vs{}, fs{}, gs{}; }; } // namespace OpenGL::GLShader |