[gl] Added mbgl::gl::ShaderHolder

This commit is contained in:
Bruno de Oliveira Abinader
2016-02-14 18:18:24 +02:00
parent 69fa8fe3c0
commit a503233d1c
4 changed files with 53 additions and 42 deletions

View File

@@ -22,6 +22,20 @@ void ProgramHolder::reset() {
id = 0;
}
void ShaderHolder::create() {
if (id) return;
assert(util::ThreadContext::currentlyOn(util::ThreadType::Map));
id = MBGL_CHECK_ERROR(glCreateShader(type));
}
void ShaderHolder::reset() {
if (!id) return;
assert(util::ThreadContext::currentlyOn(util::ThreadType::Map));
MBGL_CHECK_ERROR(glDeleteShader(id));
id = 0;
}
void GLObjectStore::abandonVAO(GLuint vao) {
assert(util::ThreadContext::currentlyOn(util::ThreadType::Map));
abandonedVAOs.emplace_back(vao);

View File

@@ -36,6 +36,21 @@ public:
void reset();
};
class ShaderHolder : public GLHolder {
public:
ShaderHolder(GLenum type_) : type(type_) {}
~ShaderHolder() { reset(); }
ShaderHolder(ShaderHolder&& o) noexcept : GLHolder(std::move(o)), type(o.type) {}
ShaderHolder& operator=(ShaderHolder&& o) noexcept { GLHolder::operator=(std::move(o)); type = o.type; return *this; }
void create();
void reset();
private:
GLenum type = 0;
};
class GLObjectStore : private util::noncopyable {
public:
// Mark OpenGL objects for deletion

View File

@@ -11,7 +11,7 @@
#include <fstream>
#include <cstdio>
using namespace mbgl;
namespace mbgl {
Shader::Shader(const char *name_, const GLchar *vertSource, const GLchar *fragSource)
: name(name_)
@@ -19,24 +19,21 @@ Shader::Shader(const char *name_, const GLchar *vertSource, const GLchar *fragSo
util::stopwatch stopwatch("shader compilation", Event::Shader);
program.create();
if (!compileShader(&vertShader, GL_VERTEX_SHADER, &vertSource)) {
vertexShader.create();
if (!compileShader(vertexShader, &vertSource)) {
Log::Error(Event::Shader, "Vertex shader %s failed to compile: %s", name, vertSource);
program.reset();
throw util::ShaderException(std::string { "Vertex shader " } + name + " failed to compile");
}
if (!compileShader(&fragShader, GL_FRAGMENT_SHADER, &fragSource)) {
fragmentShader.create();
if (!compileShader(fragmentShader, &fragSource)) {
Log::Error(Event::Shader, "Fragment shader %s failed to compile: %s", name, fragSource);
MBGL_CHECK_ERROR(glDeleteShader(vertShader));
vertShader = 0;
program.reset();
throw util::ShaderException(std::string { "Fragment shader " } + name + " failed to compile");
}
// Attach shaders
MBGL_CHECK_ERROR(glAttachShader(program.getID(), vertexShader));
MBGL_CHECK_ERROR(glAttachShader(program.getID(), fragmentShader));
MBGL_CHECK_ERROR(glAttachShader(program.getID(), vertexShader.getID()));
MBGL_CHECK_ERROR(glAttachShader(program.getID(), fragmentShader.getID()));
{
// Link program
@@ -52,49 +49,36 @@ Shader::Shader(const char *name_, const GLchar *vertSource, const GLchar *fragSo
MBGL_CHECK_ERROR(glGetProgramInfoLog(program.getID(), logLength, &logLength, log.get()));
Log::Error(Event::Shader, "Program failed to link: %s", log.get());
}
MBGL_CHECK_ERROR(glDeleteShader(vertShader));
vertShader = 0;
MBGL_CHECK_ERROR(glDeleteShader(fragShader));
fragShader = 0;
program.reset();
throw util::ShaderException(std::string { "Program " } + name + " failed to link: " + log.get());
throw util::ShaderException(std::string { "Program " } + name + " failed to link: " + log.get());
}
}
a_pos = MBGL_CHECK_ERROR(glGetAttribLocation(program.getID(), "a_pos"));
}
bool Shader::compileShader(gl::ShaderHolder& shader, const GLchar *source[]) {
GLint status = 0;
bool Shader::compileShader(GLuint *shader, GLenum type, const GLchar *source[]) {
GLint status;
*shader = MBGL_CHECK_ERROR(glCreateShader(type));
const GLsizei lengths = static_cast<GLsizei>(std::strlen(*source));
MBGL_CHECK_ERROR(glShaderSource(*shader, 1, source, &lengths));
MBGL_CHECK_ERROR(glShaderSource(shader.getID(), 1, source, &lengths));
MBGL_CHECK_ERROR(glCompileShader(*shader));
MBGL_CHECK_ERROR(glCompileShader(shader.getID()));
MBGL_CHECK_ERROR(glGetShaderiv(*shader, GL_COMPILE_STATUS, &status));
MBGL_CHECK_ERROR(glGetShaderiv(shader.getID(), GL_COMPILE_STATUS, &status));
if (status == 0) {
GLint logLength;
MBGL_CHECK_ERROR(glGetShaderiv(*shader, GL_INFO_LOG_LENGTH, &logLength));
MBGL_CHECK_ERROR(glGetShaderiv(shader.getID(), GL_INFO_LOG_LENGTH, &logLength));
if (logLength > 0) {
const auto log = std::make_unique<GLchar[]>(logLength);
MBGL_CHECK_ERROR(glGetShaderInfoLog(*shader, logLength, &logLength, log.get()));
MBGL_CHECK_ERROR(glGetShaderInfoLog(shader.getID(), logLength, &logLength, log.get()));
Log::Error(Event::Shader, "Shader failed to compile: %s", log.get());
}
MBGL_CHECK_ERROR(glDeleteShader(*shader));
*shader = 0;
return false;
}
MBGL_CHECK_ERROR(glGetShaderiv(*shader, GL_COMPILE_STATUS, &status));
MBGL_CHECK_ERROR(glGetShaderiv(shader.getID(), GL_COMPILE_STATUS, &status));
if (status == GL_FALSE) {
Log::Error(Event::Shader, "Shader %s failed to compile.", name);
MBGL_CHECK_ERROR(glDeleteShader(*shader));
*shader = 0;
return false;
}
@@ -103,11 +87,9 @@ bool Shader::compileShader(GLuint *shader, GLenum type, const GLchar *source[])
Shader::~Shader() {
if (program) {
MBGL_CHECK_ERROR(glDetachShader(program.getID(), vertexShader));
MBGL_CHECK_ERROR(glDetachShader(program.getID(), fragmentShader));
MBGL_CHECK_ERROR(glDeleteShader(vertShader));
vertShader = 0;
MBGL_CHECK_ERROR(glDeleteShader(fragShader));
fragShader = 0;
MBGL_CHECK_ERROR(glDetachShader(program.getID(), vertexShader.getID()));
MBGL_CHECK_ERROR(glDetachShader(program.getID(), fragmentShader.getID()));
}
}
} // namespace mbgl

View File

@@ -14,7 +14,7 @@ public:
~Shader();
const GLchar *name;
inline const GLuint& getID() const {
GLuint getID() const {
return program.getID();
}
@@ -24,11 +24,11 @@ protected:
GLint a_pos = -1;
private:
bool compileShader(GLuint *shader, GLenum type, const GLchar *source[]);
bool compileShader(gl::ShaderHolder&, const GLchar *source[]);
gl::ProgramHolder program;
GLuint vertShader = 0;
GLuint fragShader = 0;
gl::ShaderHolder vertexShader = { GL_VERTEX_SHADER };
gl::ShaderHolder fragmentShader = { GL_FRAGMENT_SHADER };
};
} // namespace mbgl