Skip to content
This repository has been archived by the owner on Aug 8, 2023. It is now read-only.

[core] Implement data-driven styling for {text,icon}-{color,opacity,halo-color,halo-blur,halo-width} #7939

Merged
merged 9 commits into from
Mar 1, 2017

Conversation

anandthakker
Copy link
Contributor

No description provided.

@mention-bot
Copy link

@anandthakker, thanks for your PR! By analyzing this pull request, we identified @jfirebaugh and @ansis to be potential reviewers.

@anandthakker anandthakker force-pushed the dds-symbol branch 2 times, most recently from 5a6df6d to 9a2d6e0 Compare February 17, 2017 21:49
@anandthakker anandthakker changed the title WIP - dds for {text,icon}-{color,halo-color} WIP - dds for {text,icon}-{color,halo-color,halo-blur,halo-width} Feb 17, 2017
@anandthakker anandthakker changed the title WIP - dds for {text,icon}-{color,halo-color,halo-blur,halo-width} WIP - dds for {text,icon}-{color,opacity,halo-color,halo-blur,halo-width} Feb 17, 2017
@anandthakker
Copy link
Contributor Author

anandthakker commented Feb 17, 2017

Currently running into the following problem:

  • SymbolIconProgram and SymbolSDFProgram both use SymbolPaintProperties when instantiating Program<>.
  • SymbolPaintProperties, being generated from the style spec, includes properties that bind to GL attributes like a_halo_color that are not present in the (non-sdf-)icon shader.

I think this is the reason that I'm getting a glBindAttribLocation(id, location, name): Error GL_INVALID_VALUE error: according to the debugger, this is happening during mbgl::gl::bindAttributeLocation(id, location, "a_halo_color_max"), during the instantiation of the symbolIcon program.

update: I believe the reason this isn't blowing up in GL JS is that, there, we:

  • inspect each program, storing off the indexes for each attribute & uniform that are actually present in the shaders.
  • and then simply bail if a program configuration includes an attribute that isn't actually available to bind to.

@anandthakker anandthakker added the ⚠️ DO NOT MERGE Work in progress, proof of concept, or on hold label Feb 17, 2017
@anandthakker anandthakker changed the title WIP - dds for {text,icon}-{color,opacity,halo-color,halo-blur,halo-width} [core] Implement data-driven styling for {text,icon}-{color,opacity,halo-color,halo-blur,halo-width} Feb 17, 2017
@anandthakker anandthakker added Core The cross-platform C++ core, aka mbgl GL JS parity For feature parity with Mapbox GL JS labels Feb 17, 2017
@jfirebaugh
Copy link
Contributor

I don't think that's the reason -- that pattern occurs elsewhere, like with a_outline_color and fill programs. I suspect the reason is rather that we've now introduced more than GL_MAX_VERTEX_ATTRIBS attributes. This is a problem. We're either going to have to find creative ways of packing multiple attributes into one, or move to a system more like mapbox-gl-js, where shaders are dynamically generated that use only as many attributes as required by data-driven properties, and use uniforms otherwise -- this moves the failure condition to the point when someone tries to use too many data-driven properties at the same time.

@anandthakker
Copy link
Contributor Author

Yeah - so it looks like we're ending up with attribute ids >= 16 because each data-driven icon- / text- property is mapping to a separate attribute, so we're ending up with many more than we need. E.g., text-opacity and icon-opacity both become a_opacity, but they take up two separate positions in the parameter list:

mbgl::gl::Attributes<
mbgl::attributes::a_pos,
mbgl::attributes::a_offset<2>,
mbgl::attributes::a_texture_pos,
mbgl::attributes::a_data<4>,
mbgl::attributes::Min<mbgl::attributes::a_opacity>,
mbgl::attributes::Min<mbgl::attributes::a_fill_color>,
mbgl::attributes::Min<mbgl::attributes::a_halo_color>,
mbgl::attributes::Min<mbgl::attributes::a_halo_width>,
mbgl::attributes::Min<mbgl::attributes::a_halo_blur>,
mbgl::attributes::Min<mbgl::attributes::a_opacity>,
mbgl::attributes::Min<mbgl::attributes::a_fill_color>,
mbgl::attributes::Min<mbgl::attributes::a_halo_color>,
mbgl::attributes::Min<mbgl::attributes::a_halo_width>,
mbgl::attributes::Min<mbgl::attributes::a_halo_blur>,
mbgl::attributes::Max<mbgl::attributes::a_opacity>,
mbgl::attributes::Max<mbgl::attributes::a_fill_color>,
mbgl::attributes::Max<mbgl::attributes::a_halo_color>,
mbgl::attributes::Max<mbgl::attributes::a_halo_width>,
mbgl::attributes::Max<mbgl::attributes::a_halo_blur>,
mbgl::attributes::Max<mbgl::attributes::a_opacity>,
mbgl::attributes::Max<mbgl::attributes::a_fill_color>,
mbgl::attributes::Max<mbgl::attributes::a_halo_color>,
mbgl::attributes::Max<mbgl::attributes::a_halo_width>,
mbgl::attributes::Max<mbgl::attributes::a_halo_blur> >

@@ -94,7 +94,7 @@ class SymbolIconProgram : public Program<
const TransformState&);
};

class SymbolSDFProgram : public Program<
class SymbolSDFIconProgram : public Program<
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I initially tried to just parameterize SymbolSDFProgram on the paint property types, but it was proving sort of unweildy. Opted to duplicate the declarations and minimize code duplication in implementation via the shared makeSDFValues function

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about:

template <class PaintProperties>
class SymbolSDFProgram : public Program<
    ...
    PaintProperties>
{
    ...
};

using SymbolSDFIconProgram = SymbolSDFProgram<style::IconPaintProperties>;
using SymbolSDFTextProgram = SymbolSDFProgram<style::TextPaintProperties>;

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, that's something like what I was trying before and having trouble with -- but it's very possible that it was just other mid-refactor issues that were making it hard to see clearly. Lemme try again.

@anandthakker
Copy link
Contributor Author

@jfirebaugh Okay, I think this is ready for a 👀 .

  • History is hopefully reasonable to read commit-by-commit (with the generated code in its own commit).
  • There are three render tests failing for what seem like maybe platform-specific detail reasons? In two of the failures the difference between expected/actual isn't visible to the naked eye... The text-halo-blur one could actually be related to the blur property, but it seems more like something weird w/ the background.

@@ -28,6 +28,7 @@ class SymbolInstance {
CollisionFeature textCollisionFeature;
CollisionFeature iconCollisionFeature;
WritingModeType writingModes;
std::size_t featureIndex;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In GL JS, we did this with a direct reference to the associated feature. Would it be better to do a similar thing here, making this a SymbolFeature *?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

^ note: the reason I didn't was because, since SymbolInstance:SymbolFeature is many:1, it seemed like there would have to be some weird acrobatics using std::shared_ptr. Rather than introduce that machinery, I figured since both of these objects are really internal to SymbolLayout, this index-based coupling seemed okay.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is okay for now. I started learning more about the various classes used during symbol placement and I'm thinking maybe we can move to a hierarchy where SymbolFeature owns SymbolInstances, and can provide a direct SymbolFeature& reference at the appropriate time.

@anandthakker
Copy link
Contributor Author

anandthakker commented Feb 21, 2017

Almost there, I think:

  • Working on trying to run the android tests locally (as @ivovandongen indicated that most are skipped in CI bc of timing issues)
  • One of the Qt travis builds failed the Memory.Footprint test. Re-running it now just in case it was a fluke... but no real clue where to start on solving that one.

Update: @tmpsantos explained the context of the Memory.Footprint test. Some additional memory usage is necessary, because we now need to hold on to feature properties after SymbolLayout::prepare() (whereas before, we cleared the features vector when we were done). I tried to mitigate it some in 13d1d30 by clearing each feature's geometry, but it doesn't seem to have helped.

@tmpsantos indicates that this isn't necessarily a blocker.

cc @jfirebaugh (also FYI the remaining tests appear to be passing now)

@jfirebaugh
Copy link
Contributor

So we're going ~660kb over the Memory.Footprint test limit. How much under the limit are we before this change, i.e. how much is the total increase?

@anandthakker
Copy link
Contributor Author

anandthakker commented Feb 21, 2017

So we're going ~660kb over the Memory.Footprint test limit. How much under the limit are we before this change, i.e. how much is the total increase?

Force-logged it off of master (by setting the threshold to 0 in the unit test, because apparently googletest doesn't let you just arbitrary informational stuff 🙄 ):

Expected: (vectorFootprint) < (0), actual: 6.71485e+07 vs 0

( https://travis-ci.org/mapbox/mapbox-gl-native/jobs/204010132#L1013 )

On this branch, we get:

Expected: (vectorFootprint) < (65 * 1024 * 1024), actual: 6.88349e+07 vs 68157440

So that's a 1.7MB increase. Seems pretty significant.

@anandthakker
Copy link
Contributor Author

It occurs to me that this test is measuring RSS, and so I'm not sure whether these literal numbers are meaningfully interpretable as "the increase in memory usage".

@tmpsantos
Copy link
Contributor

It occurs to me that this test is measuring RSS, and so I'm not sure whether these literal numbers are meaningfully interpretable as "the increase in memory usage".

What this test is doing is:

  1. "Warming up" the memory by rendering 10x and deleting the map object after rendering.
  2. Measure the RSS, which should now include all the static data, thread locals and 3rd party libraries initialization data.
  3. Render N times (currently 15), but keep the map objects.
  4. Measure the current RSS compared to the first measurement and divide by N (15). This should be roughly how much each Map object is using. I set the bar at 65 MB per Map for vector and 25 MB per Map for raster. These numbers are arbitrary.
  5. Fail if it goes over this limit.

Few notes:

  • We use jmalloc because it is very aggressive at freeing memory, making the measurement more precise.
  • This test is surprisingly stable, and has protected us from memory growth in the past. Last one I remember was a PR that would pre-allocate a buffer for the annotations layer even if you don't have any annotation on the map. The regression was prevented by making this allocation lazy.
  • We could have used more sophisticated ways of tracking memory allocations, but RSS snapshots look reliable and fast enough for running on Travis. That said, any suggestion is welcome here.

@tmpsantos
Copy link
Contributor

One last thing that is worth mentioning. This test is focused on Map objects rather than tiles. If your code increases tile memory usage by 250 Kb per tile it is unlikely that this test will catch it, but the effects will be seen in an app when rendering 10 tiles at once in a tilted map (~2.5 MB memory increase).

Additional manual testing with larger maps is advised, I personally like this tool:
https://github.com/pixelb/ps_mem

@anandthakker
Copy link
Contributor Author

Capturing some notes from chat:

@anandthakker:

Agreed that this test seems like a good/reliable way to detect when a regression has occurred in memory usage.
My question is because, now that I know that the regression exists in my branch, I am interested in assessing more quantitatively what the memory impact of these changes are

@tmpsantos:

the other thing is, as we add more features, eventually we will have to use more memory
so it is just a matter of raise the memory bar there and life goes on

@anandthakker:

yeah, this branch is one such case, for sure: it includes a necessary change wherein SymbolLayout (one per symbol style layer) now holds on to a vector of features, rather than clearing it
we might, in the end, have to raise the memory bar. But if we’re going to do that, then ideally I’d like to:

  1. Determine how much more memory usage we’re incurring for this change.
  2. Actually account for (roughly) that amount based on the known increases in the change (e.g. the symbol features)

I’m working on 2 by doing some napkin math on the number of symbol layers / symbols that show up in this test, but I’m not sure how to do 1 with any confidence/accuracy (edited)

@tmpsantos
Copy link
Contributor

Did some tests to measure the memory impact of this change. On my Linux box, for rendering this map (1920x1200) using GLFW:

screenshot from 2017-02-22 16-14-46

$ cat /tmp/mbgl-native.cfg 
-73.9976
40.7333
14.128
-57.7533
60
2

I started the map with the same configuration 10x with this PR applied and without (the hash just before the first commit of this branch.

In average ps_mem was giving me 139.17 MB with this PR and 128.01 MB without. An increase of 11.16 MB.

Repeating the method with a 1024x768 map, the observed increase was 8 MB.

@anandthakker
Copy link
Contributor Author

Looks like in the Memory.Footprint test, we're dealing with 980 symbol features total... that's 1.7KB per symbol feature, which would be plausible if we're keeping the geometries around but seems too big for just the text, placement, properties.

@jfirebaugh two questions:

  1. Do you see any reason why clearing each feature's geometry here is failing to release the memory?
  2. Could the paint vertex buffers be part of the problem here? I've been assuming not thus far, because I figured that, like in GL JS, they'd be destroyed after uploading to GL.

@anandthakker
Copy link
Contributor Author

stats from profiling in Instruments:

master
screen shot 2017-02-22 at 3 57 02 pm

dds-symbol
screen shot 2017-02-22 at 3 54 05 pm

Obtained by profiling the Memory.Footprint test, and the filtering the Instruments time range to go from the beginning to point of peak heap usage.

The +43MB delta in heap usage includes:

+8MB - Malloc 4.00 MiB
+8MB - Malloc 1.00 MiB
+9.5MB - Malloc 80 Bytes
+3.91MB - SymbolFeature

Other than SymbolFeature, hard to say what these others are... probably allocations by various container classes?

@jfirebaugh
Copy link
Contributor

Here are a couple things I would try to reduce the memory growth:

  • Have SymbolFeature assume and hold ownership of the std::unique_ptr<GeometryTileFeature>, rather than copying its constituent parts. This may help reduce fragmentation.
  • Remove SymbolFeature::iconOffset and iconRotation in favor of calculating them as needed, like with the other properties in this PR.

@@ -229,7 +232,8 @@ void SymbolLayout::prepare(uintptr_t tileUID,
const bool textAlongLine = layout.get<TextRotationAlignment>() == AlignmentType::Map &&
layout.get<SymbolPlacement>() == SymbolPlacementType::Line;

for (const auto& feature : features) {
for (auto it = features.begin(); it != features.end(); ++it) {
auto feature = *it;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is creating a copy; it should be auto& feature = *it;. Then feature.geometry.clear(); will have a meaningful effect.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🙈

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Alas, this change only seems to take us down by 51K in the Memory.Footprint test: 6.88349e+07 => 6.87836e+07.

@@ -496,6 +502,12 @@ std::unique_ptr<SymbolBucket> SymbolLayout::place(CollisionTile& collisionTile)
layout.get<IconKeepUpright>(), iconPlacement, collisionTile.config.angle, symbolInstance.writingModes);
}
}

const auto feature = features.at(symbolInstance.featureIndex);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here, should be const auto& feature = ....

@anandthakker
Copy link
Contributor Author

Have SymbolFeature assume and hold ownership of the std::unique_ptr, rather than copying its constituent parts. This may help reduce fragmentation.

I think that one consequence of this is that it would be problematic to then clear the geometries after we didn't need them anymore (unless we added something like a clearGeometries() mutator to the GeometryTileFeature interface). I guess since clearing them didn't do much, maybe that's okay.

properties(feature->getProperties())
SymbolFeature(std::unique_ptr<GeometryTileFeature> feature_) :
feature(std::move(feature_)),
geometry(feature->getGeometries()) // we need a mutable copy of the geometry for mergeLines()
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

☝️ @jfirebaugh note - mergeLines relies on mutating the SymbolFeatures' geometries, but getGeometries() returns a copy, so this bit of copying still needed to happen.

@anandthakker
Copy link
Contributor Author

anandthakker commented Feb 23, 2017

@jfirebaugh implemented your two suggestions from #7939 (comment). Moving iconOffset and iconRotate off only helped marginally, but transferring ownership of the GeometryTileFeatures made a pretty big difference: brought us down to 6.81918e+07 in the Memory.Footprint test -- so that's a +1MB delta from master (instead of +1.7MB).

}

// Determine and load glyph ranges
const size_t featureCount = sourceLayer.featureCount();
for (size_t i = 0; i < featureCount; ++i) {
auto feature = sourceLayer.getFeature(i);
if (!leader.filter(feature->getType(), feature->getID(), [&] (const auto& key) { return feature->getValue(key); }))
SymbolFeature ft(sourceLayer.getFeature(i));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be better to construct SymbolFeature only for features that pass the filter, to avoid unnecessarily building and copying the geometry.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, should have been more explicit:

auto feature = sourceLayer.getFeature(i);
if (!filter)
    continue;
SymbolFeature ft(std::move(feature));

We don't want to call sourceLayer.getFeature(i) twice.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh whoops, yeah that's what I'd intended -- trying to go too fast heh

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jfirebaugh amended.

@@ -1,14 +1,21 @@
#include <iostream>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Leftover from debugging?


namespace mbgl {

using namespace style;

static_assert(sizeof(SymbolLayoutVertex) == 16, "expected SymbolLayoutVertex size");

MBGL_DEFINE_ENUM(SymbolSDFPart, {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

MBGL_DEFINE_ENUM is needed only where enum ↔ string conversion is required, which isn't the case with SymbolSDFPart.

@@ -8,6 +8,7 @@
#include <mbgl/util/geometry.hpp>
#include <mbgl/util/size.hpp>
#include <mbgl/style/layers/symbol_layer_properties.hpp>
#include <mbgl/style/layers/symbol_layer_impl.hpp>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't be necessary.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is needed here because it's where style::{Icon,Text}PaintProperties are declared.

using SymbolLayoutVertex = SymbolLayoutAttributes::Vertex;
using SymbolAttributes = SymbolIconProgram::Attributes;
using SymbolIconAttributes = SymbolIconProgram::Attributes;
using SymbolGlyphAttributes = SymbolSDFTextProgram::Attributes;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rename this to SymbolTextAttributes.

@anandthakker
Copy link
Contributor Author

anandthakker commented Feb 24, 2017

A little more on the memory usage increase. Running a single iteration from the Memory.Footprint test and estimating each symbol feature's footprint as 4 * # coordinates + sum(length(each string property)) + 8 * # numeric properties yields a total of 1,481,348 bytes (213,664 from geometry, the rest from properties).

update: Property values are shared among features within a tile, so this is actually overestimate.

update 2: Corrected to not double-count shared property values in each tile layer: 434,632

@@ -15,9 +15,17 @@ class VectorTileLayer;

using packed_iter_type = protozero::iterator_range<protozero::pbf_reader::const_uint32_iterator>;

struct VectorTileLayerData {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should also have a shared_ptr<const std::string> data member, to ensure that the data backing the tags_iter and geometry_iter is retained.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jfirebaugh 👍 done.

Copy link
Contributor

@springmeyer springmeyer Apr 5, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@anandthakker @jfirebaugh - Landed here in a revised effort to integrate https://github.com/mapbox/vector-tile back into mbgl. I have some questions.

  1. Without VectorTileLayerData and is shared_ptr<const std::string> data member what exactly would go wrong? I figure there must be somewhere in the code that expects to create a VectorTileLayer and use it/cache it in such a way beyond when the underlying data would be kept alive. So keeping a shared_ptr to the data keeps it alive as long as all VectorTileLayer instances are alive? Can you point to the code that needs this? (I could not find it)

  2. Why does the VectorTileFeature need a std::shared_ptr<VectorTileLayerData> layerData rather than just const VectorTileLayer&. This indicates to me that somewhere in the code expects to keep a VectorTileFeature instance alive longer than the parent VectorTileLayer. Is this happening and can you point to the place in the code that requires is? Or is this perhaps unneeded - in that the VectorTileLayer will always be alive as long as the VectorTileFeature created from it?

Copy link
Contributor Author

@anandthakker anandthakker Apr 5, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why does the VectorTileFeature need a std::shared_ptr layerData rather than just const VectorTileLayer&. This indicates to me that somewhere in the code expects to keep a VectorTileFeature instance alive longer than the parent VectorTileLayer

@springmeyer Yeah -- this is a possibility that did not exist before, but was introduced in this PR. (And apologies: I should have left a comment justifying the shared_ptrs introduced here.)

The reason it can now happen is over in SymbolLayout, and specifically SymbolFeature (here). SymbolLayout is constructed with a vector tile layer, and then later on--when there's no guarantee that the vector tile data is still around--expected to produce a "bucket" containing final rendering data. Before this PR, we copied the necessary data into SymbolFeature structs which SymbolLayout could hang on to; but because we need feature properties for data-driven styling--and because these turn out to be quite expensive to copy--SymbolFeature now holds a reference to the VectorTileFeature.

Thus, VectorTileFeatures may need to outlive their parent VectorTileLayers, so they need shared ownership of VectorTileLayerData.

As for the shared_ptr<const std::string> data that's held by VectorTileLayerData -- I think we need this basically as a consequence of the above, since VectorTileFeatures may parse PBF data lazily. But even without these symbol-layout-related changes, it's making explicit a dependency that already existed, since there's no explicit guarantee that the parent VectorTileData would outlive a particular VectorTileLayer. The lifecycles happened to be okay before this, but only because of implicit constraints on how we used these objects.

@jfirebaugh should probably check my math on this, as I haven't spent time in the parts of our vector tile parsing/caching stuff outside of SymbolLayout.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, that's correct. One minor note is that shared_ptr<const std::string> predated the addition of VectorTileLayerData and comes from the definition of Response. I believe this was originally done to avoid string copies. Might be better to use move semantics now.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@anandthakker and @jfirebaugh - awesome thank you for the confirmation. I'm grateful for the confirmation and will now proceed with my PR revising this code and keep all the explicit ownership relationships fully intact. The context I should have mentioned before is that I hope my PR will help performance so I was looking closely at the nearby code for any optimization potential, which is what lead me to the question of whether the shared pointers were absolutely needed. Great to know they are.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ticketed @jfirebaugh's idea: #9167

VectorTileFeature::VectorTileFeature(protozero::pbf_reader feature_pbf, const VectorTileLayer& layer_)
: layer(layer_) {
VectorTileFeature::VectorTileFeature(protozero::pbf_reader feature_pbf, std::shared_ptr<VectorTileLayerData> layerData_)
: layerData(layerData_) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

layerData(std::move(layerData_))

@anandthakker
Copy link
Contributor Author

Latest changes bring us down to 68096819, which is under the Memory.Footprint ceiling. This is great! (Except: I really am not sure why this helped. If anything, I thought that using shared_ptrs to a separate VectorTileLayerData, rather than reference to VectorTileLayer, should have cause a small increase in memory footprint...)

Anand Thakker and others added 8 commits February 28, 2017 14:06
Prepares for enabling DDS on symbol paint properties by allowing the
SymbolFeatures, which we keep around after constructing SymbolLayout,
to be used in evaluating data-driven paint properties later in the
layout process.
The `Program` types are set up to bind GL attributes to each of the
data-driven paint properties specified in the `PaintProperties` type
provided.  Since `SymbolPaintProperties` specifies both `Text*` and
`Icon*` properties, the symbolIcon, symbolIconSDF, and symbolGlyph
programs each attempt to bind roughly double the number of attributes
that they actually need.

This change addresses this by:
- Adding the more specific `IconPaintProperties` and `TextPaintProperties` types, which are subsets of the full `SymbolPaintProperties`.
- The symbol layer continues to use its `SymbolPaintProperties paint` member to track layer property state, but it provides helpers that construct objects of each the specific `{Icon,Text}PaintProperties::Evaluated` type, for use by the painter.
- The three symbol programs instantiate `Program<>` using the appropriate `{Icon,Text}PaintProperties` type.
@anandthakker anandthakker merged commit f901e77 into master Mar 1, 2017
@anandthakker anandthakker deleted the dds-symbol branch March 1, 2017 03:54
@1ec5 1ec5 removed the ⚠️ DO NOT MERGE Work in progress, proof of concept, or on hold label May 6, 2017
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Core The cross-platform C++ core, aka mbgl GL JS parity For feature parity with Mapbox GL JS
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants