diff --git a/engine/src/flutter/ci/licenses_golden/licenses_flutter b/engine/src/flutter/ci/licenses_golden/licenses_flutter index 6377aad2d8..4217faaa8b 100644 --- a/engine/src/flutter/ci/licenses_golden/licenses_flutter +++ b/engine/src/flutter/ci/licenses_golden/licenses_flutter @@ -1492,6 +1492,8 @@ ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/pipeline_library_vk.cc ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/pipeline_library_vk.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/pipeline_vk.cc + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/pipeline_vk.h + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/queue_vk.cc + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/queue_vk.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/render_pass_vk.cc + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/render_pass_vk.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/sampler_library_vk.cc + ../../../flutter/LICENSE @@ -4069,6 +4071,8 @@ FILE: ../../../flutter/impeller/renderer/backend/vulkan/pipeline_library_vk.cc FILE: ../../../flutter/impeller/renderer/backend/vulkan/pipeline_library_vk.h FILE: ../../../flutter/impeller/renderer/backend/vulkan/pipeline_vk.cc FILE: ../../../flutter/impeller/renderer/backend/vulkan/pipeline_vk.h +FILE: ../../../flutter/impeller/renderer/backend/vulkan/queue_vk.cc +FILE: ../../../flutter/impeller/renderer/backend/vulkan/queue_vk.h FILE: ../../../flutter/impeller/renderer/backend/vulkan/render_pass_vk.cc FILE: ../../../flutter/impeller/renderer/backend/vulkan/render_pass_vk.h FILE: ../../../flutter/impeller/renderer/backend/vulkan/sampler_library_vk.cc diff --git a/engine/src/flutter/impeller/renderer/backend/vulkan/BUILD.gn b/engine/src/flutter/impeller/renderer/backend/vulkan/BUILD.gn index 2e9a091030..303d5f6f1c 100644 --- a/engine/src/flutter/impeller/renderer/backend/vulkan/BUILD.gn +++ b/engine/src/flutter/impeller/renderer/backend/vulkan/BUILD.gn @@ -38,6 +38,8 @@ impeller_component("vulkan") { "pipeline_library_vk.h", "pipeline_vk.cc", "pipeline_vk.h", + "queue_vk.cc", + "queue_vk.h", "render_pass_vk.cc", "render_pass_vk.h", "sampler_library_vk.cc", diff --git a/engine/src/flutter/impeller/renderer/backend/vulkan/command_encoder_vk.cc b/engine/src/flutter/impeller/renderer/backend/vulkan/command_encoder_vk.cc index 5539708330..35e0da71a9 100644 --- a/engine/src/flutter/impeller/renderer/backend/vulkan/command_encoder_vk.cc +++ b/engine/src/flutter/impeller/renderer/backend/vulkan/command_encoder_vk.cc @@ -82,12 +82,12 @@ class TrackedObjectsVK { }; CommandEncoderVK::CommandEncoderVK(vk::Device device, - vk::Queue queue, + const std::shared_ptr& queue, const std::shared_ptr& pool, std::shared_ptr fence_waiter) : fence_waiter_(std::move(fence_waiter)), tracked_objects_(std::make_shared(device, pool)) { - if (!fence_waiter_ || !tracked_objects_->IsValid()) { + if (!fence_waiter_ || !tracked_objects_->IsValid() || !queue) { return; } vk::CommandBufferBeginInfo begin_info; @@ -131,7 +131,7 @@ bool CommandEncoderVK::Submit() { vk::SubmitInfo submit_info; std::vector buffers = {command_buffer}; submit_info.setCommandBuffers(buffers); - if (queue_.submit(submit_info, *fence) != vk::Result::eSuccess) { + if (queue_->Submit(submit_info, *fence) != vk::Result::eSuccess) { return false; } @@ -207,9 +207,6 @@ void CommandEncoderVK::PushDebugGroup(const char* label) const { if (auto command_buffer = GetCommandBuffer()) { command_buffer.beginDebugUtilsLabelEXT(label_info); } - if (queue_) { - queue_.beginDebugUtilsLabelEXT(label_info); - } } void CommandEncoderVK::PopDebugGroup() const { @@ -219,9 +216,6 @@ void CommandEncoderVK::PopDebugGroup() const { if (auto command_buffer = GetCommandBuffer()) { command_buffer.endDebugUtilsLabelEXT(); } - if (queue_) { - queue_.endDebugUtilsLabelEXT(); - } } void CommandEncoderVK::InsertDebugMarker(const char* label) const { @@ -234,7 +228,7 @@ void CommandEncoderVK::InsertDebugMarker(const char* label) const { command_buffer.insertDebugUtilsLabelEXT(label_info); } if (queue_) { - queue_.insertDebugUtilsLabelEXT(label_info); + queue_->InsertDebugMarker(label); } } diff --git a/engine/src/flutter/impeller/renderer/backend/vulkan/command_encoder_vk.h b/engine/src/flutter/impeller/renderer/backend/vulkan/command_encoder_vk.h index 8db33b50c1..9e79fb36ee 100644 --- a/engine/src/flutter/impeller/renderer/backend/vulkan/command_encoder_vk.h +++ b/engine/src/flutter/impeller/renderer/backend/vulkan/command_encoder_vk.h @@ -10,6 +10,7 @@ #include "flutter/fml/macros.h" #include "impeller/renderer/backend/vulkan/command_pool_vk.h" #include "impeller/renderer/backend/vulkan/descriptor_pool_vk.h" +#include "impeller/renderer/backend/vulkan/queue_vk.h" #include "impeller/renderer/backend/vulkan/shared_object_vk.h" #include "impeller/renderer/backend/vulkan/vk.h" @@ -53,14 +54,13 @@ class CommandEncoderVK { friend class ContextVK; vk::Device device_ = {}; - vk::Queue queue_ = {}; - + std::shared_ptr queue_; std::shared_ptr fence_waiter_; std::shared_ptr tracked_objects_; bool is_valid_ = false; CommandEncoderVK(vk::Device device, - vk::Queue queue, + const std::shared_ptr& queue, const std::shared_ptr& pool, std::shared_ptr fence_waiter); diff --git a/engine/src/flutter/impeller/renderer/backend/vulkan/command_pool_vk.cc b/engine/src/flutter/impeller/renderer/backend/vulkan/command_pool_vk.cc index 5ed2ed4048..0ccac93548 100644 --- a/engine/src/flutter/impeller/renderer/backend/vulkan/command_pool_vk.cc +++ b/engine/src/flutter/impeller/renderer/backend/vulkan/command_pool_vk.cc @@ -70,7 +70,7 @@ CommandPoolVK::CommandPoolVK(const ContextVK* context) : owner_id_(std::this_thread::get_id()) { vk::CommandPoolCreateInfo pool_info; - pool_info.queueFamilyIndex = context->GetGraphicsQueueInfo().index; + pool_info.queueFamilyIndex = context->GetGraphicsQueue()->GetIndex().family; pool_info.flags = vk::CommandPoolCreateFlagBits::eTransient; auto pool = context->GetDevice().createCommandPoolUnique(pool_info); if (pool.result != vk::Result::eSuccess) { diff --git a/engine/src/flutter/impeller/renderer/backend/vulkan/context_vk.cc b/engine/src/flutter/impeller/renderer/backend/vulkan/context_vk.cc index 1497e47728..e0d65d0f76 100644 --- a/engine/src/flutter/impeller/renderer/backend/vulkan/context_vk.cc +++ b/engine/src/flutter/impeller/renderer/backend/vulkan/context_vk.cc @@ -50,7 +50,7 @@ static std::optional PickPhysicalDevice( } static std::vector GetQueueCreateInfos( - std::initializer_list queues) { + std::initializer_list queues) { std::map family_index_map; for (const auto& queue : queues) { family_index_map[queue.family] = 0; @@ -72,8 +72,8 @@ static std::vector GetQueueCreateInfos( return infos; } -static std::optional PickQueue(const vk::PhysicalDevice& device, - vk::QueueFlagBits flags) { +static std::optional PickQueue(const vk::PhysicalDevice& device, + vk::QueueFlagBits flags) { // This can be modified to ensure that dedicated queues are returned for each // queue type depending on support. const auto families = device.getQueueFamilyProperties(); @@ -81,7 +81,7 @@ static std::optional PickQueue(const vk::PhysicalDevice& device, if (!(families[i].queueFlags & flags)) { continue; } - return QueueVK{.family = i, .index = 0}; + return QueueIndexVK{.family = i, .index = 0}; } return std::nullopt; } @@ -331,6 +331,19 @@ void ContextVK::Setup(Settings settings) { return; } + //---------------------------------------------------------------------------- + /// Fetch the queues. + /// + QueuesVK queues(device.value.get(), // + graphics_queue.value(), // + compute_queue.value(), // + transfer_queue.value() // + ); + if (!queues.IsValid()) { + VALIDATION_LOG << "Could not fetch device queues."; + return; + } + //---------------------------------------------------------------------------- /// All done! /// @@ -342,15 +355,7 @@ void ContextVK::Setup(Settings settings) { shader_library_ = std::move(shader_library); sampler_library_ = std::move(sampler_library); pipeline_library_ = std::move(pipeline_library); - graphics_queue_ = - device_->getQueue(graphics_queue->family, graphics_queue->index); - compute_queue_ = - device_->getQueue(compute_queue->family, compute_queue->index); - transfer_queue_ = - device_->getQueue(transfer_queue->family, transfer_queue->index); - graphics_queue_info_ = graphics_queue.value(); - compute_queue_info_ = compute_queue.value(); - transfer_queue_info_ = transfer_queue.value(); + queues_ = std::move(queues); device_capabilities_ = std::move(caps); fence_waiter_ = std::move(fence_waiter); is_valid_ = true; @@ -360,11 +365,6 @@ void ContextVK::Setup(Settings settings) { /// messengers have had a chance to be setup. /// SetDebugName(device_.get(), device_.get(), "ImpellerDevice"); - SetDebugName(device_.get(), graphics_queue_, "ImpellerGraphicsQ"); - SetDebugName(device_.get(), compute_queue_, "ImpellerComputeQ"); - if (transfer_queue_ != graphics_queue_) { - SetDebugName(device_.get(), transfer_queue_, "ImpellerTransferQ"); - } } bool ContextVK::IsValid() const { @@ -451,12 +451,8 @@ const std::shared_ptr& ContextVK::GetCapabilities() const { return device_capabilities_; } -vk::Queue ContextVK::GetGraphicsQueue() const { - return graphics_queue_; -} - -QueueVK ContextVK::GetGraphicsQueueInfo() const { - return graphics_queue_info_; +const std::shared_ptr& ContextVK::GetGraphicsQueue() const { + return queues_.graphics_queue; } vk::PhysicalDevice ContextVK::GetPhysicalDevice() const { @@ -474,10 +470,10 @@ std::unique_ptr ContextVK::CreateGraphicsCommandEncoder() return nullptr; } auto encoder = std::unique_ptr(new CommandEncoderVK( - *device_, // - graphics_queue_, // - tls_pool, // - fence_waiter_ // + *device_, // + queues_.graphics_queue, // + tls_pool, // + fence_waiter_ // )); if (!encoder->IsValid()) { return nullptr; diff --git a/engine/src/flutter/impeller/renderer/backend/vulkan/context_vk.h b/engine/src/flutter/impeller/renderer/backend/vulkan/context_vk.h index 5c930ec688..b7dcc82067 100644 --- a/engine/src/flutter/impeller/renderer/backend/vulkan/context_vk.h +++ b/engine/src/flutter/impeller/renderer/backend/vulkan/context_vk.h @@ -13,6 +13,7 @@ #include "impeller/base/backend_cast.h" #include "impeller/core/formats.h" #include "impeller/renderer/backend/vulkan/pipeline_library_vk.h" +#include "impeller/renderer/backend/vulkan/queue_vk.h" #include "impeller/renderer/backend/vulkan/sampler_library_vk.h" #include "impeller/renderer/backend/vulkan/shader_library_vk.h" #include "impeller/renderer/backend/vulkan/swapchain_vk.h" @@ -110,9 +111,7 @@ class ContextVK final : public Context, public BackendCast { vk::UniqueSurfaceKHR CreateAndroidSurface(ANativeWindow* window) const; #endif // FML_OS_ANDROID - vk::Queue GetGraphicsQueue() const; - - QueueVK GetGraphicsQueueInfo() const; + const std::shared_ptr& GetGraphicsQueue() const; vk::PhysicalDevice GetPhysicalDevice() const; @@ -127,12 +126,7 @@ class ContextVK final : public Context, public BackendCast { std::shared_ptr shader_library_; std::shared_ptr sampler_library_; std::shared_ptr pipeline_library_; - vk::Queue graphics_queue_ = {}; - vk::Queue compute_queue_ = {}; - vk::Queue transfer_queue_ = {}; - QueueVK graphics_queue_info_ = {}; - QueueVK compute_queue_info_ = {}; - QueueVK transfer_queue_info_ = {}; + QueuesVK queues_; std::shared_ptr swapchain_; std::shared_ptr device_capabilities_; std::shared_ptr fence_waiter_; diff --git a/engine/src/flutter/impeller/renderer/backend/vulkan/fence_waiter_vk.cc b/engine/src/flutter/impeller/renderer/backend/vulkan/fence_waiter_vk.cc index 06c4c094cb..d3b027cf68 100644 --- a/engine/src/flutter/impeller/renderer/backend/vulkan/fence_waiter_vk.cc +++ b/engine/src/flutter/impeller/renderer/backend/vulkan/fence_waiter_vk.cc @@ -7,6 +7,7 @@ #include #include "flutter/fml/thread.h" +#include "flutter/fml/trace_event.h" namespace impeller { @@ -78,6 +79,7 @@ FenceWaiterVK::TrimAndCreateWaitSetLocked() { if (terminate_) { return std::nullopt; } + TRACE_EVENT0("impeller", "TrimFences"); std::vector fences; fences.reserve(wait_set_.size()); for (auto it = wait_set_.begin(); it != wait_set_.end();) { diff --git a/engine/src/flutter/impeller/renderer/backend/vulkan/queue_vk.cc b/engine/src/flutter/impeller/renderer/backend/vulkan/queue_vk.cc new file mode 100644 index 0000000000..a0c82344d1 --- /dev/null +++ b/engine/src/flutter/impeller/renderer/backend/vulkan/queue_vk.cc @@ -0,0 +1,74 @@ +// 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/renderer/backend/vulkan/queue_vk.h" + +#include "impeller/renderer/backend/vulkan/context_vk.h" + +namespace impeller { + +QueueVK::QueueVK(QueueIndexVK index, vk::Queue queue) + : index_(index), queue_(queue) {} + +QueueVK::~QueueVK() = default; + +const QueueIndexVK& QueueVK::GetIndex() const { + return index_; +} + +vk::Result QueueVK::Submit(const vk::SubmitInfo& submit_info, + const vk::Fence& fence) const { + Lock lock(queue_mutex_); + return queue_.submit(submit_info, fence); +} + +void QueueVK::InsertDebugMarker(const char* label) const { + if (!HasValidationLayers()) { + return; + } + vk::DebugUtilsLabelEXT label_info; + label_info.pLabelName = label; + Lock lock(queue_mutex_); + queue_.insertDebugUtilsLabelEXT(label_info); +} + +QueuesVK::QueuesVK() = default; + +QueuesVK::QueuesVK(const vk::Device& device, + QueueIndexVK graphics, + QueueIndexVK compute, + QueueIndexVK transfer) { + auto vk_graphics = device.getQueue(graphics.family, graphics.index); + auto vk_compute = device.getQueue(compute.family, compute.index); + auto vk_transfer = device.getQueue(transfer.family, transfer.index); + + // Always setup the graphics queue. + graphics_queue = std::make_shared(graphics, vk_graphics); + ContextVK::SetDebugName(device, vk_graphics, "ImpellerGraphicsQ"); + + // Setup the compute queue if its different from the graphics queue. + if (compute == graphics) { + compute_queue = graphics_queue; + } else { + compute_queue = std::make_shared(compute, vk_compute); + ContextVK::SetDebugName(device, vk_compute, "ImpellerComputeQ"); + } + + // Setup the transfer queue if its different from the graphics or compute + // queues. + if (transfer == graphics) { + transfer_queue = graphics_queue; + } else if (transfer == compute) { + transfer_queue = compute_queue; + } else { + transfer_queue = std::make_shared(transfer, vk_transfer); + ContextVK::SetDebugName(device, vk_transfer, "ImpellerTransferQ"); + } +} + +bool QueuesVK::IsValid() const { + return graphics_queue && compute_queue && transfer_queue; +} + +} // namespace impeller diff --git a/engine/src/flutter/impeller/renderer/backend/vulkan/queue_vk.h b/engine/src/flutter/impeller/renderer/backend/vulkan/queue_vk.h new file mode 100644 index 0000000000..6ba3b9116f --- /dev/null +++ b/engine/src/flutter/impeller/renderer/backend/vulkan/queue_vk.h @@ -0,0 +1,72 @@ +// 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. + +#pragma once + +#include + +#include "flutter/fml/macros.h" +#include "impeller/base/thread.h" +#include "impeller/renderer/backend/vulkan/vk.h" + +namespace impeller { + +struct QueueIndexVK { + size_t family = 0; + size_t index = 0; + + constexpr bool operator==(const QueueIndexVK& other) const { + return family == other.family && index == other.index; + } +}; + +//------------------------------------------------------------------------------ +/// @brief A thread safe object that can be used to access device queues. +/// If multiple objects are created with the same underlying queue, +/// then the external synchronization guarantees of Vulkan queues +/// cannot be met. So care must be taken the same device queue +/// doesn't form the basis of multiple `QueueVK`s. +/// +class QueueVK { + public: + QueueVK(QueueIndexVK index, vk::Queue queue); + + ~QueueVK(); + + const QueueIndexVK& GetIndex() const; + + vk::Result Submit(const vk::SubmitInfo& submit_info, + const vk::Fence& fence) const; + + void InsertDebugMarker(const char* label) const; + + private: + mutable Mutex queue_mutex_; + + const QueueIndexVK index_; + const vk::Queue queue_ IPLR_GUARDED_BY(queue_mutex_); + + FML_DISALLOW_COPY_AND_ASSIGN(QueueVK); +}; + +//------------------------------------------------------------------------------ +/// @brief The collection of queues used by the context. The queues may all +/// be the same. +/// +struct QueuesVK { + std::shared_ptr graphics_queue; + std::shared_ptr compute_queue; + std::shared_ptr transfer_queue; + + QueuesVK(); + + QueuesVK(const vk::Device& device, + QueueIndexVK graphics, + QueueIndexVK compute, + QueueIndexVK transfer); + + bool IsValid() const; +}; + +} // namespace impeller diff --git a/engine/src/flutter/impeller/renderer/backend/vulkan/swapchain_impl_vk.cc b/engine/src/flutter/impeller/renderer/backend/vulkan/swapchain_impl_vk.cc index 027c19ddb5..9e4deb598f 100644 --- a/engine/src/flutter/impeller/renderer/backend/vulkan/swapchain_impl_vk.cc +++ b/engine/src/flutter/impeller/renderer/backend/vulkan/swapchain_impl_vk.cc @@ -418,7 +418,7 @@ bool SwapchainImplVK::Present(const std::shared_ptr& image, submit_info.setWaitSemaphores(*sync->render_ready); submit_info.setSignalSemaphores(*sync->present_ready); auto result = - context.GetGraphicsQueue().submit(submit_info, *sync->acquire); + context.GetGraphicsQueue()->Submit(submit_info, *sync->acquire); if (result != vk::Result::eSuccess) { VALIDATION_LOG << "Could not wait on render semaphore: " << vk::to_string(result); diff --git a/engine/src/flutter/impeller/renderer/backend/vulkan/vk.h b/engine/src/flutter/impeller/renderer/backend/vulkan/vk.h index 788b41bb6f..3eef9a3cf6 100644 --- a/engine/src/flutter/impeller/renderer/backend/vulkan/vk.h +++ b/engine/src/flutter/impeller/renderer/backend/vulkan/vk.h @@ -69,12 +69,3 @@ static_assert(VK_HEADER_VERSION >= 215, "Vulkan headers must not be too old."); #include "flutter/flutter_vma/flutter_vma.h" - -namespace impeller { - -struct QueueVK { - size_t family = 0; - size_t index = 0; -}; - -} // namespace impeller