Join GitHub today
GitHub is home to over 50 million developers working together to host and review code, manage projects, and build software together.
Sign upTrack removed pipelines and expose them in the renderer. #2347
Conversation
|
Could we perhaps add a special value |
|
Looks like a compile error on CI - I haven't looked any deeper than that. |
We can if you feel strongly about it. Personally I prefer keeping the epoch map (which represent the continuous state of epochs whether they change or not, and that you look at when needed) and the removed pipelines (which are more like one-off events, and missing any of them can be a leak) separated because they represent information somewhat differently and the consumer of the API presumably doesn't do exactly the same things with them. The build error is odd, this code compiles locally and rustc is complaining that the document is not mutable while it is declared mut a few lines above. I wonder if the recent switch to rustc 1.23 fixed it. |
|
I just find this to be too verbose, especially considering that both flushes are very similar (and can be combined as I suggested). Leaving for @glennw to look over. |
|
We can address the verbosity of the API by storing the pipeline epoch map and the removed pipeline list in a |
|
I do think it's probably a good idea to keep them as separate concepts. It makes sense to me that the user would potentially care about removed pipelines, but not really care about rendered pipelines, in some cases. It does seem unfortunate that we effectively leak memory (in tiny amounts) if the user never calls those flush APIs, but that's maybe not a huge deal. Perhaps we could consider a single flush function that returns the two vectors to reduce the API surface? Or would it make sense for one or both of those vectors to be returned from either Either way, I don't feel strongly about any of the above - we can always iterate and improve on this later as required. So I'll delegate r+ to @nical and leave to work out with @kvark if he feels further changes are needed :) @bors-servo delegate+ |
|
|
|
I added a commit that does what I suggested in my previous comment. @kvark let me know if you feel better about this.
Agreed. I didn't feel bad enough about it that I'd add debug logic to track whether we render N frames without ever flushing the removed pipelines, but that would be easy to add. I think that it'd be error prone to just flush every frame unless we return the PipelineInfo in the render function. Whoever feels strongly about this can fix it as a followup, though. There are many more important things that we could be spending our time on. |
| RenderedDocument::new( | ||
| PipelineInfo { | ||
| epochs: self.pipeline_epoch_map.clone(), | ||
| removed_pipelines: replace(&mut self.removed_pipelines, Vec::new()), |
This comment has been minimized.
This comment has been minimized.
kvark
Jan 31, 2018
Member
wouldn't this suffer from the same problem we have with GPU cache, where the consistency of the system depends on strictly producing and consuming rendered documents in order? Instead, I'd like to see the backend being able to produce any number of rendered documents, and Renderer being able to skip any of them, and still be correct. At least the current GPU cache updates are structured this way.
This comment has been minimized.
This comment has been minimized.
nical
Jan 31, 2018
•
Author
Collaborator
On the render backend side I believe I made sure that ordering is preserved and notifications are not lost no matter which order we build the scenes and frames in (that's the reason why the removed pipelines vector goes through all of the various pieces of the render backend and not just the scene and/or frame context).
On the renderer side, I think that it works as long as all documents render to the same swap chain, in the sense that the goal is to notify removed pipelines at least one frame after the last time it was rendered, so even if we skip rendering a document but notify its removed pipelines, said pipelines have already been removed, won't be around next time we do render the document and can be safely removed, I think.
As far as ordering go when sending to the renderer, I think that there shouldn't be any mismatch because the information is passed along with the frame itself (isn't in an separate channel or something that would need extra synchronization).
So I believe that this should work as intended even if we don't render some documents as long as it's in one swap chain (when we support direct composition and friends we'll need to track this information per swap chain). Unless by skipping rendering a document you mean receive a document in the renderer but keep sending drawing the commands of its previous version, in which case we need to add some extra logic to manage that, probably by tracking this information per document in the renderer.
This comment has been minimized.
This comment has been minimized.
kvark
Jan 31, 2018
Member
My desire here is to have rendering independent of modelling. The backend should be able to spew as many frames as it needs, and the renderer should be able to consume any subset of those. This is reflected in the type system by the fact we don't mutate most of the things when producing a RenderedDocument.
This comment has been minimized.
This comment has been minimized.
nical
Jan 31, 2018
Author
Collaborator
I agree with this desire, I don't think this interferes.
Since removed pipelines aren't states that define the scene but really events associated to it that must be sent once, there is no getting around moving them through the pipeline which requires the events to be mutable.
In addition, we need these events to be ordered with frames that are sent to the renderer. By far the easiest way to preserve this ordering is to send the information along with the frames and require that the renderer (whether or not it ends up rendering the frames) at least collects the events and makes them available to the embedder.
To preserve the non-mutable ref to the scene we would need to track the removed pipelines in parallel to the scene instead of inside the scene, make sure that we associate the right list of removed pipelines with the right scene and not forget to send the removed pipelines of a given scene when we produce a frame out of it. That sounds a lot more error prone. If you care a lot about the scene being passed immutably, then I wouldn't be opposed to using a Cell for the removed pipelines vector.
This comment has been minimized.
This comment has been minimized.
kvark
Jan 31, 2018
Member
In addition, we need these events to be ordered with frames that are sent to the renderer.
They don't have to be 1:1. We only have to guarantee that a pipeline is not used after the removed pipeline event arrives. I see the situation exactly matching GPU cache updates, and I want the handling to be consistent. Can we have a single mechanism/entity responsible for those one-time updates? Perhaps, by extending and renaming UpdateGpuCache event or something. Just handle it all in the same way.
That sounds a lot more error prone.
This is much easier than you imply. We already have association of the Document - Scene.
| @@ -314,6 +314,7 @@ pub fn main_wrapper<E: Example>( | |||
|
|
|||
| renderer.update(); | |||
| renderer.render(framebuffer_size).unwrap(); | |||
| let _ = renderer.flush_pipeline_info(); | |||
This comment has been minimized.
This comment has been minimized.
| @@ -120,7 +120,7 @@ impl Document { | |||
| // this code is why we have `Option`, which is never `None` | |||
| let frame_builder = self.frame_ctx.create( | |||
| self.frame_builder.take().unwrap(), | |||
| &self.scene, | |||
| &mut self.scene, | |||
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
nical
Jan 31, 2018
Author
Collaborator
it's unfortunately needed to flush the removed pipelines out of the scene. Storing them in the scene itself is part of what helps making sure we don't mess up ordering if we modify a scene and render frames from previous versions. I don't think there is much we can do about the mutability here other than things like Cell which I find more worrying.
This comment has been minimized.
This comment has been minimized.
kvark
Jan 31, 2018
Member
Perhaps we could keep the list of removed pipelines in the Document itself as opposed to the Scene? There are two spots where remove_pipelines is called, so we aren't going to be doing much extra work, but the semantics of Scene would be better then.
| } | ||
|
|
||
| impl PipelineInfo { | ||
| pub fn new() -> Self { |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
|
@staktrace heads up this is an API breaking change. |
|
@nical please have that patch reviewed by somebody prior to merging this PR. |
|
@bors-servo r=glennw |
|
|
Track removed pipelines and expose them in the renderer. This information is useful to manage the lifetime of resources that are owned by the embedder and used by the renderer such as external images. Fixes #2345. <!-- Reviewable:start --> --- This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/webrender/2347) <!-- Reviewable:end -->
|
|
nical commentedJan 26, 2018
•
edited by larsbergstrom
This information is useful to manage the lifetime of resources that are owned by the embedder and used by the renderer such as external images.
Fixes #2345.
This change is