diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/mbgl/gl/attribute.hpp | 13 | ||||
-rw-r--r-- | src/mbgl/gl/context.cpp | 49 | ||||
-rw-r--r-- | src/mbgl/gl/context.hpp | 10 | ||||
-rw-r--r-- | src/mbgl/gl/features.hpp | 7 | ||||
-rw-r--r-- | src/mbgl/gl/program.hpp | 30 | ||||
-rw-r--r-- | src/mbgl/gl/program_binary.cpp | 24 | ||||
-rw-r--r-- | src/mbgl/gl/program_binary.hpp | 27 | ||||
-rw-r--r-- | src/mbgl/gl/types.hpp | 2 | ||||
-rw-r--r-- | src/mbgl/gl/uniform.hpp | 13 | ||||
-rw-r--r-- | src/mbgl/map/map.cpp | 16 | ||||
-rw-r--r-- | src/mbgl/programs/binary_program.cpp | 117 | ||||
-rw-r--r-- | src/mbgl/programs/binary_program.hpp | 43 | ||||
-rw-r--r-- | src/mbgl/programs/program.hpp | 58 | ||||
-rw-r--r-- | src/mbgl/programs/program_parameters.hpp | 15 | ||||
-rw-r--r-- | src/mbgl/programs/programs.hpp | 4 | ||||
-rw-r--r-- | src/mbgl/renderer/painter.cpp | 16 | ||||
-rw-r--r-- | src/mbgl/renderer/painter.hpp | 2 | ||||
-rw-r--r-- | src/mbgl/shaders/shaders.cpp | 14 | ||||
-rw-r--r-- | src/mbgl/shaders/shaders.hpp | 2 | ||||
-rw-r--r-- | src/mbgl/util/io.cpp | 10 | ||||
-rw-r--r-- | src/mbgl/util/io.hpp | 3 |
21 files changed, 443 insertions, 32 deletions
diff --git a/src/mbgl/gl/attribute.hpp b/src/mbgl/gl/attribute.hpp index ab97ada0f2..d5e8edfc70 100644 --- a/src/mbgl/gl/attribute.hpp +++ b/src/mbgl/gl/attribute.hpp @@ -7,6 +7,7 @@ #include <mbgl/util/variant.hpp> #include <cstddef> +#include <vector> #include <functional> namespace mbgl { @@ -244,16 +245,26 @@ public: using VariableBindings = IndexedTuple< TypeList<As...>, TypeList<optional<typename As::Type::VariableBinding>...>>; + using NamedLocations = std::vector<std::pair<const std::string, AttributeLocation>>; using Vertex = detail::Vertex<typename As::Type...>; template <class A> static constexpr std::size_t Index = TypeIndex<A, As...>::value; - static Locations locations(const ProgramID& id) { + static Locations bindLocations(const ProgramID& id) { return Locations { bindAttributeLocation(id, Index<As>, As::name())... }; } + template <class Program> + static Locations loadNamedLocations(const Program& program) { + return Locations{ program.attributeLocation(As::name())... }; + } + + static NamedLocations getNamedLocations(const Locations& locations) { + return NamedLocations{ { As::name(), locations.template get<As>() }... }; + } + template <class DrawMode> static Bindings allVariableBindings(const VertexBuffer<Vertex, DrawMode>& buffer) { return Bindings { As::Type::variableBinding(buffer, Index<As>)... }; diff --git a/src/mbgl/gl/context.cpp b/src/mbgl/gl/context.cpp index 9c2031ccfd..97ebf687f9 100644 --- a/src/mbgl/gl/context.cpp +++ b/src/mbgl/gl/context.cpp @@ -2,6 +2,7 @@ #include <mbgl/gl/context.hpp> #include <mbgl/gl/gl.hpp> #include <mbgl/gl/vertex_array.hpp> +#include <mbgl/gl/program_binary.hpp> #include <mbgl/util/traits.hpp> #include <mbgl/util/std.hpp> #include <mbgl/util/logging.hpp> @@ -34,6 +35,8 @@ static_assert(std::is_same<std::underlying_type_t<TextureFormat>, GLenum>::value static_assert(underlying_type(TextureFormat::RGBA) == GL_RGBA, "OpenGL type mismatch"); static_assert(underlying_type(TextureFormat::Alpha) == GL_ALPHA, "OpenGL type mismatch"); +static_assert(std::is_same<BinaryProgramFormat, GLenum>::value, "OpenGL type mismatch"); + Context::~Context() { reset(); } @@ -72,9 +75,27 @@ UniqueProgram Context::createProgram(ShaderID vertexShader, ShaderID fragmentSha return result; } +#if MBGL_HAS_BINARY_PROGRAMS +UniqueProgram Context::createProgram(BinaryProgramFormat binaryFormat, + const std::string& binaryProgram) { + UniqueProgram result{ MBGL_CHECK_ERROR(glCreateProgram()), { this } }; + MBGL_CHECK_ERROR(ProgramBinary(result, static_cast<GLenum>(binaryFormat), binaryProgram.data(), + static_cast<GLint>(binaryProgram.size()))); + verifyProgramLinkage(result); + return result; +} +#else +UniqueProgram Context::createProgram(BinaryProgramFormat, const std::string&) { + throw std::runtime_error("binary programs are not supported"); +} +#endif + void Context::linkProgram(ProgramID program_) { MBGL_CHECK_ERROR(glLinkProgram(program_)); + verifyProgramLinkage(program_); +} +void Context::verifyProgramLinkage(ProgramID program_) { GLint status; MBGL_CHECK_ERROR(glGetProgramiv(program_, GL_LINK_STATUS, &status)); if (status == GL_TRUE) { @@ -129,6 +150,34 @@ bool Context::supportsVertexArrays() const { !disableVAOExtension; } +#if MBGL_HAS_BINARY_PROGRAMS +bool Context::supportsProgramBinaries() const { + return gl::ProgramBinary && gl::GetProgramBinary; +} + +optional<std::pair<BinaryProgramFormat, std::string>> +Context::getBinaryProgram(ProgramID program_) const { + if (!supportsProgramBinaries()) { + return {}; + } + GLint binaryLength; + MBGL_CHECK_ERROR(glGetProgramiv(program_, GL_PROGRAM_BINARY_LENGTH, &binaryLength)); + std::string binary; + binary.resize(binaryLength); + GLenum binaryFormat; + MBGL_CHECK_ERROR(GetProgramBinary(program_, binaryLength, &binaryLength, &binaryFormat, + const_cast<char*>(binary.data()))); + if (size_t(binaryLength) != binary.size()) { + return {}; + } + return { { binaryFormat, std::move(binary) } }; +} +#else +optional<std::pair<BinaryProgramFormat, std::string>> Context::getBinaryProgram(ProgramID) const { + return {}; +} +#endif + UniqueVertexArray Context::createVertexArray() { assert(supportsVertexArrays()); VertexArrayID id = 0; diff --git a/src/mbgl/gl/context.hpp b/src/mbgl/gl/context.hpp index e4cc5a3af2..10ff4360d3 100644 --- a/src/mbgl/gl/context.hpp +++ b/src/mbgl/gl/context.hpp @@ -1,5 +1,6 @@ #pragma once +#include <mbgl/gl/features.hpp> #include <mbgl/gl/object.hpp> #include <mbgl/gl/state.hpp> #include <mbgl/gl/value.hpp> @@ -36,12 +37,21 @@ public: UniqueShader createShader(ShaderType type, const std::string& source); UniqueProgram createProgram(ShaderID vertexShader, ShaderID fragmentShader); + UniqueProgram createProgram(BinaryProgramFormat binaryFormat, const std::string& binaryProgram); + void verifyProgramLinkage(ProgramID); void linkProgram(ProgramID); UniqueTexture createTexture(); bool supportsVertexArrays() const; UniqueVertexArray createVertexArray(); +#if MBGL_HAS_BINARY_PROGRAMS + bool supportsProgramBinaries() const; +#else + constexpr bool supportsProgramBinaries() const { return false; } +#endif + optional<std::pair<BinaryProgramFormat, std::string>> getBinaryProgram(ProgramID) const; + template <class Vertex, class DrawMode> VertexBuffer<Vertex, DrawMode> createVertexBuffer(VertexVector<Vertex, DrawMode>&& v) { return VertexBuffer<Vertex, DrawMode> { diff --git a/src/mbgl/gl/features.hpp b/src/mbgl/gl/features.hpp new file mode 100644 index 0000000000..04dc4fa02e --- /dev/null +++ b/src/mbgl/gl/features.hpp @@ -0,0 +1,7 @@ +#pragma once + +#if __APPLE__ + #define MBGL_HAS_BINARY_PROGRAMS 0 +#else + #define MBGL_HAS_BINARY_PROGRAMS 1 +#endif
\ No newline at end of file diff --git a/src/mbgl/gl/program.hpp b/src/mbgl/gl/program.hpp index fa0470796e..7d7fca5263 100644 --- a/src/mbgl/gl/program.hpp +++ b/src/mbgl/gl/program.hpp @@ -24,11 +24,29 @@ public: using AttributeBindings = typename Attributes::Bindings; Program(Context& context, const std::string& vertexSource, const std::string& fragmentSource) - : vertexShader(context.createShader(ShaderType::Vertex, vertexSource)), - fragmentShader(context.createShader(ShaderType::Fragment, fragmentSource)), - program(context.createProgram(vertexShader, fragmentShader)), - attributeLocations(Attributes::locations(program)), - uniformsState((context.linkProgram(program), Uniforms::state(program))) {} + : program( + context.createProgram(context.createShader(ShaderType::Vertex, vertexSource), + context.createShader(ShaderType::Fragment, fragmentSource))), + attributeLocations(Attributes::bindLocations(program)), + uniformsState((context.linkProgram(program), Uniforms::bindLocations(program))) { + } + + template <class BinaryProgram> + Program(Context& context, const BinaryProgram& binaryProgram) + : program(context.createProgram(binaryProgram.format(), binaryProgram.code())), + attributeLocations(Attributes::loadNamedLocations(binaryProgram)), + uniformsState(Uniforms::loadNamedLocations(binaryProgram)) { + } + + 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, Attributes::getNamedLocations(attributeLocations), + Uniforms::getNamedLocations(uniformsState) }; + } + return {}; + } template <class DrawMode> void draw(Context& context, @@ -64,8 +82,6 @@ public: } private: - UniqueShader vertexShader; - UniqueShader fragmentShader; UniqueProgram program; typename Attributes::Locations attributeLocations; diff --git a/src/mbgl/gl/program_binary.cpp b/src/mbgl/gl/program_binary.cpp new file mode 100644 index 0000000000..ad147c819f --- /dev/null +++ b/src/mbgl/gl/program_binary.cpp @@ -0,0 +1,24 @@ +#include <mbgl/gl/program_binary.hpp> + +#if MBGL_HAS_BINARY_PROGRAMS + +namespace mbgl { +namespace gl { + +ExtensionFunction< + void(GLuint program, GLsizei bufSize, GLsizei* length, GLenum* binaryFormat, GLvoid* binary)> + GetProgramBinary({ + { "GL_OES_get_program_binary", "glGetProgramBinaryOES" }, + { "GL_ARB_get_program_binary", "glGetProgramBinary" }, + }); + +ExtensionFunction<void(GLuint program, GLenum binaryFormat, const GLvoid* binary, GLint length)> + ProgramBinary({ + { "GL_OES_get_program_binary", "glProgramBinaryOES" }, + { "GL_ARB_get_program_binary", "glProgramBinary" }, + }); + +} // namespace gl +} // namespace mbgl + +#endif diff --git a/src/mbgl/gl/program_binary.hpp b/src/mbgl/gl/program_binary.hpp new file mode 100644 index 0000000000..e888ed3d4a --- /dev/null +++ b/src/mbgl/gl/program_binary.hpp @@ -0,0 +1,27 @@ +#pragma once + +#include <mbgl/gl/features.hpp> +#include <mbgl/gl/extension.hpp> +#include <mbgl/gl/gl.hpp> + +#if MBGL_HAS_BINARY_PROGRAMS + +#define GL_PROGRAM_BINARY_LENGTH 0x8741 +#define GL_NUM_PROGRAM_BINARY_FORMATS 0x87FE +#define GL_PROGRAM_BINARY_FORMATS 0x87FF + +namespace mbgl { +namespace gl { + +extern ExtensionFunction<void( + GLuint program, GLsizei bufSize, GLsizei* length, GLenum* binaryFormat, GLvoid* binary)> + GetProgramBinary; + +extern ExtensionFunction<void( + GLuint program, GLenum binaryFormat, const GLvoid* binary, GLint length)> + ProgramBinary; + +} // namespace gl +} // namespace mbgl + +#endif diff --git a/src/mbgl/gl/types.hpp b/src/mbgl/gl/types.hpp index 565ca5754f..7d436693c9 100644 --- a/src/mbgl/gl/types.hpp +++ b/src/mbgl/gl/types.hpp @@ -73,5 +73,7 @@ constexpr bool operator!=(const PixelStorageType& a, const PixelStorageType& b) #endif // MBGL_USE_GLES2 +using BinaryProgramFormat = uint32_t; + } // namespace gl } // namespace mbgl diff --git a/src/mbgl/gl/uniform.hpp b/src/mbgl/gl/uniform.hpp index 92136b61c2..34a32aeee9 100644 --- a/src/mbgl/gl/uniform.hpp +++ b/src/mbgl/gl/uniform.hpp @@ -6,6 +6,7 @@ #include <mbgl/util/indexed_tuple.hpp> #include <array> +#include <vector> #include <functional> namespace mbgl { @@ -66,11 +67,21 @@ public: using Types = TypeList<Us...>; using State = IndexedTuple<TypeList<Us...>, TypeList<typename Us::State...>>; using Values = IndexedTuple<TypeList<Us...>, TypeList<typename Us::Value...>>; + using NamedLocations = std::vector<std::pair<const std::string, UniformLocation>>; - static State state(const ProgramID& id) { + static State bindLocations(const ProgramID& id) { return State { { uniformLocation(id, Us::name()) }... }; } + template <class Program> + static State loadNamedLocations(const Program& program) { + return State{ { program.uniformLocation(Us::name()) }... }; + } + + static NamedLocations getNamedLocations(const State& state) { + return NamedLocations{ { Us::name(), state.template get<Us>().location }... }; + } + static void bind(State& state, Values&& values) { util::ignore({ (state.template get<Us>() = values.template get<Us>(), 0)... }); } diff --git a/src/mbgl/map/map.cpp b/src/mbgl/map/map.cpp index 24ae5643ee..4c787eb660 100644 --- a/src/mbgl/map/map.cpp +++ b/src/mbgl/map/map.cpp @@ -57,7 +57,8 @@ public: MapMode, GLContextMode, ConstrainMode, - ViewportMode); + ViewportMode, + const std::string& programCacheDir); void onSourceChanged(style::Source&) override; void onUpdate(Update) override; @@ -82,6 +83,7 @@ public: const MapMode mode; const GLContextMode contextMode; const float pixelRatio; + const std::string programCacheDir; MapDebugOptions debugOptions { MapDebugOptions::NoDebug }; @@ -113,7 +115,8 @@ Map::Map(Backend& backend, MapMode mapMode, GLContextMode contextMode, ConstrainMode constrainMode, - ViewportMode viewportMode) + ViewportMode viewportMode, + const std::string& programCacheDir) : impl(std::make_unique<Impl>(*this, backend, pixelRatio, @@ -122,7 +125,8 @@ Map::Map(Backend& backend, mapMode, contextMode, constrainMode, - viewportMode)) { + viewportMode, + programCacheDir)) { impl->transform.resize(size); } @@ -134,7 +138,8 @@ Map::Impl::Impl(Map& map_, MapMode mode_, GLContextMode contextMode_, ConstrainMode constrainMode_, - ViewportMode viewportMode_) + ViewportMode viewportMode_, + const std::string& programCacheDir_) : map(map_), observer(backend_), backend(backend_), @@ -146,6 +151,7 @@ Map::Impl::Impl(Map& map_, mode(mode_), contextMode(contextMode_), pixelRatio(pixelRatio_), + programCacheDir(programCacheDir_), annotationManager(std::make_unique<AnnotationManager>(pixelRatio)), asyncInvalidate([this] { if (mode == MapMode::Continuous) { @@ -262,7 +268,7 @@ void Map::Impl::render(View& view) { updateFlags = Update::Nothing; if (!painter) { - painter = std::make_unique<Painter>(backend.getContext(), transform.getState(), pixelRatio); + painter = std::make_unique<Painter>(backend.getContext(), transform.getState(), pixelRatio, programCacheDir); } if (mode == MapMode::Continuous) { diff --git a/src/mbgl/programs/binary_program.cpp b/src/mbgl/programs/binary_program.cpp new file mode 100644 index 0000000000..3b37cfa442 --- /dev/null +++ b/src/mbgl/programs/binary_program.cpp @@ -0,0 +1,117 @@ +#include <mbgl/programs/binary_program.hpp> + +#include <protozero/pbf_reader.hpp> +#include <protozero/pbf_writer.hpp> + +template <class Binding> +static std::pair<const std::string, Binding> parseBinding(protozero::pbf_reader&& pbf) { + bool hasName = false, hasValue = false; + std::pair<std::string, Binding> binding; + while (pbf.next()) { + switch (pbf.tag()) { + case 1: // name + binding.first = pbf.get_string(); + hasName = true; + break; + case 2: // value + binding.second = pbf.get_uint32(); + hasValue = true; + break; + default: + pbf.skip(); + break; + } + } + if (!hasName || !hasValue) { + throw std::runtime_error("BinaryProgram binding is missing required fields"); + } + return binding; +} + +namespace mbgl { + +BinaryProgram::BinaryProgram(std::string&& data) { + bool hasFormat = false, hasCode = false; + protozero::pbf_reader pbf(data); + while (pbf.next()) { + switch (pbf.tag()) { + case 1: // format + binaryFormat = pbf.get_uint32(); + hasFormat = true; + break; + case 2: // code + binaryCode = pbf.get_bytes(); + hasCode = true; + break; + case 3: // variable + attributes.emplace_back(parseBinding<gl::AttributeLocation>(pbf.get_message())); + break; + case 4: // uniform + uniforms.emplace_back(parseBinding<gl::UniformLocation>(pbf.get_message())); + break; + case 5: // identifier + default: + binaryIdentifier = pbf.get_string(); + break; + } + } + + if (!hasFormat || !hasCode) { + throw std::runtime_error("BinaryProgram is missing required fields"); + } +} + +BinaryProgram::BinaryProgram( + gl::BinaryProgramFormat binaryFormat_, + std::string&& binaryCode_, + const std::string& binaryIdentifier_, + std::vector<std::pair<const std::string, gl::AttributeLocation>>&& attributes_, + std::vector<std::pair<const std::string, gl::UniformLocation>>&& uniforms_) + : binaryFormat(binaryFormat_), + binaryCode(std::move(binaryCode_)), + binaryIdentifier(binaryIdentifier_), + attributes(std::move(attributes_)), + uniforms(std::move(uniforms_)) { +} + +std::string BinaryProgram::serialize() const { + std::string data; + data.reserve(32 + binaryCode.size() + uniforms.size() * 32 + attributes.size() * 32); + protozero::pbf_writer pbf(data); + pbf.add_uint32(1 /* format */, binaryFormat); + pbf.add_bytes(2 /* code */, binaryCode.data(), binaryCode.size()); + for (const auto& binding : attributes) { + protozero::pbf_writer pbf_binding(pbf, 3 /* attribute */); + pbf_binding.add_string(1 /* name */, binding.first); + pbf_binding.add_uint32(2 /* value */, binding.second); + } + for (const auto& binding : uniforms) { + protozero::pbf_writer pbf_binding(pbf, 4 /* uniform */); + pbf_binding.add_string(1 /* name */, binding.first); + pbf_binding.add_uint32(2 /* value */, binding.second); + } + if (!binaryIdentifier.empty()) { + pbf.add_string(5 /* identifier */, binaryIdentifier); + } + return data; +} + +gl::AttributeLocation BinaryProgram::attributeLocation(const std::string& name) const { + for (const auto& pair : attributes) { + if (pair.first == name) { + return pair.second; + } + } + return {}; +} + +gl::UniformLocation BinaryProgram::uniformLocation(const std::string& name) const { + for (const auto& pair : uniforms) { + if (pair.first == name) { + return pair.second; + } + } + return {}; +} + +} // namespace mbgl diff --git a/src/mbgl/programs/binary_program.hpp b/src/mbgl/programs/binary_program.hpp new file mode 100644 index 0000000000..8ff3863dc1 --- /dev/null +++ b/src/mbgl/programs/binary_program.hpp @@ -0,0 +1,43 @@ +#pragma once + +#include <mbgl/gl/types.hpp> + +#include <string> +#include <vector> + +namespace mbgl { + +class BinaryProgram { +public: + // Initialize a BinaryProgram object from a serialized represenation. + BinaryProgram(std::string&& data); + + BinaryProgram(gl::BinaryProgramFormat, + std::string&& binaryCode, + const std::string& binaryIdentifier, + std::vector<std::pair<const std::string, gl::AttributeLocation>>&&, + std::vector<std::pair<const std::string, gl::UniformLocation>>&&); + + std::string serialize() const; + + gl::BinaryProgramFormat format() const { + return binaryFormat; + } + const std::string& code() const { + return binaryCode; + } + const std::string& identifier() const { + return binaryIdentifier; + } + gl::AttributeLocation attributeLocation(const std::string& name) const; + gl::UniformLocation uniformLocation(const std::string& name) const; + +private: + gl::BinaryProgramFormat binaryFormat = 0; + std::string binaryCode; + std::string binaryIdentifier; + std::vector<std::pair<const std::string, gl::AttributeLocation>> attributes; + std::vector<std::pair<const std::string, gl::UniformLocation>> uniforms; +}; + +} // namespace mbgl diff --git a/src/mbgl/programs/program.hpp b/src/mbgl/programs/program.hpp index 8437e3a651..8925bc75d6 100644 --- a/src/mbgl/programs/program.hpp +++ b/src/mbgl/programs/program.hpp @@ -1,9 +1,13 @@ #pragma once #include <mbgl/gl/program.hpp> +#include <mbgl/gl/features.hpp> +#include <mbgl/programs/binary_program.hpp> #include <mbgl/programs/attributes.hpp> +#include <mbgl/programs/program_parameters.hpp> #include <mbgl/style/paint_property.hpp> #include <mbgl/shaders/shaders.hpp> +#include <mbgl/util/io.hpp> namespace mbgl { @@ -30,10 +34,56 @@ public: ProgramType program; Program(gl::Context& context, const ProgramParameters& programParameters) - : program(context, - shaders::vertexSource(programParameters, Shaders::vertexSource), - shaders::fragmentSource(programParameters, Shaders::fragmentSource)) - {} + : program([&] { +#if MBGL_HAS_BINARY_PROGRAMS + if (!programParameters.cacheDir.empty() && context.supportsProgramBinaries()) { + const std::string vertexSource = + shaders::vertexSource(programParameters, Shaders::vertexSource); + const std::string fragmentSource = + shaders::fragmentSource(programParameters, Shaders::fragmentSource); + const std::string cachePath = + shaders::programCachePath(programParameters, Shaders::name); + const std::string identifier = + shaders::programIdentifier(vertexSource, fragmentSource); + + try { + if (auto cachedBinaryProgram = util::readFile(cachePath)) { + const BinaryProgram binaryProgram(std::move(*cachedBinaryProgram)); + if (binaryProgram.identifier() == identifier) { + return ProgramType{ context, binaryProgram }; + } else { + Log::Warning(Event::OpenGL, + "Cached program %s changed. Recompilation required.", + Shaders::name); + } + } + } catch (std::runtime_error& error) { + Log::Warning(Event::OpenGL, "Could not load cached program: %s", + error.what()); + } + + // Compile the shader + ProgramType result{ 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()); + } + } catch (std::runtime_error& error) { + Log::Warning(Event::OpenGL, "Failed to cache program: %s", error.what()); + } + + return std::move(result); + } +#endif + return ProgramType{ + context, shaders::vertexSource(programParameters, Shaders::vertexSource), + shaders::fragmentSource(programParameters, Shaders::fragmentSource) + }; + }()) { + } template <class DrawMode> void draw(gl::Context& context, diff --git a/src/mbgl/programs/program_parameters.hpp b/src/mbgl/programs/program_parameters.hpp index ad8cbf1bf8..b91b41f358 100644 --- a/src/mbgl/programs/program_parameters.hpp +++ b/src/mbgl/programs/program_parameters.hpp @@ -1,15 +1,20 @@ #pragma once +#include <string> + namespace mbgl { class ProgramParameters { public: - ProgramParameters(float pixelRatio_ = 1.0, bool overdraw_ = false) - : pixelRatio(pixelRatio_), - overdraw(overdraw_) {} + ProgramParameters(float pixelRatio_ = 1.0, + bool overdraw_ = false, + const std::string& cacheDir_ = "") + : pixelRatio(pixelRatio_), overdraw(overdraw_), cacheDir(cacheDir_) { + } - float pixelRatio; - bool overdraw; + const float pixelRatio; + const bool overdraw; + const std::string cacheDir; }; } // namespace mbgl diff --git a/src/mbgl/programs/programs.hpp b/src/mbgl/programs/programs.hpp index 742c5a221b..dbf5b9e87d 100644 --- a/src/mbgl/programs/programs.hpp +++ b/src/mbgl/programs/programs.hpp @@ -26,8 +26,8 @@ public: symbolIcon(context, programParameters), symbolIconSDF(context, programParameters), symbolGlyph(context, programParameters), - debug(context, ProgramParameters(programParameters.pixelRatio, false)), - collisionBox(context, ProgramParameters(programParameters.pixelRatio, false)) { + debug(context, ProgramParameters(programParameters.pixelRatio, false, programParameters.cacheDir)), + collisionBox(context, ProgramParameters(programParameters.pixelRatio, false, programParameters.cacheDir)) { } CircleProgram circle; diff --git a/src/mbgl/renderer/painter.cpp b/src/mbgl/renderer/painter.cpp index 27d24d14a9..754959438b 100644 --- a/src/mbgl/renderer/painter.cpp +++ b/src/mbgl/renderer/painter.cpp @@ -33,6 +33,8 @@ #include <mbgl/util/offscreen_texture.hpp> +#include <mbgl/util/stopwatch.hpp> + #include <cassert> #include <algorithm> #include <iostream> @@ -77,7 +79,10 @@ static gl::VertexVector<RasterLayoutVertex> rasterVertices() { return result; } -Painter::Painter(gl::Context& context_, const TransformState& state_, float pixelRatio) +Painter::Painter(gl::Context& context_, + const TransformState& state_, + float pixelRatio, + const std::string& programCacheDir) : context(context_), state(state_), tileVertexBuffer(context.createVertexBuffer(tileVertices())), @@ -91,12 +96,11 @@ Painter::Painter(gl::Context& context_, const TransformState& state_, float pixe gl::debugging::enable(); - ProgramParameters programParameters{ pixelRatio, false }; - programs = std::make_unique<Programs>(context, programParameters); + programs = std::make_unique<Programs>(context, + ProgramParameters{ pixelRatio, false, programCacheDir }); #ifndef NDEBUG - - ProgramParameters programParametersOverdraw{ pixelRatio, true }; - overdrawPrograms = std::make_unique<Programs>(context, programParametersOverdraw); + overdrawPrograms = + std::make_unique<Programs>(context, ProgramParameters{ pixelRatio, true, programCacheDir }); #endif } diff --git a/src/mbgl/renderer/painter.hpp b/src/mbgl/renderer/painter.hpp index 91f329a6eb..3dcc1d5d46 100644 --- a/src/mbgl/renderer/painter.hpp +++ b/src/mbgl/renderer/painter.hpp @@ -68,7 +68,7 @@ struct FrameData { class Painter : private util::noncopyable { public: - Painter(gl::Context&, const TransformState&, float pixelRatio); + Painter(gl::Context&, const TransformState&, float pixelRatio, const std::string& programCacheDir); ~Painter(); void render(const style::Style&, diff --git a/src/mbgl/shaders/shaders.cpp b/src/mbgl/shaders/shaders.cpp index f7f5b4d44f..03d796edba 100644 --- a/src/mbgl/shaders/shaders.cpp +++ b/src/mbgl/shaders/shaders.cpp @@ -4,6 +4,7 @@ #include <cassert> #include <sstream> +#include <iomanip> namespace mbgl { namespace shaders { @@ -29,5 +30,18 @@ std::string vertexSource(const ProgramParameters& parameters, const char* vertex return pixelRatioDefine(parameters) + vertexPrelude + vertexSource; } +std::string programCachePath(const ProgramParameters& parameters, const char* name) { + return parameters.cacheDir + "/com.mapbox.gl.shader." + name + + (parameters.overdraw ? ".overdraw.pbf" : ".pbf"); +} + +std::string programIdentifier(const std::string& vertexSource, const std::string& fragmentSource) { + std::ostringstream ss; + ss << std::setfill('0') << std::setw(sizeof(size_t) * 2) << std::hex; + ss << std::hash<std::string>()(vertexSource); + ss << std::hash<std::string>()(fragmentSource); + return ss.str(); +} + } // namespace shaders } // namespace mbgl diff --git a/src/mbgl/shaders/shaders.hpp b/src/mbgl/shaders/shaders.hpp index e2912c5688..126c64bb9e 100644 --- a/src/mbgl/shaders/shaders.hpp +++ b/src/mbgl/shaders/shaders.hpp @@ -10,6 +10,8 @@ namespace shaders { std::string fragmentSource(const ProgramParameters&, const char* fragmentSource); std::string vertexSource(const ProgramParameters&, const char* vertexSource); +std::string programCachePath(const ProgramParameters&, const char* name); +std::string programIdentifier(const std::string& vertexSource, const std::string& fragmentSource); } // namespace shaders } // namespace mbgl diff --git a/src/mbgl/util/io.cpp b/src/mbgl/util/io.cpp index f37ce09cff..9adc3b8988 100644 --- a/src/mbgl/util/io.cpp +++ b/src/mbgl/util/io.cpp @@ -32,6 +32,16 @@ std::string read_file(const std::string &filename) { } } +optional<std::string> readFile(const std::string &filename) { + std::ifstream file(filename); + if (file.good()) { + std::stringstream data; + data << file.rdbuf(); + return data.str(); + } + return {}; +} + void deleteFile(const std::string& filename) { const int ret = unlink(filename.c_str()); if (ret == -1) { diff --git a/src/mbgl/util/io.hpp b/src/mbgl/util/io.hpp index 795a465328..847271acf0 100644 --- a/src/mbgl/util/io.hpp +++ b/src/mbgl/util/io.hpp @@ -1,5 +1,7 @@ #pragma once +#include <mbgl/util/optional.hpp> + #include <string> #include <stdexcept> @@ -15,6 +17,7 @@ struct IOException : std::runtime_error { void write_file(const std::string &filename, const std::string &data); std::string read_file(const std::string &filename); +optional<std::string> readFile(const std::string &filename); void deleteFile(const std::string& filename); } // namespace util |