Separate rendering part from specification part for layers#8797
Conversation
9194b7a to
3ab7f47
Compare
jfirebaugh
left a comment
There was a problem hiding this comment.
Looks great overall! The most significant feedback I have is about ownership of the Layer::Impl -- I don't think we need to introduce shared pointers yet.
Public LayerType enum is fine. 👍 on moving rendering related source files.
|
|
||
| // Private implementation | ||
| const std::unique_ptr<Impl> baseImpl; | ||
| const std::shared_ptr<Impl> baseImpl; |
There was a problem hiding this comment.
If we go the route of using immutable objects, we may use shared pointers internally (albeit probably behind an Immutable<T> class template), but for now let's keep the Layer owning the Impl uniquely. RenderLayers should never outlive their associated Layer and can therefore have a regular non-owning const Impl& reference.
There was a problem hiding this comment.
RenderLayersshould never outlive their associatedLayer
Just realized this isn't the case. RenderLayers copied into the worker may outlive the Layer. Need to think about this.
There was a problem hiding this comment.
Per chat: good solution is probably to continue to pass copies of Layers to the worker, rather than RenderLayers. The worker can then create its own RenderLayers, allowing us to preserve the invariant "RenderLayers never outlive their associated Layer" and avoid (unintentionally) sharing a Layer::Impl between the main thread and worker.
There was a problem hiding this comment.
@jfirebaugh If we copy layers in GeometryTile to pass to GeometryTileWorker::setLayers and then create RenderLayers from that in the GeometryTileWorker; we would be copying the associated Impl twice right? In that case, maybe we should revert the changes to GeometryTileWorker and group_by_layout.hpp to continue to work on Layers?
There was a problem hiding this comment.
@jfirebaugh I Fixed up ownership as discussed above in 7f0ad32. I Left the pointers to the concrete Implementations in the subclasses as is (const style::FooLayer::Impl* const impl; as opposed to a const style::FooLayer::Impl&) to avoid modifying all call sites.
There was a problem hiding this comment.
@jfirebaugh This does not work as hoped. Since the Layer::Impl subclasses no longer contain a reference to the cascaded/evaluated paint properties, the render layers created in the GeometryTileWorker start with a blank copy, disjointed from the copy in the render layers in the style.
There was a problem hiding this comment.
Do we actually need the cascaded/evaluated paint properties? Evaluated paint properties can be generated from the cascaded paint properties plus tile zoom level. With regards to cascaded properties, cascading would mainly be needed in supporting the combination of data-driven paint properties with style classes, which I don't think we support.
There was a problem hiding this comment.
@jfirebaugh I figured this must be the reason that all the property-function render tests are failing. It makes me think it's because there is some state now not copied over / held on to when creating the buckets (since that is the main change).
If I understand correctly; in the painter the paint property binders (created in the bucket from the copied paint properties) and the evaluated paint properties form the Layer::Impl come together and then in the program the current properties are bound to attributes and interpolated from the values the binders were originally created with right?
There was a problem hiding this comment.
c397125 fixes the render tests.
It's true that the current paint properties are inspected at render time as well as the binder, but it's either one or the other:
- If the current value is a constant or camera function, it's used and the value the binder was originally created from is ignored.
- Otherwise, the value the binder was originally created from is used, and the current value is ignored.
| { | ||
|
|
||
| const SymbolLayer::Impl& leader = *layers.at(0)->as<SymbolLayer>()->impl; | ||
| const auto& leader = *layers.at(0)->as<RenderSymbolLayer>()->impl; |
There was a problem hiding this comment.
Don't use auto unless the type is written elsewhere in the same line (e.g. assigning from the result of std::make_unique) or is uninteresting (iterators). Here explicitly specifying SymbolLayer::Impl aids readability.
|
|
||
| // Create a new layer with the specified `id` and `sourceID`. All other properties | ||
| // are copied from this layer. | ||
| // TODO: evaluate if this still meets expectations |
There was a problem hiding this comment.
copy is only used in one place: StyleSourcedAnnotationImpl, which is code supporting a pre-runtime styling feature that we should remove. We can save that for a separate change though.
| } | ||
|
|
||
| // TODO | ||
| // auto layer = std::move(*it); |
There was a problem hiding this comment.
This can be deleted. When a custom layer is removed, the custom layer deinitialize function only needs to be called once.
|
|
||
| std::unique_ptr<Bucket> createBucket(const BucketParameters&, const std::vector<const Layer*>&) const override; | ||
| std::unique_ptr<SymbolLayout> createLayout(const BucketParameters&, const std::vector<const Layer*>&, | ||
| // TODO move to RenderSymbolLayer? |
There was a problem hiding this comment.
Yes, it should. This is the symbol layer equivalent of createBucket.
c397125 to
4fde1da
Compare
4fde1da to
2677a3a
Compare
|
@jfirebaugh I update the pr with your review comments. I refrained from moving more files to the renderer package for now as the ones I had my eye on are all referred to from |
In an attempt to separate rendering on a different thread..
Open ends:
Use ofstd::enable_shared_from_thiseg here so we can do thisLayer::Typein a separate header to re-use it forRenderLayersubclasses. This makes it public though.Maybe we should just duplicate it, especially if we want this to be part of the public API./rendererpackage:cc @jfirebaugh