7 #include "flutter/fml/trace_event.h"
40 const std::weak_ptr<Context>& context,
41 std::weak_ptr<android::SurfaceControl> surface_control,
44 size_t swapchain_image_count) {
45 auto impl = std::shared_ptr<AHBSwapchainImplVK>(
47 enable_msaa, swapchain_image_count));
48 return impl->IsValid() ? impl :
nullptr;
52 const std::weak_ptr<Context>& context,
53 std::weak_ptr<android::SurfaceControl> surface_control,
56 size_t swapchain_image_count)
57 : surface_control_(
std::move(surface_control)),
61 std::make_shared<AHBTexturePoolVK>(context, desc_, swapchain_image_count);
62 if (!pool_->IsValid()) {
65 transients_ = std::make_shared<SwapchainTransientsVK>(
68 auto control = surface_control_.lock();
69 is_valid_ = control && control->IsValid();
89 TRACE_EVENT0(
"impeller",
"CompositorPendingWait");
90 if (!pending_presents_->Wait()) {
96 AutoSemaSignaler auto_sema_signaler =
97 std::make_shared<fml::ScopedCleanupClosure>(
98 [sema = pending_presents_]() { sema->Signal(); });
104 auto pool_entry = pool_->Pop();
106 if (!pool_entry.IsValid()) {
113 if (!SubmitWaitForRenderReady(pool_entry.render_ready_fence,
114 pool_entry.texture)) {
120 auto context = transients_->GetContext().lock();
127 transients_, pool_entry.texture,
128 [signaler = auto_sema_signaler, weak = weak_from_this(),
129 texture = pool_entry.texture]() {
130 auto thiz = weak.lock();
132 VALIDATION_LOG <<
"Swapchain died before image could be presented.";
135 return thiz->Present(signaler, texture);
145 bool AHBSwapchainImplVK::Present(
146 const AutoSemaSignaler& signaler,
147 const std::shared_ptr<AHBTextureSourceVK>& texture) {
148 auto control = surface_control_.lock();
149 if (!control || !control->IsValid()) {
150 VALIDATION_LOG <<
"Surface control died before swapchain image could be "
156 auto context = transients_->GetContext().lock();
158 ContextVK::Cast(*context).GetGPUTracer()->MarkFrameEnd();
166 auto fence = SubmitSignalForPresentReady(texture);
173 android::SurfaceTransaction transaction;
174 if (!transaction.SetContents(control.get(),
175 texture->GetBackingStore(),
178 VALIDATION_LOG <<
"Could not set swapchain image contents on the surface "
182 return transaction.Apply([signaler, texture, weak = weak_from_this()](
183 ASurfaceTransactionStats* stats) {
184 auto thiz = weak.lock();
188 thiz->OnTextureUpdatedOnSurfaceControl(signaler, texture, stats);
192 void AHBSwapchainImplVK::AddFinalCommandBuffer(
193 std::shared_ptr<CommandBuffer> cmd_buffer) {
194 frame_data_[frame_index_].command_buffer = std::move(cmd_buffer);
197 std::shared_ptr<ExternalFenceVK>
198 AHBSwapchainImplVK::SubmitSignalForPresentReady(
199 const std::shared_ptr<AHBTextureSourceVK>& texture)
const {
200 auto context = transients_->GetContext().lock();
204 auto fence = std::make_shared<ExternalFenceVK>(context);
205 if (!fence || !fence->IsValid()) {
209 auto command_buffer = frame_data_[frame_index_].command_buffer;
210 if (!command_buffer) {
213 CommandBufferVK& command_buffer_vk = CommandBufferVK::Cast(*command_buffer);
214 const auto command_encoder_vk = command_buffer_vk.GetCommandBuffer();
215 command_buffer_vk.Track(fence->GetSharedHandle());
217 if (!command_buffer_vk.EndCommandBuffer()) {
221 vk::SubmitInfo submit_info;
222 vk::PipelineStageFlags wait_stage =
223 vk::PipelineStageFlagBits::eColorAttachmentOutput;
224 if (frame_data_[frame_index_].semaphore) {
225 submit_info.setPWaitSemaphores(&frame_data_[frame_index_].semaphore.get());
226 submit_info.setWaitSemaphoreCount(1);
227 submit_info.setWaitDstStageMask(wait_stage);
229 submit_info.setCommandBuffers(command_encoder_vk);
231 auto result = ContextVK::Cast(*context).GetGraphicsQueue()->Submit(
232 submit_info, fence->GetHandle());
233 if (result != vk::Result::eSuccess) {
239 vk::UniqueSemaphore AHBSwapchainImplVK::CreateRenderReadySemaphore(
240 const std::shared_ptr<fml::UniqueFD>& fd)
const {
241 if (!fd->is_valid()) {
245 auto context = transients_->GetContext().lock();
250 const auto& context_vk = ContextVK::Cast(*context);
251 const auto& device = context_vk.GetDevice();
253 auto signal_wait = device.createSemaphoreUnique({});
255 if (signal_wait.result != vk::Result::eSuccess) {
259 context_vk.SetDebugName(*signal_wait.value,
"AHBRenderReadySemaphore");
261 vk::ImportSemaphoreFdInfoKHR import_info;
262 import_info.semaphore = *signal_wait.value;
263 import_info.fd = fd->get();
264 import_info.handleType = vk::ExternalSemaphoreHandleTypeFlagBits::eSyncFd;
266 import_info.flags = vk::SemaphoreImportFlagBitsKHR::eTemporary;
268 const auto import_result = device.importSemaphoreFdKHR(import_info);
270 if (import_result != vk::Result::eSuccess) {
272 << vk::to_string(import_result);
280 [[maybe_unused]]
auto released = fd->release();
282 return std::move(signal_wait.value);
285 bool AHBSwapchainImplVK::SubmitWaitForRenderReady(
286 const std::shared_ptr<fml::UniqueFD>& render_ready_fence,
287 const std::shared_ptr<AHBTextureSourceVK>& texture) {
290 if (!render_ready_fence || !render_ready_fence->is_valid()) {
291 frame_data_[frame_index_].semaphore = {};
295 auto context = transients_->GetContext().lock();
300 auto semaphore = CreateRenderReadySemaphore(render_ready_fence);
306 frame_data_[frame_index_].semaphore = std::move(semaphore);
310 void AHBSwapchainImplVK::OnTextureUpdatedOnSurfaceControl(
311 const AutoSemaSignaler& signaler,
312 std::shared_ptr<AHBTextureSourceVK> texture,
313 ASurfaceTransactionStats* stats) {
314 auto control = surface_control_.lock();
321 auto render_ready_fence =
327 Lock lock(currently_displayed_texture_mutex_);
328 auto old_texture = currently_displayed_texture_;
329 currently_displayed_texture_ = std::move(texture);
330 pool_->Push(std::move(old_texture), std::move(render_ready_fence));
AHBSwapchainImplVK(const AHBSwapchainImplVK &)=delete
static std::shared_ptr< AHBSwapchainImplVK > Create(const std::weak_ptr< Context > &context, std::weak_ptr< android::SurfaceControl > surface_control, const ISize &size, bool enable_msaa, size_t swapchain_image_count)
Create a swapchain of a specific size whose images will be presented to the provided surface control.
std::unique_ptr< Surface > AcquireNextDrawable()
Acquire the next surface that can be used to present to the swapchain.
const android::HardwareBufferDescriptor & GetDescriptor() const
Get the descriptor used to create the hardware buffers that will be displayed on the surface control.
const ISize & GetSize() const
static ContextVK & Cast(Context &base)
std::shared_ptr< GPUTracerVK > GetGPUTracer() const
static std::unique_ptr< SurfaceVK > WrapSwapchainImage(const std::shared_ptr< SwapchainTransientsVK > &transients, const std::shared_ptr< TextureSourceVK > &swapchain_image, SwapCallback swap_callback)
Wrap the swapchain image in a Surface, which provides the additional configuration required for usage...
fml::UniqueFD CreatePreviousReleaseFence(const SurfaceControl &control, ASurfaceTransactionStats *stats)
static constexpr const size_t kMaxPendingPresents
static PixelFormat ToPixelFormat(AHardwareBuffer_Format format)
static TextureDescriptor ToSwapchainTextureDescriptor(const android::HardwareBufferDescriptor &ahb_desc)
A lightweight object that describes the attributes of a texture that can then used an allocator to cr...
CompressionType compression_type
A descriptor use to specify hardware buffer allocations.
static HardwareBufferDescriptor MakeForSwapchainImage(const ISize &size)
Create a descriptor of the given size that is suitable for use as a swapchain image.
HardwareBufferFormat format