summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLeith Bade <leith@mapbox.com>2014-12-07 00:29:20 +1100
committerLeith Bade <leith@mapbox.com>2014-12-07 00:29:20 +1100
commitb534520d6c60d45555e8a704ebeaec70800f0eaa (patch)
tree9da36f6adafadfae47f2e7660e8e8fff36e371d8
parentf2776c0854067e31391bff129bcfe9e7fbd72cf1 (diff)
parent004d12ea0b89d5fe369ab5631e20cc7e2caef429 (diff)
downloadqtlocation-mapboxgl-b534520d6c60d45555e8a704ebeaec70800f0eaa.tar.gz
Merge branch 'master' of github.com:mapbox/mapbox-gl-native into android-mason
Conflicts: include/mbgl/platform/gl.hpp src/mbgl/platform/gl.cpp src/mbgl/shader/shader.cpp
-rw-r--r--gyp/mbgl-ios.gypi1
-rw-r--r--gyp/mbgl-linux.gypi1
-rw-r--r--gyp/mbgl-osx.gypi1
-rw-r--r--include/mbgl/platform/gl.hpp13
-rw-r--r--include/mbgl/platform/platform.hpp3
-rw-r--r--platform/default/glfw_view.cpp38
-rw-r--r--platform/default/shader_cache_tmp.cpp12
-rw-r--r--platform/ios/shader_cache_library.mm21
-rw-r--r--platform/osx/shader_cache_application_support.mm31
-rw-r--r--src/mbgl/platform/gl.cpp6
-rw-r--r--src/mbgl/shader/shader.cpp156
-rw-r--r--src/mbgl/shader/shader.hpp3
12 files changed, 248 insertions, 38 deletions
diff --git a/gyp/mbgl-ios.gypi b/gyp/mbgl-ios.gypi
index c2cb2eed5f..a79737b0cd 100644
--- a/gyp/mbgl-ios.gypi
+++ b/gyp/mbgl-ios.gypi
@@ -32,6 +32,7 @@
'hard_dependency': 1,
'sources': [
'../platform/ios/cache_database_library.mm',
+ '../platform/ios/shader_cache_library.mm',
'../platform/darwin/log_nslog.mm',
'../platform/darwin/string_nsstring.mm',
'../platform/darwin/http_request_baton_cocoa.mm',
diff --git a/gyp/mbgl-linux.gypi b/gyp/mbgl-linux.gypi
index 5bfa8f757d..c42a49d9d1 100644
--- a/gyp/mbgl-linux.gypi
+++ b/gyp/mbgl-linux.gypi
@@ -28,6 +28,7 @@
},
'sources': [
'../platform/default/cache_database_tmp.cpp',
+ '../platform/default/shader_cache_tmp.cpp',
'../platform/default/log_stderr.cpp',
'../platform/default/string_stdlib.cpp',
'../platform/default/http_request_baton_curl.cpp',
diff --git a/gyp/mbgl-osx.gypi b/gyp/mbgl-osx.gypi
index 0ca00a81e9..542f6cb9e3 100644
--- a/gyp/mbgl-osx.gypi
+++ b/gyp/mbgl-osx.gypi
@@ -7,6 +7,7 @@
'hard_dependency': 1,
'sources': [
'../platform/osx/cache_database_application_support.mm',
+ '../platform/osx/shader_cache_application_support.mm',
'../platform/darwin/log_nslog.mm',
'../platform/darwin/string_nsstring.mm',
'../platform/darwin/http_request_baton_cocoa.mm',
diff --git a/include/mbgl/platform/gl.hpp b/include/mbgl/platform/gl.hpp
index 53386626a0..ba1ac9f008 100644
--- a/include/mbgl/platform/gl.hpp
+++ b/include/mbgl/platform/gl.hpp
@@ -119,6 +119,7 @@ typedef void (* PFNGLGETOBJECTLABELEXTPROC) (GLenum type, GLuint object, GLsizei
extern PFNGLLABELOBJECTEXTPROC LabelObjectEXT;
extern PFNGLGETOBJECTLABELEXTPROC GetObjectLabelEXT;
+// GL_ARB_vertex_array_object / GL_OES_vertex_array_object
#define GL_VERTEX_ARRAY_BINDING 0x85B5
typedef void (* PFNGLBINDVERTEXARRAYPROC) (GLuint array);
typedef void (* PFNGLDELETEVERTEXARRAYSPROC) (GLsizei n, const GLuint* arrays);
@@ -135,6 +136,18 @@ extern bool isPackedDepthStencilSupported;
extern bool isDepth24Supported;
#define GL_DEPTH_COMPONENT24 0x81A6
+// GL_ARB_get_program_binary / GL_OES_get_program_binary
+#define GL_PROGRAM_BINARY_RETRIEVABLE_HINT 0x8257
+#define GL_PROGRAM_BINARY_LENGTH 0x8741
+#define GL_NUM_PROGRAM_BINARY_FORMATS 0x87FE
+#define GL_PROGRAM_BINARY_FORMATS 0x87FF
+typedef void (* PFNGLGETPROGRAMBINARYPROC) (GLuint program, GLsizei bufSize, GLsizei *length, GLenum *binaryFormat, void *binary);
+typedef void (* PFNGLPROGRAMBINARYPROC) (GLuint program, GLenum binaryFormat, const void *binary, GLsizei length);
+typedef void (* PFNGLPROGRAMPARAMETERIPROC) (GLuint program, GLenum pname, GLint value);
+extern PFNGLGETPROGRAMBINARYPROC GetProgramBinary;
+extern PFNGLPROGRAMBINARYPROC ProgramBinary;
+extern PFNGLPROGRAMPARAMETERIPROC ProgramParameteri;
+
// Debug group markers, useful for debugging on iOS
#if defined(DEBUG)
// static int indent = 0;
diff --git a/include/mbgl/platform/platform.hpp b/include/mbgl/platform/platform.hpp
index b7107bb9cd..9edcc23ccd 100644
--- a/include/mbgl/platform/platform.hpp
+++ b/include/mbgl/platform/platform.hpp
@@ -20,6 +20,9 @@ std::string lowercase(const std::string &string);
// Returns the path to the default cache database on this system.
std::string defaultCacheDatabase();
+// Returns the path to the default shader cache on this system.
+std::string defaultShaderCache();
+
// Shows an alpha image with the specified dimensions in a named window.
void show_debug_image(std::string name, const char *data, size_t width, size_t height);
diff --git a/platform/default/glfw_view.cpp b/platform/default/glfw_view.cpp
index 95903d5f8e..4d7e2c17cf 100644
--- a/platform/default/glfw_view.cpp
+++ b/platform/default/glfw_view.cpp
@@ -82,6 +82,17 @@ void GLFWView::initialize(mbgl::Map *map_) {
gl::GetObjectLabel = (gl::PFNGLGETOBJECTLABELPROC)glfwGetProcAddress("glGetObjectLabel");
gl::ObjectPtrLabel = (gl::PFNGLOBJECTPTRLABELPROC)glfwGetProcAddress("glObjectPtrLabel");
gl::GetObjectPtrLabel = (gl::PFNGLGETOBJECTPTRLABELPROC)glfwGetProcAddress("glGetObjectPtrLabel");
+ assert(gl::DebugMessageControl != nullptr);
+ assert(gl::DebugMessageInsert != nullptr);
+ assert(gl::DebugMessageCallback != nullptr);
+ assert(gl::GetDebugMessageLog != nullptr);
+ assert(gl::GetPointerv != nullptr);
+ assert(gl::PushDebugGroup != nullptr);
+ assert(gl::PopDebugGroup != nullptr);
+ assert(gl::ObjectLabel != nullptr);
+ assert(gl::GetObjectLabel != nullptr);
+ assert(gl::ObjectPtrLabel != nullptr);
+ assert(gl::GetObjectPtrLabel != nullptr);
} else {
if (extensions.find("GL_ARB_debug_output") != std::string::npos) {
gl::DebugMessageControl = (gl::PFNGLDEBUGMESSAGECONTROLPROC)glfwGetProcAddress("glDebugMessageControlARB");
@@ -89,17 +100,27 @@ void GLFWView::initialize(mbgl::Map *map_) {
gl::DebugMessageCallback = (gl::PFNGLDEBUGMESSAGECALLBACKPROC)glfwGetProcAddress("glDebugMessageCallbackARB");
gl::GetDebugMessageLog = (gl::PFNGLGETDEBUGMESSAGELOGPROC)glfwGetProcAddress("glGetDebugMessageLogARB");
gl::GetPointerv = (gl::PFNGLGETPOINTERVPROC)glfwGetProcAddress("glGetPointerv");
+ assert(gl::DebugMessageControl != nullptr);
+ assert(gl::DebugMessageInsert != nullptr);
+ assert(gl::DebugMessageCallback != nullptr);
+ assert(gl::GetDebugMessageLog != nullptr);
+ assert(gl::GetPointerv != nullptr);
}
if (extensions.find("GL_EXT_debug_marker") != std::string::npos) {
gl::InsertEventMarkerEXT = (gl::PFNGLINSERTEVENTMARKEREXTPROC)glfwGetProcAddress("glInsertEventMarkerEXT");
gl::PushGroupMarkerEXT = (gl::PFNGLPUSHGROUPMARKEREXTPROC)glfwGetProcAddress("glPushGroupMarkerEXT");
gl::PopGroupMarkerEXT = (gl::PFNGLPOPGROUPMARKEREXTPROC)glfwGetProcAddress("glPopGroupMarkerEXT");
+ assert(gl::InsertEventMarkerEXT != nullptr);
+ assert(gl::PushGroupMarkerEXT != nullptr);
+ assert(gl::PopGroupMarkerEXT != nullptr);
}
if (extensions.find("GL_EXT_debug_label") != std::string::npos) {
gl::LabelObjectEXT = (gl::PFNGLLABELOBJECTEXTPROC)glfwGetProcAddress("glLabelObjectEXT");
gl::GetObjectLabelEXT = (gl::PFNGLGETOBJECTLABELEXTPROC)glfwGetProcAddress("glGetObjectLabelEXT");
+ assert(gl::LabelObjectEXT != nullptr);
+ assert(gl::GetObjectLabelEXT != nullptr);
}
}
@@ -108,11 +129,28 @@ void GLFWView::initialize(mbgl::Map *map_) {
gl::DeleteVertexArrays = (gl::PFNGLDELETEVERTEXARRAYSPROC)glfwGetProcAddress("glDeleteVertexArrays");
gl::GenVertexArrays = (gl::PFNGLGENVERTEXARRAYSPROC)glfwGetProcAddress("glGenVertexArrays");
gl::IsVertexArray = (gl::PFNGLISVERTEXARRAYPROC)glfwGetProcAddress("glIsVertexArray");
+ assert(gl::BindVertexArray != nullptr);
+ assert(gl::DeleteVertexArrays != nullptr);
+ assert(gl::GenVertexArrays != nullptr);
+ assert(gl::IsVertexArray != nullptr);
} else if (extensions.find("GL_APPLE_vertex_array_object") != std::string::npos) {
gl::BindVertexArray = (gl::PFNGLBINDVERTEXARRAYPROC)glfwGetProcAddress("glBindVertexArrayAPPLE");
gl::DeleteVertexArrays = (gl::PFNGLDELETEVERTEXARRAYSPROC)glfwGetProcAddress("glDeleteVertexArraysAPPLE");
gl::GenVertexArrays = (gl::PFNGLGENVERTEXARRAYSPROC)glfwGetProcAddress("glGenVertexArraysAPPLE");
gl::IsVertexArray = (gl::PFNGLISVERTEXARRAYPROC)glfwGetProcAddress("glIsVertexArrayAPPLE");
+ assert(gl::BindVertexArray != nullptr);
+ assert(gl::DeleteVertexArrays != nullptr);
+ assert(gl::GenVertexArrays != nullptr);
+ assert(gl::IsVertexArray != nullptr);
+ }
+
+ if (extensions.find("GL_ARB_get_program_binary") != std::string::npos) {
+ gl::GetProgramBinary = (gl::PFNGLGETPROGRAMBINARYPROC)glfwGetProcAddress("glGetProgramBinary");
+ gl::ProgramBinary = (gl::PFNGLPROGRAMBINARYPROC)glfwGetProcAddress("glProgramBinary");
+ gl::ProgramParameteri = (gl::PFNGLPROGRAMPARAMETERIPROC)glfwGetProcAddress("glProgramParameteri");
+ assert(gl::GetProgramBinary != nullptr);
+ assert(gl::ProgramBinary != nullptr);
+ assert(gl::ProgramParameteri != nullptr);
}
}
diff --git a/platform/default/shader_cache_tmp.cpp b/platform/default/shader_cache_tmp.cpp
new file mode 100644
index 0000000000..d76f7aea4c
--- /dev/null
+++ b/platform/default/shader_cache_tmp.cpp
@@ -0,0 +1,12 @@
+#include <mbgl/platform/platform.hpp>
+
+namespace mbgl {
+namespace platform {
+
+// Returns the path to the default shader cache on this system.
+std::string defaultShaderCache() {
+ return "/tmp/mbgl-shader-cache-";
+}
+
+}
+}
diff --git a/platform/ios/shader_cache_library.mm b/platform/ios/shader_cache_library.mm
new file mode 100644
index 0000000000..68d8e959ca
--- /dev/null
+++ b/platform/ios/shader_cache_library.mm
@@ -0,0 +1,21 @@
+#import <Foundation/Foundation.h>
+
+#include <mbgl/platform/platform.hpp>
+
+namespace mbgl {
+namespace platform {
+
+// Returns the path to the default shader cache on this system.
+std::string defaultShaderCache() {
+ NSArray *paths = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES);
+ if ([paths count] == 0) {
+ // Disable the cache if we don't have a location to write.
+ return "";
+ }
+
+ NSString *libraryDirectory = [paths objectAtIndex:0];
+ return [[libraryDirectory stringByAppendingPathComponent:@"shader-cache-"] UTF8String];
+}
+
+}
+}
diff --git a/platform/osx/shader_cache_application_support.mm b/platform/osx/shader_cache_application_support.mm
new file mode 100644
index 0000000000..459cf6535f
--- /dev/null
+++ b/platform/osx/shader_cache_application_support.mm
@@ -0,0 +1,31 @@
+#import <Foundation/Foundation.h>
+
+#include <mbgl/platform/platform.hpp>
+
+namespace mbgl {
+namespace platform {
+
+// Returns the path to the default shader cache on this system.
+std::string defaultShaderCache() {
+ NSArray *paths =
+ NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, YES);
+ if ([paths count] == 0) {
+ // Disable the cache if we don't have a location to write.
+ return "";
+ }
+
+ NSString *path = [[paths objectAtIndex:0] stringByAppendingPathComponent:@"Mapbox GL"];
+
+ if (![[NSFileManager defaultManager] createDirectoryAtPath:path
+ withIntermediateDirectories:YES
+ attributes:nil
+ error:nil]) {
+ // Disable the cache if we couldn't create the directory.
+ return "";
+ }
+
+ return [[path stringByAppendingPathComponent:@"shader-cache-"] UTF8String];
+}
+
+}
+}
diff --git a/src/mbgl/platform/gl.cpp b/src/mbgl/platform/gl.cpp
index 155fd70d95..f99883a4e5 100644
--- a/src/mbgl/platform/gl.cpp
+++ b/src/mbgl/platform/gl.cpp
@@ -70,12 +70,14 @@ PFNGLDELETEVERTEXARRAYSPROC DeleteVertexArrays = nullptr;
PFNGLGENVERTEXARRAYSPROC GenVertexArrays = nullptr;
PFNGLISVERTEXARRAYPROC IsVertexArray = nullptr;
-// GL_OES_packed_depth_stencil
bool isPackedDepthStencilSupported = false;
-// GL_OES_depth24
bool isDepth24Supported = false;
+PFNGLGETPROGRAMBINARYPROC GetProgramBinary = nullptr;
+PFNGLPROGRAMBINARYPROC ProgramBinary = nullptr;
+PFNGLPROGRAMPARAMETERIPROC ProgramParameteri = nullptr;
+
}
}
diff --git a/src/mbgl/shader/shader.cpp b/src/mbgl/shader/shader.cpp
index 46fed32fda..af6ba627e1 100644
--- a/src/mbgl/shader/shader.cpp
+++ b/src/mbgl/shader/shader.cpp
@@ -2,9 +2,11 @@
#include <mbgl/platform/gl.hpp>
#include <mbgl/util/stopwatch.hpp>
#include <mbgl/platform/log.hpp>
+#include <mbgl/platform/platform.hpp>
#include <cstring>
#include <cstdlib>
+#include <cassert>
using namespace mbgl;
@@ -14,48 +16,97 @@ Shader::Shader(const char *name_, const GLchar *vertSource, const GLchar *fragSo
program(0) {
util::stopwatch stopwatch("shader compilation", Event::Shader);
- GLuint vertShader;
- if (!compileShader(&vertShader, GL_VERTEX_SHADER, vertSource)) {
- Log::Error(Event::Shader, "Vertex shader failed to compile: %s", vertSource);
- return;
- }
-
- GLuint fragShader;
- if (!compileShader(&fragShader, GL_FRAGMENT_SHADER, fragSource)) {
- Log::Error(Event::Shader, "Fragment shader failed to compile: %s", fragSource);
- return;
- }
-
program = glCreateProgram();
- // Attach shaders
- glAttachShader(program, vertShader);
- glAttachShader(program, fragShader);
+ if (!mbgl::platform::defaultShaderCache().empty()) {
+ binaryFileName = mbgl::platform::defaultShaderCache() + name + ".bin";
+ }
+ // Load binary shader if it exists
+ bool skipCompile = false;
+ if (!binaryFileName.empty() && (gl::ProgramBinary != nullptr)) {
+ FILE *binaryFile = fopen(binaryFileName.c_str(), "rb");
+ if (binaryFile != nullptr) {
+ GLsizei binaryLength;
+ GLenum binaryFormat;
+ bool lengthOk = fread(&binaryLength, sizeof(binaryLength), 1, binaryFile) == 1;
+ bool formatOk = fread(&binaryFormat, sizeof(binaryFormat), 1, binaryFile) == 1;
+
+ if (lengthOk && formatOk && binaryLength > 0) {
+ std::unique_ptr<char[]> binary = mbgl::util::make_unique<char[]>(binaryLength);
+
+ if (binary != nullptr) {
+ bool binaryOk = fread(binary.get(), binaryLength, 1, binaryFile) == 1;
+
+ if (binaryOk) {
+ gl::ProgramBinary(program, binaryFormat, binary.get(), binaryLength);
+
+ // Check if the binary was valid
+ GLint status;
+ glGetProgramiv(program, GL_LINK_STATUS, &status);
+ if (status == GL_TRUE) {
+ skipCompile = true;
+ }
+ }
+ }
+ }
- {
- // Link program
- GLint status;
- glLinkProgram(program);
+ fclose(binaryFile);
+ binaryFile = nullptr;
+ }
+ }
- glGetProgramiv(program, GL_LINK_STATUS, &status);
- if (status == 0) {
- GLint logLength;
- glGetProgramiv(program, GL_INFO_LOG_LENGTH, &logLength);
- if (logLength > 0) {
- std::unique_ptr<GLchar[]> log = mbgl::util::make_unique<GLchar[]>(logLength);
- glGetProgramInfoLog(program, logLength, &logLength, log.get());
- Log::Error(Event::Shader, "Program failed to link: %s", log.get());
- }
+ GLuint vertShader = 0;
+ GLuint fragShader = 0;
+ if (!skipCompile) {
+ if (!compileShader(&vertShader, GL_VERTEX_SHADER, vertSource)) {
+ Log::Error(Event::Shader, "Vertex shader %s failed to compile: %s", name, vertSource);
+ glDeleteProgram(program);
+ program = 0;
+ return;
+ }
+ if (!compileShader(&fragShader, GL_FRAGMENT_SHADER, fragSource)) {
+ Log::Error(Event::Shader, "Fragment shader %s failed to compile: %s", name, fragSource);
glDeleteShader(vertShader);
vertShader = 0;
- glDeleteShader(fragShader);
- fragShader = 0;
glDeleteProgram(program);
program = 0;
return;
}
+
+ // Attach shaders
+ glAttachShader(program, vertShader);
+ glAttachShader(program, fragShader);
+
+ {
+ if (!binaryFileName.empty() && (gl::ProgramParameteri != nullptr)) {
+ gl::ProgramParameteri(program, GL_PROGRAM_BINARY_RETRIEVABLE_HINT, GL_TRUE);
+ }
+
+ // Link program
+ GLint status;
+ glLinkProgram(program);
+
+ glGetProgramiv(program, GL_LINK_STATUS, &status);
+ if (status == 0) {
+ GLint logLength;
+ glGetProgramiv(program, GL_INFO_LOG_LENGTH, &logLength);
+ if (logLength > 0) {
+ std::unique_ptr<GLchar[]> log = mbgl::util::make_unique<GLchar[]>(logLength);
+ glGetProgramInfoLog(program, logLength, &logLength, log.get());
+ Log::Error(Event::Shader, "Program failed to link: %s", log.get());
+ }
+
+ glDeleteShader(vertShader);
+ vertShader = 0;
+ glDeleteShader(fragShader);
+ fragShader = 0;
+ glDeleteProgram(program);
+ program = 0;
+ return;
+ }
+ }
}
{
@@ -82,11 +133,13 @@ Shader::Shader(const char *name_, const GLchar *vertSource, const GLchar *fragSo
}
}
- // Remove the compiled shaders; they are now part of the program.
- glDetachShader(program, vertShader);
- glDeleteShader(vertShader);
- glDetachShader(program, fragShader);
- glDeleteShader(fragShader);
+ if (!skipCompile) {
+ // Remove the compiled shaders; they are now part of the program.
+ glDetachShader(program, vertShader);
+ glDeleteShader(vertShader);
+ glDetachShader(program, fragShader);
+ glDeleteShader(fragShader);
+ }
valid = true;
}
@@ -97,7 +150,7 @@ bool Shader::compileShader(GLuint *shader, GLenum type, const GLchar *source) {
*shader = glCreateShader(type);
const GLchar *strings[] = { source };
- const GLint lengths[] = { (GLint)strlen(source) };
+ const GLsizei lengths[] = { (GLsizei)strlen(source) };
glShaderSource(*shader, 1, strings, lengths);
glCompileShader(*shader);
@@ -117,10 +170,41 @@ bool Shader::compileShader(GLuint *shader, GLenum type, const GLchar *source) {
return false;
}
+ glGetShaderiv(*shader, GL_COMPILE_STATUS, &status);
+ if (status == GL_FALSE) {
+ Log::Error(Event::Shader, "Shader %s failed to compile.", name, type);
+ glDeleteShader(*shader);
+ *shader = 0;
+ return false;
+ }
+
return true;
}
Shader::~Shader() {
+ if (!binaryFileName.empty() && (gl::GetProgramBinary != nullptr)) {
+ // Retrieve the program binary
+ GLsizei binaryLength;
+ GLenum binaryFormat;
+ glGetProgramiv(program, GL_PROGRAM_BINARY_LENGTH, &binaryLength);
+ if (binaryLength > 0) {
+ std::unique_ptr<char[]> binary = mbgl::util::make_unique<char[]>(binaryLength);
+ if (binary != nullptr) {
+ gl::GetProgramBinary(program, binaryLength, NULL, &binaryFormat, binary.get());
+
+ // Write the binary to a file
+ FILE *binaryFile = fopen(binaryFileName.c_str(), "wb");
+ if (binaryFile != nullptr) {
+ fwrite(&binaryLength, sizeof(binaryLength), 1, binaryFile);
+ fwrite(&binaryFormat, sizeof(binaryFormat), 1, binaryFile);
+ fwrite(binary.get(), binaryLength, 1, binaryFile);
+ fclose(binaryFile);
+ binaryFile = nullptr;
+ }
+ }
+ }
+ }
+
if (program) {
glDeleteProgram(program);
program = 0;
diff --git a/src/mbgl/shader/shader.hpp b/src/mbgl/shader/shader.hpp
index 27e831a510..beaaa8b756 100644
--- a/src/mbgl/shader/shader.hpp
+++ b/src/mbgl/shader/shader.hpp
@@ -3,6 +3,7 @@
#include <cstdint>
#include <array>
+#include <string>
#include <mbgl/util/noncopyable.hpp>
namespace mbgl {
@@ -21,6 +22,8 @@ public:
private:
bool compileShader(uint32_t *shader, uint32_t type, const char *source);
+
+ std::string binaryFileName;
};
}