-
Notifications
You must be signed in to change notification settings - Fork 6k
WIP: [impeller] Add tessellation cache #44324
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -329,6 +329,7 @@ struct ContentContextOptions { | |
| }; | ||
|
|
||
| class Tessellator; | ||
| class TessellationCache; | ||
|
|
||
| class ContentContext { | ||
| public: | ||
|
|
@@ -342,6 +343,10 @@ class ContentContext { | |
|
|
||
| std::shared_ptr<Tessellator> GetTessellator() const; | ||
|
|
||
| TessellationCache& GetTessellationCache() const { | ||
| return *tessellation_cache_; | ||
| } | ||
|
|
||
| #ifdef IMPELLER_DEBUG | ||
| std::shared_ptr<Pipeline<PipelineDescriptor>> GetCheckerboardPipeline( | ||
| ContentContextOptions opts) const { | ||
|
|
@@ -853,6 +858,7 @@ class ContentContext { | |
|
|
||
| bool is_valid_ = false; | ||
| std::shared_ptr<Tessellator> tessellator_; | ||
| std::unique_ptr<TessellationCache> tessellation_cache_; | ||
|
Comment on lines
860
to
+861
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can we make the tessellation cache own the tessellator? |
||
| std::shared_ptr<scene::SceneContext> scene_context_; | ||
| bool wireframe_ = false; | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,70 @@ | ||
| // Copyright 2013 The Flutter Authors. All rights reserved. | ||
| // Use of this source code is governed by a BSD-style license that can be | ||
| // found in the LICENSE file. | ||
|
|
||
| #include "impeller/entity/contents/tessellation_cache.h" | ||
|
|
||
| #define IMPELLER_ENABLE_TESSELLATION_CACHE 1 | ||
|
|
||
| namespace impeller { | ||
|
|
||
| Path::Polyline TessellationCache::GetOrCreatePolyline( | ||
| const impeller::Path& path, | ||
| Scalar scale) { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If you take the exact scale as a cache key then animated transformations will thrash your cache each frame despite the vertices being almost unchanged. |
||
| #if IMPELLER_ENABLE_TESSELLATION_CACHE == 1 | ||
| auto path_identifier = path.GetPathIdentifier(); | ||
| if (!path_identifier) { | ||
| // We can't match path without a valid identifier. | ||
| return path.CreatePolyline(scale); | ||
| } | ||
| PolylineKey key{*path_identifier, scale}; | ||
| auto result = polyline_cache_.Get(key); | ||
| if (result) { | ||
| return *result; | ||
| } | ||
| auto polyline = path.CreatePolyline(scale); | ||
| polyline_cache_.Set(key, polyline); | ||
| return polyline; | ||
| #else | ||
| return path.CreatePolyline(scale); | ||
| #endif | ||
| } | ||
|
|
||
| Tessellator::Result TessellationCache::Tessellate( | ||
| const Tessellator& tesselator, | ||
| FillType fill_type, | ||
| const Path::Polyline& polyline, | ||
| const Tessellator::BuilderCallback& callback) { | ||
| #if IMPELLER_ENABLE_TESSELLATION_CACHE == 1 | ||
| auto path_identifier = polyline.original_path_identifier; | ||
| if (!path_identifier) { | ||
| return tesselator.Tessellate(fill_type, polyline, callback); | ||
| } | ||
|
|
||
| TessellatorKey key{*path_identifier, fill_type}; | ||
| auto result = tessellator_cache_.Get(key); | ||
| if (result) { | ||
| if (callback(result->vertices.data(), result->vertices.size(), | ||
| result->indices.data(), result->indices.size())) { | ||
| return Tessellator::Result::kSuccess; | ||
| } else { | ||
| return Tessellator::Result::kInputError; | ||
| } | ||
| } | ||
|
|
||
| return tesselator.Tessellate( | ||
| fill_type, polyline, | ||
| [&](const float* vertices, size_t vertices_size, const uint16_t* indices, | ||
| size_t indices_size) { | ||
| TessellatorData data; | ||
| data.vertices.assign(vertices, vertices + vertices_size); | ||
| data.indices.assign(indices, indices + indices_size); | ||
| tessellator_cache_.Set(key, data); | ||
| return callback(vertices, vertices_size, indices, indices_size); | ||
| }); | ||
| #else | ||
| return tesselator.Tessellate(fill_type, polyline, callback); | ||
| #endif | ||
|
Comment on lines
+55
to
+67
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It would be nice if the tessellation cache was a bit more general and could also cache data that was generated by compute. For an example, look at the draw points geometry. For that to work, it would likely have to be able to vend device buffers instead. On the other hand, we'll likely batch compute workloads in ways that make these buffers difficult to use. So perhaps only using the tessellation cache for the CPU bound workloads is the way forward. |
||
| } | ||
|
|
||
| } // namespace impeller | ||
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.
There is no concept of a frame, but you could probably use the concept of a particular presentation. See context_vk, this tracks increments in the swapchain. We might need to bring a similar concept out of the platform specific backend.