Reduce symbol buffers memory by using instancing (Core optimization) (#4383)

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
This commit is contained in:
Alex Cristici
2026-08-27 00:12:07 +03:00
committed by GitHub
parent 1d0908bdaa
commit cbe4681ef1
41 changed files with 1398 additions and 727 deletions

View File

@@ -182,6 +182,17 @@ struct MBGL_VERTEX_ALIGN VertexType<A1, A2, A3, A4, A5> {
typename A5::Value a5;
};
template <class A1, class A2, class A3, class A4, class A5, class A6>
struct MBGL_VERTEX_ALIGN VertexType<A1, A2, A3, A4, A5, A6> {
using Type = VertexType<A1, A2, A3, A4, A5, A6>;
typename A1::Value a1;
typename A2::Value a2;
typename A3::Value a3;
typename A4::Value a4;
typename A5::Value a5;
typename A6::Value a6;
};
template <class>
struct Descriptor;

View File

@@ -224,6 +224,8 @@ void DrawableBuilder::setSegments(const gfx::DrawMode mode,
seg.indexOffset,
seg.vertexLength,
seg.indexLength,
seg.baseInstance,
seg.instanceCount,
seg.sortKey,
};
impl->segments.emplace_back(createSegment(mode, std::move(segCopy)));

View File

@@ -204,7 +204,7 @@ void DrawableBuilder::Impl::setupForWideVectors(gfx::Context& context, gfx::Draw
// segments
SegmentVector triangleSegments;
triangleSegments.emplace_back(0, 0, 12, 18);
triangleSegments.emplace_back(0, 0, 12, 18, 0, sharedInstanceData->elements());
// add to builder
{

View File

@@ -104,6 +104,8 @@ void DrawableGL::updateVertexAttributes(gfx::VertexAttributeArrayPtr vertices,
seg.indexOffset,
seg.vertexLength,
seg.indexLength,
seg.baseInstance,
seg.instanceCount,
seg.sortKey,
};
auto drawSeg = std::make_unique<DrawableGL::DrawSegmentGL>(

View File

@@ -115,7 +115,7 @@ private:
if (segments.empty() ||
segments.back().vertexLength + vertexLength > std::numeric_limits<uint16_t>::max()) {
// Move to a new segments because the old one can't hold the geometry.
segments.emplace_back(vertices.elements(), triangles.elements(), 0ul, 0ul, sortKey);
segments.emplace_back(vertices.elements(), triangles.elements(), 0ul, 0ul, 0ul, 1ul, sortKey);
}
// this geometry will be of the Point type, and we'll derive

View File

@@ -5,6 +5,7 @@
#include <mln/math/angles.hpp>
#include <mln/renderer/bucket_parameters.hpp>
#include <mln/renderer/layers/render_symbol_layer.hpp>
#include <mln/renderer/render_static_data.hpp>
#include <mln/text/get_anchors.hpp>
#include <mln/text/shaping.hpp>
#include <mln/text/glyph_manager.hpp>
@@ -1064,7 +1065,7 @@ void SymbolLayout::createBucket(const ImagePositions&,
iconSymbol.angle = (allowVerticalPlacement && writingMode == WritingModeType::Vertical)
? pi_v<float> / 2
: 0.0f;
iconSymbol.vertexStartIndex = addSymbols(
iconSymbol.startIndex = addSymbols(
iconBuffer, sizeData, iconQuads, symbolInstance.getAnchor(), iconSymbol, feature.sortKey);
};
@@ -1078,8 +1079,12 @@ void SymbolLayout::createBucket(const ImagePositions&,
}
for (auto& pair : bucket->paintProperties) {
pair.second.iconBinders.populateVertexVectors(
feature, iconBuffer.vertices().elements(), symbolInstance.getDataFeatureIndex(), {}, {}, canonical);
pair.second.iconBinders.populateVertexVectors(feature,
iconBuffer.attributeData().elements(),
symbolInstance.getDataFeatureIndex(),
{},
{},
canonical);
}
}
@@ -1169,7 +1174,7 @@ void SymbolLayout::updatePaintPropertiesForSection(SymbolBucket& bucket,
const auto& formattedSection = sectionOptionsToValue((*feature.formattedText).sectionAt(sectionIndex));
for (auto& pair : bucket.paintProperties) {
pair.second.textBinders.populateVertexVectors(
feature, bucket.text.vertices().elements(), feature.index, {}, {}, canonical, formattedSection);
feature, bucket.text.attributeData().elements(), feature.index, {}, {}, canonical, formattedSection);
}
}
@@ -1209,7 +1214,7 @@ std::size_t SymbolLayout::addSymbolGlyphQuads(SymbolBucket& bucket,
const std::size_t index = addSymbol(
bucket.text, sizeData, symbolQuad, symbolInstance.getAnchor(), placedSymbol, feature.sortKey);
if (firstSymbol) {
placedSymbol.vertexStartIndex = index;
placedSymbol.startIndex = index;
firstSymbol = false;
}
}
@@ -1217,6 +1222,40 @@ std::size_t SymbolLayout::addSymbolGlyphQuads(SymbolBucket& bucket,
return lastAddedSection ? *lastAddedSection : 0u;
}
#if MLN_USE_SYMBOL_INSTANCING
size_t SymbolLayout::addSymbol(SymbolBucket::Buffer& buffer,
const Range<float> sizeData,
const SymbolQuad& symbol,
const Anchor& labelAnchor,
PlacedSymbol& placedSymbol,
float sortKey) {
constexpr const uint16_t instanceCount = 1;
const uint16_t baseInstance = buffer.segments.empty() ? 0 : buffer.segments.back().instanceCount;
if (buffer.segments.empty() || baseInstance + instanceCount > std::numeric_limits<uint16_t>::max() ||
std::fabs(buffer.segments.back().sortKey - sortKey) > std::numeric_limits<float>::epsilon()) {
buffer.segments.emplace_back(RenderStaticData::symbolSegment(baseInstance, sortKey));
}
auto& segment = buffer.segments.back();
auto index = static_cast<uint16_t>(segment.baseInstance + segment.instanceCount);
auto attributes = SymbolBucket::layoutAttributes(symbol, labelAnchor, sizeData);
buffer.attributeData().emplace_back(attributes);
auto dynamicAttributes = SymbolBucket::dynamicLayoutAttributes(labelAnchor.point, 0);
buffer.dynamicAttributeData().emplace_back(dynamicAttributes);
auto opacityAttributes = SymbolBucket::opacityAttributes(true, 1.0);
buffer.opacityAttributeData().emplace_back(opacityAttributes);
segment.instanceCount += instanceCount;
placedSymbol.glyphOffsets.push_back(symbol.glyphOffset.x);
return index;
}
#else
size_t SymbolLayout::addSymbol(SymbolBucket::Buffer& buffer,
const Range<float> sizeData,
const SymbolQuad& symbol,
@@ -1237,7 +1276,8 @@ size_t SymbolLayout::addSymbol(SymbolBucket::Buffer& buffer,
if (buffer.segments.empty() ||
buffer.segments.back().vertexLength + vertexLength > std::numeric_limits<uint16_t>::max() ||
std::fabs(buffer.segments.back().sortKey - sortKey) > std::numeric_limits<float>::epsilon()) {
buffer.segments.emplace_back(buffer.vertices().elements(), buffer.triangles.elements(), 0ul, 0ul, sortKey);
buffer.segments.emplace_back(
buffer.attributeData().elements(), buffer.triangles.elements(), 0ul, 0ul, 0ul, 1ul, sortKey);
}
// We're generating triangle fans, so we always start with the first
@@ -1247,58 +1287,58 @@ size_t SymbolLayout::addSymbol(SymbolBucket::Buffer& buffer,
auto index = static_cast<uint16_t>(segment.vertexLength);
// coordinates (2 triangles)
auto& vertices = buffer.vertices();
vertices.emplace_back(SymbolBucket::layoutVertex(labelAnchor.point,
tl,
symbol.glyphOffset.y,
tex.x,
tex.y,
sizeData,
symbol.isSDF,
pixelOffsetTL,
minFontScale));
vertices.emplace_back(SymbolBucket::layoutVertex(labelAnchor.point,
tr,
symbol.glyphOffset.y,
tex.x + tex.w,
tex.y,
sizeData,
symbol.isSDF,
{pixelOffsetBR.x, pixelOffsetTL.y},
minFontScale));
vertices.emplace_back(SymbolBucket::layoutVertex(labelAnchor.point,
bl,
symbol.glyphOffset.y,
tex.x,
tex.y + tex.h,
sizeData,
symbol.isSDF,
{pixelOffsetTL.x, pixelOffsetBR.y},
minFontScale));
vertices.emplace_back(SymbolBucket::layoutVertex(labelAnchor.point,
br,
symbol.glyphOffset.y,
tex.x + tex.w,
tex.y + tex.h,
sizeData,
symbol.isSDF,
pixelOffsetBR,
minFontScale));
auto& attributeData = buffer.attributeData();
attributeData.emplace_back(SymbolBucket::layoutAttributes(labelAnchor.point,
tl,
symbol.glyphOffset.y,
tex.x,
tex.y,
sizeData,
symbol.isSDF,
pixelOffsetTL,
minFontScale));
attributeData.emplace_back(SymbolBucket::layoutAttributes(labelAnchor.point,
tr,
symbol.glyphOffset.y,
tex.x + tex.w,
tex.y,
sizeData,
symbol.isSDF,
{pixelOffsetBR.x, pixelOffsetTL.y},
minFontScale));
attributeData.emplace_back(SymbolBucket::layoutAttributes(labelAnchor.point,
bl,
symbol.glyphOffset.y,
tex.x,
tex.y + tex.h,
sizeData,
symbol.isSDF,
{pixelOffsetTL.x, pixelOffsetBR.y},
minFontScale));
attributeData.emplace_back(SymbolBucket::layoutAttributes(labelAnchor.point,
br,
symbol.glyphOffset.y,
tex.x + tex.w,
tex.y + tex.h,
sizeData,
symbol.isSDF,
pixelOffsetBR,
minFontScale));
// Dynamic/Opacity vertices are initialized so that the vertex count always
// agrees with the layout vertex buffer, but they will always be updated
// before rendering happens
auto dynamicVertex = SymbolBucket::dynamicLayoutVertex(labelAnchor.point, 0);
buffer.dynamicVertices().emplace_back(dynamicVertex);
buffer.dynamicVertices().emplace_back(dynamicVertex);
buffer.dynamicVertices().emplace_back(dynamicVertex);
buffer.dynamicVertices().emplace_back(dynamicVertex);
auto dynamicAttributes = SymbolBucket::dynamicLayoutAttributes(labelAnchor.point, 0);
buffer.dynamicAttributeData().emplace_back(dynamicAttributes);
buffer.dynamicAttributeData().emplace_back(dynamicAttributes);
buffer.dynamicAttributeData().emplace_back(dynamicAttributes);
buffer.dynamicAttributeData().emplace_back(dynamicAttributes);
auto opacityVertex = SymbolBucket::opacityVertex(true, 1.0);
buffer.opacityVertices().emplace_back(opacityVertex);
buffer.opacityVertices().emplace_back(opacityVertex);
buffer.opacityVertices().emplace_back(opacityVertex);
buffer.opacityVertices().emplace_back(opacityVertex);
auto opacityAttributes = SymbolBucket::opacityAttributes(true, 1.0);
buffer.opacityAttributeData().emplace_back(opacityAttributes);
buffer.opacityAttributeData().emplace_back(opacityAttributes);
buffer.opacityAttributeData().emplace_back(opacityAttributes);
buffer.opacityAttributeData().emplace_back(opacityAttributes);
// add the two triangles, referencing the four coordinates we just inserted.
buffer.triangles.emplace_back(index + 0, index + 1, index + 2);
@@ -1311,6 +1351,7 @@ size_t SymbolLayout::addSymbol(SymbolBucket::Buffer& buffer,
return index;
}
#endif
size_t SymbolLayout::addSymbols(SymbolBucket::Buffer& buffer,
const Range<float> sizeData,

View File

@@ -180,18 +180,25 @@ bool isVisible(const vec4& anchorPos, const std::array<double, 2>& clippingBuffe
void addDynamicAttributes(const Point<float>& anchorPoint,
const float angle,
gfx::VertexVector<gfx::Vertex<SymbolDynamicLayoutAttributes>>& dynamicVertexArray) {
auto dynamicVertex = SymbolBucket::dynamicLayoutVertex(anchorPoint, angle);
dynamicVertexArray.emplace_back(dynamicVertex);
dynamicVertexArray.emplace_back(dynamicVertex);
dynamicVertexArray.emplace_back(dynamicVertex);
dynamicVertexArray.emplace_back(dynamicVertex);
SymbolBucket::DynamicAttributeVector& dynamicAttributeData) {
auto dynamicAttributes = SymbolBucket::dynamicLayoutAttributes(anchorPoint, angle);
dynamicAttributeData.emplace_back(dynamicAttributes);
#if !MLN_USE_SYMBOL_INSTANCING
dynamicAttributeData.emplace_back(dynamicAttributes);
dynamicAttributeData.emplace_back(dynamicAttributes);
dynamicAttributeData.emplace_back(dynamicAttributes);
#endif
}
void hideGlyphs(size_t numGlyphs, gfx::VertexVector<gfx::Vertex<SymbolDynamicLayoutAttributes>>& dynamicVertexArray) {
void hideGlyphs(size_t numGlyphs, SymbolBucket::DynamicAttributeVector& dynamicVertexArray) {
#if MLN_USE_SYMBOL_INSTANCING
const size_t count = 1;
#else
const size_t count = 4;
#endif
const Point<float> offscreenPoint = {-INFINITY, -INFINITY};
if (dynamicVertexArray.empty()) {
dynamicVertexArray.reserve(4 * numGlyphs);
dynamicVertexArray.reserve(count * numGlyphs);
}
for (size_t i = 0; i < numGlyphs; i++) {
addDynamicAttributes(offscreenPoint, 0, dynamicVertexArray);
@@ -378,7 +385,7 @@ PlacementResult placeGlyphsAlongLine(const PlacedSymbol& symbol,
const mat4& posMatrix,
const mat4& labelPlaneMatrix,
const mat4& glCoordMatrix,
gfx::VertexVector<gfx::Vertex<SymbolDynamicLayoutAttributes>>& dynamicVertexArray,
SymbolBucket::DynamicAttributeVector& dynamicVertexArray,
const Point<float>& projectedAnchorPoint,
const float aspectRatio) {
const float fontScale = fontSize / util::ONE_EM;
@@ -486,7 +493,7 @@ PlacementResult placeGlyphsAlongLine(const PlacedSymbol& symbol,
return PlacementResult::OK;
}
void reprojectLineLabels(gfx::VertexVector<gfx::Vertex<SymbolDynamicLayoutAttributes>>& dynamicVertexArray,
void reprojectLineLabels(SymbolBucket::DynamicAttributeVector& dynamicVertexArray,
const std::vector<PlacedSymbol>& placedSymbols,
const mat4& posMatrix,
bool pitchWithMap,

View File

@@ -48,7 +48,7 @@ mat4 getGlCoordMatrix(
using PointAndCameraDistance = std::pair<Point<float>, float>;
PointAndCameraDistance project(const Point<float>& point, const mat4& matrix);
void reprojectLineLabels(gfx::VertexVector<gfx::Vertex<SymbolDynamicLayoutAttributes>>&,
void reprojectLineLabels(SymbolBucket::DynamicAttributeVector&,
const std::vector<PlacedSymbol>&,
const mat4& posMatrix,
bool pitchWithMap,
@@ -68,10 +68,9 @@ std::optional<std::pair<PlacedGlyph, PlacedGlyph>> placeFirstAndLastGlyph(float
const mat4& labelPlaneMatrix,
bool returnTileDistance);
void hideGlyphs(std::size_t numGlyphs,
gfx::VertexVector<gfx::Vertex<SymbolDynamicLayoutAttributes>>& dynamicVertexArray);
void hideGlyphs(std::size_t numGlyphs, SymbolBucket::DynamicAttributeVector& dynamicVertexArray);
void addDynamicAttributes(const Point<float>& anchorPoint,
float angle,
gfx::VertexVector<gfx::Vertex<SymbolDynamicLayoutAttributes>>& dynamicVertexArray);
SymbolBucket::DynamicAttributeVector& dynamicAttributeData);
} // end namespace mln

View File

@@ -276,8 +276,8 @@ void Drawable::draw(PaintParameters& parameters) const {
const auto primitiveType = getPrimitiveType(mode.type);
constexpr auto indexType = MTL::IndexType::IndexTypeUInt16;
constexpr auto indexSize = sizeof(std::uint16_t);
const NS::UInteger instanceCount = instanceAttributes ? instanceAttributes->getMinCount() : 1;
constexpr NS::UInteger baseInstance = 0;
const NS::UInteger instanceCount = mlSegment.instanceCount;
const NS::UInteger baseInstance = mlSegment.baseInstance;
const NS::UInteger indexOffset = static_cast<NS::UInteger>(indexSize *
mlSegment.indexOffset); // in bytes, not indexes
const NS::Integer baseVertex = static_cast<NS::Integer>(mlSegment.vertexOffset);
@@ -373,6 +373,8 @@ void Drawable::updateVertexAttributes(gfx::VertexAttributeArrayPtr vertices,
seg.indexOffset,
seg.vertexLength,
seg.indexLength,
seg.baseInstance,
seg.instanceCount,
seg.sortKey,
};
drawSegs.push_back(std::make_unique<Drawable::DrawSegment>(mode, std::move(segCopy)));
@@ -548,10 +550,8 @@ void Drawable::upload(gfx::UploadPass& uploadPass_) {
const bool buildVertexAttribs = !impl->vertexDesc || !vertexAttributes || !attributeUpdateTime ||
vertexAttributes->isModifiedAfter(*attributeUpdateTime);
const bool buildInstanceAttribs = instanceAttributes && (!attributeUpdateTime ||
instanceAttributes->isModifiedAfter(*attributeUpdateTime));
if (buildVertexAttribs || buildInstanceAttribs) {
if (buildVertexAttribs) {
#if !defined(NDEBUG)
const auto debugGroup = uploadPass.createDebugGroup(debugLabel(*this));
#endif
@@ -574,87 +574,94 @@ void Drawable::upload(gfx::UploadPass& uploadPass_) {
vertexAttributes->visitAttributes([](gfx::VertexAttribute& attrib) { attrib.setDirty(false); });
// Build instance attribute buffers
gfx::AttributeBindingArray instanceBindings_;
if (instanceAttributes) {
std::vector<std::unique_ptr<gfx::VertexBufferResource>> instanceBuffers;
instanceBindings_ = uploadPass.buildAttributeBindings(instanceAttributes->getMinCount(),
/*vertexType*/ gfx::AttributeDataType::Byte,
/*vertexAttributeIndex=*/-1,
/*vertexData=*/{},
shader->getInstanceAttributes(),
*instanceAttributes,
usage,
attributeUpdateTime,
instanceBuffers);
// clear dirty flag
instanceAttributes->visitAttributes([](gfx::VertexAttribute& attrib) { attrib.setDirty(false); });
}
if (impl->attributeBindings != attributeBindings_ || impl->instanceBindings != instanceBindings_) {
if (impl->attributeBindings != attributeBindings_) {
impl->attributeBindings = std::move(attributeBindings_);
impl->instanceBindings = std::move(instanceBindings_);
// hash
std::size_t hash{0};
// Create a layout descriptor for each attribute
auto vertDesc = NS::RetainPtr(MTL::VertexDescriptor::vertexDescriptor());
const auto applyBindings = [&](const gfx::AttributeBindingArray& attributeBindings,
MTL::VertexStepFunction stepFunction) {
NS::UInteger index = 0;
for (auto& binding : attributeBindings) {
if (!binding) {
assert("Missing attribute binding");
index += 1;
continue;
}
if (!binding->vertexBufferResource && !impl->noBindingBuffer) {
if (const auto& buf = context.getEmptyVertexBuffer()) {
impl->noBindingBuffer = buf.get();
}
}
const auto& attribDesc = vertDesc->attributes()->object(index);
attribDesc->setBufferIndex(binding->bufferIndex);
attribDesc->setOffset(static_cast<NS::UInteger>(binding->attribute.offset));
attribDesc->setFormat(mtlVertexTypeOf(binding->attribute.dataType));
const auto& layoutDesc = vertDesc->layouts()->object(binding->bufferIndex);
if (!layoutDesc->stride()) {
assert(binding->vertexStride > 0);
layoutDesc->setStride(static_cast<NS::UInteger>(binding->vertexStride));
layoutDesc->setStepFunction(binding->vertexBufferResource ? stepFunction
: MTL::VertexStepFunctionConstant);
layoutDesc->setStepRate(binding->vertexBufferResource ? 1 : 0);
} else {
assert(layoutDesc->stride() == static_cast<NS::UInteger>(binding->vertexStride));
assert(layoutDesc->stepRate() == (binding->vertexBufferResource ? 1 : 0));
}
mln::util::hash_combine(hash,
mln::util::hash(index,
binding->attribute.offset,
binding->attribute.dataType,
binding->vertexStride,
static_cast<bool>(binding->vertexBufferResource)));
index += 1;
}
};
applyBindings(impl->attributeBindings, MTL::VertexStepFunctionPerVertex);
applyBindings(impl->instanceBindings, MTL::VertexStepFunctionPerInstance);
impl->vertexDesc = std::move(vertDesc);
impl->vertexDescHash = hash;
impl->pipelineState.reset();
}
}
const bool buildInstanceAttribs = instanceAttributes && (!attributeUpdateTime ||
instanceAttributes->isModifiedAfter(*attributeUpdateTime));
if (buildInstanceAttribs) {
// Build instance attribute buffers
std::vector<std::unique_ptr<gfx::VertexBufferResource>> instanceBuffers;
auto instanceBindings_ = uploadPass.buildAttributeBindings(instanceAttributes->getMinCount(),
/*vertexType*/ gfx::AttributeDataType::Byte,
/*vertexAttributeIndex=*/-1,
/*vertexData=*/{},
shader->getInstanceAttributes(),
*instanceAttributes,
usage,
attributeUpdateTime,
instanceBuffers);
// clear dirty flag
instanceAttributes->visitAttributes([](gfx::VertexAttribute& attrib) { attrib.setDirty(false); });
if (impl->instanceBindings != instanceBindings_) {
impl->instanceBindings = std::move(instanceBindings_);
}
}
if (buildVertexAttribs || buildInstanceAttribs) {
// hash
std::size_t hash{0};
// Create a layout descriptor for each attribute
auto vertDesc = NS::RetainPtr(MTL::VertexDescriptor::vertexDescriptor());
const auto applyBindings = [&](const gfx::AttributeBindingArray& attributeBindings,
MTL::VertexStepFunction stepFunction) {
NS::UInteger index = 0;
for (auto& binding : attributeBindings) {
if (!binding) {
assert("Missing attribute binding");
index += 1;
continue;
}
if (!binding->vertexBufferResource && !impl->noBindingBuffer) {
if (const auto& buf = context.getEmptyVertexBuffer()) {
impl->noBindingBuffer = buf.get();
}
}
const auto& attribDesc = vertDesc->attributes()->object(index);
attribDesc->setBufferIndex(binding->bufferIndex);
attribDesc->setOffset(static_cast<NS::UInteger>(binding->attribute.offset));
attribDesc->setFormat(mtlVertexTypeOf(binding->attribute.dataType));
const auto& layoutDesc = vertDesc->layouts()->object(binding->bufferIndex);
if (!layoutDesc->stride()) {
assert(binding->vertexStride > 0);
layoutDesc->setStride(static_cast<NS::UInteger>(binding->vertexStride));
layoutDesc->setStepFunction(binding->vertexBufferResource ? stepFunction
: MTL::VertexStepFunctionConstant);
layoutDesc->setStepRate(binding->vertexBufferResource ? 1 : 0);
} else {
assert(layoutDesc->stride() == static_cast<NS::UInteger>(binding->vertexStride));
assert(layoutDesc->stepRate() == (binding->vertexBufferResource ? 1 : 0));
}
mln::util::hash_combine(hash,
mln::util::hash(index,
binding->attribute.offset,
binding->attribute.dataType,
binding->vertexStride,
static_cast<bool>(binding->vertexBufferResource)));
index += 1;
}
};
applyBindings(impl->attributeBindings, MTL::VertexStepFunctionPerVertex);
applyBindings(impl->instanceBindings, MTL::VertexStepFunctionPerInstance);
impl->vertexDesc = std::move(vertDesc);
impl->vertexDescHash = hash;
impl->pipelineState.reset();
}
const bool texturesNeedUpload = std::any_of(
textures.begin(), textures.end(), [](const auto& texture) { return texture && texture->needsUpload(); });

View File

@@ -2,6 +2,7 @@
#include <mln/renderer/bucket_parameters.hpp>
#include <mln/style/layers/fill_extrusion_layer_impl.hpp>
#include <mln/renderer/layers/render_fill_extrusion_layer.hpp>
#include <mln/renderer/render_static_data.hpp>
#include <mln/map/transform_state.hpp>
#include <mln/util/math.hpp>
#include <mln/util/constants.hpp>
@@ -201,6 +202,11 @@ void FillExtrusionBucket::addFeature(const GeometryTileFeature& feature,
triangleSegment.vertexLength += totalVertices;
triangleSegment.indexLength += nIndices;
if (instanceSegments.empty()) {
instanceSegments.emplace_back(RenderStaticData::fillExtrusionSegment());
}
instanceSegments.back().instanceCount += totalVertices;
}
for (auto& pair : paintPropertyBinders) {

View File

@@ -97,6 +97,7 @@ public:
TriangleIndexVector& triangles = *sharedTriangles;
SegmentVector triangleSegments;
SegmentVector instanceSegments;
std::unordered_map<std::string, FillExtrusionBinders> paintPropertyBinders;
};

View File

@@ -73,16 +73,40 @@ SymbolBucket::SymbolBucket(Immutable<style::SymbolLayoutProperties::PossiblyEval
placementModes(std::move(placementModes_)) {
for (const auto& pair : paintProperties_) {
const auto& evaluated = getEvaluated<SymbolLayerProperties>(pair.second);
paintProperties.emplace(std::piecewise_construct,
std::forward_as_tuple(pair.first),
std::forward_as_tuple(PaintProperties{
.iconBinders = {RenderSymbolLayer::iconPaintProperties(evaluated), zoom},
.textBinders = {RenderSymbolLayer::textPaintProperties(evaluated), zoom}}));
paintProperties.emplace(
std::piecewise_construct,
std::forward_as_tuple(pair.first),
std::forward_as_tuple(PaintProperties{.iconBinders = {iconPaintProperties(evaluated), zoom},
.textBinders = {textPaintProperties(evaluated), zoom}}));
}
}
SymbolBucket::~SymbolBucket() = default;
// static
style::IconPaintProperties::PossiblyEvaluated SymbolBucket::iconPaintProperties(
const style::SymbolPaintProperties::PossiblyEvaluated& evaluated_) {
return style::IconPaintProperties::PossiblyEvaluated{evaluated_.get<style::IconOpacity>(),
evaluated_.get<style::IconColor>(),
evaluated_.get<style::IconHaloColor>(),
evaluated_.get<style::IconHaloWidth>(),
evaluated_.get<style::IconHaloBlur>(),
evaluated_.get<style::IconTranslate>(),
evaluated_.get<style::IconTranslateAnchor>()};
}
// static
style::TextPaintProperties::PossiblyEvaluated SymbolBucket::textPaintProperties(
const style::SymbolPaintProperties::PossiblyEvaluated& evaluated_) {
return style::TextPaintProperties::PossiblyEvaluated{evaluated_.get<style::TextOpacity>(),
evaluated_.get<style::TextColor>(),
evaluated_.get<style::TextHaloColor>(),
evaluated_.get<style::TextHaloWidth>(),
evaluated_.get<style::TextHaloBlur>(),
evaluated_.get<style::TextTranslate>(),
evaluated_.get<style::TextTranslateAnchor>()};
}
void SymbolBucket::upload([[maybe_unused]] gfx::UploadPass& uploadPass) {
uploaded = true;
staticUploaded = true;
@@ -136,9 +160,17 @@ bool SymbolBucket::hasTextCollisionCircleData() const {
return textCollisionCircle && !textCollisionCircle->segments.empty();
}
void addPlacedSymbol(gfx::IndexVector<gfx::Triangles>& triangles, const PlacedSymbol& placedSymbol) {
auto endIndex = placedSymbol.vertexStartIndex + placedSymbol.glyphOffsets.size() * 4;
for (auto vertexIndex = placedSymbol.vertexStartIndex; vertexIndex < endIndex; vertexIndex += 4) {
#if MLN_USE_SYMBOL_INSTANCING
void addPlacedSymbol(SymbolBucket::SortedInstanceVector& sortedInstances, const PlacedSymbol& placedSymbol) {
auto endIndex = placedSymbol.startIndex + placedSymbol.glyphOffsets.size() * 1;
for (auto instanceIndex = placedSymbol.startIndex; instanceIndex < endIndex; instanceIndex += 1) {
sortedInstances.emplace_back(SymbolSortedInstance{static_cast<uint16_t>(instanceIndex)});
}
}
#else
void addPlacedSymbol(SymbolBucket::TriangleIndexVector& triangles, const PlacedSymbol& placedSymbol) {
auto endIndex = placedSymbol.startIndex + placedSymbol.glyphOffsets.size() * 4;
for (auto vertexIndex = placedSymbol.startIndex; vertexIndex < endIndex; vertexIndex += 4) {
triangles.emplace_back(static_cast<uint16_t>(vertexIndex + 0),
static_cast<uint16_t>(vertexIndex + 1),
static_cast<uint16_t>(vertexIndex + 2));
@@ -147,6 +179,7 @@ void addPlacedSymbol(gfx::IndexVector<gfx::Triangles>& triangles, const PlacedSy
static_cast<uint16_t>(vertexIndex + 3));
}
}
#endif
void SymbolBucket::sortFeatures(const float angle) {
if (!sortFeaturesByY) {
@@ -170,9 +203,19 @@ void SymbolBucket::sortFeatures(const float angle) {
sortUploaded = false;
uploaded = false;
text.triangles.clear();
icon.triangles.clear();
sdfIcon.triangles.clear();
#if MLN_USE_SYMBOL_INSTANCING
auto& textVector = text.sortedInstances();
auto& iconVector = icon.sortedInstances();
auto& sdfIconVector = sdfIcon.sortedInstances();
#else
auto& textVector = text.triangles;
auto& iconVector = icon.triangles;
auto& sdfIconVector = sdfIcon.triangles;
#endif
textVector.clear();
iconVector.clear();
sdfIconVector.clear();
auto symbolsSortOrder = std::make_unique<std::vector<size_t>>();
symbolsSortOrder->reserve(symbolInstances.size());
@@ -189,29 +232,29 @@ void SymbolBucket::sortFeatures(const float angle) {
symbolsSortOrder->push_back(symbolInstance.getDataFeatureIndex());
if (symbolInstance.getPlacedRightTextIndex()) {
addPlacedSymbol(text.triangles, text.placedSymbols[*symbolInstance.getPlacedRightTextIndex()]);
addPlacedSymbol(textVector, text.placedSymbols[*symbolInstance.getPlacedRightTextIndex()]);
}
if (symbolInstance.getPlacedCenterTextIndex() && !symbolInstance.getSingleLine()) {
addPlacedSymbol(text.triangles, text.placedSymbols[*symbolInstance.getPlacedCenterTextIndex()]);
addPlacedSymbol(textVector, text.placedSymbols[*symbolInstance.getPlacedCenterTextIndex()]);
}
if (symbolInstance.getPlacedLeftTextIndex() && !symbolInstance.getSingleLine()) {
addPlacedSymbol(text.triangles, text.placedSymbols[*symbolInstance.getPlacedLeftTextIndex()]);
addPlacedSymbol(textVector, text.placedSymbols[*symbolInstance.getPlacedLeftTextIndex()]);
}
if (symbolInstance.getPlacedVerticalTextIndex()) {
addPlacedSymbol(text.triangles, text.placedSymbols[*symbolInstance.getPlacedVerticalTextIndex()]);
addPlacedSymbol(textVector, text.placedSymbols[*symbolInstance.getPlacedVerticalTextIndex()]);
}
auto& iconBuffer = symbolInstance.hasSdfIcon() ? sdfIcon : icon;
auto& iconVectorBuffer = symbolInstance.hasSdfIcon() ? sdfIconVector : iconVector;
if (symbolInstance.getPlacedIconIndex()) {
addPlacedSymbol(iconBuffer.triangles, iconBuffer.placedSymbols[*symbolInstance.getPlacedIconIndex()]);
addPlacedSymbol(iconVectorBuffer, iconBuffer.placedSymbols[*symbolInstance.getPlacedIconIndex()]);
}
if (symbolInstance.getPlacedVerticalIconIndex()) {
addPlacedSymbol(iconBuffer.triangles,
iconBuffer.placedSymbols[*symbolInstance.getPlacedVerticalIconIndex()]);
addPlacedSymbol(iconVectorBuffer, iconBuffer.placedSymbols[*symbolInstance.getPlacedVerticalIconIndex()]);
}
}
@@ -248,12 +291,12 @@ SymbolInstanceReferences SymbolBucket::getSymbols(const std::optional<SortKeyRan
#if MLN_SYMBOL_GUARDS
bool SymbolBucket::check(source_location source) {
if (text.vertices().elements() != text.dynamicVertices().elements() ||
text.vertices().elements() != text.opacityVertices().elements() ||
icon.vertices().elements() != icon.dynamicVertices().elements() ||
icon.vertices().elements() != icon.opacityVertices().elements() ||
sdfIcon.vertices().elements() != sdfIcon.dynamicVertices().elements() ||
sdfIcon.vertices().elements() != sdfIcon.opacityVertices().elements()) {
if (text.attributeData().elements() != text.dynamicAttributeData().elements() ||
text.attributeData().elements() != text.opacityAttributeData().elements() ||
icon.attributeData().elements() != icon.dynamicAttributeData().elements() ||
icon.attributeData().elements() != icon.opacityAttributeData().elements() ||
sdfIcon.attributeData().elements() != sdfIcon.dynamicAttributeData().elements() ||
sdfIcon.attributeData().elements() != sdfIcon.opacityAttributeData().elements()) {
// This bucket was left in a partial state and it cannot be used
return false;
}
@@ -311,7 +354,7 @@ void SymbolBucket::updateVertices(const Placement& placement,
uploaded = false;
}
if (placement.updateBucketDynamicVertices(*this, state, tile)) {
if (placement.updateBucketDynamicAttributeData(*this, state, tile)) {
dynamicUploaded = false;
uploaded = false;
}

View File

@@ -8,7 +8,6 @@
#include <mln/shaders/segment.hpp>
#include <mln/renderer/bucket.hpp>
#include <mln/renderer/paint_property_binder.hpp>
#include <mln/renderer/layers/render_symbol_layer.hpp>
#include <mln/style/layers/symbol_layer_properties.hpp>
#include <mln/text/glyph_range.hpp>
@@ -17,17 +16,54 @@
namespace mln {
namespace style {
// {icon,text}-specific paint-property packs for use in the symbol Programs.
// Since each program deals either with icons or text, using a smaller property set
// lets us avoid unnecessarily binding attributes for properties the program wouldn't use.
class IconPaintProperties : public Properties<IconOpacity,
IconColor,
IconHaloColor,
IconHaloWidth,
IconHaloBlur,
IconTranslate,
IconTranslateAnchor> {};
class TextPaintProperties : public Properties<TextOpacity,
TextColor,
TextHaloColor,
TextHaloWidth,
TextHaloBlur,
TextTranslate,
TextTranslateAnchor> {};
} // namespace style
class CrossTileSymbolLayerIndex;
using SymbolIconBinders = PaintPropertyBinders<style::IconPaintProperties::DataDrivenProperties>;
using SymbolTextBinders = PaintPropertyBinders<style::TextPaintProperties::DataDrivenProperties>;
using SymbolLayoutVertex =
gfx::Vertex<TypeList<attributes::pos_offset, attributes::data<uint16_t, 4>, attributes::pixeloffset>>;
using SymbolDynamicLayoutAttributes = TypeList<attributes::projected_pos>;
using SymbolOpacityAttributes = TypeList<attributes::fade_opacity>;
using SymbolStaticVertexAttributes = gfx::Vertex<TypeList<attributes::pos>>;
using CollisionBoxLayoutAttributes = TypeList<attributes::pos, attributes::anchor_pos, attributes::extrude>;
using CollisionBoxDynamicAttributes = TypeList<attributes::placed, attributes::shift>;
#if MLN_USE_SYMBOL_INSTANCING
using SymbolSortedInstance = gfx::Vertex<TypeList<attributes::sorted_instance>>;
using SymbolLayoutAttributes = gfx::Vertex<TypeList<attributes::pos_scale,
attributes::offset_tltr,
attributes::offset_blbr,
attributes::texture_rect,
attributes::pixeloffset,
attributes::size_sdf>>;
#else
using SymbolLayoutAttributes =
gfx::Vertex<TypeList<attributes::pos_offset, attributes::data<uint16_t, 4>, attributes::pixeloffset>>;
#endif
using SymbolDynamicLayoutAttributes = gfx::Vertex<TypeList<attributes::projected_pos>>;
using SymbolOpacityAttributes = gfx::Vertex<TypeList<attributes::fade_opacity>>;
using CollisionBoxLayoutVertexAttributes =
gfx::Vertex<TypeList<attributes::pos, attributes::anchor_pos, attributes::extrude>>;
using CollisionBoxDynamicVertexAttributes = gfx::Vertex<TypeList<attributes::placed, attributes::shift>>;
const uint16_t MAX_GLYPH_ICON_SIZE = 255;
const uint16_t SIZE_PACK_FACTOR = 128;
@@ -184,7 +220,7 @@ public:
line(std::move(line_)),
tileDistances(std::move(tileDistances_)),
hidden(false),
vertexStartIndex(0),
startIndex(0),
placedIconIndex(std::move(placedIconIndex_)) {}
Point<float> anchorPoint;
std::size_t segment;
@@ -196,7 +232,7 @@ public:
std::vector<float> tileDistances;
std::vector<float> glyphOffsets;
bool hidden;
size_t vertexStartIndex;
size_t startIndex;
// The crossTileID is only filled/used on the foreground for variable text anchors
uint32_t crossTileID = 0u;
// The placedOrientation is only used when symbol layer's property is set to
@@ -226,6 +262,11 @@ public:
bool iconsInText);
~SymbolBucket() override;
static style::IconPaintProperties::PossiblyEvaluated iconPaintProperties(
const style::SymbolPaintProperties::PossiblyEvaluated&);
static style::TextPaintProperties::PossiblyEvaluated textPaintProperties(
const style::SymbolPaintProperties::PossiblyEvaluated&);
void upload(gfx::UploadPass&) override;
bool hasData() const override;
void update(const FeatureStates&, const GeometryTileLayer&, const std::string&, const ImagePositions&) override;
@@ -255,15 +296,50 @@ public:
bool check(source_location) override;
#endif
static SymbolLayoutVertex layoutVertex(Point<float> labelAnchor,
Point<float> o,
float glyphOffsetY,
uint16_t tx,
uint16_t ty,
const Range<float>& sizeData,
bool isSDF,
Point<float> pixelOffset,
Point<float> minFontScale) {
#if MLN_USE_SYMBOL_INSTANCING
static SymbolLayoutAttributes layoutAttributes(const SymbolQuad& symbol,
const Anchor& labelAnchor,
const Range<float>& sizeData) {
const uint16_t aSizeMin = (std::min(MAX_PACKED_SIZE, static_cast<uint16_t>(sizeData.min * SIZE_PACK_FACTOR))
<< 1) +
uint16_t(symbol.isSDF);
const uint16_t aSizeMax = std::min(MAX_PACKED_SIZE, static_cast<uint16_t>(sizeData.max * SIZE_PACK_FACTOR));
return {{static_cast<int16_t>(labelAnchor.point.x),
static_cast<int16_t>(labelAnchor.point.y),
static_cast<int16_t>(symbol.minFontScale.x * 256),
static_cast<int16_t>(symbol.minFontScale.y * 256)},
{static_cast<int16_t>(std::round(symbol.tl.x * 32)),
static_cast<int16_t>(std::round((symbol.tl.y + symbol.glyphOffset.y) * 32)),
static_cast<int16_t>(std::round(symbol.tr.x * 32)),
static_cast<int16_t>(std::round((symbol.tr.y + symbol.glyphOffset.y) * 32))},
{static_cast<int16_t>(std::round(symbol.bl.x * 32)),
static_cast<int16_t>(std::round((symbol.bl.y + symbol.glyphOffset.y) * 32)),
static_cast<int16_t>(std::round(symbol.br.x * 32)),
static_cast<int16_t>(std::round((symbol.br.y + symbol.glyphOffset.y) * 32))},
{symbol.tex.x, symbol.tex.y, symbol.tex.w, symbol.tex.h},
{static_cast<int16_t>(symbol.pixelOffsetTL.x * 16),
static_cast<int16_t>(symbol.pixelOffsetTL.y * 16),
static_cast<int16_t>(symbol.pixelOffsetBR.x * 16),
static_cast<int16_t>(symbol.pixelOffsetBR.y * 16)},
{ aSizeMin,
aSizeMax }};
}
#else
static SymbolLayoutAttributes layoutAttributes(Point<float> labelAnchor,
Point<float> o,
float glyphOffsetY,
uint16_t tx,
uint16_t ty,
const Range<float>& sizeData,
bool isSDF,
Point<float> pixelOffset,
Point<float> minFontScale) {
const uint16_t aSizeMin = (std::min(MAX_PACKED_SIZE, static_cast<uint16_t>(sizeData.min * SIZE_PACK_FACTOR))
<< 1) +
uint16_t(isSDF);
@@ -282,12 +358,13 @@ public:
static_cast<int16_t>(minFontScale.y * 256)}},
};
}
#endif
static gfx::Vertex<SymbolDynamicLayoutAttributes> dynamicLayoutVertex(Point<float> anchorPoint, float labelAngle) {
static SymbolDynamicLayoutAttributes dynamicLayoutAttributes(Point<float> anchorPoint, float labelAngle) {
return {{{anchorPoint.x, anchorPoint.y, labelAngle}}};
}
static gfx::Vertex<SymbolOpacityAttributes> opacityVertex(bool placed, float opacity) {
static SymbolOpacityAttributes opacityAttributes(bool placed, float opacity) {
return {{{static_cast<float>((static_cast<uint8_t>(opacity * 127) << 1) | static_cast<uint8_t>(placed))}}};
}
@@ -319,47 +396,63 @@ public:
std::unique_ptr<SymbolSizeBinder> textSizeBinder;
using VertexVector = gfx::VertexVector<SymbolLayoutVertex>;
using VertexBuffer = gfx::VertexBuffer<SymbolLayoutVertex>;
using DynamicVertexVector = gfx::VertexVector<gfx::Vertex<SymbolDynamicLayoutAttributes>>;
using DynamicVertexBuffer = gfx::VertexBuffer<gfx::Vertex<SymbolDynamicLayoutAttributes>>;
using OpacityVertexVector = gfx::VertexVector<gfx::Vertex<SymbolOpacityAttributes>>;
using OpacityVertexBuffer = gfx::VertexBuffer<gfx::Vertex<SymbolOpacityAttributes>>;
using AttributeVector = gfx::VertexVector<SymbolLayoutAttributes>;
using DynamicAttributeVector = gfx::VertexVector<SymbolDynamicLayoutAttributes>;
using OpacityAttributeVector = gfx::VertexVector<SymbolOpacityAttributes>;
#if MLN_USE_SYMBOL_INSTANCING
using SortedInstanceVector = gfx::VertexVector<SymbolSortedInstance>;
#else
using TriangleIndexVector = gfx::IndexVector<gfx::Triangles>;
#endif
struct Buffer final {
~Buffer() {
sharedVertices->release();
sharedDynamicVertices->release();
sharedOpacityVertices->release();
sharedAttributeData->release();
sharedDynamicAttributeData->release();
sharedOpacityAttributeData->release();
#if MLN_USE_SYMBOL_INSTANCING
sharedSortedInstances->release();
#endif
}
void updateModified() {
if (sharedVertices) {
sharedVertices->updateModified();
if (sharedAttributeData) {
sharedAttributeData->updateModified();
}
if (sharedDynamicVertices) {
sharedDynamicVertices->updateModified();
if (sharedDynamicAttributeData) {
sharedDynamicAttributeData->updateModified();
}
if (sharedOpacityVertices) {
sharedOpacityVertices->updateModified();
if (sharedOpacityAttributeData) {
sharedOpacityAttributeData->updateModified();
}
#if MLN_USE_SYMBOL_INSTANCING
if (sharedSortedInstances) {
sharedSortedInstances->updateModified();
}
#endif
}
std::shared_ptr<VertexVector> sharedVertices = std::make_shared<VertexVector>();
VertexVector& vertices() { return *sharedVertices; }
const VertexVector& vertices() const { return *sharedVertices; }
std::shared_ptr<AttributeVector> sharedAttributeData = std::make_shared<AttributeVector>();
AttributeVector& attributeData() { return *sharedAttributeData; }
const AttributeVector& attributeData() const { return *sharedAttributeData; }
std::shared_ptr<DynamicVertexVector> sharedDynamicVertices = std::make_shared<DynamicVertexVector>();
DynamicVertexVector& dynamicVertices() { return *sharedDynamicVertices; }
const DynamicVertexVector& dynamicVertices() const { return *sharedDynamicVertices; }
std::shared_ptr<DynamicAttributeVector> sharedDynamicAttributeData = std::make_shared<DynamicAttributeVector>();
DynamicAttributeVector& dynamicAttributeData() { return *sharedDynamicAttributeData; }
const DynamicAttributeVector& dynamicAttributeData() const { return *sharedDynamicAttributeData; }
std::shared_ptr<OpacityVertexVector> sharedOpacityVertices = std::make_shared<OpacityVertexVector>();
OpacityVertexVector& opacityVertices() { return *sharedOpacityVertices; }
const OpacityVertexVector& opacityVertices() const { return *sharedOpacityVertices; }
std::shared_ptr<OpacityAttributeVector> sharedOpacityAttributeData = std::make_shared<OpacityAttributeVector>();
OpacityAttributeVector& opacityAttributeData() { return *sharedOpacityAttributeData; }
const OpacityAttributeVector& opacityAttributeData() const { return *sharedOpacityAttributeData; }
using TriangleIndexVector = gfx::IndexVector<gfx::Triangles>;
#if MLN_USE_SYMBOL_INSTANCING
std::shared_ptr<SortedInstanceVector> sharedSortedInstances = std::make_shared<SortedInstanceVector>();
SortedInstanceVector& sortedInstances() { return *sharedSortedInstances; }
const SortedInstanceVector& sortedInstances() const { return *sharedSortedInstances; }
#else
const std::shared_ptr<TriangleIndexVector> sharedTriangles = std::make_shared<TriangleIndexVector>();
TriangleIndexVector& triangles = *sharedTriangles;
#endif
SegmentVector segments;
std::vector<PlacedSymbol> placedSymbols;
@@ -370,8 +463,8 @@ public:
Buffer icon;
Buffer sdfIcon;
using CollisionVertexVector = gfx::VertexVector<gfx::Vertex<CollisionBoxLayoutAttributes>>;
using CollisionDynamicVertexVector = gfx::VertexVector<gfx::Vertex<CollisionBoxDynamicAttributes>>;
using CollisionVertexVector = gfx::VertexVector<CollisionBoxLayoutVertexAttributes>;
using CollisionDynamicVertexVector = gfx::VertexVector<CollisionBoxDynamicVertexAttributes>;
struct CollisionBuffer {
std::shared_ptr<CollisionVertexVector> sharedVertices = std::make_shared<CollisionVertexVector>();
@@ -422,17 +515,15 @@ public:
return *textCollisionCircle;
}
static gfx::Vertex<CollisionBoxLayoutAttributes> collisionLayoutVertex(Point<float> a,
Point<float> anchor,
Point<float> o) {
static CollisionBoxLayoutVertexAttributes collisionLayoutVertex(Point<float> a,
Point<float> anchor,
Point<float> o) {
return {{{static_cast<int16_t>(a.x), static_cast<int16_t>(a.y)}},
{{static_cast<int16_t>(anchor.x), static_cast<int16_t>(anchor.y)}},
{{static_cast<int16_t>(::round(o.x)), static_cast<int16_t>(::round(o.y))}}};
}
static gfx::Vertex<CollisionBoxDynamicAttributes> collisionDynamicVertex(bool placed,
bool notUsed,
Point<float> shift) {
static CollisionBoxDynamicVertexAttributes collisionDynamicVertex(bool placed, bool notUsed, Point<float> shift) {
return {{{static_cast<uint16_t>(placed), static_cast<uint16_t>(notUsed)}}, {{shift.x, shift.y}}};
}

View File

@@ -178,9 +178,6 @@ void RenderFillExtrusionLayer::update(gfx::ShaderRegistry& shaders,
if (!staticDataIndices) {
staticDataIndices = std::make_shared<TriangleIndexVector>(RenderStaticData::fillExtrusionTriangleIndices());
}
if (!staticDataSegments) {
staticDataSegments = std::make_shared<SegmentVector>(RenderStaticData::fillExtrusionSegments());
}
const auto& instancedShaderGroup = hasPattern ? fillExtrusionPatternInstancedGroup : fillExtrusionInstancedGroup;
if (!instancedShaderGroup) {
@@ -472,7 +469,7 @@ void RenderFillExtrusionLayer::update(gfx::ShaderRegistry& shaders,
return;
}
instancedBuilder.setSegments(
gfx::Triangles(), staticDataIndices, staticDataSegments->data(), staticDataSegments->size());
gfx::Triangles(), staticDataIndices, bucket.instanceSegments.data(), bucket.instanceSegments.size());
instancedBuilder.flush(context);

View File

@@ -51,7 +51,6 @@ private:
std::shared_ptr<FillExtrusionVertexVector> staticDataVertices;
std::shared_ptr<TriangleIndexVector> staticDataIndices;
std::shared_ptr<SegmentVector> staticDataSegments;
#endif
};

View File

@@ -8,6 +8,7 @@
#include <mln/renderer/paint_parameters.hpp>
#include <mln/renderer/property_evaluation_parameters.hpp>
#include <mln/renderer/render_source.hpp>
#include <mln/renderer/render_static_data.hpp>
#include <mln/renderer/render_tile.hpp>
#include <mln/renderer/tile_render_data.hpp>
#include <mln/renderer/upload_parameters.hpp>
@@ -192,30 +193,6 @@ bool RenderSymbolLayer::hasCrossfade() const {
return false;
}
// static
style::IconPaintProperties::PossiblyEvaluated RenderSymbolLayer::iconPaintProperties(
const style::SymbolPaintProperties::PossiblyEvaluated& evaluated_) {
return style::IconPaintProperties::PossiblyEvaluated{evaluated_.get<style::IconOpacity>(),
evaluated_.get<style::IconColor>(),
evaluated_.get<style::IconHaloColor>(),
evaluated_.get<style::IconHaloWidth>(),
evaluated_.get<style::IconHaloBlur>(),
evaluated_.get<style::IconTranslate>(),
evaluated_.get<style::IconTranslateAnchor>()};
}
// static
style::TextPaintProperties::PossiblyEvaluated RenderSymbolLayer::textPaintProperties(
const style::SymbolPaintProperties::PossiblyEvaluated& evaluated_) {
return style::TextPaintProperties::PossiblyEvaluated{evaluated_.get<style::TextOpacity>(),
evaluated_.get<style::TextColor>(),
evaluated_.get<style::TextHaloColor>(),
evaluated_.get<style::TextHaloWidth>(),
evaluated_.get<style::TextHaloBlur>(),
evaluated_.get<style::TextTranslate>(),
evaluated_.get<style::TextTranslateAnchor>()};
}
void RenderSymbolLayer::prepare(const LayerPrepareParameters& params) {
renderTiles = params.source->getRenderTilesSortedByYPosition();
@@ -261,6 +238,7 @@ void RenderSymbolLayer::prepare(const LayerPrepareParameters& params) {
namespace {
const SegmentVector emptySegmentVector;
constexpr auto posOffsetAttribName = "a_pos_offset";
[[maybe_unused]] constexpr auto sortedInstanceUniformName = "sorted_instance";
void updateTileAttributes(const SymbolBucket::Buffer& buffer,
const bool isText,
@@ -268,51 +246,106 @@ void updateTileAttributes(const SymbolBucket::Buffer& buffer,
const SymbolPaintProperties::PossiblyEvaluated& evaluated,
gfx::VertexAttributeArray& attribs,
StringIDSetsPair* propertiesAsUniforms) {
if (const auto& attr = attribs.set(idSymbolPosOffsetVertexAttribute)) {
attr->setSharedRawData(buffer.sharedVertices,
offsetof(SymbolLayoutVertex, a1),
/*vertexOffset=*/0,
sizeof(SymbolLayoutVertex),
gfx::AttributeDataType::Short4);
}
if (const auto& attr = attribs.set(idSymbolDataVertexAttribute)) {
attr->setSharedRawData(buffer.sharedVertices,
offsetof(SymbolLayoutVertex, a2),
/*vertexOffset=*/0,
sizeof(SymbolLayoutVertex),
gfx::AttributeDataType::UShort4);
}
if (const auto& attr = attribs.set(idSymbolPixelOffsetVertexAttribute)) {
attr->setSharedRawData(buffer.sharedVertices,
offsetof(SymbolLayoutVertex, a3),
/*vertexOffset=*/0,
sizeof(SymbolLayoutVertex),
gfx::AttributeDataType::Short4);
}
if (const auto& attr = attribs.set(idSymbolProjectedPosVertexAttribute)) {
using Vertex = gfx::Vertex<SymbolDynamicLayoutAttributes>;
attr->setSharedRawData(buffer.sharedDynamicVertices,
offsetof(Vertex, a1),
/*vertexOffset=*/0,
sizeof(Vertex),
gfx::AttributeDataType::Float3);
}
if (const auto& attr = attribs.set(idSymbolFadeOpacityVertexAttribute)) {
using Vertex = gfx::Vertex<SymbolOpacityAttributes>;
attr->setSharedRawData(buffer.sharedOpacityVertices,
offsetof(Vertex, a1),
/*vertexOffset=*/0,
sizeof(Vertex),
gfx::AttributeDataType::Float);
}
if (isText) {
attribs.readDataDrivenPaintProperties<TextOpacity, TextColor, TextHaloColor, TextHaloWidth, TextHaloBlur>(
paintProps.textBinders, evaluated, propertiesAsUniforms, idSymbolOpacityVertexAttribute);
paintProps.textBinders, evaluated, propertiesAsUniforms, idSymbolOpacityAttribute);
} else {
attribs.readDataDrivenPaintProperties<IconOpacity, IconColor, IconHaloColor, IconHaloWidth, IconHaloBlur>(
paintProps.iconBinders, evaluated, propertiesAsUniforms, idSymbolOpacityVertexAttribute);
paintProps.iconBinders, evaluated, propertiesAsUniforms, idSymbolOpacityAttribute);
}
#if MLN_USE_SYMBOL_INSTANCING
if (!buffer.sortedInstances().empty()) {
if (const auto& attr = attribs.set(idSymbolSortedInstanceAttribute)) {
attr->setSharedRawData(buffer.sharedSortedInstances,
offsetof(SymbolSortedInstance, a1),
/*vertexOffset=*/0,
sizeof(SymbolSortedInstance),
gfx::AttributeDataType::UShort);
}
} else if (propertiesAsUniforms) {
propertiesAsUniforms->first.emplace(sortedInstanceUniformName);
propertiesAsUniforms->second.emplace(idSymbolSortedInstanceAttribute);
}
if (const auto& attr = attribs.set(idSymbolPosScaleAttribute)) {
attr->setSharedRawData(buffer.sharedAttributeData,
offsetof(SymbolLayoutAttributes, a1),
/*vertexOffset=*/0,
sizeof(SymbolLayoutAttributes),
gfx::AttributeDataType::Short4);
}
if (const auto& attr = attribs.set(idSymbolOffsetTlTrAttribute)) {
attr->setSharedRawData(buffer.sharedAttributeData,
offsetof(SymbolLayoutAttributes, a2),
/*vertexOffset=*/0,
sizeof(SymbolLayoutAttributes),
gfx::AttributeDataType::Short4);
}
if (const auto& attr = attribs.set(idSymbolOffsetBlBrAttribute)) {
attr->setSharedRawData(buffer.sharedAttributeData,
offsetof(SymbolLayoutAttributes, a3),
/*vertexOffset=*/0,
sizeof(SymbolLayoutAttributes),
gfx::AttributeDataType::Short4);
}
if (const auto& attr = attribs.set(idSymbolTextureRectAttribute)) {
attr->setSharedRawData(buffer.sharedAttributeData,
offsetof(SymbolLayoutAttributes, a4),
/*vertexOffset=*/0,
sizeof(SymbolLayoutAttributes),
gfx::AttributeDataType::UShort4);
}
if (const auto& attr = attribs.set(idSymbolPixelOffsetAttribute)) {
attr->setSharedRawData(buffer.sharedAttributeData,
offsetof(SymbolLayoutAttributes, a5),
/*vertexOffset=*/0,
sizeof(SymbolLayoutAttributes),
gfx::AttributeDataType::Short4);
}
if (const auto& attr = attribs.set(idSymbolSizeSdfAttribute)) {
attr->setSharedRawData(buffer.sharedAttributeData,
offsetof(SymbolLayoutAttributes, a6),
/*vertexOffset=*/0,
sizeof(SymbolLayoutAttributes),
gfx::AttributeDataType::UShort2);
}
#else
if (const auto& attr = attribs.set(idSymbolPosOffsetAttribute)) {
attr->setSharedRawData(buffer.sharedAttributeData,
offsetof(SymbolLayoutAttributes, a1),
/*vertexOffset=*/0,
sizeof(SymbolLayoutAttributes),
gfx::AttributeDataType::Short4);
}
if (const auto& attr = attribs.set(idSymbolDataAttribute)) {
attr->setSharedRawData(buffer.sharedAttributeData,
offsetof(SymbolLayoutAttributes, a2),
/*vertexOffset=*/0,
sizeof(SymbolLayoutAttributes),
gfx::AttributeDataType::UShort4);
}
if (const auto& attr = attribs.set(idSymbolPixelOffsetAttribute)) {
attr->setSharedRawData(buffer.sharedAttributeData,
offsetof(SymbolLayoutAttributes, a3),
/*vertexOffset=*/0,
sizeof(SymbolLayoutAttributes),
gfx::AttributeDataType::Short4);
}
#endif
if (const auto& attr = attribs.set(idSymbolProjectedPosAttribute)) {
attr->setSharedRawData(buffer.sharedDynamicAttributeData,
offsetof(SymbolDynamicLayoutAttributes, a1),
/*vertexOffset=*/0,
sizeof(SymbolDynamicLayoutAttributes),
gfx::AttributeDataType::Float3);
}
if (const auto& attr = attribs.set(idSymbolFadeOpacityAttribute)) {
attr->setSharedRawData(buffer.sharedOpacityAttributeData,
offsetof(SymbolOpacityAttributes, a1),
/*vertexOffset=*/0,
sizeof(SymbolOpacityAttributes),
gfx::AttributeDataType::Float);
}
}
@@ -332,59 +365,62 @@ void updateTileDrawable(gfx::Drawable& drawable,
drawData.bucketVariablePlacement = bucket.hasVariablePlacement;
const auto& buffer = isText ? bucket.text : (sdfIcons ? bucket.sdfIcon : bucket.icon);
const auto vertexCount = buffer.vertices().elements();
#if MLN_USE_SYMBOL_INSTANCING
if (auto& instanceAttribs = drawable.getInstanceAttributes()) {
updateTileAttributes(buffer, isText, paintProps, evaluated, *instanceAttribs, nullptr);
}
#else
const auto vertexCount = buffer.attributeData().elements();
drawable.setVertices({}, vertexCount, gfx::AttributeDataType::Short4);
// TODO: detect whether anything has actually changed
// See `Placement::updateBucketDynamicVertices`
// See `Placement::updateBucketDynamicAttributeData`
if (auto& attribs = drawable.getVertexAttributes()) {
updateTileAttributes(buffer, isText, paintProps, evaluated, *attribs, nullptr);
}
#endif
}
gfx::VertexAttributeArrayPtr getCollisionVertexAttributes(gfx::Context& context,
const SymbolBucket::CollisionBuffer& buffer) {
auto vertexAttrs = context.createVertexAttributeArray();
using LayoutVertex = gfx::Vertex<CollisionBoxLayoutAttributes>;
if (const auto& attr = vertexAttrs->set(idCollisionPosVertexAttribute)) {
attr->setSharedRawData(buffer.sharedVertices,
offsetof(LayoutVertex, a1),
offsetof(CollisionBoxLayoutVertexAttributes, a1),
/*vertexOffset=*/0,
sizeof(LayoutVertex),
sizeof(CollisionBoxLayoutVertexAttributes),
gfx::AttributeDataType::Short2);
}
if (const auto& attr = vertexAttrs->set(idCollisionAnchorPosVertexAttribute)) {
attr->setSharedRawData(buffer.sharedVertices,
offsetof(LayoutVertex, a2),
offsetof(CollisionBoxLayoutVertexAttributes, a2),
/*vertexOffset=*/0,
sizeof(LayoutVertex),
sizeof(CollisionBoxLayoutVertexAttributes),
gfx::AttributeDataType::Short2);
}
if (const auto& attr = vertexAttrs->set(idCollisionExtrudeVertexAttribute)) {
attr->setSharedRawData(buffer.sharedVertices,
offsetof(LayoutVertex, a3),
offsetof(CollisionBoxLayoutVertexAttributes, a3),
/*vertexOffset=*/0,
sizeof(LayoutVertex),
sizeof(CollisionBoxLayoutVertexAttributes),
gfx::AttributeDataType::Short2);
}
using DynamicVertex = gfx::Vertex<CollisionBoxDynamicAttributes>;
if (const auto& attr = vertexAttrs->set(idCollisionPlacedVertexAttribute)) {
attr->setSharedRawData(buffer.sharedDynamicVertices,
offsetof(DynamicVertex, a1),
offsetof(CollisionBoxDynamicVertexAttributes, a1),
/*vertexOffset=*/0,
sizeof(DynamicVertex),
sizeof(CollisionBoxDynamicVertexAttributes),
gfx::AttributeDataType::UShort2);
}
if (const auto& attr = vertexAttrs->set(idCollisionShiftVertexAttribute)) {
attr->setSharedRawData(buffer.sharedDynamicVertices,
offsetof(DynamicVertex, a2),
offsetof(CollisionBoxDynamicVertexAttributes, a2),
/*vertexOffset=*/0,
sizeof(DynamicVertex),
sizeof(CollisionBoxDynamicVertexAttributes),
gfx::AttributeDataType::Float2);
}
@@ -492,6 +528,15 @@ void RenderSymbolLayer::update(gfx::ShaderRegistry& shaders,
collisionCircleGroup = shaders.getShaderGroup(std::string(CollisionCircleShaderName));
}
#if MLN_USE_SYMBOL_INSTANCING
if (!staticDataVertices) {
staticDataVertices = std::make_shared<SymbolVertexVector>(RenderStaticData::symbolVertices());
}
if (!staticDataIndices) {
staticDataIndices = std::make_shared<TriangleIndexVector>(RenderStaticData::symbolTriangleIndices());
}
#endif
// remove drawables that are dropped out of scope
auto* tileLayerGroup = static_cast<TileLayerGroup*>(layerGroup.get());
stats.drawablesRemoved += tileLayerGroup->removeDrawablesIf([&](gfx::Drawable& drawable) {
@@ -648,7 +693,11 @@ void RenderSymbolLayer::update(gfx::ShaderRegistry& shaders,
if (sortFeaturesByKey) {
// Features need to be rendered in a specific order, so we add each segment individually
for (const auto& segment : buffer.segments) {
assert(segment.vertexOffset + segment.vertexLength <= buffer.vertices().elements());
#if MLN_USE_SYMBOL_INSTANCING
assert(segment.baseInstance + segment.instanceCount <= buffer.attributeData().elements());
#else
assert(segment.vertexOffset + segment.vertexLength <= buffer.attributeData().elements());
#endif
renderableSegments.emplace(SegmentGroup{
.renderable = {segment, tile, renderData, bucketPaintProperties, segment.sortKey, type},
.segments = emptySegmentVector});
@@ -705,9 +754,15 @@ void RenderSymbolLayer::update(gfx::ShaderRegistry& shaders,
auto& bucket = static_cast<SymbolBucket&>(*renderable.renderData.bucket);
const auto& buffer = isText ? bucket.text : (sdfIcons ? bucket.sdfIcon : bucket.icon);
#if MLN_USE_SYMBOL_INSTANCING
if (!buffer.attributeData().elements()) {
continue;
}
#else
if (!buffer.sharedTriangles->elements()) {
continue;
}
#endif
const auto& evaluated = getEvaluated<SymbolLayerProperties>(renderable.renderData.layerProperties);
auto& bucketPaintProperties = bucket.paintProperties.at(getID());
@@ -724,13 +779,25 @@ void RenderSymbolLayer::update(gfx::ShaderRegistry& shaders,
auto& tileInfo = tileCache[tile.id];
const auto vertexCount = buffer.vertices().elements();
propertiesAsUniforms.first.clear();
propertiesAsUniforms.second.clear();
auto attribs = context.createVertexAttributeArray();
updateTileAttributes(buffer, isText, bucketPaintProperties, evaluated, *attribs, &propertiesAsUniforms);
#if MLN_USE_SYMBOL_INSTANCING
auto vertexAttribs = context.createVertexAttributeArray();
if (const auto& attr = vertexAttribs->set(idSymbolPosAttribute)) {
attr->setSharedRawData(staticDataVertices,
offsetof(SymbolStaticVertexAttributes, a1),
/*vertexOffset=*/0,
sizeof(SymbolStaticVertexAttributes),
gfx::AttributeDataType::Short2);
}
auto instanceAttribs = context.createVertexAttributeArray();
updateTileAttributes(buffer, isText, bucketPaintProperties, evaluated, *instanceAttribs, &propertiesAsUniforms);
#else
auto vertexAttribs = context.createVertexAttributeArray();
updateTileAttributes(buffer, isText, bucketPaintProperties, evaluated, *vertexAttribs, &propertiesAsUniforms);
#endif
const auto textHalo = evaluated.get<style::TextHaloColor>().constantOr(Color::black()).a > 0.0f &&
evaluated.get<style::TextHaloWidth>().constantOr(1);
@@ -796,14 +863,24 @@ void RenderSymbolLayer::update(gfx::ShaderRegistry& shaders,
builder->clearTweakers();
builder->addTweaker(isText ? tileInfo.textTweaker : tileInfo.iconTweaker);
builder->setRawVertices({}, vertexCount, gfx::AttributeDataType::Short4);
builder->setDrawableName(layerPrefix + std::string(suffix));
builder->setVertexAttributes(attribs);
builder->setVertexAttributes(vertexAttribs);
#if MLN_USE_SYMBOL_INSTANCING
builder->setInstanceAttributes(instanceAttribs);
builder->setRawVertices({}, staticDataVertices->elements(), gfx::AttributeDataType::Short2);
auto& triangleIndices = staticDataIndices;
#else
builder->setRawVertices({}, buffer.attributeData().elements(), gfx::AttributeDataType::Short4);
auto& triangleIndices = buffer.sharedTriangles;
#endif
if (segments.empty()) {
builder->setSegments(gfx::Triangles(), buffer.sharedTriangles, &renderable.segment.get(), 1);
builder->setSegments(gfx::Triangles(), triangleIndices, &renderable.segment.get(), 1);
} else {
builder->setSegments(gfx::Triangles(), buffer.sharedTriangles, segments.data(), segments.size());
builder->setSegments(gfx::Triangles(), triangleIndices, segments.data(), segments.size());
}
builder->flush(context);

View File

@@ -2,6 +2,7 @@
#include <mln/text/glyph.hpp>
#include <mln/renderer/render_layer.hpp>
#include <mln/renderer/buckets/symbol_bucket.hpp>
#include <mln/style/image_impl.hpp>
#include <mln/style/layers/symbol_layer_impl.hpp>
#include <mln/style/layers/symbol_layer_properties.hpp>
@@ -12,25 +13,6 @@ namespace mln {
namespace style {
// {icon,text}-specific paint-property packs for use in the symbol Programs.
// Since each program deals either with icons or text, using a smaller property set
// lets us avoid unnecessarily binding attributes for properties the program wouldn't use.
class IconPaintProperties : public Properties<IconOpacity,
IconColor,
IconHaloColor,
IconHaloWidth,
IconHaloBlur,
IconTranslate,
IconTranslateAnchor> {};
class TextPaintProperties : public Properties<TextOpacity,
TextColor,
TextHaloColor,
TextHaloWidth,
TextHaloBlur,
TextTranslate,
TextTranslateAnchor> {};
// Repackaging evaluated values from SymbolLayoutProperties +
// SymbolPaintProperties for genericity over icons vs. text.
class SymbolPropertyValues {
@@ -64,11 +46,6 @@ public:
explicit RenderSymbolLayer(Immutable<style::SymbolLayer::Impl>);
~RenderSymbolLayer() override;
static style::IconPaintProperties::PossiblyEvaluated iconPaintProperties(
const style::SymbolPaintProperties::PossiblyEvaluated &);
static style::TextPaintProperties::PossiblyEvaluated textPaintProperties(
const style::SymbolPaintProperties::PossiblyEvaluated &);
/// Generate any changes needed by the layer
void update(gfx::ShaderRegistry &,
gfx::Context &,
@@ -126,6 +103,14 @@ private:
std::shared_ptr<TileLayerGroup> collisionTileLayerGroup;
LayerTweakerPtr collisionLayerTweaker;
#if MLN_USE_SYMBOL_INSTANCING
using SymbolVertexVector = gfx::VertexVector<SymbolStaticVertexAttributes>;
using TriangleIndexVector = gfx::IndexVector<gfx::Triangles>;
std::shared_ptr<SymbolVertexVector> staticDataVertices;
std::shared_ptr<TriangleIndexVector> staticDataIndices;
#endif
};
} // namespace mln

View File

@@ -10,6 +10,7 @@
#include <mln/renderer/layer_group.hpp>
#include <mln/renderer/paint_parameters.hpp>
#include <mln/renderer/paint_property_binder.hpp>
#include <mln/renderer/layers/render_symbol_layer.hpp>
#include <mln/renderer/render_tree.hpp>
#include <mln/shaders/shader_program_base.hpp>
#include <mln/shaders/symbol_layer_ubo.hpp>

View File

@@ -175,8 +175,9 @@ public:
void setInterleavedBuffer(InterleavedVertexBuffer& buffer) {
interleavedVertexBuffer = &buffer;
if (vertexOffset == 0) {
vertexOffset = interleavedVertexBuffer->extendVertexFormat<VertexFormat>();
auto newVertexOffset = interleavedVertexBuffer->extendVertexFormat<VertexFormat>();
if (vertexOffset == std::numeric_limits<size_t>::max()) {
vertexOffset = newVertexOffset;
}
}
@@ -184,7 +185,7 @@ public:
PaintPropertyStatistics<T> statistics;
InterleavedVertexBuffer* interleavedVertexBuffer = nullptr;
std::size_t vertexOffset = 0;
std::size_t vertexOffset = std::numeric_limits<size_t>::max();
};
namespace detail {

View File

@@ -56,6 +56,15 @@ gfx::VertexVector<FillExtrusionStaticVertex> RenderStaticData::fillExtrusionVert
return vertices;
}
gfx::VertexVector<SymbolStaticVertexAttributes> RenderStaticData::symbolVertices() {
gfx::VertexVector<HeatmapTextureLayoutVertex> vertices;
vertices.emplace_back(FillExtrusionStaticVertex{0, 0});
vertices.emplace_back(FillExtrusionStaticVertex{1, 0});
vertices.emplace_back(FillExtrusionStaticVertex{0, 1});
vertices.emplace_back(FillExtrusionStaticVertex{1, 1});
return vertices;
}
gfx::IndexVector<gfx::Triangles> RenderStaticData::quadTriangleIndices() {
gfx::IndexVector<gfx::Triangles> indices;
indices.emplace_back(0, 1, 2);
@@ -85,6 +94,13 @@ gfx::IndexVector<gfx::Triangles> RenderStaticData::fillExtrusionTriangleIndices(
return indices;
}
gfx::IndexVector<gfx::Triangles> RenderStaticData::symbolTriangleIndices() {
gfx::IndexVector<gfx::Triangles> indices;
indices.emplace_back(0, 1, 2);
indices.emplace_back(1, 2, 3);
return indices;
}
SegmentVector RenderStaticData::tileTriangleSegments() {
SegmentVector segments;
segments.emplace_back(0, 0, 4, 6);
@@ -109,10 +125,12 @@ SegmentVector RenderStaticData::heatmapTextureSegments() {
return segments;
}
SegmentVector RenderStaticData::fillExtrusionSegments() {
SegmentVector segments;
segments.emplace_back(0, 0, 4, 6);
return segments;
SegmentBase RenderStaticData::fillExtrusionSegment() {
return SegmentBase(0, 0, 4, 6, 0, 0);
}
SegmentBase RenderStaticData::symbolSegment(std::size_t baseInstance, float sortKey) {
return SegmentBase(0, 0, 4, 6, baseInstance, 0, sortKey);
}
} // namespace mln

View File

@@ -7,6 +7,7 @@
#include <mln/renderer/buckets/heatmap_bucket.hpp>
#include <mln/renderer/buckets/raster_bucket.hpp>
#include <mln/renderer/buckets/fill_extrusion_bucket.hpp>
#include <mln/renderer/buckets/symbol_bucket.hpp>
#include <string>
#include <optional>
@@ -30,16 +31,19 @@ public:
static gfx::VertexVector<RasterLayoutVertex> rasterVertices();
static gfx::VertexVector<HeatmapTextureLayoutVertex> heatmapTextureVertices();
static gfx::VertexVector<FillExtrusionStaticVertex> fillExtrusionVertices();
static gfx::VertexVector<SymbolStaticVertexAttributes> symbolVertices();
static gfx::IndexVector<gfx::Triangles> quadTriangleIndices();
static gfx::IndexVector<gfx::LineStrip> tileLineStripIndices();
static gfx::IndexVector<gfx::Triangles> fillExtrusionTriangleIndices();
static gfx::IndexVector<gfx::Triangles> symbolTriangleIndices();
static SegmentVector tileTriangleSegments();
static SegmentVector tileBorderSegments();
static SegmentVector rasterSegments();
static SegmentVector heatmapTextureSegments();
static SegmentVector fillExtrusionSegments();
static SegmentBase fillExtrusionSegment();
static SegmentBase symbolSegment(std::size_t baseInstance, float sortKey);
std::optional<gfx::Renderbuffer<gfx::RenderbufferPixelType::Depth>> depthRenderbuffer;
bool has3D = false;

View File

@@ -25,6 +25,15 @@ MBGL_DEFINE_ATTRIBUTE(float, 2, shift);
MBGL_DEFINE_ATTRIBUTE(uint16_t, 2, decimals_ed);
MBGL_DEFINE_ATTRIBUTE(int16_t, 2, normal2d);
#if MLN_USE_SYMBOL_INSTANCING
MBGL_DEFINE_ATTRIBUTE(uint16_t, 1, sorted_instance);
MBGL_DEFINE_ATTRIBUTE(int16_t, 4, pos_scale);
MBGL_DEFINE_ATTRIBUTE(int16_t, 4, offset_tltr);
MBGL_DEFINE_ATTRIBUTE(int16_t, 4, offset_blbr);
MBGL_DEFINE_ATTRIBUTE(uint16_t, 4, texture_rect);
MBGL_DEFINE_ATTRIBUTE(uint16_t, 2, size_sdf);
#endif
template <typename T, std::size_t N>
struct data {
using Type = gfx::AttributeType<T, N>;

View File

@@ -475,12 +475,12 @@ const std::vector<UniformBlockInfo> SymbolIconShaderInfo::uniformBlocks = {
UniformBlockInfo{"SymbolEvaluatedPropsUBO", idSymbolEvaluatedPropsUBO},
};
const std::vector<AttributeInfo> SymbolIconShaderInfo::attributes = {
AttributeInfo{"a_pos_offset", idSymbolPosOffsetVertexAttribute},
AttributeInfo{"a_data", idSymbolDataVertexAttribute},
AttributeInfo{"a_pixeloffset", idSymbolPixelOffsetVertexAttribute},
AttributeInfo{"a_projected_pos", idSymbolProjectedPosVertexAttribute},
AttributeInfo{"a_fade_opacity", idSymbolFadeOpacityVertexAttribute},
AttributeInfo{"a_opacity", idSymbolOpacityVertexAttribute},
AttributeInfo{"a_pos_offset", idSymbolPosOffsetAttribute},
AttributeInfo{"a_data", idSymbolDataAttribute},
AttributeInfo{"a_pixeloffset", idSymbolPixelOffsetAttribute},
AttributeInfo{"a_projected_pos", idSymbolProjectedPosAttribute},
AttributeInfo{"a_fade_opacity", idSymbolFadeOpacityAttribute},
AttributeInfo{"a_opacity", idSymbolOpacityAttribute},
};
const std::vector<TextureInfo> SymbolIconShaderInfo::textures = {
TextureInfo{"u_texture", idSymbolImageTexture},
@@ -496,16 +496,16 @@ const std::vector<UniformBlockInfo> SymbolSDFShaderInfo::uniformBlocks = {
UniformBlockInfo{"SymbolEvaluatedPropsUBO", idSymbolEvaluatedPropsUBO},
};
const std::vector<AttributeInfo> SymbolSDFShaderInfo::attributes = {
AttributeInfo{"a_pos_offset", idSymbolPosOffsetVertexAttribute},
AttributeInfo{"a_data", idSymbolDataVertexAttribute},
AttributeInfo{"a_pixeloffset", idSymbolPixelOffsetVertexAttribute},
AttributeInfo{"a_projected_pos", idSymbolProjectedPosVertexAttribute},
AttributeInfo{"a_fade_opacity", idSymbolFadeOpacityVertexAttribute},
AttributeInfo{"a_fill_color", idSymbolColorVertexAttribute},
AttributeInfo{"a_halo_color", idSymbolHaloColorVertexAttribute},
AttributeInfo{"a_opacity", idSymbolOpacityVertexAttribute},
AttributeInfo{"a_halo_width", idSymbolHaloWidthVertexAttribute},
AttributeInfo{"a_halo_blur", idSymbolHaloBlurVertexAttribute},
AttributeInfo{"a_pos_offset", idSymbolPosOffsetAttribute},
AttributeInfo{"a_data", idSymbolDataAttribute},
AttributeInfo{"a_pixeloffset", idSymbolPixelOffsetAttribute},
AttributeInfo{"a_projected_pos", idSymbolProjectedPosAttribute},
AttributeInfo{"a_fade_opacity", idSymbolFadeOpacityAttribute},
AttributeInfo{"a_fill_color", idSymbolColorAttribute},
AttributeInfo{"a_halo_color", idSymbolHaloColorAttribute},
AttributeInfo{"a_opacity", idSymbolOpacityAttribute},
AttributeInfo{"a_halo_width", idSymbolHaloWidthAttribute},
AttributeInfo{"a_halo_blur", idSymbolHaloBlurAttribute},
};
const std::vector<TextureInfo> SymbolSDFShaderInfo::textures = {
TextureInfo{"u_texture", idSymbolImageTexture},
@@ -521,15 +521,15 @@ const std::vector<UniformBlockInfo> SymbolTextAndIconShaderInfo::uniformBlocks =
UniformBlockInfo{"SymbolEvaluatedPropsUBO", idSymbolEvaluatedPropsUBO},
};
const std::vector<AttributeInfo> SymbolTextAndIconShaderInfo::attributes = {
AttributeInfo{"a_pos_offset", idSymbolPosOffsetVertexAttribute},
AttributeInfo{"a_data", idSymbolDataVertexAttribute},
AttributeInfo{"a_projected_pos", idSymbolProjectedPosVertexAttribute},
AttributeInfo{"a_fade_opacity", idSymbolFadeOpacityVertexAttribute},
AttributeInfo{"a_fill_color", idSymbolColorVertexAttribute},
AttributeInfo{"a_halo_color", idSymbolHaloColorVertexAttribute},
AttributeInfo{"a_opacity", idSymbolOpacityVertexAttribute},
AttributeInfo{"a_halo_width", idSymbolHaloWidthVertexAttribute},
AttributeInfo{"a_halo_blur", idSymbolHaloBlurVertexAttribute},
AttributeInfo{"a_pos_offset", idSymbolPosOffsetAttribute},
AttributeInfo{"a_data", idSymbolDataAttribute},
AttributeInfo{"a_projected_pos", idSymbolProjectedPosAttribute},
AttributeInfo{"a_fade_opacity", idSymbolFadeOpacityAttribute},
AttributeInfo{"a_fill_color", idSymbolColorAttribute},
AttributeInfo{"a_halo_color", idSymbolHaloColorAttribute},
AttributeInfo{"a_opacity", idSymbolOpacityAttribute},
AttributeInfo{"a_halo_width", idSymbolHaloWidthAttribute},
AttributeInfo{"a_halo_blur", idSymbolHaloBlurAttribute},
};
const std::vector<TextureInfo> SymbolTextAndIconShaderInfo::textures = {
TextureInfo{"u_texture", idSymbolImageTexture},

View File

@@ -15,8 +15,8 @@ const std::array<AttributeInfo, 5> FillExtrusionShaderSource::attributes = {
// Data driven
AttributeInfo{2, gfx::AttributeDataType::Float4, fillExtrusionUBOCount + 1, idFillExtrusionColorVertexAttribute},
AttributeInfo{3, gfx::AttributeDataType::Float, fillExtrusionUBOCount + 1, idFillExtrusionBaseVertexAttribute},
AttributeInfo{4, gfx::AttributeDataType::Float, fillExtrusionUBOCount + 1, idFillExtrusionHeightVertexAttribute},
AttributeInfo{3, gfx::AttributeDataType::Float2, fillExtrusionUBOCount + 1, idFillExtrusionBaseVertexAttribute},
AttributeInfo{4, gfx::AttributeDataType::Float2, fillExtrusionUBOCount + 1, idFillExtrusionHeightVertexAttribute},
};
const std::array<TextureInfo, 0> FillExtrusionShaderSource::textures = {};
@@ -35,8 +35,8 @@ const std::array<AttributeInfo, 5> FillExtrusionInstancedShaderSource::instanceA
// Data driven
AttributeInfo{3, gfx::AttributeDataType::Float4, fillExtrusionUBOCount + 2, idFillExtrusionColorVertexAttribute},
AttributeInfo{4, gfx::AttributeDataType::Float, fillExtrusionUBOCount + 2, idFillExtrusionBaseVertexAttribute},
AttributeInfo{5, gfx::AttributeDataType::Float, fillExtrusionUBOCount + 2, idFillExtrusionHeightVertexAttribute},
AttributeInfo{4, gfx::AttributeDataType::Float2, fillExtrusionUBOCount + 2, idFillExtrusionBaseVertexAttribute},
AttributeInfo{5, gfx::AttributeDataType::Float2, fillExtrusionUBOCount + 2, idFillExtrusionHeightVertexAttribute},
};
const std::array<TextureInfo, 0> FillExtrusionInstancedShaderSource::textures = {};
@@ -50,8 +50,8 @@ const std::array<AttributeInfo, 6> FillExtrusionPatternShaderSource::attributes
AttributeInfo{1, gfx::AttributeDataType::UShort2, fillExtrusionUBOCount + 0, idFillExtrusionDecimalsEdAttribute},
// Data driven
AttributeInfo{2, gfx::AttributeDataType::Float, fillExtrusionUBOCount + 1, idFillExtrusionBaseVertexAttribute},
AttributeInfo{3, gfx::AttributeDataType::Float, fillExtrusionUBOCount + 1, idFillExtrusionHeightVertexAttribute},
AttributeInfo{2, gfx::AttributeDataType::Float2, fillExtrusionUBOCount + 1, idFillExtrusionBaseVertexAttribute},
AttributeInfo{3, gfx::AttributeDataType::Float2, fillExtrusionUBOCount + 1, idFillExtrusionHeightVertexAttribute},
AttributeInfo{
4, gfx::AttributeDataType::UShort4, fillExtrusionUBOCount + 1, idFillExtrusionPatternFromVertexAttribute},
AttributeInfo{
@@ -75,8 +75,8 @@ const std::array<AttributeInfo, 6> FillExtrusionPatternInstancedShaderSource::in
AttributeInfo{2, gfx::AttributeDataType::UShort2, fillExtrusionUBOCount + 1, idFillExtrusionDecimalsEdAttribute},
// Data driven
AttributeInfo{3, gfx::AttributeDataType::Float, fillExtrusionUBOCount + 2, idFillExtrusionBaseVertexAttribute},
AttributeInfo{4, gfx::AttributeDataType::Float, fillExtrusionUBOCount + 2, idFillExtrusionHeightVertexAttribute},
AttributeInfo{3, gfx::AttributeDataType::Float2, fillExtrusionUBOCount + 2, idFillExtrusionBaseVertexAttribute},
AttributeInfo{4, gfx::AttributeDataType::Float2, fillExtrusionUBOCount + 2, idFillExtrusionHeightVertexAttribute},
AttributeInfo{
5, gfx::AttributeDataType::UShort4, fillExtrusionUBOCount + 2, idFillExtrusionPatternFromVertexAttribute},
AttributeInfo{

View File

@@ -9,19 +9,28 @@ namespace shaders {
using SymbolIconShaderSource = ShaderSource<BuiltIn::SymbolIconShader, gfx::Backend::Type::Metal>;
const std::array<AttributeInfo, 6> SymbolIconShaderSource::attributes = {
AttributeInfo{0, gfx::AttributeDataType::Short4, symbolUBOCount + 0, idSymbolPosOffsetVertexAttribute},
AttributeInfo{1, gfx::AttributeDataType::UShort4, symbolUBOCount + 0, idSymbolDataVertexAttribute},
AttributeInfo{2, gfx::AttributeDataType::Short4, symbolUBOCount + 0, idSymbolPixelOffsetVertexAttribute},
const std::array<AttributeInfo, 1> SymbolIconShaderSource::attributes = {
AttributeInfo{0, gfx::AttributeDataType::Short2, symbolUBOCount + 0, idSymbolPosAttribute},
};
const std::array<AttributeInfo, 10> SymbolIconShaderSource::instanceAttributes = {
AttributeInfo{1, gfx::AttributeDataType::UShort, symbolUBOCount + 1, idSymbolSortedInstanceAttribute},
AttributeInfo{2, gfx::AttributeDataType::Short4, symbolUBOCount + 2, idSymbolPosScaleAttribute},
AttributeInfo{3, gfx::AttributeDataType::Short4, symbolUBOCount + 2, idSymbolOffsetTlTrAttribute},
AttributeInfo{4, gfx::AttributeDataType::Short4, symbolUBOCount + 2, idSymbolOffsetBlBrAttribute},
AttributeInfo{5, gfx::AttributeDataType::UShort4, symbolUBOCount + 2, idSymbolTextureRectAttribute},
AttributeInfo{6, gfx::AttributeDataType::Short4, symbolUBOCount + 2, idSymbolPixelOffsetAttribute},
AttributeInfo{7, gfx::AttributeDataType::UShort4, symbolUBOCount + 2, idSymbolSizeSdfAttribute},
// Dynamic
AttributeInfo{3, gfx::AttributeDataType::Float3, symbolUBOCount + 1, idSymbolProjectedPosVertexAttribute},
AttributeInfo{8, gfx::AttributeDataType::Float3, symbolUBOCount + 3, idSymbolProjectedPosAttribute},
// Opacity
AttributeInfo{4, gfx::AttributeDataType::Float, symbolUBOCount + 2, idSymbolFadeOpacityVertexAttribute},
AttributeInfo{9, gfx::AttributeDataType::Float, symbolUBOCount + 4, idSymbolFadeOpacityAttribute},
// Data driven
AttributeInfo{5, gfx::AttributeDataType::Float, symbolUBOCount + 3, idSymbolOpacityVertexAttribute},
AttributeInfo{10, gfx::AttributeDataType::Float2, symbolUBOCount + 5, idSymbolOpacityAttribute},
};
const std::array<TextureInfo, 1> SymbolIconShaderSource::textures = {
TextureInfo{0, idSymbolImageTexture},
@@ -32,23 +41,32 @@ const std::array<TextureInfo, 1> SymbolIconShaderSource::textures = {
using SymbolSDFShaderSource = ShaderSource<BuiltIn::SymbolSDFShader, gfx::Backend::Type::Metal>;
const std::array<AttributeInfo, 10> SymbolSDFShaderSource::attributes = {
AttributeInfo{0, gfx::AttributeDataType::Short4, symbolUBOCount + 0, idSymbolPosOffsetVertexAttribute},
AttributeInfo{1, gfx::AttributeDataType::UShort4, symbolUBOCount + 0, idSymbolDataVertexAttribute},
AttributeInfo{2, gfx::AttributeDataType::Short4, symbolUBOCount + 0, idSymbolPixelOffsetVertexAttribute},
const std::array<AttributeInfo, 1> SymbolSDFShaderSource::attributes = {
AttributeInfo{0, gfx::AttributeDataType::Short2, symbolUBOCount + 0, idSymbolPosAttribute},
};
const std::array<AttributeInfo, 14> SymbolSDFShaderSource::instanceAttributes = {
AttributeInfo{1, gfx::AttributeDataType::UShort, symbolUBOCount + 1, idSymbolSortedInstanceAttribute},
AttributeInfo{2, gfx::AttributeDataType::Short4, symbolUBOCount + 2, idSymbolPosScaleAttribute},
AttributeInfo{3, gfx::AttributeDataType::Short4, symbolUBOCount + 2, idSymbolOffsetTlTrAttribute},
AttributeInfo{4, gfx::AttributeDataType::Short4, symbolUBOCount + 2, idSymbolOffsetBlBrAttribute},
AttributeInfo{5, gfx::AttributeDataType::UShort4, symbolUBOCount + 2, idSymbolTextureRectAttribute},
AttributeInfo{6, gfx::AttributeDataType::Short4, symbolUBOCount + 2, idSymbolPixelOffsetAttribute},
AttributeInfo{7, gfx::AttributeDataType::UShort2, symbolUBOCount + 2, idSymbolSizeSdfAttribute},
// Dynamic
AttributeInfo{3, gfx::AttributeDataType::Float3, symbolUBOCount + 1, idSymbolProjectedPosVertexAttribute},
AttributeInfo{8, gfx::AttributeDataType::Float3, symbolUBOCount + 3, idSymbolProjectedPosAttribute},
// Opacity
AttributeInfo{4, gfx::AttributeDataType::Float, symbolUBOCount + 2, idSymbolFadeOpacityVertexAttribute},
AttributeInfo{9, gfx::AttributeDataType::Float, symbolUBOCount + 4, idSymbolFadeOpacityAttribute},
// Data driven
AttributeInfo{5, gfx::AttributeDataType::Float4, symbolUBOCount + 3, idSymbolColorVertexAttribute},
AttributeInfo{6, gfx::AttributeDataType::Float4, symbolUBOCount + 3, idSymbolHaloColorVertexAttribute},
AttributeInfo{7, gfx::AttributeDataType::Float, symbolUBOCount + 3, idSymbolOpacityVertexAttribute},
AttributeInfo{8, gfx::AttributeDataType::Float, symbolUBOCount + 3, idSymbolHaloWidthVertexAttribute},
AttributeInfo{9, gfx::AttributeDataType::Float, symbolUBOCount + 3, idSymbolHaloBlurVertexAttribute},
AttributeInfo{10, gfx::AttributeDataType::Float2, symbolUBOCount + 5, idSymbolOpacityAttribute},
AttributeInfo{11, gfx::AttributeDataType::Float4, symbolUBOCount + 5, idSymbolColorAttribute},
AttributeInfo{12, gfx::AttributeDataType::Float4, symbolUBOCount + 5, idSymbolHaloColorAttribute},
AttributeInfo{13, gfx::AttributeDataType::Float2, symbolUBOCount + 5, idSymbolHaloWidthAttribute},
AttributeInfo{14, gfx::AttributeDataType::Float2, symbolUBOCount + 5, idSymbolHaloBlurAttribute},
};
const std::array<TextureInfo, 1> SymbolSDFShaderSource::textures = {
TextureInfo{0, idSymbolImageTexture},
@@ -59,22 +77,32 @@ const std::array<TextureInfo, 1> SymbolSDFShaderSource::textures = {
using SymbolTextAndIconShaderSource = ShaderSource<BuiltIn::SymbolTextAndIconShader, gfx::Backend::Type::Metal>;
const std::array<AttributeInfo, 9> SymbolTextAndIconShaderSource::attributes = {
AttributeInfo{0, gfx::AttributeDataType::Short4, symbolUBOCount + 0, idSymbolPosOffsetVertexAttribute},
AttributeInfo{1, gfx::AttributeDataType::UShort4, symbolUBOCount + 0, idSymbolDataVertexAttribute},
const std::array<AttributeInfo, 1> SymbolTextAndIconShaderSource::attributes = {
AttributeInfo{0, gfx::AttributeDataType::Short2, symbolUBOCount + 0, idSymbolPosAttribute},
};
const std::array<AttributeInfo, 14> SymbolTextAndIconShaderSource::instanceAttributes = {
AttributeInfo{1, gfx::AttributeDataType::UShort, symbolUBOCount + 1, idSymbolSortedInstanceAttribute},
AttributeInfo{2, gfx::AttributeDataType::Short4, symbolUBOCount + 2, idSymbolPosScaleAttribute},
AttributeInfo{3, gfx::AttributeDataType::Short4, symbolUBOCount + 2, idSymbolOffsetTlTrAttribute},
AttributeInfo{4, gfx::AttributeDataType::Short4, symbolUBOCount + 2, idSymbolOffsetBlBrAttribute},
AttributeInfo{5, gfx::AttributeDataType::UShort4, symbolUBOCount + 2, idSymbolTextureRectAttribute},
AttributeInfo{6, gfx::AttributeDataType::Short4, symbolUBOCount + 2, idSymbolPixelOffsetAttribute},
AttributeInfo{7, gfx::AttributeDataType::UShort2, symbolUBOCount + 2, idSymbolSizeSdfAttribute},
// Dynamic
AttributeInfo{2, gfx::AttributeDataType::Float3, symbolUBOCount + 1, idSymbolProjectedPosVertexAttribute},
AttributeInfo{8, gfx::AttributeDataType::Float3, symbolUBOCount + 3, idSymbolProjectedPosAttribute},
// Opacity
AttributeInfo{3, gfx::AttributeDataType::Float, symbolUBOCount + 2, idSymbolFadeOpacityVertexAttribute},
AttributeInfo{9, gfx::AttributeDataType::Float, symbolUBOCount + 4, idSymbolFadeOpacityAttribute},
// Data driven
AttributeInfo{4, gfx::AttributeDataType::Float4, symbolUBOCount + 3, idSymbolColorVertexAttribute},
AttributeInfo{5, gfx::AttributeDataType::Float4, symbolUBOCount + 3, idSymbolHaloColorVertexAttribute},
AttributeInfo{6, gfx::AttributeDataType::Float, symbolUBOCount + 3, idSymbolOpacityVertexAttribute},
AttributeInfo{7, gfx::AttributeDataType::Float, symbolUBOCount + 3, idSymbolHaloWidthVertexAttribute},
AttributeInfo{8, gfx::AttributeDataType::Float, symbolUBOCount + 3, idSymbolHaloBlurVertexAttribute},
AttributeInfo{10, gfx::AttributeDataType::Float2, symbolUBOCount + 5, idSymbolOpacityAttribute},
AttributeInfo{11, gfx::AttributeDataType::Float4, symbolUBOCount + 5, idSymbolColorAttribute},
AttributeInfo{12, gfx::AttributeDataType::Float4, symbolUBOCount + 5, idSymbolHaloColorAttribute},
AttributeInfo{13, gfx::AttributeDataType::Float2, symbolUBOCount + 5, idSymbolHaloWidthAttribute},
AttributeInfo{14, gfx::AttributeDataType::Float2, symbolUBOCount + 5, idSymbolHaloBlurAttribute},
};
const std::array<TextureInfo, 2> SymbolTextAndIconShaderSource::textures = {
TextureInfo{0, idSymbolImageTexture},

View File

@@ -15,11 +15,15 @@ public:
std::size_t indexOffset_,
std::size_t vertexLength_ = 0,
std::size_t indexLength_ = 0,
std::size_t baseInstance_ = 0,
std::size_t instanceCount_ = 1,
float sortKey_ = 0.0f)
: vertexOffset(vertexOffset_),
indexOffset(indexOffset_),
vertexLength(vertexLength_),
indexLength(indexLength_),
baseInstance(baseInstance_),
instanceCount(instanceCount_),
sortKey(sortKey_) {}
// FIXME: clang-tidy-8 still complains here and clang-cl
@@ -35,6 +39,9 @@ public:
std::size_t vertexLength;
std::size_t indexLength;
const std::size_t baseInstance;
std::size_t instanceCount;
// One DrawScope per layer ID. This minimizes rebinding in cases where
// several layers share buckets but have different sets of active
// attributes. This can happen:

View File

@@ -5,7 +5,7 @@
namespace mln {
namespace shaders {
// idFillExtrusionInstanced is shared between instanced and non-instanced drawables
// idFillExtrusionInstancedDrawableUBO is shared between instanced and non-instanced drawables
//
// Fill extrusion
@@ -13,11 +13,13 @@ namespace shaders {
using FillExtrusionShaderSource = ShaderSource<BuiltIn::FillExtrusionShader, gfx::Backend::Type::Vulkan>;
const std::array<AttributeInfo, 5> FillExtrusionShaderSource::attributes = {
AttributeInfo{0, gfx::AttributeDataType::Short2, idFillExtrusionPosVertexAttribute, idFillExtrusionInstanced},
AttributeInfo{1, gfx::AttributeDataType::UShort2, idFillExtrusionDecimalsEdAttribute, idFillExtrusionInstanced},
AttributeInfo{
0, gfx::AttributeDataType::Short2, idFillExtrusionPosVertexAttribute, idFillExtrusionInstancedDrawableUBO},
AttributeInfo{
1, gfx::AttributeDataType::UShort2, idFillExtrusionDecimalsEdAttribute, idFillExtrusionInstancedDrawableUBO},
AttributeInfo{2, gfx::AttributeDataType::Float4, idFillExtrusionColorVertexAttribute},
AttributeInfo{3, gfx::AttributeDataType::Float, idFillExtrusionBaseVertexAttribute},
AttributeInfo{4, gfx::AttributeDataType::Float, idFillExtrusionHeightVertexAttribute},
AttributeInfo{3, gfx::AttributeDataType::Float2, idFillExtrusionBaseVertexAttribute},
AttributeInfo{4, gfx::AttributeDataType::Float2, idFillExtrusionHeightVertexAttribute},
};
const std::array<TextureInfo, 0> FillExtrusionShaderSource::textures = {};
@@ -31,13 +33,15 @@ const std::array<AttributeInfo, 1> FillExtrusionInstancedShaderSource::attribute
AttributeInfo{0, gfx::AttributeDataType::Short2, idFillExtrusionPosVertexAttribute},
};
const std::array<AttributeInfo, 5> FillExtrusionInstancedShaderSource::instanceAttributes = {
AttributeInfo{1, gfx::AttributeDataType::Short2, idFillExtrusionOutlinePosAttribute, idFillExtrusionInstanced},
AttributeInfo{2, gfx::AttributeDataType::UShort2, idFillExtrusionDecimalsEdAttribute, idFillExtrusionInstanced},
AttributeInfo{
1, gfx::AttributeDataType::Short2, idFillExtrusionOutlinePosAttribute, idFillExtrusionInstancedDrawableUBO},
AttributeInfo{
2, gfx::AttributeDataType::UShort2, idFillExtrusionDecimalsEdAttribute, idFillExtrusionInstancedDrawableUBO},
// Data driven
AttributeInfo{3, gfx::AttributeDataType::Float4, idFillExtrusionColorVertexAttribute},
AttributeInfo{4, gfx::AttributeDataType::Float, idFillExtrusionBaseVertexAttribute},
AttributeInfo{5, gfx::AttributeDataType::Float, idFillExtrusionHeightVertexAttribute},
AttributeInfo{4, gfx::AttributeDataType::Float2, idFillExtrusionBaseVertexAttribute},
AttributeInfo{5, gfx::AttributeDataType::Float2, idFillExtrusionHeightVertexAttribute},
};
const std::array<TextureInfo, 0> FillExtrusionInstancedShaderSource::textures = {};
@@ -47,10 +51,12 @@ const std::array<TextureInfo, 0> FillExtrusionInstancedShaderSource::textures =
using FillExtrusionPatternShaderSource = ShaderSource<BuiltIn::FillExtrusionPatternShader, gfx::Backend::Type::Vulkan>;
const std::array<AttributeInfo, 6> FillExtrusionPatternShaderSource::attributes = {
AttributeInfo{0, gfx::AttributeDataType::Short2, idFillExtrusionPosVertexAttribute, idFillExtrusionInstanced},
AttributeInfo{1, gfx::AttributeDataType::UShort2, idFillExtrusionDecimalsEdAttribute, idFillExtrusionInstanced},
AttributeInfo{2, gfx::AttributeDataType::Float, idFillExtrusionBaseVertexAttribute},
AttributeInfo{3, gfx::AttributeDataType::Float, idFillExtrusionHeightVertexAttribute},
AttributeInfo{
0, gfx::AttributeDataType::Short2, idFillExtrusionPosVertexAttribute, idFillExtrusionInstancedDrawableUBO},
AttributeInfo{
1, gfx::AttributeDataType::UShort2, idFillExtrusionDecimalsEdAttribute, idFillExtrusionInstancedDrawableUBO},
AttributeInfo{2, gfx::AttributeDataType::Float2, idFillExtrusionBaseVertexAttribute},
AttributeInfo{3, gfx::AttributeDataType::Float2, idFillExtrusionHeightVertexAttribute},
AttributeInfo{4, gfx::AttributeDataType::UShort4, idFillExtrusionPatternFromVertexAttribute},
AttributeInfo{5, gfx::AttributeDataType::UShort4, idFillExtrusionPatternToVertexAttribute},
};
@@ -68,12 +74,14 @@ const std::array<AttributeInfo, 1> FillExtrusionPatternInstancedShaderSource::at
AttributeInfo{0, gfx::AttributeDataType::Short2, idFillExtrusionPosVertexAttribute},
};
const std::array<AttributeInfo, 6> FillExtrusionPatternInstancedShaderSource::instanceAttributes = {
AttributeInfo{1, gfx::AttributeDataType::Short2, idFillExtrusionOutlinePosAttribute, idFillExtrusionInstanced},
AttributeInfo{2, gfx::AttributeDataType::UShort2, idFillExtrusionDecimalsEdAttribute, idFillExtrusionInstanced},
AttributeInfo{
1, gfx::AttributeDataType::Short2, idFillExtrusionOutlinePosAttribute, idFillExtrusionInstancedDrawableUBO},
AttributeInfo{
2, gfx::AttributeDataType::UShort2, idFillExtrusionDecimalsEdAttribute, idFillExtrusionInstancedDrawableUBO},
// Data driven
AttributeInfo{3, gfx::AttributeDataType::Float, idFillExtrusionBaseVertexAttribute},
AttributeInfo{4, gfx::AttributeDataType::Float, idFillExtrusionHeightVertexAttribute},
AttributeInfo{3, gfx::AttributeDataType::Float2, idFillExtrusionBaseVertexAttribute},
AttributeInfo{4, gfx::AttributeDataType::Float2, idFillExtrusionHeightVertexAttribute},
AttributeInfo{5, gfx::AttributeDataType::UShort4, idFillExtrusionPatternFromVertexAttribute},
AttributeInfo{6, gfx::AttributeDataType::UShort4, idFillExtrusionPatternToVertexAttribute},
};

View File

@@ -10,16 +10,27 @@ namespace shaders {
using SymbolIconShaderSource = ShaderSource<BuiltIn::SymbolIconShader, gfx::Backend::Type::Vulkan>;
const std::array<AttributeInfo, 6> SymbolIconShaderSource::attributes = {
const std::array<AttributeInfo, 1> SymbolIconShaderSource::attributes = {
AttributeInfo{0, gfx::AttributeDataType::Short2, idSymbolPosAttribute},
};
const std::array<AttributeInfo, 10> SymbolIconShaderSource::instanceAttributes = {
// always attributes
AttributeInfo{0, gfx::AttributeDataType::Short4, idSymbolPosOffsetVertexAttribute},
AttributeInfo{1, gfx::AttributeDataType::UShort4, idSymbolDataVertexAttribute},
AttributeInfo{2, gfx::AttributeDataType::Short4, idSymbolPixelOffsetVertexAttribute},
AttributeInfo{3, gfx::AttributeDataType::Float3, idSymbolProjectedPosVertexAttribute},
AttributeInfo{4, gfx::AttributeDataType::Float, idSymbolFadeOpacityVertexAttribute},
AttributeInfo{1, gfx::AttributeDataType::UShort, idSymbolSortedInstanceAttribute},
AttributeInfo{2, gfx::AttributeDataType::Short4, idSymbolPosScaleAttribute, idSymbolInstancedDrawableUBO},
AttributeInfo{3, gfx::AttributeDataType::Short4, idSymbolOffsetTlTrAttribute, idSymbolInstancedDrawableUBO},
AttributeInfo{4, gfx::AttributeDataType::Short4, idSymbolOffsetBlBrAttribute, idSymbolInstancedDrawableUBO},
AttributeInfo{5, gfx::AttributeDataType::UShort4, idSymbolTextureRectAttribute, idSymbolInstancedDrawableUBO},
AttributeInfo{6, gfx::AttributeDataType::Short4, idSymbolPixelOffsetAttribute, idSymbolInstancedDrawableUBO},
AttributeInfo{7, gfx::AttributeDataType::UShort4, idSymbolSizeSdfAttribute, idSymbolInstancedDrawableUBO},
AttributeInfo{
8, gfx::AttributeDataType::Float3, idSymbolProjectedPosAttribute, idSymbolDynamicInstancedDrawableUBO},
AttributeInfo{9, gfx::AttributeDataType::Float, idSymbolFadeOpacityAttribute, idSymbolOpacityInstancedDrawableUBO},
// sometimes uniforms
AttributeInfo{5, gfx::AttributeDataType::Float, idSymbolOpacityVertexAttribute},
AttributeInfo{10, gfx::AttributeDataType::Float2, idSymbolOpacityAttribute, idSymbolDataInstancedDrawableUBO},
};
const std::array<TextureInfo, 1> SymbolIconShaderSource::textures = {
TextureInfo{0, idSymbolImageTexture},
@@ -30,20 +41,32 @@ const std::array<TextureInfo, 1> SymbolIconShaderSource::textures = {
using SymbolSDFShaderSource = ShaderSource<BuiltIn::SymbolSDFShader, gfx::Backend::Type::Vulkan>;
const std::array<AttributeInfo, 10> SymbolSDFShaderSource::attributes = {
const std::array<AttributeInfo, 1> SymbolSDFShaderSource::attributes = {
// always attributes
AttributeInfo{0, gfx::AttributeDataType::Short4, idSymbolPosOffsetVertexAttribute},
AttributeInfo{1, gfx::AttributeDataType::UShort4, idSymbolDataVertexAttribute},
AttributeInfo{2, gfx::AttributeDataType::Short4, idSymbolPixelOffsetVertexAttribute},
AttributeInfo{3, gfx::AttributeDataType::Float3, idSymbolProjectedPosVertexAttribute},
AttributeInfo{4, gfx::AttributeDataType::Float, idSymbolFadeOpacityVertexAttribute},
AttributeInfo{0, gfx::AttributeDataType::Short2, idSymbolPosAttribute},
};
const std::array<AttributeInfo, 14> SymbolSDFShaderSource::instanceAttributes = {
// always attributes
AttributeInfo{1, gfx::AttributeDataType::UShort, idSymbolSortedInstanceAttribute},
AttributeInfo{2, gfx::AttributeDataType::Short4, idSymbolPosScaleAttribute, idSymbolInstancedDrawableUBO},
AttributeInfo{3, gfx::AttributeDataType::Short4, idSymbolOffsetTlTrAttribute, idSymbolInstancedDrawableUBO},
AttributeInfo{4, gfx::AttributeDataType::Short4, idSymbolOffsetBlBrAttribute, idSymbolInstancedDrawableUBO},
AttributeInfo{5, gfx::AttributeDataType::UShort4, idSymbolTextureRectAttribute, idSymbolInstancedDrawableUBO},
AttributeInfo{6, gfx::AttributeDataType::Short4, idSymbolPixelOffsetAttribute, idSymbolInstancedDrawableUBO},
AttributeInfo{7, gfx::AttributeDataType::UShort4, idSymbolSizeSdfAttribute, idSymbolInstancedDrawableUBO},
AttributeInfo{
8, gfx::AttributeDataType::Float3, idSymbolProjectedPosAttribute, idSymbolDynamicInstancedDrawableUBO},
AttributeInfo{9, gfx::AttributeDataType::Float, idSymbolFadeOpacityAttribute, idSymbolOpacityInstancedDrawableUBO},
// sometimes uniforms
AttributeInfo{5, gfx::AttributeDataType::Float4, idSymbolColorVertexAttribute},
AttributeInfo{6, gfx::AttributeDataType::Float4, idSymbolHaloColorVertexAttribute},
AttributeInfo{7, gfx::AttributeDataType::Float, idSymbolOpacityVertexAttribute},
AttributeInfo{8, gfx::AttributeDataType::Float, idSymbolHaloWidthVertexAttribute},
AttributeInfo{9, gfx::AttributeDataType::Float, idSymbolHaloBlurVertexAttribute},
AttributeInfo{10, gfx::AttributeDataType::Float2, idSymbolOpacityAttribute, idSymbolDataInstancedDrawableUBO},
AttributeInfo{11, gfx::AttributeDataType::Float4, idSymbolColorAttribute, idSymbolDataInstancedDrawableUBO},
AttributeInfo{12, gfx::AttributeDataType::Float4, idSymbolHaloColorAttribute, idSymbolDataInstancedDrawableUBO},
AttributeInfo{13, gfx::AttributeDataType::Float2, idSymbolHaloWidthAttribute, idSymbolDataInstancedDrawableUBO},
AttributeInfo{14, gfx::AttributeDataType::Float2, idSymbolHaloBlurAttribute, idSymbolDataInstancedDrawableUBO},
};
const std::array<TextureInfo, 1> SymbolSDFShaderSource::textures = {
TextureInfo{0, idSymbolImageTexture},
@@ -54,19 +77,32 @@ const std::array<TextureInfo, 1> SymbolSDFShaderSource::textures = {
using SymbolTextAndIconShaderSource = ShaderSource<BuiltIn::SymbolTextAndIconShader, gfx::Backend::Type::Vulkan>;
const std::array<AttributeInfo, 9> SymbolTextAndIconShaderSource::attributes = {
const std::array<AttributeInfo, 1> SymbolTextAndIconShaderSource::attributes = {
// always attributes
AttributeInfo{0, gfx::AttributeDataType::Short4, idSymbolPosOffsetVertexAttribute},
AttributeInfo{1, gfx::AttributeDataType::UShort4, idSymbolDataVertexAttribute},
AttributeInfo{2, gfx::AttributeDataType::Float3, idSymbolProjectedPosVertexAttribute},
AttributeInfo{3, gfx::AttributeDataType::Float, idSymbolFadeOpacityVertexAttribute},
AttributeInfo{0, gfx::AttributeDataType::Short2, idSymbolPosAttribute},
};
const std::array<AttributeInfo, 14> SymbolTextAndIconShaderSource::instanceAttributes = {
// always attributes
AttributeInfo{1, gfx::AttributeDataType::UShort, idSymbolSortedInstanceAttribute},
AttributeInfo{2, gfx::AttributeDataType::Short4, idSymbolPosScaleAttribute, idSymbolInstancedDrawableUBO},
AttributeInfo{3, gfx::AttributeDataType::Short4, idSymbolOffsetTlTrAttribute, idSymbolInstancedDrawableUBO},
AttributeInfo{4, gfx::AttributeDataType::Short4, idSymbolOffsetBlBrAttribute, idSymbolInstancedDrawableUBO},
AttributeInfo{5, gfx::AttributeDataType::UShort4, idSymbolTextureRectAttribute, idSymbolInstancedDrawableUBO},
AttributeInfo{6, gfx::AttributeDataType::Short4, idSymbolPixelOffsetAttribute, idSymbolInstancedDrawableUBO},
AttributeInfo{7, gfx::AttributeDataType::UShort4, idSymbolSizeSdfAttribute, idSymbolInstancedDrawableUBO},
AttributeInfo{
8, gfx::AttributeDataType::Float3, idSymbolProjectedPosAttribute, idSymbolDynamicInstancedDrawableUBO},
AttributeInfo{9, gfx::AttributeDataType::Float, idSymbolFadeOpacityAttribute, idSymbolOpacityInstancedDrawableUBO},
// sometimes uniforms
AttributeInfo{4, gfx::AttributeDataType::Float4, idSymbolColorVertexAttribute},
AttributeInfo{5, gfx::AttributeDataType::Float4, idSymbolHaloColorVertexAttribute},
AttributeInfo{6, gfx::AttributeDataType::Float, idSymbolOpacityVertexAttribute},
AttributeInfo{7, gfx::AttributeDataType::Float, idSymbolHaloWidthVertexAttribute},
AttributeInfo{8, gfx::AttributeDataType::Float, idSymbolHaloBlurVertexAttribute},
AttributeInfo{10, gfx::AttributeDataType::Float2, idSymbolOpacityAttribute, idSymbolDataInstancedDrawableUBO},
AttributeInfo{11, gfx::AttributeDataType::Float4, idSymbolColorAttribute, idSymbolDataInstancedDrawableUBO},
AttributeInfo{12, gfx::AttributeDataType::Float4, idSymbolHaloColorAttribute, idSymbolDataInstancedDrawableUBO},
AttributeInfo{13, gfx::AttributeDataType::Float2, idSymbolHaloWidthAttribute, idSymbolDataInstancedDrawableUBO},
AttributeInfo{14, gfx::AttributeDataType::Float2, idSymbolHaloBlurAttribute, idSymbolDataInstancedDrawableUBO},
};
const std::array<TextureInfo, 2> SymbolTextAndIconShaderSource::textures = {
TextureInfo{0, idSymbolImageTexture},

View File

@@ -9,12 +9,12 @@ namespace shaders {
using SymbolIconShaderSource = ShaderSource<BuiltIn::SymbolIconShader, gfx::Backend::Type::WebGPU>;
const std::array<AttributeInfo, 6> SymbolIconShaderSource::attributes = {
AttributeInfo{3, gfx::AttributeDataType::Short4, idSymbolPosOffsetVertexAttribute},
AttributeInfo{4, gfx::AttributeDataType::UShort4, idSymbolDataVertexAttribute},
AttributeInfo{5, gfx::AttributeDataType::Short4, idSymbolPixelOffsetVertexAttribute},
AttributeInfo{6, gfx::AttributeDataType::Float3, idSymbolProjectedPosVertexAttribute},
AttributeInfo{7, gfx::AttributeDataType::Float, idSymbolFadeOpacityVertexAttribute},
AttributeInfo{8, gfx::AttributeDataType::Float, idSymbolOpacityVertexAttribute},
AttributeInfo{3, gfx::AttributeDataType::Short4, idSymbolPosOffsetAttribute},
AttributeInfo{4, gfx::AttributeDataType::UShort4, idSymbolDataAttribute},
AttributeInfo{5, gfx::AttributeDataType::Short4, idSymbolPixelOffsetAttribute},
AttributeInfo{6, gfx::AttributeDataType::Float3, idSymbolProjectedPosAttribute},
AttributeInfo{7, gfx::AttributeDataType::Float, idSymbolFadeOpacityAttribute},
AttributeInfo{8, gfx::AttributeDataType::Float, idSymbolOpacityAttribute},
};
const std::array<TextureInfo, 1> SymbolIconShaderSource::textures = {
@@ -25,16 +25,16 @@ const std::array<TextureInfo, 1> SymbolIconShaderSource::textures = {
using SymbolSDFShaderSource = ShaderSource<BuiltIn::SymbolSDFShader, gfx::Backend::Type::WebGPU>;
const std::array<AttributeInfo, 10> SymbolSDFShaderSource::attributes = {
AttributeInfo{3, gfx::AttributeDataType::Short4, idSymbolPosOffsetVertexAttribute},
AttributeInfo{4, gfx::AttributeDataType::UShort4, idSymbolDataVertexAttribute},
AttributeInfo{5, gfx::AttributeDataType::Short4, idSymbolPixelOffsetVertexAttribute},
AttributeInfo{6, gfx::AttributeDataType::Float3, idSymbolProjectedPosVertexAttribute},
AttributeInfo{7, gfx::AttributeDataType::Float, idSymbolFadeOpacityVertexAttribute},
AttributeInfo{8, gfx::AttributeDataType::Float4, idSymbolColorVertexAttribute},
AttributeInfo{9, gfx::AttributeDataType::Float4, idSymbolHaloColorVertexAttribute},
AttributeInfo{10, gfx::AttributeDataType::Float, idSymbolOpacityVertexAttribute},
AttributeInfo{11, gfx::AttributeDataType::Float, idSymbolHaloWidthVertexAttribute},
AttributeInfo{12, gfx::AttributeDataType::Float, idSymbolHaloBlurVertexAttribute},
AttributeInfo{3, gfx::AttributeDataType::Short4, idSymbolPosOffsetAttribute},
AttributeInfo{4, gfx::AttributeDataType::UShort4, idSymbolDataAttribute},
AttributeInfo{5, gfx::AttributeDataType::Short4, idSymbolPixelOffsetAttribute},
AttributeInfo{6, gfx::AttributeDataType::Float3, idSymbolProjectedPosAttribute},
AttributeInfo{7, gfx::AttributeDataType::Float, idSymbolFadeOpacityAttribute},
AttributeInfo{8, gfx::AttributeDataType::Float4, idSymbolColorAttribute},
AttributeInfo{9, gfx::AttributeDataType::Float4, idSymbolHaloColorAttribute},
AttributeInfo{10, gfx::AttributeDataType::Float, idSymbolOpacityAttribute},
AttributeInfo{11, gfx::AttributeDataType::Float, idSymbolHaloWidthAttribute},
AttributeInfo{12, gfx::AttributeDataType::Float, idSymbolHaloBlurAttribute},
};
const std::array<TextureInfo, 1> SymbolSDFShaderSource::textures = {
@@ -45,15 +45,15 @@ const std::array<TextureInfo, 1> SymbolSDFShaderSource::textures = {
using SymbolTextAndIconShaderSource = ShaderSource<BuiltIn::SymbolTextAndIconShader, gfx::Backend::Type::WebGPU>;
const std::array<AttributeInfo, 9> SymbolTextAndIconShaderSource::attributes = {
AttributeInfo{3, gfx::AttributeDataType::Short4, idSymbolPosOffsetVertexAttribute},
AttributeInfo{4, gfx::AttributeDataType::UShort4, idSymbolDataVertexAttribute},
AttributeInfo{5, gfx::AttributeDataType::Float3, idSymbolProjectedPosVertexAttribute},
AttributeInfo{6, gfx::AttributeDataType::Float, idSymbolFadeOpacityVertexAttribute},
AttributeInfo{7, gfx::AttributeDataType::Float4, idSymbolColorVertexAttribute},
AttributeInfo{8, gfx::AttributeDataType::Float4, idSymbolHaloColorVertexAttribute},
AttributeInfo{9, gfx::AttributeDataType::Float, idSymbolOpacityVertexAttribute},
AttributeInfo{10, gfx::AttributeDataType::Float, idSymbolHaloWidthVertexAttribute},
AttributeInfo{11, gfx::AttributeDataType::Float, idSymbolHaloBlurVertexAttribute},
AttributeInfo{3, gfx::AttributeDataType::Short4, idSymbolPosOffsetAttribute},
AttributeInfo{4, gfx::AttributeDataType::UShort4, idSymbolDataAttribute},
AttributeInfo{5, gfx::AttributeDataType::Float3, idSymbolProjectedPosAttribute},
AttributeInfo{6, gfx::AttributeDataType::Float, idSymbolFadeOpacityAttribute},
AttributeInfo{7, gfx::AttributeDataType::Float4, idSymbolColorAttribute},
AttributeInfo{8, gfx::AttributeDataType::Float4, idSymbolHaloColorAttribute},
AttributeInfo{9, gfx::AttributeDataType::Float, idSymbolOpacityAttribute},
AttributeInfo{10, gfx::AttributeDataType::Float, idSymbolHaloWidthAttribute},
AttributeInfo{11, gfx::AttributeDataType::Float, idSymbolHaloBlurAttribute},
};
const std::array<TextureInfo, 2> SymbolTextAndIconShaderSource::textures = {

View File

@@ -773,9 +773,9 @@ Point<float> calculateVariableRenderShift(style::SymbolAnchorType anchor,
}
} // namespace
bool Placement::updateBucketDynamicVertices(SymbolBucket& bucket,
const TransformState& state,
const RenderTile& tile) const {
bool Placement::updateBucketDynamicAttributeData(SymbolBucket& bucket,
const TransformState& state,
const RenderTile& tile) const {
using namespace style;
const auto& layout = *bucket.layout;
const bool alongLine = layout.get<SymbolPlacement>() != SymbolPlacementType::Point;
@@ -790,7 +790,7 @@ bool Placement::updateBucketDynamicVertices(SymbolBucket& bucket,
const bool pitchWithMap = layout.get<style::IconPitchAlignment>() == style::AlignmentType::Map;
const bool keepUpright = layout.get<style::IconKeepUpright>();
if (bucket.hasSdfIconData()) {
reprojectLineLabels(bucket.sdfIcon.dynamicVertices(),
reprojectLineLabels(bucket.sdfIcon.dynamicAttributeData(),
bucket.sdfIcon.placedSymbols,
tile.matrix,
pitchWithMap,
@@ -802,7 +802,7 @@ bool Placement::updateBucketDynamicVertices(SymbolBucket& bucket,
result = true;
}
if (bucket.hasIconData()) {
reprojectLineLabels(bucket.icon.dynamicVertices(),
reprojectLineLabels(bucket.icon.dynamicAttributeData(),
bucket.icon.placedSymbols,
tile.matrix,
pitchWithMap,
@@ -818,7 +818,7 @@ bool Placement::updateBucketDynamicVertices(SymbolBucket& bucket,
if (bucket.hasTextData() && layout.get<TextRotationAlignment>() == AlignmentType::Map) {
const bool pitchWithMap = layout.get<style::TextPitchAlignment>() == style::AlignmentType::Map;
const bool keepUpright = layout.get<style::TextKeepUpright>();
reprojectLineLabels(bucket.text.dynamicVertices(),
reprojectLineLabels(bucket.text.dynamicAttributeData(),
bucket.text.placedSymbols,
tile.matrix,
pitchWithMap,
@@ -830,7 +830,7 @@ bool Placement::updateBucketDynamicVertices(SymbolBucket& bucket,
result = true;
}
} else if (hasVariableAnchors) {
bucket.text.sharedDynamicVertices->clear();
bucket.text.sharedDynamicAttributeData->clear();
bucket.hasVariablePlacement = false;
const auto partiallyEvaluatedSize = bucket.textSizeBinder->evaluateForZoom(static_cast<float>(state.getZoom()));
@@ -859,7 +859,7 @@ bool Placement::updateBucketDynamicVertices(SymbolBucket& bucket,
// These symbols are from a justification that is not being
// used, or a label that wasn't placed so we don't need to do
// the extra math to figure out what incremental shift to apply.
hideGlyphs(symbol.glyphOffsets.size(), bucket.text.dynamicVertices());
hideGlyphs(symbol.glyphOffsets.size(), bucket.text.dynamicAttributeData());
} else {
const Point<float> tileAnchor = symbol.anchorPoint;
const auto projectedAnchor = project(tileAnchor, pitchWithMap ? tile.matrix : labelPlaneMatrix);
@@ -902,26 +902,26 @@ bool Placement::updateBucketDynamicVertices(SymbolBucket& bucket,
}
for (std::size_t j = 0; j < symbol.glyphOffsets.size(); ++j) {
addDynamicAttributes(shiftedAnchor, symbol.angle, bucket.text.dynamicVertices());
addDynamicAttributes(shiftedAnchor, symbol.angle, bucket.text.dynamicAttributeData());
}
}
}
if (updateTextFitIcon && bucket.hasVariablePlacement) {
auto updateIcon = [&](SymbolBucket::Buffer& iconBuffer) {
iconBuffer.sharedDynamicVertices->clear();
iconBuffer.sharedDynamicAttributeData->clear();
for (std::size_t i = 0; i < iconBuffer.placedSymbols.size(); ++i) {
const PlacedSymbol& placedIcon = iconBuffer.placedSymbols[i];
if (placedIcon.hidden || (!placedIcon.placedOrientation && bucket.allowVerticalPlacement)) {
hideGlyphs(placedIcon.glyphOffsets.size(), iconBuffer.dynamicVertices());
hideGlyphs(placedIcon.glyphOffsets.size(), iconBuffer.dynamicAttributeData());
} else {
const auto& pair = placedTextShifts.find(i);
if (pair == placedTextShifts.end()) {
hideGlyphs(placedIcon.glyphOffsets.size(), iconBuffer.dynamicVertices());
hideGlyphs(placedIcon.glyphOffsets.size(), iconBuffer.dynamicAttributeData());
} else {
for (std::size_t j = 0; j < placedIcon.glyphOffsets.size(); ++j) {
addDynamicAttributes(
pair->second.second, placedIcon.angle, iconBuffer.dynamicVertices());
pair->second.second, placedIcon.angle, iconBuffer.dynamicAttributeData());
}
}
}
@@ -933,24 +933,24 @@ bool Placement::updateBucketDynamicVertices(SymbolBucket& bucket,
result = true;
} else if (bucket.allowVerticalPlacement && bucket.hasTextData()) {
const auto updateDynamicVertices = [](SymbolBucket::Buffer& buffer) {
buffer.sharedDynamicVertices->clear();
const auto updateDynamicAttributeData = [](SymbolBucket::Buffer& buffer) {
buffer.sharedDynamicAttributeData->clear();
for (const PlacedSymbol& symbol : buffer.placedSymbols) {
if (symbol.hidden || !symbol.placedOrientation) {
hideGlyphs(symbol.glyphOffsets.size(), buffer.dynamicVertices());
hideGlyphs(symbol.glyphOffsets.size(), buffer.dynamicAttributeData());
} else {
for (std::size_t j = 0; j < symbol.glyphOffsets.size(); ++j) {
addDynamicAttributes(symbol.anchorPoint, symbol.angle, buffer.dynamicVertices());
addDynamicAttributes(symbol.anchorPoint, symbol.angle, buffer.dynamicAttributeData());
}
}
}
};
updateDynamicVertices(bucket.text);
updateDynamicAttributeData(bucket.text);
// When text box is rotated, icon-text-fit icon must be rotated as well.
if (updateTextFitIcon) {
updateDynamicVertices(bucket.icon);
updateDynamicVertices(bucket.sdfIcon);
updateDynamicAttributeData(bucket.icon);
updateDynamicAttributeData(bucket.sdfIcon);
}
result = true;
@@ -962,9 +962,9 @@ bool Placement::updateBucketDynamicVertices(SymbolBucket& bucket,
void Placement::updateBucketOpacities(SymbolBucket& bucket,
const TransformState& state,
std::set<uint32_t>& seenCrossTileIDs) const {
if (bucket.hasTextData()) bucket.text.sharedOpacityVertices->clear();
if (bucket.hasIconData()) bucket.icon.sharedOpacityVertices->clear();
if (bucket.hasSdfIconData()) bucket.sdfIcon.sharedOpacityVertices->clear();
if (bucket.hasTextData()) bucket.text.sharedOpacityAttributeData->clear();
if (bucket.hasIconData()) bucket.icon.sharedOpacityAttributeData->clear();
if (bucket.hasSdfIconData()) bucket.sdfIcon.sharedOpacityAttributeData->clear();
if (bucket.hasIconCollisionBoxData()) bucket.iconCollisionBox->dynamicVertices().clear();
if (bucket.hasIconCollisionCircleData()) bucket.iconCollisionCircle->dynamicVertices().clear();
if (bucket.hasTextCollisionBoxData()) bucket.textCollisionBox->dynamicVertices().clear();
@@ -1014,32 +1014,37 @@ void Placement::updateBucketOpacities(SymbolBucket& bucket,
SYM_GUARD_LOC))
return;
}
#if MLN_USE_SYMBOL_INSTANCING
const size_t count = 1;
#else
const size_t count = 4;
#endif
if (symbolInstance.hasText()) {
size_t textOpacityVerticesSize = 0u;
const auto& opacityVertex = SymbolBucket::opacityVertex(opacityState.text.placed,
opacityState.text.opacity);
const auto& opacityAttributes = SymbolBucket::opacityAttributes(opacityState.text.placed,
opacityState.text.opacity);
if (symbolInstance.getPlacedRightTextIndex()) {
textOpacityVerticesSize += symbolInstance.getRightJustifiedGlyphQuadsSize() * 4;
textOpacityVerticesSize += symbolInstance.getRightJustifiedGlyphQuadsSize() * count;
PlacedSymbol& placed = bucket.text.placedSymbols[*symbolInstance.getPlacedRightTextIndex()];
placed.hidden = opacityState.isHidden();
}
if (symbolInstance.getPlacedCenterTextIndex() && !symbolInstance.getSingleLine()) {
textOpacityVerticesSize += symbolInstance.getCenterJustifiedGlyphQuadsSize() * 4;
textOpacityVerticesSize += symbolInstance.getCenterJustifiedGlyphQuadsSize() * count;
PlacedSymbol& placed = bucket.text.placedSymbols[*symbolInstance.getPlacedCenterTextIndex()];
placed.hidden = opacityState.isHidden();
}
if (symbolInstance.getPlacedLeftTextIndex() && !symbolInstance.getSingleLine()) {
textOpacityVerticesSize += symbolInstance.getLeftJustifiedGlyphQuadsSize() * 4;
textOpacityVerticesSize += symbolInstance.getLeftJustifiedGlyphQuadsSize() * count;
PlacedSymbol& placed = bucket.text.placedSymbols[*symbolInstance.getPlacedLeftTextIndex()];
placed.hidden = opacityState.isHidden();
}
if (symbolInstance.getPlacedVerticalTextIndex()) {
textOpacityVerticesSize += symbolInstance.getVerticalGlyphQuadsSize() * 4;
textOpacityVerticesSize += symbolInstance.getVerticalGlyphQuadsSize() * count;
bucket.text.placedSymbols[*symbolInstance.getPlacedVerticalTextIndex()].hidden =
opacityState.isHidden();
}
bucket.text.opacityVertices().extend(textOpacityVerticesSize, opacityVertex);
bucket.text.opacityAttributeData().extend(textOpacityVerticesSize, opacityAttributes);
style::TextWritingModeType previousOrientation = style::TextWritingModeType::Horizontal;
if (bucket.allowVerticalPlacement) {
@@ -1057,21 +1062,21 @@ void Placement::updateBucketOpacities(SymbolBucket& bucket,
}
if (symbolInstance.hasIcon()) {
size_t iconOpacityVerticesSize = 0u;
const auto& opacityVertex = SymbolBucket::opacityVertex(opacityState.icon.placed,
opacityState.icon.opacity);
const auto& opacityAttributes = SymbolBucket::opacityAttributes(opacityState.icon.placed,
opacityState.icon.opacity);
auto& iconBuffer = symbolInstance.hasSdfIcon() ? bucket.sdfIcon : bucket.icon;
if (symbolInstance.getPlacedIconIndex()) {
iconOpacityVerticesSize += symbolInstance.getIconQuadsSize() * 4;
iconOpacityVerticesSize += symbolInstance.getIconQuadsSize() * count;
iconBuffer.placedSymbols[*symbolInstance.getPlacedIconIndex()].hidden = opacityState.isHidden();
}
if (symbolInstance.getPlacedVerticalIconIndex()) {
iconOpacityVerticesSize += symbolInstance.getIconQuadsSize() * 4;
iconOpacityVerticesSize += symbolInstance.getIconQuadsSize() * count;
iconBuffer.placedSymbols[*symbolInstance.getPlacedVerticalIconIndex()].hidden = opacityState.isHidden();
}
iconBuffer.opacityVertices().extend(iconOpacityVerticesSize, opacityVertex);
iconBuffer.opacityAttributeData().extend(iconOpacityVerticesSize, opacityAttributes);
}
auto updateIconCollisionBox = [&](const auto& feature, const bool placed, const Point<float>& shift) {

View File

@@ -171,7 +171,7 @@ protected:
}
// Returns `true` if bucket vertices were updated; returns `false` otherwise.
bool updateBucketDynamicVertices(SymbolBucket&, const TransformState&, const RenderTile& tile) const;
bool updateBucketDynamicAttributeData(SymbolBucket&, const TransformState&, const RenderTile& tile) const;
void updateBucketOpacities(SymbolBucket&, const TransformState&, std::set<uint32_t>&) const;
void markUsedJustification(SymbolBucket&,
style::TextVariableAnchorType,

View File

@@ -120,6 +120,8 @@ void Drawable::updateVertexAttributes(gfx::VertexAttributeArrayPtr vertices,
seg.indexOffset,
seg.vertexLength,
seg.indexLength,
seg.baseInstance,
seg.instanceCount,
seg.sortKey,
};
drawSegs.push_back(std::make_unique<Drawable::DrawSegment>(mode, std::move(segCopy)));
@@ -337,8 +339,6 @@ void Drawable::draw(PaintParameters& parameters) const {
impl->pipelineInfo.setRenderable(renderPass_.getDescriptor().renderable);
const auto instances = instanceAttributes ? instanceAttributes->getMinCount() : 1;
for (const auto& seg : impl->segments) {
const auto& segment = seg->getSegment();
@@ -354,16 +354,16 @@ void Drawable::draw(PaintParameters& parameters) const {
if (segment.indexLength) {
commandBuffer->drawIndexed(static_cast<uint32_t>(segment.indexLength),
static_cast<uint32_t>(instances),
static_cast<uint32_t>(segment.instanceCount),
static_cast<uint32_t>(segment.indexOffset),
static_cast<int32_t>(segment.vertexOffset),
0,
static_cast<uint32_t>(segment.baseInstance),
dispatcher);
} else {
commandBuffer->draw(static_cast<uint32_t>(segment.vertexLength),
static_cast<uint32_t>(instances),
static_cast<uint32_t>(segment.instanceCount),
static_cast<uint32_t>(segment.vertexOffset),
0,
static_cast<uint32_t>(segment.baseInstance),
dispatcher);
}
@@ -411,7 +411,7 @@ void Drawable::setSharedBuffers(const gfx::VertexAttributeArray& attribs, const
const auto& vkAttrib = static_cast<const VertexAttribute&>(attrib);
int ubo = vkAttrib.getUBO();
if (ubo == -1 || impl->uniformBuffers.get(ubo) != nullptr) {
if (ubo == -1) {
return;
}

View File

@@ -1029,8 +1029,14 @@ void Drawable::updateVertexAttributes(gfx::VertexAttributeArrayPtr vertices,
drawSegs.reserve(segmentCount);
for (std::size_t i = 0; i < segmentCount; ++i) {
const auto& seg = segments[i];
drawSegs.push_back(std::make_unique<DrawSegment>(
mode, SegmentBase{seg.vertexOffset, seg.indexOffset, seg.vertexLength, seg.indexLength, seg.sortKey}));
drawSegs.push_back(std::make_unique<DrawSegment>(mode,
SegmentBase{seg.vertexOffset,
seg.indexOffset,
seg.vertexLength,
seg.indexLength,
seg.baseInstance,
seg.instanceCount,
seg.sortKey}));
}
}