summaryrefslogtreecommitdiff
path: root/src/mbgl/programs/program.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/mbgl/programs/program.hpp')
-rw-r--r--src/mbgl/programs/program.hpp58
1 files changed, 54 insertions, 4 deletions
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,