diff --git a/impeller/renderer/backend/vulkan/allocator_vk.cc b/impeller/renderer/backend/vulkan/allocator_vk.cc index 31f0f63e75d57..66cd2de602545 100644 --- a/impeller/renderer/backend/vulkan/allocator_vk.cc +++ b/impeller/renderer/backend/vulkan/allocator_vk.cc @@ -17,11 +17,11 @@ namespace impeller { AllocatorVK::AllocatorVK(std::weak_ptr context, uint32_t vulkan_api_version, const vk::PhysicalDevice& physical_device, - const vk::Device& logical_device, + const std::shared_ptr& device_holder, const vk::Instance& instance, PFN_vkGetInstanceProcAddr get_instance_proc_address, PFN_vkGetDeviceProcAddr get_device_proc_address) - : context_(std::move(context)), device_(logical_device) { + : context_(std::move(context)), device_holder_(device_holder) { vk_ = fml::MakeRefCounted(get_instance_proc_address); auto instance_handle = vulkan::VulkanHandle(instance); @@ -29,7 +29,8 @@ AllocatorVK::AllocatorVK(std::weak_ptr context, return; } - auto device_handle = vulkan::VulkanHandle(logical_device); + auto device_handle = + vulkan::VulkanHandle(device_holder->GetDevice()); if (!vk_->SetupDeviceProcAddresses(device_handle)) { return; } @@ -78,7 +79,7 @@ AllocatorVK::AllocatorVK(std::weak_ptr context, VmaAllocatorCreateInfo allocator_info = {}; allocator_info.vulkanApiVersion = vulkan_api_version; allocator_info.physicalDevice = physical_device; - allocator_info.device = logical_device; + allocator_info.device = device_holder->GetDevice(); allocator_info.instance = instance; allocator_info.pVulkanFunctions = &proc_table; @@ -333,10 +334,15 @@ std::shared_ptr AllocatorVK::OnCreateTexture( if (!IsValid()) { return nullptr; } - auto source = std::make_shared(desc, // - allocator_, // - device_ // - ); + auto device_holder = device_holder_.lock(); + if (!device_holder) { + return nullptr; + } + auto source = + std::make_shared(desc, // + allocator_, // + device_holder->GetDevice() // + ); if (!source->IsValid()) { return nullptr; } diff --git a/impeller/renderer/backend/vulkan/allocator_vk.h b/impeller/renderer/backend/vulkan/allocator_vk.h index 7b61a3f475a12..64b9ba4c2ac5c 100644 --- a/impeller/renderer/backend/vulkan/allocator_vk.h +++ b/impeller/renderer/backend/vulkan/allocator_vk.h @@ -10,6 +10,7 @@ #include "impeller/core/allocator.h" #include "impeller/renderer/backend/vulkan/context_vk.h" #include "impeller/renderer/backend/vulkan/device_buffer_vk.h" +#include "impeller/renderer/backend/vulkan/device_holder.h" #include "impeller/renderer/backend/vulkan/vk.h" #include @@ -27,14 +28,14 @@ class AllocatorVK final : public Allocator { fml::RefPtr vk_; VmaAllocator allocator_ = {}; std::weak_ptr context_; - vk::Device device_; + std::weak_ptr device_holder_; ISize max_texture_size_; bool is_valid_ = false; AllocatorVK(std::weak_ptr context, uint32_t vulkan_api_version, const vk::PhysicalDevice& physical_device, - const vk::Device& logical_device, + const std::shared_ptr& device_holder, const vk::Instance& instance, PFN_vkGetInstanceProcAddr get_instance_proc_address, PFN_vkGetDeviceProcAddr get_device_proc_address); diff --git a/impeller/renderer/backend/vulkan/blit_command_vk_unittests.cc b/impeller/renderer/backend/vulkan/blit_command_vk_unittests.cc index 63975c955e8dd..d3dc53848e350 100644 --- a/impeller/renderer/backend/vulkan/blit_command_vk_unittests.cc +++ b/impeller/renderer/backend/vulkan/blit_command_vk_unittests.cc @@ -13,7 +13,8 @@ namespace testing { TEST(BlitCommandVkTest, BlitCopyTextureToTextureCommandVK) { auto context = CreateMockVulkanContext(); auto pool = CommandPoolVK::GetThreadLocal(context.get()); - CommandEncoderVK encoder(context, context->GetGraphicsQueue(), pool, + CommandEncoderVK encoder(context->GetDeviceHolder(), + context->GetGraphicsQueue(), pool, context->GetFenceWaiter()); BlitCopyTextureToTextureCommandVK cmd; cmd.source = context->GetResourceAllocator()->CreateTexture({ @@ -31,7 +32,8 @@ TEST(BlitCommandVkTest, BlitCopyTextureToTextureCommandVK) { TEST(BlitCommandVkTest, BlitCopyTextureToBufferCommandVK) { auto context = CreateMockVulkanContext(); auto pool = CommandPoolVK::GetThreadLocal(context.get()); - CommandEncoderVK encoder(context, context->GetGraphicsQueue(), pool, + CommandEncoderVK encoder(context->GetDeviceHolder(), + context->GetGraphicsQueue(), pool, context->GetFenceWaiter()); BlitCopyTextureToBufferCommandVK cmd; cmd.source = context->GetResourceAllocator()->CreateTexture({ @@ -49,7 +51,8 @@ TEST(BlitCommandVkTest, BlitCopyTextureToBufferCommandVK) { TEST(BlitCommandVkTest, BlitGenerateMipmapCommandVK) { auto context = CreateMockVulkanContext(); auto pool = CommandPoolVK::GetThreadLocal(context.get()); - CommandEncoderVK encoder(context, context->GetGraphicsQueue(), pool, + CommandEncoderVK encoder(context->GetDeviceHolder(), + context->GetGraphicsQueue(), pool, context->GetFenceWaiter()); BlitGenerateMipmapCommandVK cmd; cmd.texture = context->GetResourceAllocator()->CreateTexture({ diff --git a/impeller/renderer/backend/vulkan/command_pool_vk.cc b/impeller/renderer/backend/vulkan/command_pool_vk.cc index d4453a3062716..505305fa60a63 100644 --- a/impeller/renderer/backend/vulkan/command_pool_vk.cc +++ b/impeller/renderer/backend/vulkan/command_pool_vk.cc @@ -78,7 +78,7 @@ CommandPoolVK::CommandPoolVK(const ContextVK* context) return; } - device_holder_ = context->weak_from_this(); + device_holder_ = context->GetDeviceHolder(); graphics_pool_ = std::move(pool.value); is_valid_ = true; } diff --git a/impeller/renderer/backend/vulkan/context_vk.cc b/impeller/renderer/backend/vulkan/context_vk.cc index 9230f8f4e5948..a46a7a1eaf671 100644 --- a/impeller/renderer/backend/vulkan/context_vk.cc +++ b/impeller/renderer/backend/vulkan/context_vk.cc @@ -107,8 +107,8 @@ uint64_t CalculateHash(void* ptr) { ContextVK::ContextVK() : hash_(CalculateHash(this)) {} ContextVK::~ContextVK() { - if (device_) { - [[maybe_unused]] auto result = device_->waitIdle(); + if (device_holder_->device) { + [[maybe_unused]] auto result = device_holder_->device->waitIdle(); } CommandPoolVK::ClearAllPools(this); } @@ -191,14 +191,17 @@ void ContextVK::Setup(Settings settings) { instance_info.setPApplicationInfo(&application_info); instance_info.setFlags(instance_flags); - auto instance = vk::createInstanceUnique(instance_info); - if (instance.result != vk::Result::eSuccess) { - VALIDATION_LOG << "Could not create Vulkan instance: " - << vk::to_string(instance.result); - return; + auto device_holder = std::make_shared(); + { + auto instance = vk::createInstanceUnique(instance_info); + if (instance.result != vk::Result::eSuccess) { + VALIDATION_LOG << "Could not create Vulkan instance: " + << vk::to_string(instance.result); + return; + } + device_holder->instance = std::move(instance.value); } - - dispatcher.init(instance.value.get()); + dispatcher.init(device_holder->instance.get()); //---------------------------------------------------------------------------- /// Setup the debug report. @@ -207,7 +210,7 @@ void ContextVK::Setup(Settings settings) { /// initialization issues. /// auto debug_report = - std::make_unique(*caps, instance.value.get()); + std::make_unique(*caps, device_holder->instance.get()); if (!debug_report->IsValid()) { VALIDATION_LOG << "Could not setup debug report."; @@ -217,21 +220,25 @@ void ContextVK::Setup(Settings settings) { //---------------------------------------------------------------------------- /// Pick the physical device. /// - auto physical_device = PickPhysicalDevice(*caps, instance.value.get()); - if (!physical_device.has_value()) { - VALIDATION_LOG << "No valid Vulkan device found."; - return; + { + auto physical_device = + PickPhysicalDevice(*caps, device_holder->instance.get()); + if (!physical_device.has_value()) { + VALIDATION_LOG << "No valid Vulkan device found."; + return; + } + device_holder->physical_device = std::move(physical_device.value()); } //---------------------------------------------------------------------------- /// Pick device queues. /// auto graphics_queue = - PickQueue(physical_device.value(), vk::QueueFlagBits::eGraphics); + PickQueue(device_holder->physical_device, vk::QueueFlagBits::eGraphics); auto transfer_queue = - PickQueue(physical_device.value(), vk::QueueFlagBits::eTransfer); + PickQueue(device_holder->physical_device, vk::QueueFlagBits::eTransfer); auto compute_queue = - PickQueue(physical_device.value(), vk::QueueFlagBits::eCompute); + PickQueue(device_holder->physical_device, vk::QueueFlagBits::eCompute); if (!graphics_queue.has_value()) { VALIDATION_LOG << "Could not pick graphics queue."; @@ -250,7 +257,7 @@ void ContextVK::Setup(Settings settings) { /// Create the logical device. /// auto enabled_device_extensions = - caps->GetRequiredDeviceExtensions(physical_device.value()); + caps->GetRequiredDeviceExtensions(device_holder->physical_device); if (!enabled_device_extensions.has_value()) { // This shouldn't happen since we already did device selection. But doesn't // hurt to check again. @@ -266,7 +273,7 @@ void ContextVK::Setup(Settings settings) { {graphics_queue.value(), compute_queue.value(), transfer_queue.value()}); const auto required_features = - caps->GetRequiredDeviceFeatures(physical_device.value()); + caps->GetRequiredDeviceFeatures(device_holder->physical_device); if (!required_features.has_value()) { // This shouldn't happen since the device can't be picked if this was not // true. But doesn't hurt to check. @@ -280,17 +287,17 @@ void ContextVK::Setup(Settings settings) { device_info.setPEnabledFeatures(&required_features.value()); // Device layers are deprecated and ignored. - auto device_result = physical_device->createDeviceUnique(device_info); - if (device_result.result != vk::Result::eSuccess) { - VALIDATION_LOG << "Could not create logical device."; - return; + { + auto device_result = + device_holder->physical_device.createDeviceUnique(device_info); + if (device_result.result != vk::Result::eSuccess) { + VALIDATION_LOG << "Could not create logical device."; + return; + } + device_holder->device = std::move(device_result.value); } - device_ = std::move(device_result.value); - // This makes sure that the device is deleted at the proper time if there is - // an error. - fml::ScopedCleanupClosure device_resetter([this]() { device_.reset(); }); - if (!caps->SetDevice(physical_device.value())) { + if (!caps->SetDevice(device_holder->physical_device)) { VALIDATION_LOG << "Capabilities could not be updated."; return; } @@ -301,9 +308,9 @@ void ContextVK::Setup(Settings settings) { auto allocator = std::shared_ptr(new AllocatorVK( weak_from_this(), // application_info.apiVersion, // - physical_device.value(), // - device_.get(), // - instance.value.get(), // + device_holder->physical_device, // + device_holder, // + device_holder->instance.get(), // dispatcher.vkGetInstanceProcAddr, // dispatcher.vkGetDeviceProcAddr // )); @@ -317,7 +324,7 @@ void ContextVK::Setup(Settings settings) { /// Setup the pipeline library. /// auto pipeline_library = std::shared_ptr( - new PipelineLibraryVK(shared_from_this(), // + new PipelineLibraryVK(device_holder, // caps, // std::move(settings.cache_directory), // worker_task_runner_ // @@ -329,10 +336,10 @@ void ContextVK::Setup(Settings settings) { } auto sampler_library = - std::shared_ptr(new SamplerLibraryVK(device_.get())); + std::shared_ptr(new SamplerLibraryVK(device_holder)); auto shader_library = std::shared_ptr( - new ShaderLibraryVK(weak_from_this(), // + new ShaderLibraryVK(device_holder, // settings.shader_libraries_data) // ); @@ -345,7 +352,7 @@ void ContextVK::Setup(Settings settings) { /// Create the fence waiter. /// auto fence_waiter = - std::shared_ptr(new FenceWaiterVK(device_.get())); + std::shared_ptr(new FenceWaiterVK(device_holder)); if (!fence_waiter->IsValid()) { VALIDATION_LOG << "Could not create fence waiter."; return; @@ -354,10 +361,10 @@ void ContextVK::Setup(Settings settings) { //---------------------------------------------------------------------------- /// Fetch the queues. /// - QueuesVK queues(device_.get(), // - graphics_queue.value(), // - compute_queue.value(), // - transfer_queue.value() // + QueuesVK queues(device_holder->device.get(), // + graphics_queue.value(), // + compute_queue.value(), // + transfer_queue.value() // ); if (!queues.IsValid()) { VALIDATION_LOG << "Could not fetch device queues."; @@ -365,16 +372,14 @@ void ContextVK::Setup(Settings settings) { } VkPhysicalDeviceProperties physical_device_properties; - dispatcher.vkGetPhysicalDeviceProperties(physical_device.value(), + dispatcher.vkGetPhysicalDeviceProperties(device_holder->physical_device, &physical_device_properties); //---------------------------------------------------------------------------- /// All done! /// - instance_ = std::move(instance.value); + device_holder_ = std::move(device_holder); debug_report_ = std::move(debug_report); - physical_device_ = physical_device.value(); - device_resetter.Release(); allocator_ = std::move(allocator); shader_library_ = std::move(shader_library); sampler_library_ = std::move(sampler_library); @@ -389,7 +394,7 @@ void ContextVK::Setup(Settings settings) { /// Label all the relevant objects. This happens after setup so that the debug /// messengers have had a chance to be setup. /// - SetDebugName(GetDevice(), device_.get(), "ImpellerDevice"); + SetDebugName(GetDevice(), device_holder_->device.get(), "ImpellerDevice"); } // |Context| @@ -429,11 +434,11 @@ std::shared_ptr ContextVK::CreateCommandBuffer() const { } vk::Instance ContextVK::GetInstance() const { - return *instance_; + return *device_holder_->instance; } const vk::Device& ContextVK::GetDevice() const { - return device_.get(); + return device_holder_->device.get(); } const std::shared_ptr @@ -454,12 +459,13 @@ std::unique_ptr ContextVK::AcquireNextSurface() { vk::UniqueSurfaceKHR ContextVK::CreateAndroidSurface( ANativeWindow* window) const { - if (!instance_) { + if (!device_holder_->instance) { return vk::UniqueSurfaceKHR{VK_NULL_HANDLE}; } auto create_info = vk::AndroidSurfaceCreateInfoKHR().setWindow(window); - auto surface_res = instance_->createAndroidSurfaceKHRUnique(create_info); + auto surface_res = + device_holder_->instance->createAndroidSurfaceKHRUnique(create_info); if (surface_res.result != vk::Result::eSuccess) { VALIDATION_LOG << "Could not create Android surface, error: " @@ -491,7 +497,7 @@ const std::shared_ptr& ContextVK::GetGraphicsQueue() const { } vk::PhysicalDevice ContextVK::GetPhysicalDevice() const { - return physical_device_; + return device_holder_->physical_device; } std::shared_ptr ContextVK::GetFenceWaiter() const { @@ -505,7 +511,7 @@ std::unique_ptr ContextVK::CreateGraphicsCommandEncoder() return nullptr; } auto encoder = std::unique_ptr(new CommandEncoderVK( - weak_from_this(), // + device_holder_, // queues_.graphics_queue, // tls_pool, // fence_waiter_ // diff --git a/impeller/renderer/backend/vulkan/context_vk.h b/impeller/renderer/backend/vulkan/context_vk.h index 71c3fbb63f565..53f51757903d3 100644 --- a/impeller/renderer/backend/vulkan/context_vk.h +++ b/impeller/renderer/backend/vulkan/context_vk.h @@ -33,7 +33,6 @@ class FenceWaiterVK; class ContextVK final : public Context, public BackendCast, - public DeviceHolder, public std::enable_shared_from_this { public: struct Settings { @@ -108,10 +107,13 @@ class ContextVK final : public Context, return true; } + std::shared_ptr GetDeviceHolder() const { + return device_holder_; + } + vk::Instance GetInstance() const; - // |DeviceHolder| - const vk::Device& GetDevice() const override; + const vk::Device& GetDevice() const; const std::shared_ptr GetConcurrentWorkerTaskRunner() const; @@ -131,10 +133,16 @@ class ContextVK final : public Context, std::shared_ptr GetFenceWaiter() const; private: - vk::UniqueInstance instance_; + struct DeviceHolderImpl : public DeviceHolder { + // |DeviceHolder| + const vk::Device& GetDevice() const override { return device.get(); } + vk::UniqueInstance instance; + vk::PhysicalDevice physical_device; + vk::UniqueDevice device; + }; + + std::shared_ptr device_holder_; std::unique_ptr debug_report_; - vk::PhysicalDevice physical_device_; - vk::UniqueDevice device_; std::shared_ptr allocator_; std::shared_ptr shader_library_; std::shared_ptr sampler_library_; diff --git a/impeller/renderer/backend/vulkan/fence_waiter_vk.cc b/impeller/renderer/backend/vulkan/fence_waiter_vk.cc index d3b027cf68db9..f17e5218d9175 100644 --- a/impeller/renderer/backend/vulkan/fence_waiter_vk.cc +++ b/impeller/renderer/backend/vulkan/fence_waiter_vk.cc @@ -11,7 +11,8 @@ namespace impeller { -FenceWaiterVK::FenceWaiterVK(vk::Device device) : device_(device) { +FenceWaiterVK::FenceWaiterVK(std::weak_ptr device_holder) + : device_holder_(device_holder) { waiter_thread_ = std::make_unique([&]() { Main(); }); is_valid_ = true; } @@ -51,7 +52,12 @@ void FenceWaiterVK::Main() { wait_set_cv_.wait(lock, [&]() { return !wait_set_.empty() || terminate_; }); - auto wait_set = TrimAndCreateWaitSetLocked(); + auto device_holder = device_holder_.lock(); + if (!device_holder) { + break; + } + + auto wait_set = TrimAndCreateWaitSetLocked(device_holder); lock.unlock(); @@ -62,7 +68,7 @@ void FenceWaiterVK::Main() { continue; } - auto result = device_.waitForFences( + auto result = device_holder->GetDevice().waitForFences( wait_set->size(), // fences count wait_set->data(), // fences false, // wait for all @@ -74,8 +80,8 @@ void FenceWaiterVK::Main() { } } -std::optional> -FenceWaiterVK::TrimAndCreateWaitSetLocked() { +std::optional> FenceWaiterVK::TrimAndCreateWaitSetLocked( + std::shared_ptr device_holder) { if (terminate_) { return std::nullopt; } @@ -83,7 +89,7 @@ FenceWaiterVK::TrimAndCreateWaitSetLocked() { std::vector fences; fences.reserve(wait_set_.size()); for (auto it = wait_set_.begin(); it != wait_set_.end();) { - switch (device_.getFenceStatus(it->first->Get())) { + switch (device_holder->GetDevice().getFenceStatus(it->first->Get())) { case vk::Result::eSuccess: // Signalled. it->second(); it = wait_set_.erase(it); diff --git a/impeller/renderer/backend/vulkan/fence_waiter_vk.h b/impeller/renderer/backend/vulkan/fence_waiter_vk.h index 0f5087f0d2514..aecc5a63a81cc 100644 --- a/impeller/renderer/backend/vulkan/fence_waiter_vk.h +++ b/impeller/renderer/backend/vulkan/fence_waiter_vk.h @@ -13,6 +13,7 @@ #include "flutter/fml/closure.h" #include "flutter/fml/macros.h" #include "impeller/base/thread.h" +#include "impeller/renderer/backend/vulkan/device_holder.h" #include "impeller/renderer/backend/vulkan/shared_object_vk.h" #include "impeller/renderer/backend/vulkan/vk.h" @@ -33,7 +34,7 @@ class FenceWaiterVK { private: friend class ContextVK; - const vk::Device device_; + std::weak_ptr device_holder_; std::unique_ptr waiter_thread_; std::mutex wait_set_mutex_; std::condition_variable wait_set_cv_; @@ -41,11 +42,12 @@ class FenceWaiterVK { bool terminate_ = false; bool is_valid_ = false; - explicit FenceWaiterVK(vk::Device device); + explicit FenceWaiterVK(std::weak_ptr device_holder); void Main(); - std::optional> TrimAndCreateWaitSetLocked(); + std::optional> TrimAndCreateWaitSetLocked( + std::shared_ptr device_holder); FML_DISALLOW_COPY_AND_ASSIGN(FenceWaiterVK); }; diff --git a/impeller/renderer/backend/vulkan/sampler_library_vk.cc b/impeller/renderer/backend/vulkan/sampler_library_vk.cc index 8d4c82e39cc15..c51829b8ec7ee 100644 --- a/impeller/renderer/backend/vulkan/sampler_library_vk.cc +++ b/impeller/renderer/backend/vulkan/sampler_library_vk.cc @@ -10,7 +10,9 @@ namespace impeller { -SamplerLibraryVK::SamplerLibraryVK(vk::Device device) : device_(device) {} +SamplerLibraryVK::SamplerLibraryVK( + const std::weak_ptr& device_holder) + : device_holder_(device_holder) {} SamplerLibraryVK::~SamplerLibraryVK() = default; @@ -20,7 +22,8 @@ std::shared_ptr SamplerLibraryVK::GetSampler( if (found != samplers_.end()) { return found->second; } - if (!device_) { + auto device_holder = device_holder_.lock(); + if (!device_holder || !device_holder->GetDevice()) { return nullptr; } @@ -43,7 +46,8 @@ std::shared_ptr SamplerLibraryVK::GetSampler( .setBorderColor(vk::BorderColor::eFloatTransparentBlack) .setMipmapMode(mip_map); - auto res = device_.createSamplerUnique(sampler_create_info); + auto res = + device_holder->GetDevice().createSamplerUnique(sampler_create_info); if (res.result != vk::Result::eSuccess) { FML_LOG(ERROR) << "Failed to create sampler: " << vk::to_string(res.result); return nullptr; @@ -56,7 +60,8 @@ std::shared_ptr SamplerLibraryVK::GetSampler( } if (!desc.label.empty()) { - ContextVK::SetDebugName(device_, sampler->GetSampler(), desc.label.c_str()); + ContextVK::SetDebugName(device_holder->GetDevice(), sampler->GetSampler(), + desc.label.c_str()); } samplers_[desc] = sampler; diff --git a/impeller/renderer/backend/vulkan/sampler_library_vk.h b/impeller/renderer/backend/vulkan/sampler_library_vk.h index 8b5a4fca82fe3..c5a6c98b283af 100644 --- a/impeller/renderer/backend/vulkan/sampler_library_vk.h +++ b/impeller/renderer/backend/vulkan/sampler_library_vk.h @@ -8,6 +8,7 @@ #include "impeller/base/backend_cast.h" #include "impeller/base/comparable.h" #include "impeller/core/sampler_descriptor.h" +#include "impeller/renderer/backend/vulkan/device_holder.h" #include "impeller/renderer/backend/vulkan/vk.h" #include "impeller/renderer/sampler_library.h" @@ -23,10 +24,10 @@ class SamplerLibraryVK final private: friend class ContextVK; - vk::Device device_; + std::weak_ptr device_holder_; SamplerMap samplers_; - explicit SamplerLibraryVK(vk::Device device); + explicit SamplerLibraryVK(const std::weak_ptr& device_holder); // |SamplerLibrary| std::shared_ptr GetSampler(