Uniform buffer objects (#1127)

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
This commit is contained in:
Alex Cristici
2023-05-11 20:33:58 +03:00
committed by Bart Louwers
parent bbb8bf3c1e
commit d8ea91de98
34 changed files with 634 additions and 163 deletions

View File

@@ -149,6 +149,8 @@ list(APPEND INCLUDE_FILES
${PROJECT_SOURCE_DIR}/include/mbgl/gfx/rendering_stats.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/gfx/shader_registry.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/gfx/shader.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/gfx/uniform_block.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/gfx/uniform_buffer.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/gfx/vertex_attribute.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/layermanager/background_layer_factory.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/layermanager/circle_layer_factory.hpp
@@ -391,6 +393,8 @@ list(APPEND SRC_FILES
${PROJECT_SOURCE_DIR}/src/mbgl/gfx/texture.hpp
${PROJECT_SOURCE_DIR}/src/mbgl/gfx/types.hpp
${PROJECT_SOURCE_DIR}/src/mbgl/gfx/uniform.hpp
${PROJECT_SOURCE_DIR}/src/mbgl/gfx/uniform_block.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/gfx/uniform_buffer.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/gfx/upload_pass.hpp
${PROJECT_SOURCE_DIR}/src/mbgl/gfx/vertex_attribute.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/gfx/vertex_buffer.hpp
@@ -910,6 +914,8 @@ if(MLN_WITH_OPENGL)
${PROJECT_SOURCE_DIR}/include/mbgl/gl/drawable_gl_tweaker.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/gl/renderable_resource.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/gl/renderer_backend.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/gl/uniform_block_gl.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/gl/uniform_buffer_gl.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/gl/vertex_attribute_gl.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/layermanager/location_indicator_layer_factory.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/platform/gl_functions.hpp
@@ -919,6 +925,7 @@ if(MLN_WITH_OPENGL)
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/shader_manifest.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/gl/prelude.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/gl/background.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/gl/background_ubo.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/gl/background_pattern.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/gl/circle.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/gl/clipping_mask.hpp
@@ -990,6 +997,8 @@ if(MLN_WITH_OPENGL)
${PROJECT_SOURCE_DIR}/src/mbgl/gl/types.hpp
${PROJECT_SOURCE_DIR}/src/mbgl/gl/uniform.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/gl/uniform.hpp
${PROJECT_SOURCE_DIR}/src/mbgl/gl/uniform_block_gl.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/gl/uniform_buffer_gl.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/gl/upload_pass.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/gl/upload_pass.hpp
${PROJECT_SOURCE_DIR}/src/mbgl/gl/value.cpp

View File

@@ -1,5 +1,6 @@
#pragma once
#include <mbgl/gfx/uniform_buffer.hpp>
#include <mbgl/gfx/vertex_attribute.hpp>
#include <mbgl/tile/tile_id.hpp>
#include <mbgl/util/identity.hpp>
@@ -22,7 +23,7 @@ enum class DepthMaskType : bool;
class DrawableTweaker;
class ShaderProgramBase;
using ShaderProgramBasePtr = std::shared_ptr<ShaderProgramBase>;
using UniformBufferPtr = std::shared_ptr<UniformBuffer>;
using DrawPriority = int64_t;
using DrawableTweakerPtr = std::shared_ptr<DrawableTweaker>;
@@ -94,6 +95,10 @@ public:
/// Get the tweakers attached to this drawable
const std::vector<DrawableTweakerPtr>& getTweakers() const { return tweakers; }
/// Get the uniform buffers attached to this drawable
virtual const gfx::UniformBufferArray& getUniformBuffers() const = 0;
virtual gfx::UniformBufferArray& mutableUniformBuffers() = 0;
// Reset a single color attribute for all vertexes
virtual void resetColor(const Color&) = 0;
@@ -137,5 +142,9 @@ private:
bool desc;
};
struct alignas(16) DrawableUBO {
std::array<float, 4 * 4> matrix;
};
} // namespace gfx
} // namespace mbgl

View File

@@ -0,0 +1,94 @@
#pragma once
#include <string>
#include <memory>
#include <unordered_map>
namespace mbgl {
namespace gfx {
class UniformBuffer;
class UniformBlock {
// Can only be created by UniformBlockArray implementations
protected:
UniformBlock(int index_, std::size_t size_)
: index(index_),
size(size_) {}
UniformBlock(const UniformBlock&) = default;
UniformBlock(UniformBlock&& other)
: index(other.index),
size(other.size) {}
public:
virtual ~UniformBlock() = default;
int getIndex() const { return index; }
std::size_t getSize() const { return size; }
virtual void bindBuffer(const UniformBuffer& uniformBuffer) = 0;
virtual void unbindBuffer() = 0;
protected:
UniformBlock& operator=(const UniformBlock&) = default;
UniformBlock& operator=(UniformBlock&& other) {
index = other.index;
size = other.size;
return *this;
}
protected:
int index;
std::size_t size;
};
/// Stores a collection of uniform blocks by name
class UniformBlockArray {
public:
using UniformBlockMap = std::unordered_map<std::string, std::unique_ptr<UniformBlock>>;
UniformBlockArray(int initCapacity = 10);
UniformBlockArray(UniformBlockArray&&);
// Would need to use the virtual assignment operator
UniformBlockArray(const UniformBlockArray&) = delete;
virtual ~UniformBlockArray() = default;
/// Get map of elements.
const UniformBlockMap& getMap() const { return uniformBlockMap; }
/// Number of elements
std::size_t size() const { return uniformBlockMap.size(); }
/// Get an uniform block element.
/// Returns a pointer to the element on success, or null if the uniform block doesn't exists.
const std::unique_ptr<UniformBlock>& get(const std::string& name) const;
/// Add a new uniform block element.
/// Returns a pointer to the new element on success, or null if the uniform block already exists.
const std::unique_ptr<UniformBlock>& add(std::string name, int index, std::size_t size);
UniformBlockArray& operator=(UniformBlockArray&&);
UniformBlockArray& operator=(const UniformBlockArray&);
protected:
const std::unique_ptr<UniformBlock>& add(std::string name, std::unique_ptr<UniformBlock>&& uniformBlock) {
const auto result = uniformBlockMap.insert(std::make_pair(std::move(name), std::unique_ptr<UniformBlock>()));
if (result.second) {
result.first->second = std::move(uniformBlock);
return result.first->second;
} else {
return nullref;
}
}
virtual std::unique_ptr<UniformBlock> create(int index, std::size_t size) = 0;
virtual std::unique_ptr<UniformBlock> copy(const UniformBlock& uniformBlock) = 0;
protected:
UniformBlockMap uniformBlockMap;
static std::unique_ptr<UniformBlock> nullref;
};
} // namespace gfx
} // namespace mbgl

View File

@@ -0,0 +1,79 @@
#pragma once
#include <memory>
#include <string>
#include <unordered_map>
namespace mbgl {
namespace gfx {
class UniformBuffer {
// Can only be created by platform specific implementations
protected:
UniformBuffer(std::size_t size_)
: size(size_) {}
UniformBuffer(const UniformBuffer&) = default;
UniformBuffer(UniformBuffer&& other)
: size(other.size) {}
public:
virtual ~UniformBuffer() = default;
std::size_t getSize() const { return size; }
protected:
UniformBuffer& operator=(const UniformBuffer&) = default;
UniformBuffer& operator=(UniformBuffer&& other) {
size = other.size;
return *this;
}
protected:
std::size_t size;
};
/// Stores a collection of uniform buffers by name
class UniformBufferArray {
public:
using UniformBufferMap = std::unordered_map<std::string, std::shared_ptr<UniformBuffer>>;
UniformBufferArray(int initCapacity = 10);
UniformBufferArray(UniformBufferArray&&);
// Would need to use the virtual assignment operator
UniformBufferArray(const UniformBufferArray&) = delete;
virtual ~UniformBufferArray() = default;
/// Number of elements
std::size_t size() const { return uniformBufferMap.size(); }
/// Get an uniform buffer element.
/// Returns a pointer to the element on success, or null if the uniform buffer doesn't exists.
const std::shared_ptr<UniformBuffer>& get(const std::string& name) const;
/// Add a new uniform buffer element or replace the existing one.
const std::shared_ptr<UniformBuffer>& addOrReplace(std::string name,
const std::shared_ptr<UniformBuffer>& uniformBuffer);
UniformBufferArray& operator=(UniformBufferArray&&);
UniformBufferArray& operator=(const UniformBufferArray&);
protected:
const std::shared_ptr<UniformBuffer>& add(std::string name, std::shared_ptr<UniformBuffer>&& uniformBuffer) {
const auto result = uniformBufferMap.insert(std::make_pair(std::move(name), std::shared_ptr<UniformBuffer>()));
if (result.second) {
result.first->second = std::move(uniformBuffer);
return result.first->second;
} else {
return nullref;
}
}
virtual std::unique_ptr<UniformBuffer> copy(const UniformBuffer& uniformBuffer) = 0;
protected:
UniformBufferMap uniformBufferMap;
static std::shared_ptr<UniformBuffer> nullref;
};
} // namespace gfx
} // namespace mbgl

View File

@@ -147,30 +147,30 @@ public:
/// Add a new attribute element.
/// Returns a pointer to the new element on success, or null if the attribute already exists.
/// The result is valid only until the next non-const method call on this class.
VertexAttribute* get(const std::string& name) const;
const std::unique_ptr<VertexAttribute>& get(const std::string& name) const;
/// Add a new attribute element.
/// Returns a pointer to the new element on success, or null if the attribute already exists.
/// The result is valid only until the next non-const method call on this class.
VertexAttribute* add(std::string name,
int index = -1,
AttributeDataType = AttributeDataType::Invalid,
int size = 1,
std::size_t count = 1);
const std::unique_ptr<VertexAttribute>& add(std::string name,
int index = -1,
AttributeDataType = AttributeDataType::Invalid,
int size = 1,
std::size_t count = 1);
/// Add a new attribute element if it doesn't already exist.
/// Returns a pointer to the new element on success, or null if the type or count conflict with an existing entry.
/// The result is valid only until the next non-const method call on this class.
VertexAttribute* getOrAdd(std::string name,
int index = -1,
AttributeDataType = AttributeDataType::Invalid,
int size = 1,
std::size_t count = 1);
const std::unique_ptr<VertexAttribute>& getOrAdd(std::string name,
int index = -1,
AttributeDataType = AttributeDataType::Invalid,
int size = 1,
std::size_t count = 1);
// Set a value if the element is present
template <typename T>
bool set(const std::string& name, std::size_t i, T value) {
if (auto* item = get(name)) {
if (const auto& item = get(name)) {
return item->set(i, value);
}
return false;
@@ -182,24 +182,22 @@ public:
attrs.begin(), attrs.end(), [](const auto& kv) { return kv.second && kv.second->isDirty(); });
}
using ResolveDelegate = std::function<void(const std::string&, const VertexAttribute&, const VertexAttribute*)>;
using ResolveDelegate =
std::function<void(const std::string&, const VertexAttribute&, const std::unique_ptr<VertexAttribute>&)>;
/// Call the provided delegate with each value, providing the override if one exists.
void resolve(const VertexAttributeArray& overrides, ResolveDelegate) const;
/// Apply to the active program
virtual void applyUniforms(const ShaderProgramBase&) = 0;
VertexAttributeArray& operator=(VertexAttributeArray&&);
VertexAttributeArray& operator=(const VertexAttributeArray&);
protected:
VertexAttribute* add(std::string name, std::unique_ptr<VertexAttribute>&& attr) {
const std::unique_ptr<VertexAttribute>& add(std::string name, std::unique_ptr<VertexAttribute>&& attr) {
const auto result = attrs.insert(std::make_pair(std::move(name), std::unique_ptr<VertexAttribute>()));
if (result.second) {
result.first->second = std::move(attr);
return result.first->second.get();
return result.first->second;
} else {
return nullptr;
return nullref;
}
}
@@ -211,6 +209,7 @@ protected:
protected:
AttributeMap attrs;
static std::unique_ptr<VertexAttribute> nullref;
};
} // namespace gfx

View File

@@ -42,6 +42,9 @@ public:
const gfx::UniqueVertexBufferResource& getBuffer() const;
const gfx::IndexBuffer& getIndexBuffer() const;
const gfx::UniformBufferArray& getUniformBuffers() const override;
gfx::UniformBufferArray& mutableUniformBuffers() override;
/// Reset a single color attribute for all vertexes
void resetColor(const Color&) override;
@@ -61,6 +64,8 @@ protected:
DrawableGL(std::unique_ptr<Impl>);
private:
void bindUniformBuffers() const;
void unbindUniformBuffers() const;
};
} // namespace gl

View File

@@ -0,0 +1,57 @@
#pragma once
#include <mbgl/gfx/uniform_block.hpp>
#include <mbgl/gfx/uniform_buffer.hpp>
namespace mbgl {
namespace gl {
class UniformBlockArrayGL;
class UniformBlockGL final : public gfx::UniformBlock {
// Can only be created by UniformBlockArrayGL
private:
friend UniformBlockArrayGL;
UniformBlockGL(int index_, std::size_t size_)
: UniformBlock(index_, size_) {}
UniformBlockGL(const UniformBlockGL& other)
: UniformBlock(other) {}
UniformBlockGL(UniformBlockGL&& other)
: UniformBlock(std::move(other)) {}
public:
void bindBuffer(const gfx::UniformBuffer& uniformBuffer) override;
void unbindBuffer() override;
};
/// Stores a collection of uniform blocks by name
class UniformBlockArrayGL final : public gfx::UniformBlockArray {
public:
UniformBlockArrayGL(int initCapacity = 10)
: UniformBlockArray(initCapacity) {}
UniformBlockArrayGL(UniformBlockArrayGL&& other)
: UniformBlockArray(std::move(other)) {}
UniformBlockArrayGL(const UniformBlockArrayGL&) = delete;
UniformBlockArrayGL& operator=(UniformBlockArrayGL&& other) {
UniformBlockArray::operator=(std::move(other));
return *this;
}
UniformBlockArrayGL& operator=(const UniformBlockArrayGL& other) {
UniformBlockArray::operator=(other);
return *this;
}
private:
std::unique_ptr<gfx::UniformBlock> create(int index, std::size_t size) override {
return std::unique_ptr<gfx::UniformBlock>(new UniformBlockGL(index, size));
}
std::unique_ptr<gfx::UniformBlock> copy(const gfx::UniformBlock& uniformBlocks) override {
return std::unique_ptr<gfx::UniformBlock>(
new UniformBlockGL(static_cast<const UniformBlockGL&>(uniformBlocks)));
}
};
} // namespace gl
} // namespace mbgl

View File

@@ -0,0 +1,49 @@
#pragma once
#include <mbgl/gfx/uniform_buffer.hpp>
#include <mbgl/gl/types.hpp>
namespace mbgl {
namespace gl {
class UniformBufferGL final : public gfx::UniformBuffer {
public:
UniformBufferGL(const void* data, std::size_t size_);
UniformBufferGL(const UniformBufferGL& other)
: UniformBuffer(other) {}
UniformBufferGL(UniformBufferGL&& other)
: UniformBuffer(std::move(other)) {}
BufferID getID() const { return id; }
protected:
BufferID id = 0;
};
/// Stores a collection of uniform buffers by name
class UniformBufferArrayGL final : public gfx::UniformBufferArray {
public:
UniformBufferArrayGL(int initCapacity = 10)
: UniformBufferArray(initCapacity) {}
UniformBufferArrayGL(UniformBufferArrayGL&& other)
: UniformBufferArray(std::move(other)) {}
UniformBufferArrayGL(const UniformBufferArrayGL&) = delete;
UniformBufferArrayGL& operator=(UniformBufferArrayGL&& other) {
UniformBufferArray::operator=(std::move(other));
return *this;
}
UniformBufferArrayGL& operator=(const UniformBufferArrayGL& other) {
UniformBufferArray::operator=(other);
return *this;
}
private:
std::unique_ptr<gfx::UniformBuffer> copy(const gfx::UniformBuffer& uniformBuffers) override {
return std::unique_ptr<gfx::UniformBuffer>(
new UniformBufferGL(static_cast<const UniformBufferGL&>(uniformBuffers)));
}
};
} // namespace gl
} // namespace mbgl

View File

@@ -62,8 +62,6 @@ public:
return *this;
}
void applyUniforms(const gfx::ShaderProgramBase&) override;
private:
std::unique_ptr<gfx::VertexAttribute> create(int index,
gfx::AttributeDataType dataType,

View File

@@ -0,0 +1,43 @@
#pragma once
#include <mbgl/shaders/shader_source.hpp>
namespace mbgl {
namespace shaders {
template <>
struct ShaderSource<BuiltIn::BackgroundProgramUBO, gfx::Backend::Type::OpenGL> {
static constexpr const char* vertex = R"(#version 300 es
precision highp float;
layout (location = 0) in vec2 a_pos;
layout (std140) uniform DrawableUBO {
mat4 u_matrix;
};
void main() {
gl_Position = u_matrix * vec4(a_pos, 0, 1);
}
)";
static constexpr const char* fragment = R"(#version 300 es
precision highp float;
layout (std140) uniform BackgroundLayerUBO {
vec4 u_color;
float u_opacity;
};
out vec4 fragColor;
void main() {
fragColor = u_color * u_opacity;
#ifdef OVERDRAW_INSPECTOR
fragColor = vec4(1.0);
#endif
}
)";
};
} // namespace shaders
} // namespace mbgl

View File

@@ -1,6 +1,7 @@
#pragma once
#include <mbgl/gl/context.hpp>
#include <mbgl/gl/uniform_block_gl.hpp>
#include <mbgl/gl/vertex_attribute_gl.hpp>
#include <mbgl/shaders/shader_program_base.hpp>
@@ -10,7 +11,7 @@ namespace gl {
class ShaderProgramGL final : public gfx::ShaderProgramBase {
public:
ShaderProgramGL(UniqueProgram&& glProgram_);
ShaderProgramGL(UniqueProgram&&, VertexAttributeArrayGL&& uniforms, VertexAttributeArrayGL&& attributes);
ShaderProgramGL(UniqueProgram&&, UniformBlockArrayGL&& uniformBlocks, VertexAttributeArrayGL&& attributes);
ShaderProgramGL(ShaderProgramGL&& other);
~ShaderProgramGL() noexcept override = default;
@@ -22,21 +23,21 @@ public:
std::string_view vertexSource,
std::string_view fragmentSource) noexcept(false);
const gfx::VertexAttributeArray& getUniforms() const override { return uniforms; }
const gfx::UniformBlockArray& getUniformBlocks() const override { return uniformBlocks; }
const gfx::VertexAttributeArray& getVertexAttributes() const override { return vertexAttributes; }
ProgramID getGLProgramID() const { return glProgram; }
protected:
gfx::VertexAttributeArray& mutableUniforms() override { return uniforms; }
gfx::UniformBlockArray& mutableUniformBlocks() override { return uniformBlocks; }
gfx::VertexAttributeArray& mutableVertexAttributes() override { return vertexAttributes; }
protected:
UniqueProgram glProgram;
VertexAttributeArrayGL uniforms;
UniformBlockArrayGL uniformBlocks;
VertexAttributeArrayGL vertexAttributes;
};

View File

@@ -32,4 +32,6 @@
#include <mbgl/shaders/gl/symbol_sdf_text.hpp>
#include <mbgl/shaders/gl/symbol_sdf_icon.hpp>
#include <mbgl/shaders/gl/symbol_text_and_icon.hpp>
#include <mbgl/shaders/gl/background_ubo.hpp>
#endif

View File

@@ -1,6 +1,7 @@
#pragma once
#include <mbgl/gfx/shader.hpp>
#include <mbgl/gfx/uniform_block.hpp>
#include <mbgl/gfx/vertex_attribute.hpp>
#include <mbgl/util/identity.hpp>
@@ -17,7 +18,7 @@ protected:
template <typename T>
bool set(gfx::VertexAttributeArray& attrs, const std::string& name, std::size_t i, T value) {
auto* item = attrs.get(name);
const auto& item = attrs.get(name);
if (item && i < item->getCount()) {
item->set(i, value);
return true;
@@ -28,26 +29,19 @@ protected:
public:
const util::SimpleIdentity& getID() const { return shaderProgramID; }
/// Get the available vertex attributes and their default values
virtual const gfx::VertexAttributeArray& getUniforms() const = 0;
/// Get the available uniform blocks attached to this shader
virtual const gfx::UniformBlockArray& getUniformBlocks() const = 0;
/// Get the available vertex attributes and their default values
virtual const gfx::VertexAttributeArray& getVertexAttributes() const = 0;
// Set a value if the element is present
template <typename T>
bool setUniform(const std::string& name, std::size_t i, T value) {
return set(mutableUniforms(), name, i, value);
}
template <typename T>
bool setAttribute(const std::string& name, std::size_t i, T value) {
return set(mutableVertexAttributes(), name, i, value);
}
void updateUniforms() { mutableUniforms().applyUniforms(*this); }
protected:
virtual gfx::VertexAttributeArray& mutableUniforms() = 0;
virtual gfx::UniformBlockArray& mutableUniformBlocks() = 0;
virtual gfx::VertexAttributeArray& mutableVertexAttributes() = 0;
protected:

View File

@@ -37,7 +37,9 @@ enum class BuiltIn {
SymbolIconProgram,
SymbolSDFTextProgram,
SymbolSDFIconProgram,
SymbolTextAndIconProgram
SymbolTextAndIconProgram,
BackgroundProgramUBO
};
/// @brief Select shader source based on a program type and a desired

View File

@@ -6,6 +6,7 @@
#include <mbgl/gfx/program.hpp>
#include <mbgl/gfx/renderbuffer.hpp>
#include <mbgl/gfx/rendering_stats.hpp>
#include <mbgl/gfx/uniform_buffer.hpp>
#include <mbgl/gfx/texture.hpp>
#include <mbgl/gfx/types.hpp>
@@ -29,6 +30,7 @@ class ShaderRegistry;
using DrawablePtr = std::shared_ptr<Drawable>;
using UniqueDrawableBuilder = std::unique_ptr<DrawableBuilder>;
using DrawableTweakerPtr = std::shared_ptr<DrawableTweaker>;
using UniformBufferPtr = std::shared_ptr<UniformBuffer>;
using ShaderProgramBasePtr = std::shared_ptr<ShaderProgramBase>;
class Context {
@@ -106,6 +108,9 @@ public:
/// Create a new drawable tweaker
virtual DrawableTweakerPtr createDrawableTweaker() = 0;
/// Create a new uniform buffer
virtual UniformBufferPtr createUniformBuffer(const void* data, std::size_t size) = 0;
/// Get the generic shader with the specified name
virtual gfx::ShaderProgramBasePtr getGenericShader(gfx::ShaderRegistry&, const std::string& name) = 0;
};

View File

@@ -0,0 +1,43 @@
#include <mbgl/gfx/uniform_block.hpp>
namespace mbgl {
namespace gfx {
std::unique_ptr<UniformBlock> UniformBlockArray::nullref = nullptr;
UniformBlockArray::UniformBlockArray(int initCapacity)
: uniformBlockMap(initCapacity) {}
UniformBlockArray::UniformBlockArray(UniformBlockArray&& other)
: uniformBlockMap(std::move(other.uniformBlockMap)) {}
UniformBlockArray& UniformBlockArray::operator=(UniformBlockArray&& other) {
uniformBlockMap = std::move(other.uniformBlockMap);
return *this;
}
UniformBlockArray& UniformBlockArray::operator=(const UniformBlockArray& other) {
uniformBlockMap.clear();
for (const auto& kv : other.uniformBlockMap) {
add(kv.first, copy(*kv.second));
}
return *this;
}
const std::unique_ptr<UniformBlock>& UniformBlockArray::get(const std::string& name) const {
const auto result = uniformBlockMap.find(name);
return (result != uniformBlockMap.end()) ? result->second : nullref;
}
const std::unique_ptr<UniformBlock>& UniformBlockArray::add(std::string name, int index, std::size_t size) {
const auto result = uniformBlockMap.insert(std::make_pair(std::move(name), std::unique_ptr<UniformBlock>()));
if (result.second) {
result.first->second = create(index, size);
return result.first->second;
} else {
return nullref;
}
}
} // namespace gfx
} // namespace mbgl

View File

@@ -0,0 +1,40 @@
#include <mbgl/gfx/uniform_buffer.hpp>
namespace mbgl {
namespace gfx {
std::shared_ptr<UniformBuffer> UniformBufferArray::nullref = nullptr;
UniformBufferArray::UniformBufferArray(int initCapacity)
: uniformBufferMap(initCapacity) {}
UniformBufferArray::UniformBufferArray(UniformBufferArray&& other)
: uniformBufferMap(std::move(other.uniformBufferMap)) {}
UniformBufferArray& UniformBufferArray::operator=(UniformBufferArray&& other) {
uniformBufferMap = std::move(other.uniformBufferMap);
return *this;
}
UniformBufferArray& UniformBufferArray::operator=(const UniformBufferArray& other) {
uniformBufferMap.clear();
for (const auto& kv : other.uniformBufferMap) {
add(kv.first, copy(*kv.second));
}
return *this;
}
const std::shared_ptr<UniformBuffer>& UniformBufferArray::get(const std::string& name) const {
const auto result = uniformBufferMap.find(name);
return (result != uniformBufferMap.end()) ? result->second : nullref;
}
const std::shared_ptr<UniformBuffer>& UniformBufferArray::addOrReplace(
std::string name, const std::shared_ptr<UniformBuffer>& uniformBuffer) {
const auto result = uniformBufferMap.insert(std::make_pair(std::move(name), std::shared_ptr<UniformBuffer>()));
result.first->second = std::move(uniformBuffer);
return result.first->second;
}
} // namespace gfx
} // namespace mbgl

View File

@@ -7,6 +7,8 @@
namespace mbgl {
namespace gfx {
std::unique_ptr<VertexAttribute> VertexAttributeArray::nullref = nullptr;
VertexAttributeArray::VertexAttributeArray(int initCapacity)
: attrs(initCapacity) {}
@@ -26,23 +28,23 @@ VertexAttributeArray& VertexAttributeArray::operator=(const VertexAttributeArray
return *this;
}
VertexAttribute* VertexAttributeArray::get(const std::string& name) const {
const std::unique_ptr<VertexAttribute>& VertexAttributeArray::get(const std::string& name) const {
const auto result = attrs.find(name);
return (result != attrs.end()) ? result->second.get() : nullptr;
return (result != attrs.end()) ? result->second : nullref;
}
VertexAttribute* VertexAttributeArray::add(
const std::unique_ptr<VertexAttribute>& VertexAttributeArray::add(
std::string name, int index, AttributeDataType dataType, int size, std::size_t count) {
const auto result = attrs.insert(std::make_pair(std::move(name), std::unique_ptr<VertexAttribute>()));
if (result.second) {
result.first->second = create(index, dataType, size, count);
return result.first->second.get();
return result.first->second;
} else {
return nullptr;
return nullref;
}
}
VertexAttribute* VertexAttributeArray::getOrAdd(
const std::unique_ptr<VertexAttribute>& VertexAttributeArray::getOrAdd(
std::string name, int index, AttributeDataType dataType, int size, std::size_t count) {
// attrs.emplace_back(std::make_unique<VertexAttribute>(dataType, count));
const auto result = attrs.insert(std::make_pair(std::move(name), std::unique_ptr<VertexAttribute>()));
@@ -50,9 +52,9 @@ VertexAttribute* VertexAttributeArray::getOrAdd(
result.first->second = create(index, dataType, size, count);
} else if (result.first->second->getDataType() != dataType ||
result.first->second->getSize() != (std::size_t)size || result.first->second->getCount() != count) {
return nullptr;
return nullref;
}
return result.first->second.get();
return result.first->second;
}
std::size_t VertexAttributeArray::getTotalSize() const {

View File

@@ -10,6 +10,7 @@
#include <mbgl/gl/enum.hpp>
#include <mbgl/gl/renderer_backend.hpp>
#include <mbgl/gl/renderbuffer_resource.hpp>
#include <mbgl/gl/uniform_buffer_gl.hpp>
#include <mbgl/gl/texture_resource.hpp>
#include <mbgl/gl/texture.hpp>
#include <mbgl/gl/offscreen_texture.hpp>
@@ -497,6 +498,10 @@ gfx::DrawableTweakerPtr Context::createDrawableTweaker() {
return std::make_shared<gl::DrawableGLTweaker>();
}
gfx::UniformBufferPtr Context::createUniformBuffer(const void* data, std::size_t size) {
return std::make_shared<gl::UniformBufferGL>(data, size);
}
gfx::ShaderProgramBasePtr Context::getGenericShader(gfx::ShaderRegistry& shaders, const std::string& name) {
return shaders.get<gl::ShaderProgramGL>(name);
}

View File

@@ -106,6 +106,7 @@ public:
gfx::UniqueDrawableBuilder createDrawableBuilder(std::string name) override;
gfx::DrawableTweakerPtr createDrawableTweaker() override;
gfx::UniformBufferPtr createUniformBuffer(const void* data, std::size_t size) override;
gfx::ShaderProgramBasePtr getGenericShader(gfx::ShaderRegistry&, const std::string& name) override;

View File

@@ -2,6 +2,8 @@
#include <mbgl/gl/drawable_gl_impl.hpp>
#include <mbgl/gl/vertex_buffer_resource.hpp>
#include <mbgl/shaders/gl/shader_program_gl.hpp>
namespace mbgl {
namespace gl {
@@ -16,7 +18,9 @@ DrawableGL::~DrawableGL() {
}
void DrawableGL::draw(const PaintParameters& parameters) const {
bindUniformBuffers();
impl->draw(parameters);
unbindUniformBuffers();
}
void DrawableGL::setIndexData(std::vector<std::uint16_t> indexes,
@@ -67,12 +71,42 @@ void DrawableGL::setVertexArray(gl::VertexArray&& vertexArray_,
impl->indexBuffer = std::move(indexBuffer_);
}
const gfx::UniformBufferArray& DrawableGL::getUniformBuffers() const {
return impl->uniformBuffers;
}
gfx::UniformBufferArray& DrawableGL::mutableUniformBuffers() {
return impl->uniformBuffers;
}
void DrawableGL::resetColor(const Color& newColor) {
if (auto* colorAttr = impl->vertexAttributes.get("a_color")) {
if (const auto& colorAttr = impl->vertexAttributes.get("a_color")) {
colorAttr->clear();
colorAttr->set(0, colorAttrValue(newColor));
}
}
void DrawableGL::bindUniformBuffers() const {
if (shader) {
const auto& shaderGL = static_cast<const ShaderProgramGL&>(*shader);
for (const auto& element : shaderGL.getUniformBlocks().getMap()) {
const auto& uniformBuffer = getUniformBuffers().get(element.first);
if (!uniformBuffer) {
continue;
}
element.second->bindBuffer(*uniformBuffer);
}
}
}
void DrawableGL::unbindUniformBuffers() const {
if (shader) {
const auto& shaderGL = static_cast<const ShaderProgramGL&>(*shader);
for (const auto& element : shaderGL.getUniformBlocks().getMap()) {
element.second->unbindBuffer();
}
}
}
} // namespace gl
} // namespace mbgl

View File

@@ -15,13 +15,13 @@ void DrawableGLBuilder::init() {
auto& drawableGL = static_cast<DrawableGL&>(*currentDrawable);
auto& attrs = drawableGL.mutableVertexAttributes();
if (auto posAttr = attrs.getOrAdd("a_pos")) {
if (const auto& posAttr = attrs.getOrAdd("a_pos")) {
std::size_t index = 0;
for (const auto& vert : impl->vertices.vector()) {
posAttr->set(index++, gfx::VertexAttribute::int2{vert.a1[0], vert.a1[1]});
}
}
if (auto colorAttr = attrs.getOrAdd("a_color")) {
if (const auto& colorAttr = attrs.getOrAdd("a_color")) {
// We should have either a single color or one per vertex. Otherwise,
// the color mode was probably changed after vertexes were added.
if (impl->colors.size() > 1 && impl->colors.size() != impl->vertices.elements()) {

View File

@@ -7,6 +7,7 @@
#include <mbgl/gl/defines.hpp>
#include <mbgl/gl/enum.hpp>
#include <mbgl/gl/program.hpp>
#include <mbgl/gl/uniform_buffer_gl.hpp>
#include <mbgl/gl/vertex_array.hpp>
#include <mbgl/platform/gl_functions.hpp>
#include <mbgl/renderer/paint_parameters.hpp>
@@ -47,6 +48,8 @@ public:
gfx::IndexBuffer indexBuffer = {0, nullptr};
gfx::UniqueVertexBufferResource attributeBuffer;
UniformBufferArrayGL uniformBuffers;
std::size_t indexOffset = 0;
std::size_t indexLength = 0;
std::size_t attributeOffset = 0;

View File

@@ -3,6 +3,7 @@
#include <mbgl/gfx/shader_registry.hpp>
#include <mbgl/gl/context.hpp>
#include <mbgl/gl/extension.hpp>
#include <mbgl/shaders/shader_manifest.hpp>
#include <mbgl/shaders/gl/shader_program_gl.hpp>
#include <mbgl/util/logging.hpp>
@@ -66,33 +67,14 @@ void RendererBackend::setScissorTest(bool enabled) {
RendererBackend::~RendererBackend() = default;
void RendererBackend::initShaders(gfx::ShaderRegistry& shaders) {
constexpr auto shaderName = "background_generic";
constexpr auto shaderName = "BackgroundProgramUBO";
gl::Context& glContext = static_cast<gl::Context&>(*context);
auto shader = shaders.get<gl::ShaderProgramGL>(shaderName);
if (!shader) {
constexpr auto vert = R"(#version 300 es
precision highp float;
uniform mat4 u_matrix;
layout (location = 0) in vec2 a_pos;
layout (location = 1) in vec4 a_color;
out vec4 v_color;
void main() {
v_color = a_color;
gl_Position = u_matrix * vec4(a_pos, 0, 1);
})";
constexpr auto frag = R"(#version 300 es
precision highp float;
in vec4 v_color;
out vec4 fragColor;
void main() {
fragColor = v_color;
})";
auto vert = shaders::ShaderSource<shaders::BuiltIn::BackgroundProgramUBO, gfx::Backend::Type::OpenGL>::vertex;
auto frag = shaders::ShaderSource<shaders::BuiltIn::BackgroundProgramUBO, gfx::Backend::Type::OpenGL>::fragment;
try {
// Compile
shader = gl::ShaderProgramGL::create(glContext, shaderName, vert, frag);

View File

@@ -0,0 +1,27 @@
#include <mbgl/gl/uniform_block_gl.hpp>
#include <mbgl/gl/uniform_buffer_gl.hpp>
#include <mbgl/gl/defines.hpp>
#include <mbgl/platform/gl_functions.hpp>
#include <cassert>
namespace mbgl {
namespace gl {
using namespace platform;
void UniformBlockGL::bindBuffer(const gfx::UniformBuffer& uniformBuffer) {
assert(size == uniformBuffer.getSize());
GLint binding = index;
const auto& uniformBufferGL = static_cast<const UniformBufferGL&>(uniformBuffer);
MBGL_CHECK_ERROR(glBindBufferBase(GL_UNIFORM_BUFFER, binding, uniformBufferGL.getID()));
}
void UniformBlockGL::unbindBuffer() {
GLint binding = index;
MBGL_CHECK_ERROR(glBindBufferBase(GL_UNIFORM_BUFFER, binding, 0));
}
} // namespace gl
} // namespace mbgl

View File

@@ -0,0 +1,20 @@
#include <mbgl/gl/uniform_buffer_gl.hpp>
#include <mbgl/gl/defines.hpp>
#include <mbgl/platform/gl_functions.hpp>
namespace mbgl {
namespace gl {
using namespace platform;
UniformBufferGL::UniformBufferGL(const void* data, std::size_t size_)
: UniformBuffer(size_) {
MBGL_CHECK_ERROR(glGenBuffers(1, &id));
MBGL_CHECK_ERROR(glBindBuffer(GL_UNIFORM_BUFFER, id));
MBGL_CHECK_ERROR(glBufferData(GL_UNIFORM_BUFFER, size, data, GL_STATIC_DRAW));
MBGL_CHECK_ERROR(glBindBuffer(GL_UNIFORM_BUFFER, 0));
}
} // namespace gl
} // namespace mbgl

View File

@@ -148,9 +148,7 @@ gfx::AttributeBindingArray UploadPass::buildAttributeBindings(
// For each attribute in the program, with the corresponding default and optional override...
defaults.resolve(overrides,
[&](const std::string& name,
const gfx::VertexAttribute& defaultAttr,
const gfx::VertexAttribute* overrideAttr) -> void {
[&](const std::string& name, const auto& defaultAttr, const auto& overrideAttr) -> void {
const auto& effectiveAttr = overrideAttr ? *overrideAttr : defaultAttr;
const auto& effectiveGL = static_cast<const gl::VertexAttributeGL&>(effectiveAttr);
const auto& defaultGL = static_cast<const gl::VertexAttributeGL&>(defaultAttr);

View File

@@ -169,57 +169,5 @@ const std::vector<std::uint8_t>& VertexAttributeGL::getRaw(platform::GLenum type
return rawData;
}
namespace {
template <typename T>
void applyUniform(GLint, const T&);
template <>
void applyUniform(GLint, const std::int32_t&) {}
template <>
void applyUniform(GLint, const gfx::VertexAttribute::int2&) {}
template <>
void applyUniform(GLint, const gfx::VertexAttribute::int3&) {}
template <>
void applyUniform(GLint, const gfx::VertexAttribute::int4&) {}
template <>
void applyUniform(GLint, const float&) {}
template <>
void applyUniform(GLint, const gfx::VertexAttribute::float2&) {}
template <>
void applyUniform(GLint, const gfx::VertexAttribute::float3&) {}
template <>
void applyUniform(GLint, const gfx::VertexAttribute::float4&) {}
template <>
void applyUniform(GLint, const gfx::VertexAttribute::matf3&) {}
template <>
void applyUniform(GLint location, const gfx::VertexAttribute::matf4& value) {
MBGL_CHECK_ERROR(glUniformMatrix4fv(location, 1, GL_FALSE, value.data()));
}
} // namespace
struct ApplyUniform {
GLint location;
template <typename T>
void operator()(const T& value) {
applyUniform(location, value);
}
};
void VertexAttributeArrayGL::applyUniforms(const gfx::ShaderProgramBase& shader) {
const auto& glShader = static_cast<const ShaderProgramGL&>(shader);
const auto program = glShader.getGLProgramID();
for (auto& kv : attrs) {
const auto& name = kv.first;
auto& uniform = kv.second;
if (uniform->getIndex() < 0) {
const auto index = MBGL_CHECK_ERROR(glGetUniformLocation(program, name.c_str()));
Log::Warning(Event::General, "Uniform '" + name + "' = " + std::to_string(index));
uniform->setIndex(index);
}
std::visit(ApplyUniform{uniform->getIndex()}, uniform->get(0));
}
}
} // namespace gl
} // namespace mbgl

View File

@@ -18,6 +18,7 @@
#include <mbgl/shaders/shader_program_base.hpp>
#include <mbgl/util/tile_cover.hpp>
#include <mbgl/map/transform_state.hpp>
#include <mbgl/util/convert.hpp>
#include <mbgl/util/logging.hpp>
#include <unordered_set>
@@ -60,6 +61,7 @@ void RenderBackgroundLayer::evaluate(const PropertyEvaluationParameters& paramet
properties->renderPasses = mbgl::underlying_type(passes);
evaluatedProperties = std::move(properties);
evaluatedPropertiesChange = true;
}
bool RenderBackgroundLayer::hasTransition() const {
@@ -194,7 +196,7 @@ void RenderBackgroundLayer::prepare(const LayerPrepareParameters& params) {
}
}
constexpr auto shaderName = "background_generic";
constexpr auto shaderName = "BackgroundProgramUBO";
void RenderBackgroundLayer::layerRemoved(UniqueChangeRequestVec& changes) {
// TODO: This isn't happening on style change, so old tile drawables are being left active
@@ -235,25 +237,23 @@ void RenderBackgroundLayer::update(const int32_t layerIndex,
// unevaluated.hasTransition();
// getCrossfade<BackgroundLayerProperties>(evaluatedProperties).t != 1;
std::optional<Color> color;
if (evaluated.get<BackgroundPattern>().from.empty()) {
const auto opacity = evaluated.get<style::BackgroundOpacity>();
if (opacity > 0.0f) {
color = evaluated.get<BackgroundColor>() * evaluated.get<BackgroundOpacity>();
}
}
// If the result is transparent or missing, just remove any existing drawables and stop
if (!color) {
if (!evaluated.get<BackgroundPattern>().from.empty() || evaluated.get<style::BackgroundOpacity>() <= 0.0f) {
removeDrawables<decltype(tileDrawables)::const_iterator>(
tileDrawables.cbegin(), tileDrawables.cend(), changes, [](auto& ii) { return ii->second->getId(); });
tileDrawables.clear();
return;
}
const bool colorChange = (color != lastColor);
if (evaluatedPropertiesChange) {
BackgroundLayerUBO backgroundLayerUBO;
backgroundLayerUBO.color = evaluated.get<BackgroundColor>();
backgroundLayerUBO.opacity = evaluated.get<BackgroundOpacity>();
uniformBuffer = context.createUniformBuffer(&backgroundLayerUBO, sizeof(backgroundLayerUBO));
evaluatedPropertiesChange = false;
}
const bool layerChange = (layerIndex != lastLayerIndex);
lastColor = color;
lastLayerIndex = layerIndex;
const auto zoom = state.getIntegerZoom();
@@ -283,10 +283,6 @@ void RenderBackgroundLayer::update(const int32_t layerIndex,
}
++iter;
// If the color evaluated to a new value, update all vertexes of the drawable to the new color
if (colorChange) {
drawable->resetColor(*color);
}
if (layerChange) {
drawable->setLayerIndex(layerIndex);
}
@@ -302,6 +298,7 @@ void RenderBackgroundLayer::update(const int32_t layerIndex,
if (!result.second) {
// Already present
// TODO: Update matrix here or in the tweaker?
result.first->second->mutableUniformBuffers().addOrReplace("BackgroundLayerUBO", uniformBuffer);
continue;
}
@@ -311,7 +308,6 @@ void RenderBackgroundLayer::update(const int32_t layerIndex,
builder->setRenderPass(drawPasses);
builder->setShader(shader);
builder->addTweaker(context.createDrawableTweaker());
builder->setColor(*color);
builder->setColorMode(gfx::DrawableBuilder::ColorMode::PerDrawable);
builder->setDepthType(gfx::DepthMaskType::ReadWrite);
builder->setLayerIndex(layerIndex);
@@ -329,6 +325,7 @@ void RenderBackgroundLayer::update(const int32_t layerIndex,
if (!newDrawables.empty()) {
auto& drawable = newDrawables[0];
drawable->setTileID(tileID);
drawable->mutableUniformBuffers().addOrReplace("BackgroundLayerUBO", uniformBuffer);
result.first->second = drawable;
changes.emplace_back(std::make_unique<AddDrawableRequest>(std::move(drawable)));
++stats.tileDrawablesAdded;

View File

@@ -50,4 +50,26 @@ private:
std::shared_ptr<BackgroundPatternProgram> backgroundPatternProgram;
};
struct alignas(16) BackgroundLayerUBO {
Color color;
float opacity;
};
struct alignas(16) BackgroundPatternLayerUBO {
std::array<float, 2> pattern_tl_a;
std::array<float, 2> pattern_br_a;
std::array<float, 2> pattern_tl_b;
std::array<float, 2> pattern_br_b;
std::array<float, 2> texsize;
std::array<float, 2> pattern_size_a;
std::array<float, 2> pattern_size_b;
std::array<float, 2> pixel_coord_upper;
std::array<float, 2> pixel_coord_lower;
float tile_units_to_pixels;
float scale_a;
float scale_b;
float mix;
float opacity;
};
} // namespace mbgl

View File

@@ -260,7 +260,7 @@ bool RenderFillLayer::queryIntersectsFeature(const GeometryCoordinates& queryGeo
feature.getGeometries());
}
constexpr auto shaderName = "background_generic";
constexpr auto shaderName = "BackgroundProgramUBO";
void RenderFillLayer::layerRemoved(UniqueChangeRequestVec& changes) {
// Remove everything

View File

@@ -180,8 +180,9 @@ protected:
std::mutex mutex;
gfx::ShaderProgramBasePtr shader;
std::unordered_map<OverscaledTileID, gfx::DrawablePtr> tileDrawables;
std::optional<Color> lastColor;
int32_t lastLayerIndex = -1;
bool evaluatedPropertiesChange = false;
gfx::UniformBufferPtr uniformBuffer = nullptr;
struct Stats {
size_t propertyEvaluations = 0;

View File

@@ -234,10 +234,10 @@ void Renderer::Impl::render(const RenderTree& renderTree) {
matrix = tileMat;
}
if (auto& shader = drawable.getShader()) {
shader->setUniform("u_matrix", 0, util::convert<float>(matrix));
shader->updateUniforms();
}
gfx::DrawableUBO drawableUBO;
drawableUBO.matrix = util::convert<float>(matrix);
auto uniformBuffer = context.createUniformBuffer(&drawableUBO, sizeof(drawableUBO));
drawable.mutableUniformBuffers().addOrReplace("DrawableUBO", uniformBuffer);
drawable.draw(parameters);
}
@@ -261,7 +261,7 @@ void Renderer::Impl::render(const RenderTree& renderTree) {
for (auto it = layerRenderItems.rbegin(); it != layerRenderItems.rend(); ++it, ++i) {
parameters.currentLayer = i;
const RenderItem& renderItem = it->get();
if (renderItem.getName() == "background") { // Replaced by drawables, above
if (renderItem.getName() == "background") {
continue;
}
if (renderItem.hasRenderPass(parameters.pass)) {

View File

@@ -82,17 +82,17 @@ ShaderProgramGL::ShaderProgramGL(UniqueProgram&& glProgram_)
glProgram(std::move(glProgram_)) {}
ShaderProgramGL::ShaderProgramGL(UniqueProgram&& program,
VertexAttributeArrayGL&& uniforms_,
UniformBlockArrayGL&& uniformBlocks_,
VertexAttributeArrayGL&& attributes_)
: ShaderProgramBase(),
glProgram(std::move(program)),
uniforms(std::move(uniforms_)),
uniformBlocks(std::move(uniformBlocks_)),
vertexAttributes(std::move(attributes_)) {}
ShaderProgramGL::ShaderProgramGL(ShaderProgramGL&& other)
: ShaderProgramBase(std::forward<ShaderProgramBase&&>(other)),
glProgram(std::move(other.glProgram)),
uniforms(std::move(other.uniforms)),
uniformBlocks(std::move(other.uniformBlocks)),
vertexAttributes(std::move(other.vertexAttributes)) {}
using namespace platform;
@@ -102,8 +102,8 @@ static void addAttr(
const auto elementType = mapType(glType);
const auto elementCount = mapCount(glType); // number of `elementType`, hopefully temporary
if (elementType != gfx::AttributeDataType::Invalid && length > 0) {
if (auto newAttr = attrs.add(name, index, elementType, elementCount, count)) {
auto* glAttr = static_cast<VertexAttributeGL*>(newAttr);
if (const auto& newAttr = attrs.add(name, index, elementType, elementCount, count)) {
const auto& glAttr = static_cast<VertexAttributeGL*>(newAttr.get());
glAttr->setGLType(glType);
}
}
@@ -125,21 +125,23 @@ std::shared_ptr<ShaderProgramGL> ShaderProgramGL::create(Context& context,
// GLint numAttribs;
// glGetProgramInterfaceiv(program, GL_PROGRAM_INPUT, GL_ACTIVE_RESOURCES, &numAttribs);
VertexAttributeArrayGL uniforms;
UniformBlockArrayGL uniformBlocks;
GLint count = 0;
GLint maxLength = 0;
MBGL_CHECK_ERROR(glGetProgramiv(program, GL_ACTIVE_UNIFORMS, &count));
MBGL_CHECK_ERROR(glGetProgramiv(program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxLength));
MBGL_CHECK_ERROR(glGetProgramiv(program, GL_ACTIVE_UNIFORM_BLOCKS, &count));
MBGL_CHECK_ERROR(glGetProgramiv(program, GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH, &maxLength));
auto name = std::vector<GLchar>(maxLength);
for (GLint index = 0; index < count; ++index) {
GLsizei length = 0;
GLint size = 0;
GLenum glType = 0;
MBGL_CHECK_ERROR(glGetActiveUniform(program, index, maxLength, &length, &size, &glType, name.data()));
const GLint location = MBGL_CHECK_ERROR(glGetUniformLocation(program, name.data()));
addAttr(uniforms, name.data(), location, length, size, glType);
GLint binding = index;
MBGL_CHECK_ERROR(glGetActiveUniformBlockName(program, index, maxLength, &length, name.data()));
MBGL_CHECK_ERROR(glGetActiveUniformBlockiv(program, index, GL_UNIFORM_BLOCK_DATA_SIZE, &size));
assert(length > 0 && size > 0);
MBGL_CHECK_ERROR(glUniformBlockBinding(program, index, binding));
uniformBlocks.add(name.data(), index, size);
}
VertexAttributeArrayGL attrs;
@@ -160,7 +162,7 @@ std::shared_ptr<ShaderProgramGL> ShaderProgramGL::create(Context& context,
addAttr(attrs, name.data(), location, length, size, glType);
}
return std::make_shared<ShaderProgramGL>(std::move(program), std::move(uniforms), std::move(attrs));
return std::make_shared<ShaderProgramGL>(std::move(program), std::move(uniformBlocks), std::move(attrs));
}
} // namespace gl