Merge pull request #745 from mapbox/fix-binary-shader

Check for IO errors when loading binary shader
This commit is contained in:
Leith Bade
2015-01-14 12:19:32 +11:00
2 changed files with 64 additions and 23 deletions

View File

@@ -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

View File

@@ -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());
}
}
}