diff --git a/include/mbgl/gfx/drawable_builder.hpp b/include/mbgl/gfx/drawable_builder.hpp index 6e576f1fa..70fb1d54f 100644 --- a/include/mbgl/gfx/drawable_builder.hpp +++ b/include/mbgl/gfx/drawable_builder.hpp @@ -69,6 +69,7 @@ public: void setColor(const Color& value); enum class ColorMode { + None, PerDrawable, PerVertex }; @@ -89,6 +90,10 @@ public: /// Set the name given to new drawables void setDrawableName(std::string value) { drawableName = std::move(value); } + /// The attribute names for automatic attributes (vertex/position and color, if color mode is not `None`) + void setVertexAttrName(std::string value) { vertexAttrName = std::move(value); } + void setColorAttrName(std::string value) { colorAttrName = std::move(value); } + /// Set the matrix applied to new drawables void setMatrix(mat4 value) { matrix = value; } @@ -100,8 +105,11 @@ public: /// Add a rectangle consisting of two triangles void addQuad(int16_t x0, int16_t y0, int16_t x1, int16_t y1); - /// Add already-set-up triangles directly + /// A set of attribute values to be added for each vertex + void setVertexAttributes(const VertexAttributeArray&); + void setVertexAttributes(VertexAttributeArray&&); + /// Add already-set-up triangles directly void addTriangles(const std::vector>& vertices, std::size_t vertexOffset, std::size_t vertexLength, @@ -122,6 +130,8 @@ protected: protected: std::string name; std::string drawableName; + std::string vertexAttrName; + std::string colorAttrName; mbgl::RenderPass renderPass; DrawPriority drawPriority = 0; int32_t layerIndex = -1; @@ -132,6 +142,7 @@ protected: std::vector drawables; std::vector tweakers; ColorMode colorMode = ColorMode::PerVertex; + VertexAttributeArray vertexAttrs; struct Impl; std::unique_ptr impl; diff --git a/include/mbgl/gfx/vertex_attribute.hpp b/include/mbgl/gfx/vertex_attribute.hpp index 192a622b8..6711f83a5 100644 --- a/include/mbgl/gfx/vertex_attribute.hpp +++ b/include/mbgl/gfx/vertex_attribute.hpp @@ -36,8 +36,6 @@ public: using ElementType = std::variant; - // Can only be created by VertexAttributeArray implementations -protected: VertexAttribute(int index_, AttributeDataType dataType_, int size_, std::size_t count_, std::size_t stride_) : index(index_), size(size_), @@ -87,6 +85,14 @@ public: } return items[i] = value; } + template <> + const ElementType& set(std::size_t i, const ElementType& value) { + if (items.size() < i + 1) { + items.resize(std::max(items.size(), i + 1)); + } + setDirty(); + return items[i] = value; + } void clear() { if (!items.empty()) { @@ -132,7 +138,7 @@ public: VertexAttributeArray(int initCapacity = 10); VertexAttributeArray(VertexAttributeArray&&); // Would need to use the virtual assignment operator - VertexAttributeArray(const VertexAttributeArray&) = delete; + VertexAttributeArray(const VertexAttributeArray&); virtual ~VertexAttributeArray() = default; /// Number of elements @@ -182,6 +188,18 @@ public: attrs.begin(), attrs.end(), [](const auto& kv) { return kv.second && kv.second->isDirty(); }); } + void clear(); + + /// Do something with each attribute + void observeAttributes(const std::function& f) { + std::for_each(attrs.begin(), attrs.end(), [&](const auto& kv) { + if (kv.second) { f(kv.first, *kv.second); }}); + } + void observeAttributes(const std::function& f) const { + std::for_each(attrs.begin(), attrs.end(), [&](const auto& kv) { + if (kv.second) { f(kv.first, *kv.second); }}); + } + using ResolveDelegate = std::function&)>; /// Call the provided delegate with each value, providing the override if one exists. @@ -190,6 +208,10 @@ public: VertexAttributeArray& operator=(VertexAttributeArray&&); VertexAttributeArray& operator=(const VertexAttributeArray&); + virtual std::unique_ptr clone() const { + return std::make_unique(*this); + } + protected: 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())); @@ -204,8 +226,12 @@ protected: virtual std::unique_ptr create(int index, AttributeDataType dataType, int size, - std::size_t count) = 0; - virtual std::unique_ptr copy(const VertexAttribute& attr) = 0; + std::size_t count) const { + return std::make_unique(index, dataType, size, count, size*count); + } + virtual std::unique_ptr copy(const gfx::VertexAttribute& attr) const { + return std::make_unique(attr); + } protected: AttributeMap attrs; diff --git a/include/mbgl/gl/vertex_attribute_gl.hpp b/include/mbgl/gl/vertex_attribute_gl.hpp index 557af0afc..8a1ce70ea 100644 --- a/include/mbgl/gl/vertex_attribute_gl.hpp +++ b/include/mbgl/gl/vertex_attribute_gl.hpp @@ -51,7 +51,8 @@ public: : VertexAttributeArray(initCapacity) {} VertexAttributeArrayGL(VertexAttributeArrayGL&& other) : VertexAttributeArray(std::move(other)) {} - VertexAttributeArrayGL(const VertexAttributeArrayGL&) = delete; + VertexAttributeArrayGL(const VertexAttributeArrayGL& other) + : VertexAttributeArray(other) {} VertexAttributeArrayGL& operator=(VertexAttributeArrayGL&& other) { VertexAttributeArray::operator=(std::move(other)); @@ -62,14 +63,18 @@ public: return *this; } + std::unique_ptr clone() const override { + return std::make_unique(*this); + } + private: std::unique_ptr create(int index, gfx::AttributeDataType dataType, int size, - std::size_t count) override { + std::size_t count) const override { return std::unique_ptr(new VertexAttributeGL(index, dataType, size, count)); } - std::unique_ptr copy(const gfx::VertexAttribute& attr) override { + std::unique_ptr copy(const gfx::VertexAttribute& attr) const override { return std::unique_ptr( new VertexAttributeGL(static_cast(attr))); } diff --git a/include/mbgl/shaders/gl/drawable_fill.hpp b/include/mbgl/shaders/gl/drawable_fill.hpp index 54e9cd6f9..b51e96924 100644 --- a/include/mbgl/shaders/gl/drawable_fill.hpp +++ b/include/mbgl/shaders/gl/drawable_fill.hpp @@ -1,5 +1,5 @@ // Generated code, do not modify this file! -// Generated on 2023-05-12T17:51:34.322Z by mwilsnd using shaders/generate_shader_code.js +// Generated on 2023-05-15T21:08:38.312Z by timsylvester using shaders/generate_shader_code.js #pragma once #include @@ -11,21 +11,62 @@ template <> struct ShaderSource { static constexpr const char* name = "FillShader"; static constexpr const char* vertex = R"(layout (location = 0) in vec2 a_pos; + layout (std140) uniform DrawableUBO { mat4 u_matrix; }; +#ifndef HAS_UNIFORM_u_color +uniform lowp float u_color_t; +layout (location = 1) in highp vec4 a_color; +out highp vec4 color; +#else +uniform highp vec4 u_color; +#endif +#ifndef HAS_UNIFORM_u_opacity +uniform lowp float u_opacity_t; +layout (location = 2) in lowp vec2 a_opacity; +out lowp float opacity; +#else +uniform lowp float u_opacity; +#endif + void main() { + #ifndef HAS_UNIFORM_u_color +color = unpack_mix_color(a_color, u_color_t); +#else +highp vec4 color = u_color; +#endif + #ifndef HAS_UNIFORM_u_opacity +opacity = unpack_mix_vec2(a_opacity, u_opacity_t); +#else +lowp float opacity = u_opacity; +#endif + gl_Position = u_matrix * vec4(a_pos, 0, 1); } )"; - static constexpr const char* fragment = R"(layout (std140) uniform BackgroundLayerUBO { - vec4 u_color; - float u_opacity; -}; + static constexpr const char* fragment = R"(#ifndef HAS_UNIFORM_u_color +in highp vec4 color; +#else +uniform highp vec4 u_color; +#endif +#ifndef HAS_UNIFORM_u_opacity +in lowp float opacity; +#else +uniform lowp float u_opacity; +#endif void main() { - fragColor = u_color * u_opacity; + #ifdef HAS_UNIFORM_u_color +highp vec4 color = u_color; +#endif + #ifdef HAS_UNIFORM_u_opacity +lowp float opacity = u_opacity; +#endif + + fragColor = color * opacity; + #ifdef OVERDRAW_INSPECTOR fragColor = vec4(1.0); #endif diff --git a/shaders/drawable.fill.fragment.glsl b/shaders/drawable.fill.fragment.glsl index 96a3eb219..ffd33c16c 100644 --- a/shaders/drawable.fill.fragment.glsl +++ b/shaders/drawable.fill.fragment.glsl @@ -1,10 +1,12 @@ -layout (std140) uniform BackgroundLayerUBO { - vec4 u_color; - float u_opacity; -}; +#pragma mapbox: define highp vec4 color +#pragma mapbox: define lowp float opacity void main() { - fragColor = u_color * u_opacity; + #pragma mapbox: initialize highp vec4 color + #pragma mapbox: initialize lowp float opacity + + fragColor = color * opacity; + #ifdef OVERDRAW_INSPECTOR fragColor = vec4(1.0); #endif diff --git a/shaders/drawable.fill.vertex.glsl b/shaders/drawable.fill.vertex.glsl index 0ab8901b0..004d27204 100644 --- a/shaders/drawable.fill.vertex.glsl +++ b/shaders/drawable.fill.vertex.glsl @@ -1,8 +1,15 @@ layout (location = 0) in vec2 a_pos; + layout (std140) uniform DrawableUBO { mat4 u_matrix; }; +#pragma mapbox: define highp vec4 color +#pragma mapbox: define lowp float opacity + void main() { + #pragma mapbox: initialize highp vec4 color + #pragma mapbox: initialize lowp float opacity + gl_Position = u_matrix * vec4(a_pos, 0, 1); } diff --git a/shaders/manifest.json b/shaders/manifest.json index 8cf11023c..a0099e144 100644 --- a/shaders/manifest.json +++ b/shaders/manifest.json @@ -11,7 +11,7 @@ "header": "drawable_fill", "glsl_vert": "drawable.fill.vertex.glsl", "glsl_frag": "drawable.fill.fragment.glsl", - "uses_ubos": true + "uses_ubos": false }, { @@ -176,4 +176,4 @@ "glsl_vert": "symbol_text_and_icon.vertex.glsl", "glsl_frag": "symbol_text_and_icon.fragment.glsl" } -] \ No newline at end of file +] diff --git a/src/mbgl/gfx/drawable_builder.cpp b/src/mbgl/gfx/drawable_builder.cpp index 8ca958608..658a472ef 100644 --- a/src/mbgl/gfx/drawable_builder.cpp +++ b/src/mbgl/gfx/drawable_builder.cpp @@ -7,6 +7,8 @@ namespace gfx { DrawableBuilder::DrawableBuilder(std::string name_) : name(std::move(name_)), + vertexAttrName("a_pos"), + colorAttrName("a_color"), renderPass(RenderPass::Opaque), impl(std::make_unique()) {} @@ -35,8 +37,21 @@ void DrawableBuilder::flush() { draw->setDepthType(depthType); draw->setShader(shader); draw->setMatrix(matrix); - draw->setVertexAttributes(getVertexAttributes()); draw->addTweakers(tweakers.begin(), tweakers.end()); + + if (auto drawAttrs = getVertexAttributes().clone()) { + + vertexAttrs.observeAttributes([&](const std::string& iName, const VertexAttribute& iAttr) { + if (auto& drawAttr = drawAttrs->getOrAdd(iName)) { + for (std::size_t i = 0; i < impl->vertices.elements(); ++i) { + drawAttr->set(i, iAttr.get(0)); + } + } + }); + + draw->setVertexAttributes(std::move(*drawAttrs)); + } + init(); } if (currentDrawable) { @@ -91,6 +106,14 @@ void DrawableBuilder::addQuad(int16_t x0, int16_t y0, int16_t x1, int16_t y1) { appendTriangle(x1, y1); } +void DrawableBuilder::setVertexAttributes(const VertexAttributeArray& attrs) { + vertexAttrs = attrs; +} + +void DrawableBuilder::setVertexAttributes(VertexAttributeArray&& attrs) { + vertexAttrs = attrs; +} + void DrawableBuilder::addTriangles(const std::vector>& vertices, std::size_t vertexOffset, std::size_t vertexLength, diff --git a/src/mbgl/gfx/vertex_attribute.cpp b/src/mbgl/gfx/vertex_attribute.cpp index 48dd51d17..a43aa230a 100644 --- a/src/mbgl/gfx/vertex_attribute.cpp +++ b/src/mbgl/gfx/vertex_attribute.cpp @@ -12,6 +12,10 @@ std::unique_ptr VertexAttributeArray::nullref = nullptr; VertexAttributeArray::VertexAttributeArray(int initCapacity) : attrs(initCapacity) {} +VertexAttributeArray::VertexAttributeArray(const VertexAttributeArray& other) { + operator=(other); +} + VertexAttributeArray::VertexAttributeArray(VertexAttributeArray&& other) : attrs(std::move(other.attrs)) {} @@ -23,7 +27,9 @@ VertexAttributeArray& VertexAttributeArray::operator=(VertexAttributeArray&& oth VertexAttributeArray& VertexAttributeArray::operator=(const VertexAttributeArray& other) { attrs.clear(); for (const auto& kv : other.attrs) { - add(kv.first, copy(*kv.second)); + if (kv.second) { + add(kv.first, copy(*kv.second)); + } } return *this; } @@ -69,6 +75,10 @@ std::size_t VertexAttributeArray::getMaxCount() const { }); } +void VertexAttributeArray::clear() { + attrs.clear(); +} + void VertexAttributeArray::resolve(const VertexAttributeArray& overrides, ResolveDelegate delegate) const { for (auto& kv : attrs) { delegate(kv.first, *kv.second, overrides.get(kv.first)); diff --git a/src/mbgl/gl/drawable_gl_builder.cpp b/src/mbgl/gl/drawable_gl_builder.cpp index a627547b4..30ab3a9d4 100644 --- a/src/mbgl/gl/drawable_gl_builder.cpp +++ b/src/mbgl/gl/drawable_gl_builder.cpp @@ -15,26 +15,28 @@ void DrawableGLBuilder::init() { auto& drawableGL = static_cast(*currentDrawable); auto& attrs = drawableGL.mutableVertexAttributes(); - if (const auto& posAttr = attrs.getOrAdd("a_pos")) { + if (const auto& posAttr = attrs.getOrAdd(vertexAttrName)) { 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 (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()) { - impl->colors.clear(); - } - - if (impl->colors.empty()) { - colorAttr->set(0, DrawableGL::colorAttrValue(getColor())); - } else { - std::size_t index = 0; - colorAttr->reserve(impl->colors.size()); - for (const auto& color : impl->colors) { - colorAttr->set(index++, DrawableGL::colorAttrValue(color)); + if (colorMode != ColorMode::None && !colorAttrName.empty()) { + if (const auto& colorAttr = attrs.getOrAdd(colorAttrName)) { + // 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()) { + impl->colors.clear(); + } + + if (impl->colors.empty()) { + colorAttr->set(0, DrawableGL::colorAttrValue(getColor())); + } else { + std::size_t index = 0; + colorAttr->reserve(impl->colors.size()); + for (const auto& color : impl->colors) { + colorAttr->set(index++, DrawableGL::colorAttrValue(color)); + } } } } diff --git a/src/mbgl/gl/layer_group_gl.cpp b/src/mbgl/gl/layer_group_gl.cpp index 1ce711e52..030cc7683 100644 --- a/src/mbgl/gl/layer_group_gl.cpp +++ b/src/mbgl/gl/layer_group_gl.cpp @@ -70,6 +70,13 @@ void TileLayerGroupGL::render(RenderOrchestrator&, PaintParameters& parameters) return; } + std::string label; + if (const auto& tileID = drawable.getTileID()) { + label = drawable.getName() + "/" + util::toString(*tileID); + } + const auto labelPtr = (label.empty() ? drawable.getName() : label).c_str(); + const auto debugGroup = parameters.encoder->createDebugGroup(labelPtr); + mat4 matrix = drawable.getMatrix(); if (drawable.getTileID()) { const UnwrappedTileID tileID = drawable.getTileID()->toUnwrapped(); diff --git a/src/mbgl/renderer/layers/render_fill_layer.cpp b/src/mbgl/renderer/layers/render_fill_layer.cpp index 9994fe1a2..d6c7a7328 100644 --- a/src/mbgl/renderer/layers/render_fill_layer.cpp +++ b/src/mbgl/renderer/layers/render_fill_layer.cpp @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -305,6 +306,7 @@ void RenderFillLayer::update(const int32_t layerIndex, std::unique_ptr builder; std::vector newTiles; + gfx::VertexAttributeArray vertexAttrs; for (const auto renderPass : {RenderPass::Opaque, RenderPass::Translucent}) { tileLayerGroup->observeDrawables([&](gfx::UniqueDrawable& drawable) { @@ -340,8 +342,8 @@ void RenderFillLayer::update(const int32_t layerIndex, auto& bucket = static_cast(*renderData->bucket); const auto& evaluated = getEvaluated(renderData->layerProperties); const auto evalColor = evaluated.get().constantOr(Color()); - const auto fillOpacity = evaluated.get().constantOr(0); - const auto fillColor = evalColor * (fillOpacity > 0.0f ? fillOpacity : 1.0f); + const auto fillOpacity = evaluated.get().constantOr(1); + //const auto fillColor = evalColor * (fillOpacity > 0.0f ? fillOpacity : 1.0f); const auto fillRenderPass = (evalColor.a >= 1.0f && fillOpacity >= 1.0f /* && parameters.currentLayer >= parameters.opaquePassCutoff*/) @@ -353,8 +355,24 @@ void RenderFillLayer::update(const int32_t layerIndex, continue; } + vertexAttrs.clear(); + if (auto& attr = vertexAttrs.getOrAdd("a_color")) { + attr->set(0, util::cast(evalColor.toArray())); + } + if (auto& attr = vertexAttrs.getOrAdd("a_opacity")) { + attr->set(0, { fillOpacity, fillOpacity }); + } + + if (evaluatedPropertiesChange) { + //FillLayerUBO fillLayerUBO; + //fillLayerUBO.color = evaluated.get(); + //fillLayerUBO.opacity = evaluated.get(); + //uniformBuffer = context.createUniformBuffer(&fillLayerUBO, sizeof(fillLayerUBO)); + evaluatedPropertiesChange = false; + } + if (tileDrawable) { - // needed and already present, update? + //tileDrawable->mutableUniformBuffers().addOrReplace("FillLayerUBO", uniformBuffer); continue; } @@ -362,7 +380,7 @@ void RenderFillLayer::update(const int32_t layerIndex, builder = context.createDrawableBuilder("fill"); builder->setShader(shader); builder->addTweaker(context.createDrawableTweaker()); - builder->setColorMode(gfx::DrawableBuilder::ColorMode::PerVertex); + builder->setColorMode(gfx::DrawableBuilder::ColorMode::None); builder->setDepthType(gfx::DepthMaskType::ReadWrite); builder->setLayerIndex(layerIndex); } @@ -370,8 +388,8 @@ void RenderFillLayer::update(const int32_t layerIndex, // tile.translatedMatrix(evaluated.get(), evaluated.get(), // parameters.state) - builder->setColor(fillColor); builder->setRenderPass(renderPass); + builder->setVertexAttributes(vertexAttrs); const std::vector>>::Vertex>& verts = bucket.vertices.vector(); @@ -423,9 +441,10 @@ void RenderFillLayer::update(const int32_t layerIndex, if (!newDrawables.empty()) { auto& drawable = newDrawables[0]; drawable->setTileID(tileID); + //drawable->mutableUniformBuffers().addOrReplace("FillLayerUBO", uniformBuffer); // Track it. - // tileLayerGroup->addDrawable(renderPass, tileID, std::move(drawable)); + tileLayerGroup->addDrawable(renderPass, tileID, std::move(drawable)); ++stats.tileDrawablesAdded; // Log::Warning(Event::General, "Adding drawable for " + util::toString(tileID) + " total " + // std::to_string(stats.tileDrawablesAdded+1));