Merge pull request #745 from mapbox/fix-binary-shader
Check for IO errors when loading binary shader
This commit is contained in:
@@ -250,6 +250,8 @@ void Map::run() {
|
||||
mode = Mode::None;
|
||||
fileSource.clearLoop();
|
||||
}
|
||||
|
||||
terminate();
|
||||
}
|
||||
|
||||
void Map::rerender() {
|
||||
@@ -258,8 +260,9 @@ void Map::rerender() {
|
||||
} else if (mode == Mode::Continuous) {
|
||||
// We only send render events if we want to continuously update the map
|
||||
// (== async rendering).
|
||||
assert(asyncRender);
|
||||
asyncRender->send();
|
||||
if (asyncRender) {
|
||||
asyncRender->send();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -279,7 +282,9 @@ void Map::swapped() {
|
||||
|
||||
void Map::terminate() {
|
||||
assert(painter);
|
||||
view.activate();
|
||||
painter->terminate();
|
||||
view.deactivate();
|
||||
}
|
||||
|
||||
#pragma mark - Setup
|
||||
|
||||
@@ -26,26 +26,53 @@ Shader::Shader(const char *name_, const GLchar *vertSource, const GLchar *fragSo
|
||||
// Load binary shader if it exists
|
||||
bool skipCompile = false;
|
||||
if (!binaryFileName.empty() && (gl::ProgramBinary != nullptr)) {
|
||||
std::ifstream binaryFile(binaryFileName, std::ios::in | std::ios::binary);
|
||||
try {
|
||||
std::ifstream binaryFile(binaryFileName, std::ios::in | std::ios::binary);
|
||||
binaryFile.exceptions(std::ifstream::failbit | std::ifstream::badbit | std::ifstream::eofbit);
|
||||
|
||||
GLsizei binaryLength;
|
||||
GLenum binaryFormat;
|
||||
binaryFile.read(reinterpret_cast<char *>(&binaryLength), sizeof(binaryLength));
|
||||
binaryFile.read(reinterpret_cast<char *>(&binaryFormat), sizeof(binaryFormat));
|
||||
GLsizei binaryLength;
|
||||
GLenum binaryFormat;
|
||||
binaryFile.read(reinterpret_cast<char *>(&binaryLength), sizeof(binaryLength));
|
||||
binaryFile.read(reinterpret_cast<char *>(&binaryFormat), sizeof(binaryFormat));
|
||||
|
||||
std::unique_ptr<char[]> binary = mbgl::util::make_unique<char[]>(binaryLength);
|
||||
binaryFile.read(binary.get(), binaryLength);
|
||||
GLint numBinaryFormats;
|
||||
MBGL_CHECK_ERROR(glGetIntegerv(GL_NUM_PROGRAM_BINARY_FORMATS, &numBinaryFormats));
|
||||
|
||||
MBGL_CHECK_ERROR(gl::ProgramBinary(program, binaryFormat, binary.get(), binaryLength));
|
||||
std::unique_ptr<GLenum[]> validBinaryFormats = mbgl::util::make_unique<GLenum[]>(numBinaryFormats);
|
||||
MBGL_CHECK_ERROR(glGetIntegerv(GL_PROGRAM_BINARY_FORMATS, reinterpret_cast<GLint *>(validBinaryFormats.get())));
|
||||
|
||||
// Check if the binary was valid
|
||||
GLint status;
|
||||
MBGL_CHECK_ERROR(glGetProgramiv(program, GL_LINK_STATUS, &status));
|
||||
if (status == GL_TRUE) {
|
||||
skipCompile = true;
|
||||
bool validBinaryFormat = false;
|
||||
for (GLint i = 0; i < numBinaryFormats; i++) {
|
||||
if (validBinaryFormats[i] == binaryFormat) {
|
||||
validBinaryFormat = true;
|
||||
}
|
||||
}
|
||||
if (!validBinaryFormat) {
|
||||
throw std::runtime_error("Trying load program binary with an invalid binaryFormat!");
|
||||
}
|
||||
|
||||
if (binaryLength == 0) {
|
||||
throw std::runtime_error("Trying load program binary with a zero length binary!");
|
||||
}
|
||||
|
||||
std::unique_ptr<char[]> binary = mbgl::util::make_unique<char[]>(binaryLength);
|
||||
binaryFile.read(binary.get(), binaryLength);
|
||||
|
||||
MBGL_CHECK_ERROR(gl::ProgramBinary(program, binaryFormat, binary.get(), binaryLength));
|
||||
|
||||
// Check if the binary was valid
|
||||
GLint status;
|
||||
MBGL_CHECK_ERROR(glGetProgramiv(program, GL_LINK_STATUS, &status));
|
||||
if (status == GL_TRUE) {
|
||||
skipCompile = true;
|
||||
}
|
||||
|
||||
} catch(std::exception& e) {
|
||||
Log::Error(Event::Shader, "Loading binary shader failed!");
|
||||
|
||||
// Delete the bad file
|
||||
std::remove(binaryFileName.c_str());
|
||||
}
|
||||
|
||||
binaryFile.close();
|
||||
}
|
||||
|
||||
GLuint vertShader = 0;
|
||||
@@ -183,12 +210,21 @@ Shader::~Shader() {
|
||||
std::unique_ptr<char[]> binary = mbgl::util::make_unique<char[]>(binaryLength);
|
||||
MBGL_CHECK_ERROR(gl::GetProgramBinary(program, binaryLength, NULL, &binaryFormat, binary.get()));
|
||||
|
||||
// Write the binary to a file
|
||||
std::ofstream binaryFile(binaryFileName, std::ios::out | std::ios::trunc | std::ios::binary);
|
||||
binaryFile.write(reinterpret_cast<char *>(&binaryLength), sizeof(binaryLength));
|
||||
binaryFile.write(reinterpret_cast<char *>(&binaryFormat), sizeof(binaryFormat));
|
||||
binaryFile.write(binary.get(), binaryLength);
|
||||
binaryFile.close();
|
||||
try {
|
||||
// Write the binary to a file
|
||||
std::ofstream binaryFile(binaryFileName, std::ios::out | std::ios::trunc | std::ios::binary);
|
||||
binaryFile.exceptions(std::ofstream::failbit | std::ofstream::badbit | std::ofstream::eofbit);
|
||||
|
||||
binaryFile.write(reinterpret_cast<char *>(&binaryLength), sizeof(binaryLength));
|
||||
binaryFile.write(reinterpret_cast<char *>(&binaryFormat), sizeof(binaryFormat));
|
||||
binaryFile.write(binary.get(), binaryLength);
|
||||
|
||||
} catch(std::exception& e) {
|
||||
Log::Error(Event::Shader, "Saving binary shader failed!");
|
||||
|
||||
// Delete the bad file
|
||||
std::remove(binaryFileName.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user