diff --git a/CMakeLists.txt b/CMakeLists.txt index 7250958c9..d798147d6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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 diff --git a/include/mbgl/gfx/drawable.hpp b/include/mbgl/gfx/drawable.hpp index 10af8446e..12a18ca58 100644 --- a/include/mbgl/gfx/drawable.hpp +++ b/include/mbgl/gfx/drawable.hpp @@ -1,5 +1,6 @@ #pragma once +#include #include #include #include @@ -22,7 +23,7 @@ enum class DepthMaskType : bool; class DrawableTweaker; class ShaderProgramBase; using ShaderProgramBasePtr = std::shared_ptr; - +using UniformBufferPtr = std::shared_ptr; using DrawPriority = int64_t; using DrawableTweakerPtr = std::shared_ptr; @@ -94,6 +95,10 @@ public: /// Get the tweakers attached to this drawable const std::vector& 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 matrix; +}; + } // namespace gfx } // namespace mbgl diff --git a/include/mbgl/gfx/uniform_block.hpp b/include/mbgl/gfx/uniform_block.hpp new file mode 100644 index 000000000..16e8ede26 --- /dev/null +++ b/include/mbgl/gfx/uniform_block.hpp @@ -0,0 +1,94 @@ +#pragma once + +#include +#include +#include + +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>; + + 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& 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& add(std::string name, int index, std::size_t size); + + UniformBlockArray& operator=(UniformBlockArray&&); + UniformBlockArray& operator=(const UniformBlockArray&); + +protected: + const std::unique_ptr& add(std::string name, std::unique_ptr&& uniformBlock) { + const auto result = uniformBlockMap.insert(std::make_pair(std::move(name), std::unique_ptr())); + if (result.second) { + result.first->second = std::move(uniformBlock); + return result.first->second; + } else { + return nullref; + } + } + + virtual std::unique_ptr create(int index, std::size_t size) = 0; + virtual std::unique_ptr copy(const UniformBlock& uniformBlock) = 0; + +protected: + UniformBlockMap uniformBlockMap; + static std::unique_ptr nullref; +}; + +} // namespace gfx +} // namespace mbgl diff --git a/include/mbgl/gfx/uniform_buffer.hpp b/include/mbgl/gfx/uniform_buffer.hpp new file mode 100644 index 000000000..5be936d9d --- /dev/null +++ b/include/mbgl/gfx/uniform_buffer.hpp @@ -0,0 +1,79 @@ +#pragma once + +#include +#include +#include + +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>; + + 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& get(const std::string& name) const; + + /// Add a new uniform buffer element or replace the existing one. + const std::shared_ptr& addOrReplace(std::string name, + const std::shared_ptr& uniformBuffer); + + UniformBufferArray& operator=(UniformBufferArray&&); + UniformBufferArray& operator=(const UniformBufferArray&); + +protected: + const std::shared_ptr& add(std::string name, std::shared_ptr&& uniformBuffer) { + const auto result = uniformBufferMap.insert(std::make_pair(std::move(name), std::shared_ptr())); + if (result.second) { + result.first->second = std::move(uniformBuffer); + return result.first->second; + } else { + return nullref; + } + } + + virtual std::unique_ptr copy(const UniformBuffer& uniformBuffer) = 0; + +protected: + UniformBufferMap uniformBufferMap; + static std::shared_ptr nullref; +}; + +} // namespace gfx +} // namespace mbgl diff --git a/include/mbgl/gfx/vertex_attribute.hpp b/include/mbgl/gfx/vertex_attribute.hpp index 06c57769a..192a622b8 100644 --- a/include/mbgl/gfx/vertex_attribute.hpp +++ b/include/mbgl/gfx/vertex_attribute.hpp @@ -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& 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& 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& 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 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; + using ResolveDelegate = + std::function&)>; /// 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&& attr) { + const std::unique_ptr& add(std::string name, std::unique_ptr&& attr) { const auto result = attrs.insert(std::make_pair(std::move(name), std::unique_ptr())); 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 nullref; }; } // namespace gfx diff --git a/include/mbgl/gl/drawable_gl.hpp b/include/mbgl/gl/drawable_gl.hpp index 754f4d200..0d46b7392 100644 --- a/include/mbgl/gl/drawable_gl.hpp +++ b/include/mbgl/gl/drawable_gl.hpp @@ -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); private: + void bindUniformBuffers() const; + void unbindUniformBuffers() const; }; } // namespace gl diff --git a/include/mbgl/gl/uniform_block_gl.hpp b/include/mbgl/gl/uniform_block_gl.hpp new file mode 100644 index 000000000..f8dc39a4a --- /dev/null +++ b/include/mbgl/gl/uniform_block_gl.hpp @@ -0,0 +1,57 @@ +#pragma once + +#include +#include + +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 create(int index, std::size_t size) override { + return std::unique_ptr(new UniformBlockGL(index, size)); + } + std::unique_ptr copy(const gfx::UniformBlock& uniformBlocks) override { + return std::unique_ptr( + new UniformBlockGL(static_cast(uniformBlocks))); + } +}; + +} // namespace gl +} // namespace mbgl diff --git a/include/mbgl/gl/uniform_buffer_gl.hpp b/include/mbgl/gl/uniform_buffer_gl.hpp new file mode 100644 index 000000000..581ea86bc --- /dev/null +++ b/include/mbgl/gl/uniform_buffer_gl.hpp @@ -0,0 +1,49 @@ +#pragma once + +#include +#include + +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 copy(const gfx::UniformBuffer& uniformBuffers) override { + return std::unique_ptr( + new UniformBufferGL(static_cast(uniformBuffers))); + } +}; + +} // namespace gl +} // namespace mbgl diff --git a/include/mbgl/gl/vertex_attribute_gl.hpp b/include/mbgl/gl/vertex_attribute_gl.hpp index d16f4da70..557af0afc 100644 --- a/include/mbgl/gl/vertex_attribute_gl.hpp +++ b/include/mbgl/gl/vertex_attribute_gl.hpp @@ -62,8 +62,6 @@ public: return *this; } - void applyUniforms(const gfx::ShaderProgramBase&) override; - private: std::unique_ptr create(int index, gfx::AttributeDataType dataType, diff --git a/include/mbgl/shaders/gl/background_ubo.hpp b/include/mbgl/shaders/gl/background_ubo.hpp new file mode 100644 index 000000000..49047d665 --- /dev/null +++ b/include/mbgl/shaders/gl/background_ubo.hpp @@ -0,0 +1,43 @@ +#pragma once +#include + +namespace mbgl { +namespace shaders { + +template <> +struct ShaderSource { + 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 diff --git a/include/mbgl/shaders/gl/shader_program_gl.hpp b/include/mbgl/shaders/gl/shader_program_gl.hpp index 3732bc645..d571b8e5f 100644 --- a/include/mbgl/shaders/gl/shader_program_gl.hpp +++ b/include/mbgl/shaders/gl/shader_program_gl.hpp @@ -1,6 +1,7 @@ #pragma once #include +#include #include #include @@ -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; }; diff --git a/include/mbgl/shaders/shader_manifest.hpp b/include/mbgl/shaders/shader_manifest.hpp index 6dc07583d..afa9da09a 100644 --- a/include/mbgl/shaders/shader_manifest.hpp +++ b/include/mbgl/shaders/shader_manifest.hpp @@ -32,4 +32,6 @@ #include #include #include + +#include #endif diff --git a/include/mbgl/shaders/shader_program_base.hpp b/include/mbgl/shaders/shader_program_base.hpp index ef79f8dce..dccc41605 100644 --- a/include/mbgl/shaders/shader_program_base.hpp +++ b/include/mbgl/shaders/shader_program_base.hpp @@ -1,6 +1,7 @@ #pragma once #include +#include #include #include @@ -17,7 +18,7 @@ protected: template 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 - bool setUniform(const std::string& name, std::size_t i, T value) { - return set(mutableUniforms(), name, i, value); - } template 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: diff --git a/include/mbgl/shaders/shader_source.hpp b/include/mbgl/shaders/shader_source.hpp index 22cf642e8..851f938e5 100644 --- a/include/mbgl/shaders/shader_source.hpp +++ b/include/mbgl/shaders/shader_source.hpp @@ -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 diff --git a/src/mbgl/gfx/context.hpp b/src/mbgl/gfx/context.hpp index d3ba924db..c6dcdf499 100644 --- a/src/mbgl/gfx/context.hpp +++ b/src/mbgl/gfx/context.hpp @@ -6,6 +6,7 @@ #include #include #include +#include #include #include @@ -29,6 +30,7 @@ class ShaderRegistry; using DrawablePtr = std::shared_ptr; using UniqueDrawableBuilder = std::unique_ptr; using DrawableTweakerPtr = std::shared_ptr; +using UniformBufferPtr = std::shared_ptr; using ShaderProgramBasePtr = std::shared_ptr; 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; }; diff --git a/src/mbgl/gfx/uniform_block.cpp b/src/mbgl/gfx/uniform_block.cpp new file mode 100644 index 000000000..9958f8324 --- /dev/null +++ b/src/mbgl/gfx/uniform_block.cpp @@ -0,0 +1,43 @@ +#include + +namespace mbgl { +namespace gfx { + +std::unique_ptr 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& UniformBlockArray::get(const std::string& name) const { + const auto result = uniformBlockMap.find(name); + return (result != uniformBlockMap.end()) ? result->second : nullref; +} + +const std::unique_ptr& 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())); + if (result.second) { + result.first->second = create(index, size); + return result.first->second; + } else { + return nullref; + } +} + +} // namespace gfx +} // namespace mbgl diff --git a/src/mbgl/gfx/uniform_buffer.cpp b/src/mbgl/gfx/uniform_buffer.cpp new file mode 100644 index 000000000..c62eb4479 --- /dev/null +++ b/src/mbgl/gfx/uniform_buffer.cpp @@ -0,0 +1,40 @@ +#include + +namespace mbgl { +namespace gfx { + +std::shared_ptr 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& UniformBufferArray::get(const std::string& name) const { + const auto result = uniformBufferMap.find(name); + return (result != uniformBufferMap.end()) ? result->second : nullref; +} + +const std::shared_ptr& UniformBufferArray::addOrReplace( + std::string name, const std::shared_ptr& uniformBuffer) { + const auto result = uniformBufferMap.insert(std::make_pair(std::move(name), std::shared_ptr())); + result.first->second = std::move(uniformBuffer); + return result.first->second; +} + +} // namespace gfx +} // namespace mbgl diff --git a/src/mbgl/gfx/vertex_attribute.cpp b/src/mbgl/gfx/vertex_attribute.cpp index 8e89625bc..48dd51d17 100644 --- a/src/mbgl/gfx/vertex_attribute.cpp +++ b/src/mbgl/gfx/vertex_attribute.cpp @@ -7,6 +7,8 @@ namespace mbgl { namespace gfx { +std::unique_ptr 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& 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& 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())); 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& VertexAttributeArray::getOrAdd( std::string name, int index, AttributeDataType dataType, int size, std::size_t count) { // attrs.emplace_back(std::make_unique(dataType, count)); const auto result = attrs.insert(std::make_pair(std::move(name), std::unique_ptr())); @@ -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 { diff --git a/src/mbgl/gl/context.cpp b/src/mbgl/gl/context.cpp index d05b48152..f3118e9f8 100644 --- a/src/mbgl/gl/context.cpp +++ b/src/mbgl/gl/context.cpp @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -497,6 +498,10 @@ gfx::DrawableTweakerPtr Context::createDrawableTweaker() { return std::make_shared(); } +gfx::UniformBufferPtr Context::createUniformBuffer(const void* data, std::size_t size) { + return std::make_shared(data, size); +} + gfx::ShaderProgramBasePtr Context::getGenericShader(gfx::ShaderRegistry& shaders, const std::string& name) { return shaders.get(name); } diff --git a/src/mbgl/gl/context.hpp b/src/mbgl/gl/context.hpp index a6b213ca2..44ebcf20d 100644 --- a/src/mbgl/gl/context.hpp +++ b/src/mbgl/gl/context.hpp @@ -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; diff --git a/src/mbgl/gl/drawable_gl.cpp b/src/mbgl/gl/drawable_gl.cpp index 3249a5ae7..0b2e65e8b 100644 --- a/src/mbgl/gl/drawable_gl.cpp +++ b/src/mbgl/gl/drawable_gl.cpp @@ -2,6 +2,8 @@ #include #include +#include + 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 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(*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(*shader); + for (const auto& element : shaderGL.getUniformBlocks().getMap()) { + element.second->unbindBuffer(); + } + } +} + } // namespace gl } // namespace mbgl diff --git a/src/mbgl/gl/drawable_gl_builder.cpp b/src/mbgl/gl/drawable_gl_builder.cpp index b151d91d5..2a44f9213 100644 --- a/src/mbgl/gl/drawable_gl_builder.cpp +++ b/src/mbgl/gl/drawable_gl_builder.cpp @@ -15,13 +15,13 @@ void DrawableGLBuilder::init() { auto& drawableGL = static_cast(*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()) { diff --git a/src/mbgl/gl/drawable_gl_impl.hpp b/src/mbgl/gl/drawable_gl_impl.hpp index 15b693763..c61cc7c67 100644 --- a/src/mbgl/gl/drawable_gl_impl.hpp +++ b/src/mbgl/gl/drawable_gl_impl.hpp @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -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; diff --git a/src/mbgl/gl/renderer_backend.cpp b/src/mbgl/gl/renderer_backend.cpp index 49690d006..49fe20c13 100644 --- a/src/mbgl/gl/renderer_backend.cpp +++ b/src/mbgl/gl/renderer_backend.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include #include @@ -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(*context); auto shader = shaders.get(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::vertex; + auto frag = shaders::ShaderSource::fragment; try { // Compile shader = gl::ShaderProgramGL::create(glContext, shaderName, vert, frag); diff --git a/src/mbgl/gl/uniform_block_gl.cpp b/src/mbgl/gl/uniform_block_gl.cpp new file mode 100644 index 000000000..8b93c87e0 --- /dev/null +++ b/src/mbgl/gl/uniform_block_gl.cpp @@ -0,0 +1,27 @@ + +#include +#include +#include +#include + +#include + +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(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 diff --git a/src/mbgl/gl/uniform_buffer_gl.cpp b/src/mbgl/gl/uniform_buffer_gl.cpp new file mode 100644 index 000000000..f6e61e6f9 --- /dev/null +++ b/src/mbgl/gl/uniform_buffer_gl.cpp @@ -0,0 +1,20 @@ + +#include +#include +#include + +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 diff --git a/src/mbgl/gl/upload_pass.cpp b/src/mbgl/gl/upload_pass.cpp index 2c6089460..b01157e39 100644 --- a/src/mbgl/gl/upload_pass.cpp +++ b/src/mbgl/gl/upload_pass.cpp @@ -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(effectiveAttr); const auto& defaultGL = static_cast(defaultAttr); diff --git a/src/mbgl/gl/vertex_attribute_gl.cpp b/src/mbgl/gl/vertex_attribute_gl.cpp index 1a23abcdf..5846b51c3 100644 --- a/src/mbgl/gl/vertex_attribute_gl.cpp +++ b/src/mbgl/gl/vertex_attribute_gl.cpp @@ -169,57 +169,5 @@ const std::vector& VertexAttributeGL::getRaw(platform::GLenum type return rawData; } -namespace { -template -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 - void operator()(const T& value) { - applyUniform(location, value); - } -}; - -void VertexAttributeArrayGL::applyUniforms(const gfx::ShaderProgramBase& shader) { - const auto& glShader = static_cast(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 diff --git a/src/mbgl/renderer/layers/render_background_layer.cpp b/src/mbgl/renderer/layers/render_background_layer.cpp index 6458875d9..92357009d 100644 --- a/src/mbgl/renderer/layers/render_background_layer.cpp +++ b/src/mbgl/renderer/layers/render_background_layer.cpp @@ -18,6 +18,7 @@ #include #include #include +#include #include #include @@ -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(evaluatedProperties).t != 1; - std::optional color; - if (evaluated.get().from.empty()) { - const auto opacity = evaluated.get(); - if (opacity > 0.0f) { - color = evaluated.get() * evaluated.get(); - } - } - // If the result is transparent or missing, just remove any existing drawables and stop - if (!color) { + if (!evaluated.get().from.empty() || evaluated.get() <= 0.0f) { removeDrawables( 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(); + backgroundLayerUBO.opacity = evaluated.get(); + 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(std::move(drawable))); ++stats.tileDrawablesAdded; diff --git a/src/mbgl/renderer/layers/render_background_layer.hpp b/src/mbgl/renderer/layers/render_background_layer.hpp index 7ece4ce6a..f368e8fd3 100644 --- a/src/mbgl/renderer/layers/render_background_layer.hpp +++ b/src/mbgl/renderer/layers/render_background_layer.hpp @@ -50,4 +50,26 @@ private: std::shared_ptr backgroundPatternProgram; }; +struct alignas(16) BackgroundLayerUBO { + Color color; + float opacity; +}; + +struct alignas(16) BackgroundPatternLayerUBO { + std::array pattern_tl_a; + std::array pattern_br_a; + std::array pattern_tl_b; + std::array pattern_br_b; + std::array texsize; + std::array pattern_size_a; + std::array pattern_size_b; + std::array pixel_coord_upper; + std::array pixel_coord_lower; + float tile_units_to_pixels; + float scale_a; + float scale_b; + float mix; + float opacity; +}; + } // namespace mbgl diff --git a/src/mbgl/renderer/layers/render_fill_layer.cpp b/src/mbgl/renderer/layers/render_fill_layer.cpp index 71adbcd50..49781151c 100644 --- a/src/mbgl/renderer/layers/render_fill_layer.cpp +++ b/src/mbgl/renderer/layers/render_fill_layer.cpp @@ -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 diff --git a/src/mbgl/renderer/render_layer.hpp b/src/mbgl/renderer/render_layer.hpp index da2fc2dcb..8fe0388b3 100644 --- a/src/mbgl/renderer/render_layer.hpp +++ b/src/mbgl/renderer/render_layer.hpp @@ -180,8 +180,9 @@ protected: std::mutex mutex; gfx::ShaderProgramBasePtr shader; std::unordered_map tileDrawables; - std::optional lastColor; int32_t lastLayerIndex = -1; + bool evaluatedPropertiesChange = false; + gfx::UniformBufferPtr uniformBuffer = nullptr; struct Stats { size_t propertyEvaluations = 0; diff --git a/src/mbgl/renderer/renderer_impl.cpp b/src/mbgl/renderer/renderer_impl.cpp index 76787ccd0..f4f113877 100644 --- a/src/mbgl/renderer/renderer_impl.cpp +++ b/src/mbgl/renderer/renderer_impl.cpp @@ -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(matrix)); - shader->updateUniforms(); - } + gfx::DrawableUBO drawableUBO; + drawableUBO.matrix = util::convert(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)) { diff --git a/src/mbgl/shaders/gl/shader_program_gl.cpp b/src/mbgl/shaders/gl/shader_program_gl.cpp index c5ce04687..dd04a1212 100644 --- a/src/mbgl/shaders/gl/shader_program_gl.cpp +++ b/src/mbgl/shaders/gl/shader_program_gl.cpp @@ -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(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(newAttr); + if (const auto& newAttr = attrs.add(name, index, elementType, elementCount, count)) { + const auto& glAttr = static_cast(newAttr.get()); glAttr->setGLType(glType); } } @@ -125,21 +125,23 @@ std::shared_ptr 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(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::create(Context& context, addAttr(attrs, name.data(), location, length, size, glType); } - return std::make_shared(std::move(program), std::move(uniforms), std::move(attrs)); + return std::make_shared(std::move(program), std::move(uniformBlocks), std::move(attrs)); } } // namespace gl