Fixes: https://github.com/flutter/flutter/issues/138877
The existing golden tests were already showing this bug, but we didn't see it. With this fix the size of the squares should be the same as the circle for the round caps in the DrawPoints playground goldens.
Test exemption request: This fix is covered by existing golden tests.
Note: The GPU tesselation for drawPoints is disabled in this test PR, but will be re-enabled when I can run some benchmarks to see where a good cutoff exists.
Tessellation for circular or quarter circular paths is now handled by a single tessellator class that provides services for DrawCircle, DrawPoints (round caps), and DrawLines (round caps). Creating a general path is avoided along with the associated overhead of recognizing and using a generic tessellation step.
This test worked by 1) releasing an item to be destructed on a background thead 2) adding a second item to this queue with a waitable event.
The idea being you could wait for the event and that would tell you when 1) was complete. Unfortunately these items are released by being placed into a std::vector, which destroyed in _reverse_ order. Somtimes when the test state was queried the work was done and sometimes it wasn't
To fix this, add a second waitable event that guarantees that both the first event and the original event have finished - because we do not add these event until the first is destructed and we do not add items to the destroy list while it is in progress.
The Impeller blur is scaling down about twice as fast as the Skia Blur. Instead adopt their approximate constant values, which results in less shaking as the blur gets bigger.
FYI @gaaclarke
Like command pools, descriptor pools can be reset on a background thread and reused to improve CPU efficiency. Unlike command pools, we create one per render pass, so the existing management of the lifecycle is handled via the Tracked objects and we need only adapt the easier parts of the command pool reset.
To make the caching more effective, we change descriptor pool allocation to round up to NPOT. this is so if we have a frame with varying numbers of draws : 33, 42, 16, 45, we still end up recycling and reusing the descriptor pool (its just a bit of extra memory).
Fixes https://github.com/flutter/flutter/issues/134968
This benchmark includes things like allocating geometry/contents, path conversions, et cetera. It doesn't include dispatching or GPU work, but should make it easier to see improvements/regressions in the efficiency of this code.
This extension only implies decal support for OES textures. Remove it from the check for generic decal support.
In practice i think it would be unlikely that a driver supports this and not regular decal, but that would only make the bugs this may cause even harder to track down.
First triangle, in the framework! 🎉
Adds shader libraries, pipelines, command buffers, render passes, etc.
* Light pipelines/shader objects. No optimization yet, pipeline warming
to come.
* "Dynamic" command style. Don't re-send bindings if you don't need to.
Essentially: https://github.com/flutter/flutter/issues/133179
* No need to explicitly encode passes.
* Minimal descriptor usage.
* Nothing is async, except for the optional command buffer completion
callback.
It took a bunch of experimenting to get here, but I think things are
starting to look pretty neat. :)
Todo:
* Land the shader bundle format/remove the testing hacks & fixtures that
piggyback off of the runtime effect system.
* Add remaining calls for blend config, clearing bindings, etc.
* Inconsistent error handling patterns that need cleanup.
* Maybe: Surface exceptions for validation errors.
* Handle the texture usage bitmask more elegantly.
Fixes https://github.com/flutter/flutter/issues/138373
When constructing overlay layers when there are platform views, make sure the same pixel format and color space as the main view is used.
Add validation to impeller HAL about blitting different pixel formats.
Commands are massive 500 byte objects, re-allocating this vector while recording them can actually add a substantial amount of overhead to applications with lots of drawing commands. Sizing to npot so that underestimating by a few commands doesn't force us to immediately copy all command objects.
This is still a herustic driven approach. An alternative exact approach would have entities/contents describe how many commands they would add. This may be more important for stencil then cover (depending on how we do it) since some contents would need to create two commands.
Some discussion here:
https://discord.com/channels/608014603317936148/1175215129135153202.
In short, `*<std::optional>` is [undefined
behavior](https://en.cppreference.com/w/cpp/utility/optional/operator*).
After talking to @bdero we are considering that this should never
happen.
I thought of a few different approaches here, none of them are great.
However given that this class is used quite minimally, this seems to
jive with similar patterns we're using in scene/scene_context.
---
Feel free to push back or suggest alternatives, mostly proposing this to
get brain juices flowing.
* Removed virtual destructor. We only use Geometry types with std::shared_ptr which remembers the correct dtor, we'd only need the virtual destructor if we were using `free` ourselves.
* Remove std:unique_ptr. We had a mix on unique and shared ptrs, and were even doing some copies/conversions between the two. I made it consistently shared_ptr, I don't see the advantage of unique given that geometries are essentially immutable.
* made geometry classes have more const methods and final.
* Added some asserts on trivial destruction.
A partial implementation of the new gaussian blur effect. This should perform enough of the code to start getting some performance numbers.
Known outstanding problems:
1) The edges of the blur are clipped. I have notes on how I plan on expanding render space in the PR.
1) Animating the sigma causes some "jumping around artifacts" resulting from the downsampling (maybe the discrete nature of texture pixel size?)
1) Coverage hints are ignored. I think depth tests will make that not much of an issue.
1) We aren't ping ponging textures yet
1) The snapshot's transform is ignored.
issue: https://github.com/flutter/flutter/issues/131580
[C++, Objective-C, Java style guides]: https://github.com/flutter/engine/blob/main/CONTRIBUTING.md#style
Had not used std::adopt_lock before and didn't realize that the unique lock destructor unlocks the mutex even when the mutex is adopted (which I suppose makes sense when you think about it). But I had added the annotations assuming the lock will remain if adopted. Found after a painful round of debugging the "safe" condition variables.
Allow creating a TextureMTL instance that is backend by a CAMetalLayer, which only acquires the drawable (and texture) lazily.
I split TextureMTL into two subclasses, one that has the standard wrapping behavior of a MTLTexture, and the other that holds a drawable. This is part of the foundational work for "removing drawable acquisition latency", as we need to delay aquisition of the drawable texture to a worker thread.
The drawable backed texture is only used in tests for now.
Part of https://github.com/flutter/flutter/issues/138490
This is a requirement for the "Remove Drawable Acquisition Latency" Change, but is otherwise a harmless improvement.
---
Submitting a command buffer causes the backend specific encoding logic to run. Metal is unique in that it is fairly easy to move this work into a background thread, allowing the engine to move onto creating the next command buffer. This improves throughput of the engine, at the cost of needing two slightly different APIs. Currently the GLES and Vulkan versions of this method still submit synchronously - for now that is out of scope as doing background work with those APIs has proved more challenging.
See also:
* https://github.com/flutter/engine/pull/42028
* https://github.com/flutter/flutter/issues/131698
Separately, as a requirement for the design in "Remove Drawable Acquisition Latency", we need to be able to defer drawable acquisition to this background thread. While this almost already works for render passes, it does not work for blit passes today. if the engine renders a backdrop filter, then the final command buffer submitted will be a blit pass that copies an offscreen onto the drawable. Therefore we need to add an async version of the blit submission, so that we have a hook to move the drawable acquisition onto a background thread for metal.
This hadn't been done until now because most blit cmd buffers have 1 or 2 cmds on them so the benefit of moving to a background thread is minimal.
Part of https://github.com/flutter/flutter/issues/138490
Usage of Scalar/Vector/Half types is desgned around implicit conversions today: we don't specifically convert to the correct generated header types, since that will depend on the target platform. Instead we rely on implicit conversions to handle this - any mistake there would still lead to a compilation error.
Impeller implements the DrawLine primitive as DrawPath on a path containing a single line. Benchmarks show that this can cost 30% overhead on apps that use a lot of DrawLine primitives. This PR creates a more direct Entity that can tesselate the geometry of a line directly.
The reduced overhead should help with https://github.com/flutter/flutter/issues/138004
The current code will back off to Path rendering for round caps. When the circle geometry work is finished (https://github.com/flutter/engine/pull/47845) we can come back and implement round caps using the code refactored in that PR.