diff options
author | Konstantin Käfer <mail@kkaefer.com> | 2019-03-19 14:02:10 +0100 |
---|---|---|
committer | Konstantin Käfer <mail@kkaefer.com> | 2019-03-20 15:40:47 +0100 |
commit | 1e30fdac36233c0fd0662e2b285b0424907bc81d (patch) | |
tree | eb61b156b5445639939eab47f5ded9a385b25fd9 /src/mbgl/gl | |
parent | 53ab65d81165daf4e23ce28fa0e42861724ea687 (diff) | |
download | qtlocation-mapboxgl-1e30fdac36233c0fd0662e2b285b0424907bc81d.tar.gz |
[core] move ProgramMap to within the gl::Program object
Diffstat (limited to 'src/mbgl/gl')
-rw-r--r-- | src/mbgl/gl/attribute.hpp | 31 | ||||
-rw-r--r-- | src/mbgl/gl/context.cpp | 6 | ||||
-rw-r--r-- | src/mbgl/gl/context.hpp | 2 | ||||
-rw-r--r-- | src/mbgl/gl/program.hpp | 203 |
4 files changed, 158 insertions, 84 deletions
diff --git a/src/mbgl/gl/attribute.hpp b/src/mbgl/gl/attribute.hpp index 62c89178cd..c7f9ba3fd4 100644 --- a/src/mbgl/gl/attribute.hpp +++ b/src/mbgl/gl/attribute.hpp @@ -95,5 +95,36 @@ public: } }; +template <class> +class AttributeKey; + +constexpr auto attributeDefinePrefix() { + return "#define HAS_UNIFORM_u_"; +} + +template <class... As> +class AttributeKey<TypeList<As...>> final { +public: + static_assert(sizeof...(As) <= 32, "attribute count exceeds 32"); + + static uint32_t compute(const gfx::AttributeBindings<TypeList<As...>>& bindings) { + uint32_t value = 0; + util::ignore( + { (bindings.template get<As>() ? (void)(value |= 1 << TypeIndex<As, As...>::value) + : (void)0, + 0)... }); + return value; + } + + static std::string defines(const gfx::AttributeBindings<TypeList<As...>>& bindings) { + std::string result; + util::ignore({ (!bindings.template get<As>() + ? (void)(result += concat_literals<&attributeDefinePrefix, &As::name, &string_literal<'\n'>::value>::value()) + : (void)0, + 0)... }); + return result; + } +}; + } // namespace gl } // namespace mbgl diff --git a/src/mbgl/gl/context.cpp b/src/mbgl/gl/context.cpp index 1f780331c2..eff3c2160c 100644 --- a/src/mbgl/gl/context.cpp +++ b/src/mbgl/gl/context.cpp @@ -160,12 +160,10 @@ void Context::enableDebugging() { MBGL_CHECK_ERROR(debugging->debugMessageCallback(extension::Debugging::DebugCallback, nullptr)); } -UniqueShader Context::createShader(ShaderType type, const std::string& source) { +UniqueShader Context::createShader(ShaderType type, const std::initializer_list<const char*>& sources) { UniqueShader result { MBGL_CHECK_ERROR(glCreateShader(static_cast<GLenum>(type))), { this } }; - const GLchar* sources = source.data(); - const auto lengths = static_cast<GLsizei>(source.length()); - MBGL_CHECK_ERROR(glShaderSource(result, 1, &sources, &lengths)); + MBGL_CHECK_ERROR(glShaderSource(result, static_cast<GLsizei>(sources.size()), sources.begin(), nullptr)); MBGL_CHECK_ERROR(glCompileShader(result)); GLint status = 0; diff --git a/src/mbgl/gl/context.hpp b/src/mbgl/gl/context.hpp index 754b29c03e..8a67213628 100644 --- a/src/mbgl/gl/context.hpp +++ b/src/mbgl/gl/context.hpp @@ -46,7 +46,7 @@ public: void enableDebugging(); - UniqueShader createShader(ShaderType type, const std::string& source); + UniqueShader createShader(ShaderType type, const std::initializer_list<const char*>& sources); UniqueProgram createProgram(ShaderID vertexShader, ShaderID fragmentShader); UniqueProgram createProgram(BinaryProgramFormat binaryFormat, const std::string& binaryProgram); void verifyProgramLinkage(ProgramID); diff --git a/src/mbgl/gl/program.hpp b/src/mbgl/gl/program.hpp index 9028ffdf53..1cec7671a1 100644 --- a/src/mbgl/gl/program.hpp +++ b/src/mbgl/gl/program.hpp @@ -18,6 +18,7 @@ #include <mbgl/util/logging.hpp> #include <mbgl/programs/program_parameters.hpp> +#include <mbgl/programs/gl/shader_source.hpp> #include <mbgl/programs/gl/shaders.hpp> #include <string> @@ -31,93 +32,128 @@ public: using AttributeList = typename Name::AttributeList; using UniformList = typename Name::UniformList; using TextureList = typename Name::TextureList; - - Program(Context& context, const std::string& vertexSource, const std::string& fragmentSource) - : program( - context.createProgram(context.createShader(ShaderType::Vertex, vertexSource), - context.createShader(ShaderType::Fragment, fragmentSource))), - attributeLocations(context, program) { - // Re-link program after manually binding only active attributes in Attributes::queryLocations - context.linkProgram(program); - - // We have to re-initialize the uniforms state from the bindings as the uniform locations - // get shifted on some implementations - uniformStates.queryLocations(program); - - // Texture units are specified via uniforms as well, so we need query their locations - textureStates.queryLocations(program); - } - template <class BinaryProgram> - Program(Context& context, const BinaryProgram& binaryProgram) - : program(context.createProgram(binaryProgram.format(), binaryProgram.code())), - attributeLocations(binaryProgram) { - uniformStates.loadNamedLocations(binaryProgram); - textureStates.loadNamedLocations(binaryProgram); + Program(ProgramParameters programParameters_) + : programParameters(std::move(programParameters_)) { } - static std::unique_ptr<Program> createProgram(gl::Context& context, - const ProgramParameters& programParameters, - const char* name, - const char* vertexSource_, - const char* fragmentSource_) { - const std::string vertexSource = programs::gl::vertexSource(programParameters, vertexSource_); - const std::string fragmentSource = programs::gl::fragmentSource(programParameters, fragmentSource_); + const ProgramParameters programParameters; + + static constexpr const auto vertexOffset = programs::gl::ShaderSource<Name>::vertexOffset; + static constexpr const auto fragmentOffset = programs::gl::ShaderSource<Name>::fragmentOffset; + + class Instance { + public: + Instance(Context& context, + const std::initializer_list<const char*>& vertexSource, + const std::initializer_list<const char*>& fragmentSource) + : program(context.createProgram( + context.createShader(ShaderType::Vertex, vertexSource), + context.createShader(ShaderType::Fragment, fragmentSource))), + attributeLocations(context, program) { + // Re-link program after manually binding only active attributes in Attributes::queryLocations + context.linkProgram(program); + + // We have to re-initialize the uniforms state from the bindings as the uniform locations + // get shifted on some implementations + uniformStates.queryLocations(program); + + // Texture units are specified via uniforms as well, so we need query their locations + textureStates.queryLocations(program); + } + + template <class BinaryProgram> + Instance(Context& context, const BinaryProgram& binaryProgram) + : program(context.createProgram(binaryProgram.format(), binaryProgram.code())), + attributeLocations(binaryProgram) { + uniformStates.loadNamedLocations(binaryProgram); + textureStates.loadNamedLocations(binaryProgram); + } + + static std::unique_ptr<Instance> + createInstance(gl::Context& context, + const ProgramParameters& programParameters, + const std::string& additionalDefines) { + + #if MBGL_HAS_BINARY_PROGRAMS - optional<std::string> cachePath = programParameters.cachePath(name); - if (cachePath && context.supportsProgramBinaries()) { - const std::string identifier = programs::gl::programIdentifier(vertexSource, fragmentSource); - - try { - if (auto cachedBinaryProgram = util::readFile(*cachePath)) { - const BinaryProgram binaryProgram(std::move(*cachedBinaryProgram)); - if (binaryProgram.identifier() == identifier) { - return std::make_unique<Program>(context, binaryProgram); - } else { - Log::Warning(Event::OpenGL, - "Cached program %s changed. Recompilation required.", - name); + optional<std::string> cachePath = + programParameters.cachePath(programs::gl::ShaderSource<Name>::name); + std::string programIdentifier; + if (cachePath && context.supportsProgramBinaries()) { + programIdentifier = programs::gl::programIdentifier( + programParameters.getDefines(), additionalDefines, programs::gl::preludeHash, + programs::gl::ShaderSource<Name>::hash); + + try { + if (auto cachedBinaryProgram = util::readFile(*cachePath)) { + const BinaryProgram binaryProgram(std::move(*cachedBinaryProgram)); + if (binaryProgram.identifier() == programIdentifier) { + return std::make_unique<Instance>(context, binaryProgram); + } else { + Log::Warning(Event::OpenGL, + "Cached program %s changed. Recompilation required.", + programs::gl::ShaderSource<Name>::name); + } } + } catch (std::runtime_error& error) { + Log::Warning(Event::OpenGL, "Could not load cached program: %s", + error.what()); } - } catch (std::runtime_error& error) { - Log::Warning(Event::OpenGL, "Could not load cached program: %s", - error.what()); } +#endif // Compile the shader - auto result = std::make_unique<Program>(context, vertexSource, fragmentSource); + const std::initializer_list<const char*> vertexSource = { + programParameters.getDefines().c_str(), + additionalDefines.c_str(), + (programs::gl::shaderSource() + programs::gl::vertexPreludeOffset), + (programs::gl::shaderSource() + vertexOffset) + }; + const std::initializer_list<const char*> fragmentSource = { + programParameters.getDefines().c_str(), + additionalDefines.c_str(), + (programs::gl::shaderSource() + programs::gl::fragmentPreludeOffset), + (programs::gl::shaderSource() + fragmentOffset) + }; + auto result = std::make_unique<Instance>(context, vertexSource, fragmentSource); - try { - if (const auto binaryProgram = - result->template get<BinaryProgram>(context, identifier)) { - util::write_file(*cachePath, binaryProgram->serialize()); - Log::Warning(Event::OpenGL, "Caching program in: %s", (*cachePath).c_str()); +#if MBGL_HAS_BINARY_PROGRAMS + if (cachePath && context.supportsProgramBinaries()) { + try { + if (const auto binaryProgram = + result->template get<BinaryProgram>(context, programIdentifier)) { + util::write_file(*cachePath, binaryProgram->serialize()); + Log::Warning(Event::OpenGL, "Caching program in: %s", (*cachePath).c_str()); + } + } catch (std::runtime_error& error) { + Log::Warning(Event::OpenGL, "Failed to cache program: %s", error.what()); } - } catch (std::runtime_error& error) { - Log::Warning(Event::OpenGL, "Failed to cache program: %s", error.what()); } - +#endif + return std::move(result); } -#endif - (void)name; - return std::make_unique<Program>(context, vertexSource, fragmentSource); - } - - template <class BinaryProgram> - optional<BinaryProgram> get(Context& context, const std::string& identifier) const { - if (auto binaryProgram = context.getBinaryProgram(program)) { - return BinaryProgram{ binaryProgram->first, - std::move(binaryProgram->second), - identifier, - attributeLocations.getNamedLocations(), - uniformStates.getNamedLocations(), - textureStates.getNamedLocations() }; + template <class BinaryProgram> + optional<BinaryProgram> get(Context& context, const std::string& identifier) const { + if (auto binaryProgram = context.getBinaryProgram(program)) { + return BinaryProgram{ binaryProgram->first, + std::move(binaryProgram->second), + identifier, + attributeLocations.getNamedLocations(), + uniformStates.getNamedLocations(), + textureStates.getNamedLocations() }; + } + return {}; } - return {}; - } + + UniqueProgram program; + gl::AttributeLocations<AttributeList> attributeLocations; + gl::UniformStates<UniformList> uniformStates; + gl::TextureStates<TextureList> textureStates; + }; void draw(gfx::Context& genericContext, const gfx::DrawMode& drawMode, @@ -139,16 +175,29 @@ public: context.setColorMode(colorMode); context.setCullFaceMode(cullFaceMode); - context.program = program; + const uint32_t key = gl::AttributeKey<AttributeList>::compute(attributeBindings); + auto it = instances.find(key); + if (it == instances.end()) { + it = instances + .emplace(key, + Instance::createInstance( + context, + programParameters, + gl::AttributeKey<AttributeList>::defines(attributeBindings))) + .first; + } - uniformStates.bind(uniformValues); + auto& instance = *it->second; + context.program = instance.program; - textureStates.bind(context, textureBindings); + instance.uniformStates.bind(uniformValues); + + instance.textureStates.bind(context, textureBindings); auto& vertexArray = reinterpret_cast<gl::DrawScopeResource&>(*drawScope.resource).vertexArray; vertexArray.bind(context, indexBuffer, - attributeLocations.toBindingArray(attributeBindings)); + instance.attributeLocations.toBindingArray(attributeBindings)); context.draw(drawMode, indexOffset, @@ -156,11 +205,7 @@ public: } private: - UniqueProgram program; - - gl::AttributeLocations<AttributeList> attributeLocations; - gl::UniformStates<UniformList> uniformStates; - gl::TextureStates<TextureList> textureStates; + std::map<uint32_t, std::unique_ptr<Instance>> instances; }; } // namespace gl |