summaryrefslogtreecommitdiff
path: root/src/mbgl/gl
diff options
context:
space:
mode:
authorKonstantin Käfer <mail@kkaefer.com>2019-03-19 14:02:10 +0100
committerKonstantin Käfer <mail@kkaefer.com>2019-03-20 15:40:47 +0100
commit1e30fdac36233c0fd0662e2b285b0424907bc81d (patch)
treeeb61b156b5445639939eab47f5ded9a385b25fd9 /src/mbgl/gl
parent53ab65d81165daf4e23ce28fa0e42861724ea687 (diff)
downloadqtlocation-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.hpp31
-rw-r--r--src/mbgl/gl/context.cpp6
-rw-r--r--src/mbgl/gl/context.hpp2
-rw-r--r--src/mbgl/gl/program.hpp203
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