summaryrefslogtreecommitdiff
path: root/src/mbgl/gl
diff options
context:
space:
mode:
authorJohn Firebaugh <john.firebaugh@gmail.com>2016-10-28 18:17:33 -0700
committerJohn Firebaugh <john.firebaugh@gmail.com>2016-11-08 08:09:29 -0800
commit66bdbc3b969083b9d647abdf72784be64a125949 (patch)
tree9f2f1c6eb3d0569926420459c2c9afda50c66fd0 /src/mbgl/gl
parent36210fe4e9c68a52dedc90548d90e77cf39a2228 (diff)
downloadqtlocation-mapboxgl-66bdbc3b969083b9d647abdf72784be64a125949.tar.gz
[core] Introduce gl::Program template
Diffstat (limited to 'src/mbgl/gl')
-rw-r--r--src/mbgl/gl/attribute.cpp4
-rw-r--r--src/mbgl/gl/attribute.hpp10
-rw-r--r--src/mbgl/gl/context.cpp55
-rw-r--r--src/mbgl/gl/context.hpp6
-rw-r--r--src/mbgl/gl/drawable.hpp16
-rw-r--r--src/mbgl/gl/program.hpp37
-rw-r--r--src/mbgl/gl/shader.cpp113
-rw-r--r--src/mbgl/gl/shader.hpp45
-rw-r--r--src/mbgl/gl/types.hpp5
-rw-r--r--src/mbgl/gl/uniform.cpp4
-rw-r--r--src/mbgl/gl/uniform.hpp14
11 files changed, 119 insertions, 190 deletions
diff --git a/src/mbgl/gl/attribute.cpp b/src/mbgl/gl/attribute.cpp
index 81ab6ac2a5..51fdd1dd12 100644
--- a/src/mbgl/gl/attribute.cpp
+++ b/src/mbgl/gl/attribute.cpp
@@ -4,6 +4,10 @@
namespace mbgl {
namespace gl {
+AttributeLocation attributeLocation(ProgramID id, const char* name) {
+ return MBGL_CHECK_ERROR(glGetAttribLocation(id, name));
+}
+
void bindAttribute(AttributeLocation location,
std::size_t count,
DataType type,
diff --git a/src/mbgl/gl/attribute.hpp b/src/mbgl/gl/attribute.hpp
index e6ef5c7f89..126da38de5 100644
--- a/src/mbgl/gl/attribute.hpp
+++ b/src/mbgl/gl/attribute.hpp
@@ -1,7 +1,6 @@
#pragma once
#include <mbgl/gl/types.hpp>
-#include <mbgl/gl/shader.hpp>
#include <cstddef>
#include <functional>
@@ -18,9 +17,6 @@ public:
class State {
public:
- State(const char* name, const Shader& shader)
- : location(shader.getAttributeLocation(name)) {}
-
AttributeLocation location;
static constexpr std::size_t count = N;
static constexpr DataType type = DataTypeOf<T>::value;
@@ -134,6 +130,8 @@ const std::size_t Vertex<A1, A2, A3, A4, A5>::attributeOffsets[5] = {
} // namespace detail
+AttributeLocation attributeLocation(ProgramID, const char * name);
+
void bindAttribute(AttributeLocation location,
std::size_t count,
DataType type,
@@ -147,8 +145,8 @@ public:
using State = std::tuple<typename As::State...>;
using Vertex = detail::Vertex<As...>;
- static State state(const Shader& shader) {
- return State { { As::name, shader }... };
+ static State state(const ProgramID& id) {
+ return State { { attributeLocation(id, As::name) }... };
}
static std::function<void (std::size_t)> binder(const State& state) {
diff --git a/src/mbgl/gl/context.cpp b/src/mbgl/gl/context.cpp
index f23dfe3dbe..b12c77c1a1 100644
--- a/src/mbgl/gl/context.cpp
+++ b/src/mbgl/gl/context.cpp
@@ -4,12 +4,16 @@
#include <mbgl/gl/vertex_array.hpp>
#include <mbgl/util/traits.hpp>
#include <mbgl/util/std.hpp>
+#include <mbgl/platform/log.hpp>
#include <boost/functional/hash.hpp>
namespace mbgl {
namespace gl {
+static_assert(underlying_type(ShaderType::Vertex) == GL_VERTEX_SHADER, "OpenGL type mismatch");
+static_assert(underlying_type(ShaderType::Fragment) == GL_FRAGMENT_SHADER, "OpenGL type mismatch");
+
static_assert(underlying_type(PrimitiveType::Points) == GL_POINTS, "OpenGL type mismatch");
static_assert(underlying_type(PrimitiveType::Lines) == GL_LINES, "OpenGL type mismatch");
static_assert(underlying_type(PrimitiveType::LineLoop) == GL_LINE_LOOP, "OpenGL type mismatch");
@@ -34,16 +38,53 @@ Context::~Context() {
reset();
}
-UniqueProgram Context::createProgram() {
- return UniqueProgram{ MBGL_CHECK_ERROR(glCreateProgram()), { this } };
-}
+UniqueShader Context::createShader(ShaderType type, const std::string& source) {
+ UniqueShader result { MBGL_CHECK_ERROR(glCreateShader(static_cast<GLenum>(type))), { this } };
+
+ const GLchar* sources = source.data();
+ const GLsizei lengths = static_cast<GLsizei>(source.length());
+ MBGL_CHECK_ERROR(glShaderSource(result, 1, &sources, &lengths));
+ MBGL_CHECK_ERROR(glCompileShader(result));
+
+ GLint status = 0;
+ MBGL_CHECK_ERROR(glGetShaderiv(result, GL_COMPILE_STATUS, &status));
+ if (status != 0) {
+ return result;
+ }
+
+ GLint logLength;
+ MBGL_CHECK_ERROR(glGetShaderiv(result, GL_INFO_LOG_LENGTH, &logLength));
+ if (logLength > 0) {
+ const auto log = std::make_unique<GLchar[]>(logLength);
+ MBGL_CHECK_ERROR(glGetShaderInfoLog(result, logLength, &logLength, log.get()));
+ Log::Error(Event::Shader, "Shader failed to compile: %s", log.get());
+ }
-UniqueShader Context::createVertexShader() {
- return UniqueShader{ MBGL_CHECK_ERROR(glCreateShader(GL_VERTEX_SHADER)), { this } };
+ throw std::runtime_error("shader failed to compile");
}
-UniqueShader Context::createFragmentShader() {
- return UniqueShader{ MBGL_CHECK_ERROR(glCreateShader(GL_FRAGMENT_SHADER)), { this } };
+UniqueProgram Context::createProgram(ShaderID vertexShader, ShaderID fragmentShader) {
+ UniqueProgram result { MBGL_CHECK_ERROR(glCreateProgram()), { this } };
+
+ MBGL_CHECK_ERROR(glAttachShader(result, vertexShader));
+ MBGL_CHECK_ERROR(glAttachShader(result, fragmentShader));
+ MBGL_CHECK_ERROR(glLinkProgram(result));
+
+ GLint status;
+ MBGL_CHECK_ERROR(glGetProgramiv(result, GL_LINK_STATUS, &status));
+ if (status != 0) {
+ return result;
+ }
+
+ GLint logLength;
+ MBGL_CHECK_ERROR(glGetProgramiv(result, GL_INFO_LOG_LENGTH, &logLength));
+ const auto log = std::make_unique<GLchar[]>(logLength);
+ if (logLength > 0) {
+ MBGL_CHECK_ERROR(glGetProgramInfoLog(result, logLength, &logLength, log.get()));
+ Log::Error(Event::Shader, "Program failed to link: %s", log.get());
+ }
+
+ throw std::runtime_error("program failed to link");
}
UniqueBuffer Context::createVertexBuffer(const void* data, std::size_t size) {
diff --git a/src/mbgl/gl/context.hpp b/src/mbgl/gl/context.hpp
index 438450fe14..2a3fbea33d 100644
--- a/src/mbgl/gl/context.hpp
+++ b/src/mbgl/gl/context.hpp
@@ -14,6 +14,7 @@
#include <memory>
#include <vector>
#include <array>
+#include <string>
#include <unordered_map>
namespace mbgl {
@@ -28,9 +29,8 @@ class Context : private util::noncopyable {
public:
~Context();
- UniqueProgram createProgram();
- UniqueShader createVertexShader();
- UniqueShader createFragmentShader();
+ UniqueShader createShader(ShaderType type, const std::string& source);
+ UniqueProgram createProgram(ShaderID vertexShader, ShaderID fragmentShader);
UniqueTexture createTexture();
template <class V>
diff --git a/src/mbgl/gl/drawable.hpp b/src/mbgl/gl/drawable.hpp
index be6b27bb83..747d8facf0 100644
--- a/src/mbgl/gl/drawable.hpp
+++ b/src/mbgl/gl/drawable.hpp
@@ -82,28 +82,28 @@ auto Segmented(const VertexBuffer<Vertex>& vertexBuffer,
class Drawable {
public:
- template <class Shader, class Subject>
+ template <class Program, class Subject>
Drawable(DepthMode depthMode_,
StencilMode stencilMode_,
ColorMode colorMode_,
- Shader& shader,
- typename Shader::UniformsType::Values&& uniformValues,
+ Program& program_,
+ typename Program::UniformValues&& uniformValues,
const Subject& subject)
: drawMode(subject.drawMode),
depthMode(std::move(depthMode_)),
stencilMode(std::move(stencilMode_)),
colorMode(std::move(colorMode_)),
- program(shader.getID()),
+ program(program_.program),
vertexBuffer(subject.vertexBuffer),
vertexSize(subject.vertexSize),
indexBuffer(subject.indexBuffer),
primitiveSize(subject.primitiveSize),
segments(subject.segments),
- bindUniforms(Shader::UniformsType::binder(shader.uniformsState, std::move(uniformValues))),
- bindAttributes(Shader::AttributesType::binder(shader.attributesState))
+ bindUniforms(Program::Uniforms::binder(program_.uniformsState, std::move(uniformValues))),
+ bindAttributes(Program::Attributes::binder(program_.attributesState))
{
- static_assert(std::is_standard_layout<typename Subject::VertexType>::value, "vertex type must use standard layout");
- static_assert(std::is_same<typename Shader::AttributesType::Vertex, typename Subject::VertexType>::value, "vertex type mismatch");
+ static_assert(std::is_standard_layout<typename Program::Vertex>::value, "vertex type must use standard layout");
+ static_assert(std::is_same<typename Program::Vertex, typename Subject::VertexType>::value, "vertex type mismatch");
}
DrawMode drawMode;
diff --git a/src/mbgl/gl/program.hpp b/src/mbgl/gl/program.hpp
new file mode 100644
index 0000000000..ea4dbcc1df
--- /dev/null
+++ b/src/mbgl/gl/program.hpp
@@ -0,0 +1,37 @@
+#pragma once
+
+#include <mbgl/gl/types.hpp>
+#include <mbgl/gl/object.hpp>
+#include <mbgl/gl/context.hpp>
+
+#include <string>
+
+namespace mbgl {
+namespace gl {
+
+template <class As, class Us>
+class Program {
+public:
+ using Attributes = As;
+ using Vertex = typename Attributes::Vertex;
+
+ using Uniforms = Us;
+ using UniformValues = typename Uniforms::Values;
+
+ Program(Context& context, const std::string& vertexSource, const std::string& fragmentSource)
+ : vertexShader(context.createShader(ShaderType::Vertex, vertexSource)),
+ fragmentShader(context.createShader(ShaderType::Fragment, fragmentSource)),
+ program(context.createProgram(vertexShader, fragmentShader)),
+ attributesState(Attributes::state(program)),
+ uniformsState(Uniforms::state(program)) {}
+
+ UniqueShader vertexShader;
+ UniqueShader fragmentShader;
+ UniqueProgram program;
+
+ typename Attributes::State attributesState;
+ typename Uniforms::State uniformsState;
+};
+
+} // namespace gl
+} // namespace mbgl
diff --git a/src/mbgl/gl/shader.cpp b/src/mbgl/gl/shader.cpp
deleted file mode 100644
index d8ee734567..0000000000
--- a/src/mbgl/gl/shader.cpp
+++ /dev/null
@@ -1,113 +0,0 @@
-#include <mbgl/gl/shader.hpp>
-#include <mbgl/gl/gl.hpp>
-#include <mbgl/gl/context.hpp>
-#include <mbgl/util/stopwatch.hpp>
-#include <mbgl/util/exception.hpp>
-#include <mbgl/platform/log.hpp>
-#include <mbgl/platform/platform.hpp>
-
-#include <cstring>
-#include <cassert>
-#include <iostream>
-#include <string>
-#include <fstream>
-#include <cstdio>
-#include <cassert>
-
-namespace mbgl {
-namespace gl {
-
-Shader::Shader(const char* name_,
- const char* vertexSource,
- const char* fragmentSource,
- Context& context,
- Defines defines)
- : name(name_),
- program(context.createProgram()),
- vertexShader(context.createVertexShader()),
- fragmentShader(context.createFragmentShader()) {
- util::stopwatch stopwatch("shader compilation", Event::Shader);
-
- if (!compileShader(vertexShader, vertexSource)) {
- Log::Error(Event::Shader, "Vertex shader %s failed to compile: %s", name, vertexSource);
- throw util::ShaderException(std::string { "Vertex shader " } + name + " failed to compile");
- }
-
- std::string fragment(fragmentSource);
- if (defines & Defines::Overdraw) {
- assert(fragment.find("#ifdef OVERDRAW_INSPECTOR") != std::string::npos);
- fragment.replace(fragment.find_first_of('\n'), 1, "\n#define OVERDRAW_INSPECTOR\n");
- }
-
- if (!compileShader(fragmentShader, fragment.c_str())) {
- Log::Error(Event::Shader, "Fragment shader %s failed to compile: %s", name, fragmentSource);
- throw util::ShaderException(std::string { "Fragment shader " } + name + " failed to compile");
- }
-
- // Attach shaders
- MBGL_CHECK_ERROR(glAttachShader(program.get(), vertexShader.get()));
- MBGL_CHECK_ERROR(glAttachShader(program.get(), fragmentShader.get()));
-
- // Link program
- GLint status;
- MBGL_CHECK_ERROR(glLinkProgram(program.get()));
-
- MBGL_CHECK_ERROR(glGetProgramiv(program.get(), GL_LINK_STATUS, &status));
- if (status == 0) {
- GLint logLength;
- MBGL_CHECK_ERROR(glGetProgramiv(program.get(), GL_INFO_LOG_LENGTH, &logLength));
- const auto log = std::make_unique<GLchar[]>(logLength);
- if (logLength > 0) {
- MBGL_CHECK_ERROR(glGetProgramInfoLog(program.get(), logLength, &logLength, log.get()));
- Log::Error(Event::Shader, "Program failed to link: %s", log.get());
- }
- throw util::ShaderException(std::string { "Program " } + name + " failed to link: " + log.get());
- }
-}
-
-bool Shader::compileShader(UniqueShader& shader, const GLchar *source) {
- GLint status = 0;
-
- const GLsizei lengths = static_cast<GLsizei>(std::strlen(source));
- MBGL_CHECK_ERROR(glShaderSource(shader.get(), 1, &source, &lengths));
-
- MBGL_CHECK_ERROR(glCompileShader(shader.get()));
-
- MBGL_CHECK_ERROR(glGetShaderiv(shader.get(), GL_COMPILE_STATUS, &status));
- if (status == 0) {
- GLint logLength;
- MBGL_CHECK_ERROR(glGetShaderiv(shader.get(), GL_INFO_LOG_LENGTH, &logLength));
- if (logLength > 0) {
- const auto log = std::make_unique<GLchar[]>(logLength);
- MBGL_CHECK_ERROR(glGetShaderInfoLog(shader.get(), logLength, &logLength, log.get()));
- Log::Error(Event::Shader, "Shader failed to compile: %s", log.get());
- }
- return false;
- }
-
- MBGL_CHECK_ERROR(glGetShaderiv(shader.get(), GL_COMPILE_STATUS, &status));
- if (status == GL_FALSE) {
- Log::Error(Event::Shader, "Shader %s failed to compile.", name);
- return false;
- }
-
- return true;
-}
-
-Shader::~Shader() {
- if (program.get()) {
- MBGL_CHECK_ERROR(glDetachShader(program.get(), vertexShader.get()));
- MBGL_CHECK_ERROR(glDetachShader(program.get(), fragmentShader.get()));
- }
-}
-
-UniformLocation Shader::getUniformLocation(const char* uniform) const {
- return MBGL_CHECK_ERROR(glGetUniformLocation(program.get(), uniform));
-}
-
-AttributeLocation Shader::getAttributeLocation(const char* attribute) const {
- return MBGL_CHECK_ERROR(glGetAttribLocation(program.get(), attribute));
-}
-
-} // namespace gl
-} // namespace mbgl
diff --git a/src/mbgl/gl/shader.hpp b/src/mbgl/gl/shader.hpp
deleted file mode 100644
index f88bd4f867..0000000000
--- a/src/mbgl/gl/shader.hpp
+++ /dev/null
@@ -1,45 +0,0 @@
-#pragma once
-
-#include <mbgl/gl/types.hpp>
-#include <mbgl/gl/object.hpp>
-#include <mbgl/util/noncopyable.hpp>
-
-namespace mbgl {
-namespace gl {
-
-class Context;
-
-class Shader : private util::noncopyable {
-public:
- ~Shader();
- const char* name;
-
- ProgramID getID() const {
- return program.get();
- }
-
- AttributeLocation getAttributeLocation(const char* uniform) const;
- UniformLocation getUniformLocation(const char* uniform) const;
-
- enum Defines : bool {
- None = false,
- Overdraw = true,
- };
-
-protected:
- Shader(const char* name_,
- const char* vertex,
- const char* fragment,
- Context&,
- Defines defines = Defines::None);
-
-private:
- bool compileShader(UniqueShader&, const char *source);
-
- UniqueProgram program;
- UniqueShader vertexShader;
- UniqueShader fragmentShader;
-};
-
-} // namespace gl
-} // namespace mbgl
diff --git a/src/mbgl/gl/types.hpp b/src/mbgl/gl/types.hpp
index 1697656469..577629d5d3 100644
--- a/src/mbgl/gl/types.hpp
+++ b/src/mbgl/gl/types.hpp
@@ -19,6 +19,11 @@ using AttributeLocation = int32_t;
using UniformLocation = int32_t;
using TextureUnit = uint8_t;
+enum class ShaderType : uint32_t {
+ Vertex = 0x8B31,
+ Fragment = 0x8B30
+};
+
enum class DataType : uint32_t {
Byte = 0x1400,
UnsignedByte = 0x1401,
diff --git a/src/mbgl/gl/uniform.cpp b/src/mbgl/gl/uniform.cpp
index 8018953fb5..7b674f2cde 100644
--- a/src/mbgl/gl/uniform.cpp
+++ b/src/mbgl/gl/uniform.cpp
@@ -7,6 +7,10 @@
namespace mbgl {
namespace gl {
+UniformLocation uniformLocation(ProgramID id, const char* name) {
+ return MBGL_CHECK_ERROR(glGetUniformLocation(id, name));
+}
+
template <>
void bindUniform<float>(UniformLocation location, const float& t) {
MBGL_CHECK_ERROR(glUniform1f(location, t));
diff --git a/src/mbgl/gl/uniform.hpp b/src/mbgl/gl/uniform.hpp
index 40a48d3af3..90ca16e46f 100644
--- a/src/mbgl/gl/uniform.hpp
+++ b/src/mbgl/gl/uniform.hpp
@@ -1,6 +1,6 @@
#pragma once
-#include <mbgl/gl/shader.hpp>
+#include <mbgl/gl/types.hpp>
#include <mbgl/util/optional.hpp>
#include <array>
@@ -27,9 +27,6 @@ public:
class State {
public:
- State(const char* name, const Shader& shader)
- : location(shader.getUniformLocation(name)) {}
-
void operator=(const Value& value) {
if (!current || *current != value.t) {
current = value.t;
@@ -37,9 +34,8 @@ public:
}
}
- private:
- optional<T> current;
UniformLocation location;
+ optional<T> current = {};
};
};
@@ -61,14 +57,16 @@ using UniformMatrix = Uniform<Tag, std::array<T, N*N>>;
#define MBGL_DEFINE_UNIFORM_MATRIX(type_, n_, name_) \
struct name_ : ::mbgl::gl::UniformMatrix<name_, type_, n_> { static constexpr auto name = #name_; }
+UniformLocation uniformLocation(ProgramID, const char * name);
+
template <class... Us>
class Uniforms {
public:
using State = std::tuple<typename Us::State...>;
using Values = std::tuple<typename Us::Value...>;
- static State state(const Shader& shader) {
- return State { { Us::name, shader }... };
+ static State state(const ProgramID& id) {
+ return State { { uniformLocation(id, Us::name) }... };
}
static std::function<void ()> binder(State& state, Values&& values_) {