summaryrefslogtreecommitdiff
path: root/src/mbgl/gl
diff options
context:
space:
mode:
authorKonstantin Käfer <mail@kkaefer.com>2017-03-15 18:43:58 +0100
committerJohn Firebaugh <john.firebaugh@gmail.com>2017-04-03 11:01:43 -0700
commitf86333961eeacb9f2dd83a4c3680d30e06f947a7 (patch)
treee26d375a7852526196428bc86e9b7b94e2baf6f9 /src/mbgl/gl
parentc1cd6759b4a87ef58442e864a192317284cf20ae (diff)
downloadqtlocation-mapboxgl-f86333961eeacb9f2dd83a4c3680d30e06f947a7.tar.gz
[core] cache binary shaders on Android
Diffstat (limited to 'src/mbgl/gl')
-rw-r--r--src/mbgl/gl/attribute.hpp13
-rw-r--r--src/mbgl/gl/context.cpp49
-rw-r--r--src/mbgl/gl/context.hpp10
-rw-r--r--src/mbgl/gl/features.hpp7
-rw-r--r--src/mbgl/gl/program.hpp30
-rw-r--r--src/mbgl/gl/program_binary.cpp24
-rw-r--r--src/mbgl/gl/program_binary.hpp27
-rw-r--r--src/mbgl/gl/types.hpp2
-rw-r--r--src/mbgl/gl/uniform.hpp13
9 files changed, 166 insertions, 9 deletions
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 <mbgl/util/variant.hpp>
#include <cstddef>
+#include <vector>
#include <functional>
namespace mbgl {
@@ -241,16 +242,26 @@ public:
using VariableBindings = IndexedTuple<
TypeList<As...>,
TypeList<optional<typename As::VariableBinding>...>>;
+ using NamedLocations = std::vector<std::pair<const std::string, AttributeLocation>>;
using Vertex = detail::Vertex<As...>;
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::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 9d3ecec662..fd6683a0cc 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>
@@ -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<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)... });
}