From 60717822e6a5f4b9262241cb4f4504d723b3a82b Mon Sep 17 00:00:00 2001 From: Anand Thakker Date: Wed, 22 Mar 2017 14:32:22 -0400 Subject: Use highp for color attributes (#8496) Addresses #8385 Updates shaders to reflect https://github.com/mapbox/mapbox-gl-js/pull/4476 --- src/mbgl/shaders/circle.cpp | 12 ++++++------ src/mbgl/shaders/debug.cpp | 2 +- src/mbgl/shaders/fill.cpp | 6 +++--- src/mbgl/shaders/fill_outline.cpp | 6 +++--- src/mbgl/shaders/line.cpp | 6 +++--- src/mbgl/shaders/line_sdf.cpp | 6 +++--- src/mbgl/shaders/symbol_sdf.cpp | 12 ++++++------ 7 files changed, 25 insertions(+), 25 deletions(-) (limited to 'src') diff --git a/src/mbgl/shaders/circle.cpp b/src/mbgl/shaders/circle.cpp index b479f1d40c..1c977d2bce 100644 --- a/src/mbgl/shaders/circle.cpp +++ b/src/mbgl/shaders/circle.cpp @@ -14,8 +14,8 @@ uniform vec2 u_extrude_scale; attribute vec2 a_pos; uniform lowp float a_color_t; -attribute lowp vec4 a_color; -varying lowp vec4 color; +attribute highp vec4 a_color; +varying highp vec4 color; uniform lowp float a_radius_t; attribute mediump vec2 a_radius; varying mediump float radius; @@ -26,8 +26,8 @@ uniform lowp float a_opacity_t; attribute lowp vec2 a_opacity; varying lowp float opacity; uniform lowp float a_stroke_color_t; -attribute lowp vec4 a_stroke_color; -varying lowp vec4 stroke_color; +attribute highp vec4 a_stroke_color; +varying highp vec4 stroke_color; uniform lowp float a_stroke_width_t; attribute mediump vec2 a_stroke_width; varying mediump float stroke_width; @@ -69,11 +69,11 @@ void main(void) { )MBGL_SHADER"; const char* circle::fragmentSource = R"MBGL_SHADER( -varying lowp vec4 color; +varying highp vec4 color; varying mediump float radius; varying lowp float blur; varying lowp float opacity; -varying lowp vec4 stroke_color; +varying highp vec4 stroke_color; varying mediump float stroke_width; varying lowp float stroke_opacity; diff --git a/src/mbgl/shaders/debug.cpp b/src/mbgl/shaders/debug.cpp index 27a15698d4..d39dcf25be 100644 --- a/src/mbgl/shaders/debug.cpp +++ b/src/mbgl/shaders/debug.cpp @@ -17,7 +17,7 @@ void main() { )MBGL_SHADER"; const char* debug::fragmentSource = R"MBGL_SHADER( -uniform lowp vec4 u_color; +uniform highp vec4 u_color; void main() { gl_FragColor = u_color; diff --git a/src/mbgl/shaders/fill.cpp b/src/mbgl/shaders/fill.cpp index a1fba4d749..0b775273d2 100644 --- a/src/mbgl/shaders/fill.cpp +++ b/src/mbgl/shaders/fill.cpp @@ -12,8 +12,8 @@ attribute vec2 a_pos; uniform mat4 u_matrix; uniform lowp float a_color_t; -attribute lowp vec4 a_color; -varying lowp vec4 color; +attribute highp vec4 a_color; +varying highp vec4 color; uniform lowp float a_opacity_t; attribute lowp vec2 a_opacity; varying lowp float opacity; @@ -27,7 +27,7 @@ void main() { )MBGL_SHADER"; const char* fill::fragmentSource = R"MBGL_SHADER( -varying lowp vec4 color; +varying highp vec4 color; varying lowp float opacity; void main() { diff --git a/src/mbgl/shaders/fill_outline.cpp b/src/mbgl/shaders/fill_outline.cpp index 74201b518d..3e160ac6c2 100644 --- a/src/mbgl/shaders/fill_outline.cpp +++ b/src/mbgl/shaders/fill_outline.cpp @@ -15,8 +15,8 @@ uniform vec2 u_world; varying vec2 v_pos; uniform lowp float a_outline_color_t; -attribute lowp vec4 a_outline_color; -varying lowp vec4 outline_color; +attribute highp vec4 a_outline_color; +varying highp vec4 outline_color; uniform lowp float a_opacity_t; attribute lowp vec2 a_opacity; varying lowp float opacity; @@ -31,7 +31,7 @@ void main() { )MBGL_SHADER"; const char* fill_outline::fragmentSource = R"MBGL_SHADER( -varying lowp vec4 outline_color; +varying highp vec4 outline_color; varying lowp float opacity; varying vec2 v_pos; diff --git a/src/mbgl/shaders/line.cpp b/src/mbgl/shaders/line.cpp index dc4aa774dc..4392bd051f 100644 --- a/src/mbgl/shaders/line.cpp +++ b/src/mbgl/shaders/line.cpp @@ -34,8 +34,8 @@ varying vec2 v_width2; varying float v_gamma_scale; uniform lowp float a_color_t; -attribute lowp vec4 a_color; -varying lowp vec4 color; +attribute highp vec4 a_color; +varying highp vec4 color; uniform lowp float a_blur_t; attribute lowp vec2 a_blur; varying lowp float blur; @@ -105,7 +105,7 @@ void main() { )MBGL_SHADER"; const char* line::fragmentSource = R"MBGL_SHADER( -varying lowp vec4 color; +varying highp vec4 color; varying lowp float blur; varying lowp float opacity; diff --git a/src/mbgl/shaders/line_sdf.cpp b/src/mbgl/shaders/line_sdf.cpp index cd0d4ac318..17a6a19739 100644 --- a/src/mbgl/shaders/line_sdf.cpp +++ b/src/mbgl/shaders/line_sdf.cpp @@ -42,8 +42,8 @@ varying vec2 v_tex_b; varying float v_gamma_scale; uniform lowp float a_color_t; -attribute lowp vec4 a_color; -varying lowp vec4 color; +attribute highp vec4 a_color; +varying highp vec4 color; uniform lowp float a_blur_t; attribute lowp vec2 a_blur; varying lowp float blur; @@ -127,7 +127,7 @@ varying vec2 v_tex_a; varying vec2 v_tex_b; varying float v_gamma_scale; -varying lowp vec4 color; +varying highp vec4 color; varying lowp float blur; varying lowp float opacity; diff --git a/src/mbgl/shaders/symbol_sdf.cpp b/src/mbgl/shaders/symbol_sdf.cpp index e0ee57b6d4..7cbc9babf5 100644 --- a/src/mbgl/shaders/symbol_sdf.cpp +++ b/src/mbgl/shaders/symbol_sdf.cpp @@ -14,11 +14,11 @@ attribute vec2 a_texture_pos; attribute vec4 a_data; uniform lowp float a_fill_color_t; -attribute lowp vec4 a_fill_color; -varying lowp vec4 fill_color; +attribute highp vec4 a_fill_color; +varying highp vec4 fill_color; uniform lowp float a_halo_color_t; -attribute lowp vec4 a_halo_color; -varying lowp vec4 halo_color; +attribute highp vec4 a_halo_color; +varying highp vec4 halo_color; uniform lowp float a_opacity_t; attribute lowp vec2 a_opacity; varying lowp float opacity; @@ -119,8 +119,8 @@ const char* symbol_sdf::fragmentSource = R"MBGL_SHADER( #define EDGE_GAMMA 0.105/DEVICE_PIXEL_RATIO uniform bool u_is_halo; -varying lowp vec4 fill_color; -varying lowp vec4 halo_color; +varying highp vec4 fill_color; +varying highp vec4 halo_color; varying lowp float opacity; varying lowp float halo_width; varying lowp float halo_blur; -- cgit v1.2.1 From 1edbb0f24b3b405bfc203803fffb1fa1ed68f142 Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Tue, 28 Mar 2017 16:02:48 -0700 Subject: [core] check null data in query source features (#8553) * [core] check null data in query source features * Include what you use --- src/mbgl/tile/geometry_tile.cpp | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'src') diff --git a/src/mbgl/tile/geometry_tile.cpp b/src/mbgl/tile/geometry_tile.cpp index 5f1fc5de66..5ccc037ce0 100644 --- a/src/mbgl/tile/geometry_tile.cpp +++ b/src/mbgl/tile/geometry_tile.cpp @@ -165,6 +165,11 @@ void GeometryTile::queryRenderedFeatures( void GeometryTile::querySourceFeatures( std::vector& result, const style::SourceQueryOptions& options) { + + // Data not yet available + if (!data) { + return; + } // No source layers, specified, nothing to do if (!options.sourceLayers) { -- cgit v1.2.1 From c1cd6759b4a87ef58442e864a192317284cf20ae Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Thu, 9 Mar 2017 07:53:02 -0800 Subject: [core] Extract and de-templatize several Program static methods --- src/mbgl/programs/program.hpp | 31 ++++--------------------------- src/mbgl/shaders/shaders.cpp | 33 +++++++++++++++++++++++++++++++++ src/mbgl/shaders/shaders.hpp | 15 +++++++++++++++ 3 files changed, 52 insertions(+), 27 deletions(-) create mode 100644 src/mbgl/shaders/shaders.cpp create mode 100644 src/mbgl/shaders/shaders.hpp (limited to 'src') diff --git a/src/mbgl/programs/program.hpp b/src/mbgl/programs/program.hpp index ffad767c3a..8437e3a651 100644 --- a/src/mbgl/programs/program.hpp +++ b/src/mbgl/programs/program.hpp @@ -1,13 +1,9 @@ #pragma once #include -#include #include #include -#include - -#include -#include +#include namespace mbgl { @@ -34,30 +30,11 @@ public: ProgramType program; Program(gl::Context& context, const ProgramParameters& programParameters) - : program(context, vertexSource(programParameters), fragmentSource(programParameters)) + : program(context, + shaders::vertexSource(programParameters, Shaders::vertexSource), + shaders::fragmentSource(programParameters, Shaders::fragmentSource)) {} - static std::string pixelRatioDefine(const ProgramParameters& parameters) { - std::ostringstream pixelRatioSS; - pixelRatioSS.imbue(std::locale("C")); - pixelRatioSS.setf(std::ios_base::showpoint); - pixelRatioSS << parameters.pixelRatio; - return std::string("#define DEVICE_PIXEL_RATIO ") + pixelRatioSS.str() + "\n"; - } - - static std::string fragmentSource(const ProgramParameters& parameters) { - std::string source = pixelRatioDefine(parameters) + shaders::fragmentPrelude + Shaders::fragmentSource; - if (parameters.overdraw) { - assert(source.find("#ifdef OVERDRAW_INSPECTOR") != std::string::npos); - source.replace(source.find_first_of('\n'), 1, "\n#define OVERDRAW_INSPECTOR\n"); - } - return source; - } - - static std::string vertexSource(const ProgramParameters& parameters) { - return pixelRatioDefine(parameters) + shaders::vertexPrelude + Shaders::vertexSource; - } - template void draw(gl::Context& context, DrawMode drawMode, diff --git a/src/mbgl/shaders/shaders.cpp b/src/mbgl/shaders/shaders.cpp new file mode 100644 index 0000000000..f7f5b4d44f --- /dev/null +++ b/src/mbgl/shaders/shaders.cpp @@ -0,0 +1,33 @@ +#include +#include +#include + +#include +#include + +namespace mbgl { +namespace shaders { + +static std::string pixelRatioDefine(const ProgramParameters& parameters) { + std::ostringstream pixelRatioSS; + pixelRatioSS.imbue(std::locale("C")); + pixelRatioSS.setf(std::ios_base::showpoint); + pixelRatioSS << parameters.pixelRatio; + return std::string("#define DEVICE_PIXEL_RATIO ") + pixelRatioSS.str() + "\n"; +} + +std::string fragmentSource(const ProgramParameters& parameters, const char* fragmentSource) { + std::string source = pixelRatioDefine(parameters) + fragmentPrelude + fragmentSource; + if (parameters.overdraw) { + assert(source.find("#ifdef OVERDRAW_INSPECTOR") != std::string::npos); + source.replace(source.find_first_of('\n'), 1, "\n#define OVERDRAW_INSPECTOR\n"); + } + return source; +} + +std::string vertexSource(const ProgramParameters& parameters, const char* vertexSource) { + return pixelRatioDefine(parameters) + vertexPrelude + vertexSource; +} + +} // namespace shaders +} // namespace mbgl diff --git a/src/mbgl/shaders/shaders.hpp b/src/mbgl/shaders/shaders.hpp new file mode 100644 index 0000000000..e2912c5688 --- /dev/null +++ b/src/mbgl/shaders/shaders.hpp @@ -0,0 +1,15 @@ +#pragma once + +#include + +namespace mbgl { + +class ProgramParameters; + +namespace shaders { + +std::string fragmentSource(const ProgramParameters&, const char* fragmentSource); +std::string vertexSource(const ProgramParameters&, const char* vertexSource); + +} // namespace shaders +} // namespace mbgl -- cgit v1.2.1 From f86333961eeacb9f2dd83a4c3680d30e06f947a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Konstantin=20K=C3=A4fer?= Date: Wed, 15 Mar 2017 18:43:58 +0100 Subject: [core] cache binary shaders on Android --- src/mbgl/gl/attribute.hpp | 13 +++- src/mbgl/gl/context.cpp | 49 +++++++++++++ src/mbgl/gl/context.hpp | 10 +++ src/mbgl/gl/features.hpp | 7 ++ src/mbgl/gl/program.hpp | 30 ++++++-- src/mbgl/gl/program_binary.cpp | 24 +++++++ src/mbgl/gl/program_binary.hpp | 27 +++++++ src/mbgl/gl/types.hpp | 2 + src/mbgl/gl/uniform.hpp | 13 +++- src/mbgl/map/map.cpp | 16 +++-- src/mbgl/programs/binary_program.cpp | 117 +++++++++++++++++++++++++++++++ src/mbgl/programs/binary_program.hpp | 43 ++++++++++++ src/mbgl/programs/program.hpp | 58 +++++++++++++-- src/mbgl/programs/program_parameters.hpp | 15 ++-- src/mbgl/programs/programs.hpp | 4 +- src/mbgl/renderer/painter.cpp | 16 +++-- src/mbgl/renderer/painter.hpp | 2 +- src/mbgl/shaders/shaders.cpp | 14 ++++ src/mbgl/shaders/shaders.hpp | 2 + src/mbgl/util/io.cpp | 10 +++ src/mbgl/util/io.hpp | 3 + 21 files changed, 443 insertions(+), 32 deletions(-) create mode 100644 src/mbgl/gl/features.hpp create mode 100644 src/mbgl/gl/program_binary.cpp create mode 100644 src/mbgl/gl/program_binary.hpp create mode 100644 src/mbgl/programs/binary_program.cpp create mode 100644 src/mbgl/programs/binary_program.hpp (limited to 'src') diff --git a/src/mbgl/gl/attribute.hpp b/src/mbgl/gl/attribute.hpp index 43e2c2d794..e23c4f9e47 100644 --- a/src/mbgl/gl/attribute.hpp +++ b/src/mbgl/gl/attribute.hpp @@ -7,6 +7,7 @@ #include #include +#include #include namespace mbgl { @@ -241,16 +242,26 @@ public: using VariableBindings = IndexedTuple< TypeList, TypeList...>>; + using NamedLocations = std::vector>; using Vertex = detail::Vertex; template static constexpr std::size_t Index = TypeIndex::value; - static Locations locations(const ProgramID& id) { + static Locations bindLocations(const ProgramID& id) { return Locations { bindAttributeLocation(id, Index, As::name())... }; } + template + 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() }... }; + } + template static Bindings allVariableBindings(const VertexBuffer& buffer) { return Bindings { As::variableBinding(buffer, Index)... }; 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 #include #include +#include #include #include #include @@ -34,6 +35,8 @@ static_assert(std::is_same, 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::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(binaryFormat), binaryProgram.data(), + static_cast(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> +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(binary.data()))); + if (size_t(binaryLength) != binary.size()) { + return {}; + } + return { { binaryFormat, std::move(binary) } }; +} +#else +optional> 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 9d3ecec662..fd6683a0cc 100644 --- a/src/mbgl/gl/context.hpp +++ b/src/mbgl/gl/context.hpp @@ -1,5 +1,6 @@ #pragma once +#include #include #include #include @@ -37,12 +38,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> getBinaryProgram(ProgramID) const; + template VertexBuffer createVertexBuffer(VertexVector&& v) { return VertexBuffer { 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 + Program(Context& context, const BinaryProgram& binaryProgram) + : program(context.createProgram(binaryProgram.format(), binaryProgram.code())), + attributeLocations(Attributes::loadNamedLocations(binaryProgram)), + uniformsState(Uniforms::loadNamedLocations(binaryProgram)) { + } + + template + optional 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 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 + +#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 + 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 +#include +#include + +#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 + GetProgramBinary; + +extern ExtensionFunction + 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 #include +#include #include namespace mbgl { @@ -66,11 +67,21 @@ public: using Types = TypeList; using State = IndexedTuple, TypeList>; using Values = IndexedTuple, TypeList>; + using NamedLocations = std::vector>; - static State state(const ProgramID& id) { + static State bindLocations(const ProgramID& id) { return State { { uniformLocation(id, Us::name()) }... }; } + template + 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().location }... }; + } + static void bind(State& state, Values&& values) { util::ignore({ (state.template get() = values.template get(), 0)... }); } diff --git a/src/mbgl/map/map.cpp b/src/mbgl/map/map.cpp index f4e994c931..aca1b77e7a 100644 --- a/src/mbgl/map/map.cpp +++ b/src/mbgl/map/map.cpp @@ -56,7 +56,8 @@ public: MapMode, GLContextMode, ConstrainMode, - ViewportMode); + ViewportMode, + const std::string& programCacheDir); void onSourceAttributionChanged(style::Source&, const std::string&) override; void onUpdate(Update) override; @@ -80,6 +81,7 @@ public: const MapMode mode; const GLContextMode contextMode; const float pixelRatio; + const std::string programCacheDir; MapDebugOptions debugOptions { MapDebugOptions::NoDebug }; @@ -111,7 +113,8 @@ Map::Map(Backend& backend, MapMode mapMode, GLContextMode contextMode, ConstrainMode constrainMode, - ViewportMode viewportMode) + ViewportMode viewportMode, + const std::string& programCacheDir) : impl(std::make_unique(*this, backend, pixelRatio, @@ -120,7 +123,8 @@ Map::Map(Backend& backend, mapMode, contextMode, constrainMode, - viewportMode)) { + viewportMode, + programCacheDir)) { impl->transform.resize(size); } @@ -132,7 +136,8 @@ Map::Impl::Impl(Map& map_, MapMode mode_, GLContextMode contextMode_, ConstrainMode constrainMode_, - ViewportMode viewportMode_) + ViewportMode viewportMode_, + const std::string& programCacheDir_) : map(map_), backend(backend_), fileSource(fileSource_), @@ -143,6 +148,7 @@ Map::Impl::Impl(Map& map_, mode(mode_), contextMode(contextMode_), pixelRatio(pixelRatio_), + programCacheDir(programCacheDir_), annotationManager(std::make_unique(pixelRatio)), asyncInvalidate([this] { if (mode == MapMode::Continuous) { @@ -259,7 +265,7 @@ void Map::Impl::render(View& view) { updateFlags = Update::Nothing; if (!painter) { - painter = std::make_unique(backend.getContext(), transform.getState(), pixelRatio); + painter = std::make_unique(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 + +#include +#include + +template +static std::pair parseBinding(protozero::pbf_reader&& pbf) { + bool hasName = false, hasValue = false; + std::pair 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(pbf.get_message())); + break; + case 4: // uniform + uniforms.emplace_back(parseBinding(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>&& attributes_, + std::vector>&& 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 + +#include +#include + +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::vector>&&); + + 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> attributes; + std::vector> 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 +#include +#include #include +#include #include #include +#include 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(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 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 + 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 +#include + #include #include #include @@ -77,7 +79,10 @@ static gl::VertexVector 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(context, programParameters); + programs = std::make_unique(context, + ProgramParameters{ pixelRatio, false, programCacheDir }); #ifndef NDEBUG - - ProgramParameters programParametersOverdraw{ pixelRatio, true }; - overdrawPrograms = std::make_unique(context, programParametersOverdraw); + overdrawPrograms = + std::make_unique(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 #include +#include 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()(vertexSource); + ss << std::hash()(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 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 + #include #include @@ -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 readFile(const std::string &filename); void deleteFile(const std::string& filename); } // namespace util -- cgit v1.2.1