Skip to content
7 changes: 7 additions & 0 deletions include/mbgl/shaders/mtl/common.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,17 @@ float4 decode_color(const float2 encoded) {
return float4(unpack_float(encoded[0]) / 255, unpack_float(encoded[1]) / 255);
}
// Unpack a pair of paint values and interpolate between them.
float unpack_mix_float(device const float packedValue[2], const float t) {
return mix(packedValue[0], packedValue[1], t == 0 ? 1 : t);
}
float unpack_mix_float(const float2 packedValue, const float t) {
return mix(packedValue[0], packedValue[1], t);
}
// Unpack a pair of paint values and interpolate between them.
float4 unpack_mix_color(device const float packedColors[4], const float t) {
return mix(decode_color(float2(packedColors[0], packedColors[1])),
decode_color(float2(packedColors[2], packedColors[3])), t == 0 ? 1 : t);
}
float4 unpack_mix_color(const float4 packedColors, const float t) {
return mix(decode_color(float2(packedColors[0], packedColors[1])),
decode_color(float2(packedColors[2], packedColors[3])), t);
Expand Down
316 changes: 247 additions & 69 deletions include/mbgl/shaders/mtl/symbol.hpp

Large diffs are not rendered by default.

14 changes: 11 additions & 3 deletions include/mbgl/shaders/shader_defines.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -521,9 +521,17 @@ enum {
};

enum {
idSymbolPosOffsetVertexAttribute,
idSymbolDataVertexAttribute,
idSymbolPixelOffsetVertexAttribute,
idSymbolPosVertexAttribute,

idSymbolInstanceAttribute,

idSymbolPosScaleAttribute,
idSymbolOffsetTlTrAttribute,
idSymbolOffsetBlBrAttribute,
idSymbolTextureRectAttribute,
idSymbolPixelOffsetAttribute,
idSymbolSizeSdfAttribute,

idSymbolProjectedPosVertexAttribute,
idSymbolFadeOpacityVertexAttribute,

Expand Down
11 changes: 11 additions & 0 deletions src/mbgl/gfx/attribute.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
2 changes: 2 additions & 0 deletions src/mbgl/gfx/drawable_builder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)));
Expand Down
41 changes: 28 additions & 13 deletions src/mbgl/layout/symbol_layout.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1223,7 +1223,9 @@ size_t SymbolLayout::addSymbol(SymbolBucket::Buffer& buffer,
const Anchor& labelAnchor,
PlacedSymbol& placedSymbol,
float sortKey) {
constexpr const uint16_t vertexLength = 4;
constexpr const uint16_t instanceCount = 1;

/*constexpr const uint16_t vertexLength = 4;

const auto& tl = symbol.tl;
const auto& tr = symbol.tr;
Expand All @@ -1238,17 +1240,26 @@ size_t SymbolLayout::addSymbol(SymbolBucket::Buffer& buffer,
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);
}*/

if (buffer.segments.empty() ||
buffer.segments.back().instanceCount + instanceCount > std::numeric_limits<uint16_t>::max() ||
std::fabs(buffer.segments.back().sortKey - sortKey) > std::numeric_limits<float>::epsilon()) {
buffer.segments.emplace_back(0, 0, 4, 6, buffer.instances().elements(), 0, sortKey);
}

// We're generating triangle fans, so we always start with the first
// coordinate in this polygon.
auto& segment = buffer.segments.back();
assert(segment.vertexLength <= std::numeric_limits<uint16_t>::max());
auto index = static_cast<uint16_t>(segment.vertexLength);
// assert(segment.vertexLength <= std::numeric_limits<uint16_t>::max());
// auto index = static_cast<uint16_t>(segment.vertexLength);
auto index = static_cast<uint16_t>(segment.baseInstance + segment.instanceCount);

// coordinates (2 triangles)
auto& vertices = buffer.vertices();
vertices.emplace_back(SymbolBucket::layoutVertex(labelAnchor.point,
vertices.emplace_back(SymbolBucket::layoutVertex(symbol, labelAnchor, sizeData));

/*vertices.emplace_back(SymbolBucket::layoutVertex(labelAnchor.point,
tl,
symbol.glyphOffset.y,
tex.x,
Expand Down Expand Up @@ -1283,29 +1294,33 @@ size_t SymbolLayout::addSymbol(SymbolBucket::Buffer& buffer,
sizeData,
symbol.isSDF,
pixelOffsetBR,
minFontScale));
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);
// buffer.dynamicVertices().emplace_back(dynamicVertex);
// buffer.dynamicVertices().emplace_back(dynamicVertex);
// buffer.dynamicVertices().emplace_back(dynamicVertex);

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);
// buffer.opacityVertices().emplace_back(opacityVertex);
// buffer.opacityVertices().emplace_back(opacityVertex);
// buffer.opacityVertices().emplace_back(opacityVertex);

// add the two triangles, referencing the four coordinates we just inserted.
buffer.triangles.emplace_back(index + 0, index + 1, index + 2);
/*buffer.triangles.emplace_back(index + 0, index + 1, index + 2);
buffer.triangles.emplace_back(index + 1, index + 2, index + 3);

segment.vertexLength += vertexLength;
segment.indexLength += 6;
segment.indexLength += 6;*/

auto instanceVertex = SymbolBucket::instanceVertex(index);
buffer.instances().emplace_back(instanceVertex);
segment.instanceCount += instanceCount;

placedSymbol.glyphOffsets.push_back(symbol.glyphOffset.x);

Expand Down
8 changes: 4 additions & 4 deletions src/mbgl/layout/symbol_projection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -183,15 +183,15 @@ void addDynamicAttributes(const Point<float>& anchorPoint,
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);
// dynamicVertexArray.emplace_back(dynamicVertex);
// dynamicVertexArray.emplace_back(dynamicVertex);
// dynamicVertexArray.emplace_back(dynamicVertex);
}

void hideGlyphs(size_t numGlyphs, gfx::VertexVector<gfx::Vertex<SymbolDynamicLayoutAttributes>>& dynamicVertexArray) {
const Point<float> offscreenPoint = {-INFINITY, -INFINITY};
if (dynamicVertexArray.empty()) {
dynamicVertexArray.reserve(4 * numGlyphs);
dynamicVertexArray.reserve(1 * numGlyphs);
}
for (size_t i = 0; i < numGlyphs; i++) {
addDynamicAttributes(offscreenPoint, 0, dynamicVertexArray);
Expand Down
6 changes: 4 additions & 2 deletions src/mbgl/mtl/drawable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -279,8 +279,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);
Expand Down Expand Up @@ -376,6 +376,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)));
Expand Down
70 changes: 49 additions & 21 deletions src/mbgl/renderer/buckets/symbol_bucket.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -97,15 +121,15 @@ bool SymbolBucket::hasData() const {
}

bool SymbolBucket::hasTextData() const {
return !text.segments.empty();
return !text.vertices().empty();
}

bool SymbolBucket::hasIconData() const {
return !icon.segments.empty();
return !icon.vertices().empty();
}

bool SymbolBucket::hasSdfIconData() const {
return !sdfIcon.segments.empty();
return !sdfIcon.vertices().empty();
}

bool SymbolBucket::hasIconCollisionBoxData() const {
Expand All @@ -124,16 +148,20 @@ 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) {
void addPlacedSymbol(gfx::VertexVector<SymbolInstanceVertex>& instances, const PlacedSymbol& placedSymbol) {
auto endIndex = placedSymbol.vertexStartIndex + placedSymbol.glyphOffsets.size() * 1;
for (auto vertexIndex = placedSymbol.vertexStartIndex; vertexIndex < endIndex; vertexIndex += 1) {
auto instanceVertex = SymbolBucket::instanceVertex(vertexIndex);
instances.emplace_back(instanceVertex);
}
/*for (auto vertexIndex = placedSymbol.vertexStartIndex; 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));
triangles.emplace_back(static_cast<uint16_t>(vertexIndex + 1),
static_cast<uint16_t>(vertexIndex + 2),
static_cast<uint16_t>(vertexIndex + 3));
}
}*/
}

void SymbolBucket::sortFeatures(const float angle) {
Expand All @@ -158,9 +186,9 @@ void SymbolBucket::sortFeatures(const float angle) {
sortUploaded = false;
uploaded = false;

text.triangles.clear();
icon.triangles.clear();
sdfIcon.triangles.clear();
text.instances().clear();
icon.instances().clear();
sdfIcon.instances().clear();

auto symbolsSortOrder = std::make_unique<std::vector<size_t>>();
symbolsSortOrder->reserve(symbolInstances.size());
Expand All @@ -177,28 +205,28 @@ void SymbolBucket::sortFeatures(const float angle) {
symbolsSortOrder->push_back(symbolInstance.getDataFeatureIndex());

if (symbolInstance.getPlacedRightTextIndex()) {
addPlacedSymbol(text.triangles, text.placedSymbols[*symbolInstance.getPlacedRightTextIndex()]);
addPlacedSymbol(text.instances(), text.placedSymbols[*symbolInstance.getPlacedRightTextIndex()]);
}

if (symbolInstance.getPlacedCenterTextIndex() && !symbolInstance.getSingleLine()) {
addPlacedSymbol(text.triangles, text.placedSymbols[*symbolInstance.getPlacedCenterTextIndex()]);
addPlacedSymbol(text.instances(), text.placedSymbols[*symbolInstance.getPlacedCenterTextIndex()]);
}

if (symbolInstance.getPlacedLeftTextIndex() && !symbolInstance.getSingleLine()) {
addPlacedSymbol(text.triangles, text.placedSymbols[*symbolInstance.getPlacedLeftTextIndex()]);
addPlacedSymbol(text.instances(), text.placedSymbols[*symbolInstance.getPlacedLeftTextIndex()]);
}

if (symbolInstance.getPlacedVerticalTextIndex()) {
addPlacedSymbol(text.triangles, text.placedSymbols[*symbolInstance.getPlacedVerticalTextIndex()]);
addPlacedSymbol(text.instances(), text.placedSymbols[*symbolInstance.getPlacedVerticalTextIndex()]);
}

auto& iconBuffer = symbolInstance.hasSdfIcon() ? sdfIcon : icon;
if (symbolInstance.getPlacedIconIndex()) {
addPlacedSymbol(iconBuffer.triangles, iconBuffer.placedSymbols[*symbolInstance.getPlacedIconIndex()]);
addPlacedSymbol(iconBuffer.instances(), iconBuffer.placedSymbols[*symbolInstance.getPlacedIconIndex()]);
}

if (symbolInstance.getPlacedVerticalIconIndex()) {
addPlacedSymbol(iconBuffer.triangles,
addPlacedSymbol(iconBuffer.instances(),
iconBuffer.placedSymbols[*symbolInstance.getPlacedVerticalIconIndex()]);
}
}
Expand Down
Loading
Loading