-
Notifications
You must be signed in to change notification settings - Fork 1.3k
Conversation
src/mbgl/renderer/style_diff.cpp
Outdated
== std::tie(rhs->id, lhs->type); | ||
}; | ||
|
||
longest_common_subsequence(a.begin(), a.end(), b.begin(), b.end(), std::back_inserter(lcs), eq); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This LCS implementation is the unrefined O(ND) space algorithm from the classic paper. I'm not sure if we need a full LCS, versus a more basic unordered set difference -- it probably depends if we want to implement a "move layer" operation rather than the current "remove and re-add" implementation (see mapbox/mapbox-gl-js#4142).
If we do end up keeping LCS, we should probably implement the O(N) space refinement presented in the paper. I haven't yet invested the time to understand it or write a high-quality implementation.
Starting to look good! One thing I'm wondering about is wether we should add the option to mutate multiple properties at once (in layers for example) to avoid unnecessary copies of the implementations. |
src/mbgl/shaders/fill_outline.cpp
Outdated
@@ -41,7 +41,7 @@ void main() { | |||
|
|||
|
|||
float dist = length(v_pos - gl_FragCoord.xy); | |||
float alpha = smoothstep(1.0, 0.0, dist); | |||
float alpha = 1.0 - smoothstep(0.0, 1.0, dist); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Did these snuck in by accident?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
a696800
to
bac2476
Compare
This is ready for review. I checked for conflicts with #8937; they are minimal (added a header file in the same place). |
src/mbgl/style/style.cpp
Outdated
} | ||
|
||
if (evaluate || layer->hasTransition()) { | ||
layer->evaluate(evaluationParameters); | ||
if (classesChanged || layerAdded || layerChanged || layer.hasTransition()) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
zoomChanged
is missing here, and none of our regression tests caught it. Will investigate.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice catch 👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good!
- Ran the Android integration tests as well, no regressions. Although the run time (locally) increased from ~5:30min to ~8:00min. No immediately obvious cause for this, it is spread fairly evenly over the style tests.
- Ran through all the Android test app activities manually, no regressions I could spot.
|
||
// Private implementation | ||
const std::unique_ptr<Impl> baseImpl; | ||
class Impl; | ||
Immutable<Impl> baseImpl; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I realize this has been public before, but is there a way we can make it private now?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Style
at a minimum would need to be friended. GeometryTile
also uses it; it's possible that use could be eliminated. I'd like to leave this for a followup change though.
@@ -44,6 +44,13 @@ public: | |||
<% } -%> | |||
|
|||
<% } -%> | |||
// Visibility | |||
void setVisibility(VisibilityType) final; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: Can we add override
to be consistent with the rest of the codebase?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You want to write override final
or final override
? Neither of those appear elsewhere in the codebase.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm specifically interested in override
(final override
reads better), to make it fully clear that this is a virtual function override.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's discuss making that style change separately. We already have quite a few uses of final
without override
.
<%- camelize(type) %>Layer(const <%- camelize(type) %>Layer&) = delete; | ||
Mutable<Impl> mutableImpl() const; | ||
<%- camelize(type) %>Layer(Immutable<Impl>); | ||
std::unique_ptr<Layer> cloneRef(const std::string& id) const final; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same note about privatization here. I know they've been public before, so this may be a follow-up change.
include/mbgl/style/layer.hpp
Outdated
@@ -98,20 +91,30 @@ class Layer : public mbgl::util::noncopyable { | |||
} | |||
} | |||
|
|||
LayerType getType() const; | |||
const std::string& getID() const; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This returns a reference to a string, which is stored in the immutable implementation. Now that we're switching this frequently, it means that the reference can become invalid when you do something like this:
auto& id = layer->getID();
layer->setMaxZoom(2);
std::cout << id;
Instead of returning a reference to objects inside the frequently-changing Immutable, we should return the ID as a value.
|
||
template <class S> friend class Immutable; | ||
template <class S, class... Args> friend Mutable<S> makeMutable(Args&&...); | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mutable
/Immutable
is vulnerable to the following scenario: Contained type inherits from std::enable_shared_from_this
. It's now possible to obtain a shared_ptr
from the Mutable
object, convert that to an Immutable
, and continue to mutate the object with the previously obtained shared_ptr
handle. The same goes for EnableImmutableFromThis
. It seems like a promise that it can't keep...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well, sure. But you could also just hold onto the raw pointer from Mutable::get()
, a reference from Mutable::operator*
, const_cast
, .... There's no way to 100% prevent misuse in C++; that would require language support in the style of Rust borrow checking.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yup, but shared_ptr
indicates shared ownership, whereas the others don't.
src/mbgl/style/layer_impl.hpp
Outdated
@@ -30,24 +27,17 @@ namespace style { | |||
* Members that are public in `FooLayer::Impl` are part of the internal API for "foo" layers. | |||
* Members that are private in `FooLayer::Impl` are internal to "foo" layers. | |||
*/ | |||
class Layer::Impl { | |||
class Layer::Impl : public EnableImmutableFromThis<Layer::Impl> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This allows converting an existing object to an Immutable, but this object has many mutable fields that cut be mutated from the original handle.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
EnableImmutableFromThis
is required only for Source::Impl::createRenderSource
and Layer::Impl::createRenderLayer
. It's probably a good idea to change how those operations are performed so that EnableImmutableFromThis
isn't necessary. I see two options:
- Require passing an
Immutable<Impl>
self reference to those methods (3e7ce6ba27b31a73a9242e4e14e8eaacefe42a5e). I'm not crazy about this because it allows the possibility of passing some other reference that doesn't matchthis
. - Replace the virtual dispatch with a static dispatch -- switch statement or
Layer::accept
.
return longest_common_subsequence(a, endA, b, endB, outIt, std::equal_to<>()); | ||
} | ||
|
||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This file could use a lot more documentation
3db6ac8
to
38d1677
Compare
Bizarre link error on linux builds:
Seems totally unrelated to any of the changes in cebc5f11cd834a6cf478b267df5f436ab5fd7362. |
Avoid dangling references in the following sequence: auto& id = layer->getID(); layer->setMaxZoom(2); std::cout << id; The reference would be dangling because mutating the layer allocates a new Immutable impl, and there may be no references to the prior impl, which held the id.
…create * Eliminates the need for EnableImmutableFromThis * Eliminates the dependency of {Source,Layer}::Impl on corresponding Render class (circular dependency)
9fffcd3
to
e859904
Compare
Implements immutability for:
Light::Impl
Source::Impl
and subclassesLayer::Impl
and subclassesRefs #8820