Fixes https://github.com/flutter/flutter/issues/158963
If the GLES version is at least 3, then we can attach a sync fence to the texture gles object. If this operation succeeds, then we can use gl.Flush instad of gl.Finish. Then, when binding the texture - if a sync fence is present we wait and then remove the fence.
Threads that add operations to the ReactorGLES assume that those operations will be executed serially.
But prior to this change, the ReactorGLES added all operations into one queue. The reactor would then execute those operations on any thread that can react. This could cause operations that were added to the reactor on the raster thread to be submitted to the GPU on the IO thread (or vice versa).
The reactor does not wait for the GPU to finish execution of those operations. So other operations added on the raster thread could be submitted by a reaction before the GPU has completed the operation that was submitted on the IO thread.
This PR ensures that operations added to the reactor on a given thread will be executed during a reaction on that same thread. If the thread can not currently react, then the operations will be queued until the thread enables reactions.
This also adds a call to CommandBuffer::WaitUntilScheduled to ImageDecoderImpeller. This ensures that the command buffer submitted on the IO thread is flushed before the image is returned.
Fixes https://github.com/flutter/flutter/issues/158535
Fixes https://github.com/flutter/flutter/issues/158388
Fixes https://github.com/flutter/flutter/issues/158390
Reland of: https://github.com/flutter/engine/pull/50139
Metal does not seem to like it when we collect 50+ command buffers at once. Adjust the aiks context logic to regularly flush the cmd buffers.
Reverts flutter/engine#50139
Initiated by: jonahwilliams
This change reverts the following previous change:
Original Description:
The Impeller Vulkan backend benefits from batching submission to the vk graphics queue. Managing this automatically is non-trivial and adds surprising/fragile thread based behavior, see: https://github.com/flutter/engine/pull/49870
Instead, introduce an impeller::CommandQueue object that command buffers must be submitted to in lieu of CommandBuffer->Submit, which has been made private.
TLDR
old
```c++
buffer->Submit();
```
new
```c++
context.GetQueue()->Submit({buffer});
```
The Metal and GLES implementations internally just call the private CommandBuffer->Submit, though there may be future opportunities to simplify here. The Vulkan implementation is where the meat is.
Aiks takes advantage of this by storing all command buffers on the aiks context while rendering a frame, and then performing one submit in aiks_context render. I don't think this will introduce any thread safety problems, as we don't guarantee much about aiks context - nor do we use it in a multithreaded context as far as I know.
Other tasks such as image upload still just directly submit their command buffers via the queue.
Fixes https://github.com/flutter/flutter/issues/141123
The Impeller Vulkan backend benefits from batching submission to the vk graphics queue. Managing this automatically is non-trivial and adds surprising/fragile thread based behavior, see: https://github.com/flutter/engine/pull/49870
Instead, introduce an impeller::CommandQueue object that command buffers must be submitted to in lieu of CommandBuffer->Submit, which has been made private.
TLDR
old
```c++
buffer->Submit();
```
new
```c++
context.GetQueue()->Submit({buffer});
```
The Metal and GLES implementations internally just call the private CommandBuffer->Submit, though there may be future opportunities to simplify here. The Vulkan implementation is where the meat is.
Aiks takes advantage of this by storing all command buffers on the aiks context while rendering a frame, and then performing one submit in aiks_context render. I don't think this will introduce any thread safety problems, as we don't guarantee much about aiks context - nor do we use it in a multithreaded context as far as I know.
Other tasks such as image upload still just directly submit their command buffers via the queue.
Fixes https://github.com/flutter/flutter/issues/141123
Part of https://github.com/flutter/flutter/issues/140804
Rather than using impeller::Command, the impeller::RenderPass records most state directly into the Vulkan command buffer. This should remove allocation/free overhead of the intermediary structures and make further improvements to the backend even easier.
This completely removes the background worker threads used for encoding, which should lower overall CPU usage without decreasing performance by much (though it may be a tad slower or a tad faster).
The original change was reverted as it broke the GPU tracer reset logic. The previous logic assumed that the first started command buffer would also be the first submitted command buffer. With the direct encoding, this is no longer the case - so we shift the logic so that we reset query pools once at startup and then after the queries are finished being recorded.
This might actually be better in general since we should be doing less work in the frame workload.
Reverts flutter/engine#49780
Initiated by: jonahwilliams
This change reverts the following previous change:
Original Description:
Part of https://github.com/flutter/flutter/issues/140804
Rather than using impeller::Command, the impeller::RenderPass records most state directly into the Vulkan command buffer. This should remove allocation/free overhead of the intermediary structures and make further improvements to the backend even easier. This required a number of other changes to the renderer:
1. The render pass holds a strong ptr to the context. This helps avoid locking continually while encoding, which is quite slow.
2. barriers need to be encoded on the _producing_ side, and not the consuming side. This is because we'll actually run the consuming code before the producing code. i.e. we transition to shader read at the end of a render pass instead of when binding.
3. I've updated the binding code to also provide the descriptor type so that we don't need to look it up from the desc. set.
4. I added a test render pass class that records commands.
Part of https://github.com/flutter/flutter/issues/140804
Rather than using impeller::Command, the impeller::RenderPass records most state directly into the Vulkan command buffer. This should remove allocation/free overhead of the intermediary structures and make further improvements to the backend even easier. This required a number of other changes to the renderer:
1. The render pass holds a strong ptr to the context. This helps avoid locking continually while encoding, which is quite slow.
2. barriers need to be encoded on the _producing_ side, and not the consuming side. This is because we'll actually run the consuming code before the producing code. i.e. we transition to shader read at the end of a render pass instead of when binding.
3. I've updated the binding code to also provide the descriptor type so that we don't need to look it up from the desc. set.
4. I added a test render pass class that records commands.
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
VkCommandBuffers are allocated out of a thread local VkCommandPool. THis command buffer is only safe to use on the thread which allocates it.
We'd like to attempt concurrent encoding on Vulkan like we've done for iOS, which means the worker threads will be accessing the VkCommandBuffer. In order for this to be safe, the VkCommandBuffer must be allocated out of a VkCommandPool from that worker thread. As a simple fix, we make the Impeller CommandBuffer defer construction of the VkCommandBuffer object, allowing us to record impeller commands on the raster thread, move the command buffer to a worker thread, create the VkCommandBuffer, and then begin encoding.
This makes the submission simpler as the allocators can be acquired from the
pass itself.
Also makes command buffer submission go through a common method that performs
error checking before dispatch to the backend.