// 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/context_vk.h"
#include <thread>
#include <unordered_map>

#include "fml/concurrent_message_loop.h"
#include "impeller/core/formats.h"
#include "impeller/core/runtime_types.h"
#include "impeller/renderer/backend/vulkan/command_queue_vk.h"
#include "impeller/renderer/backend/vulkan/descriptor_pool_vk.h"
#include "impeller/renderer/backend/vulkan/render_pass_builder_vk.h"
#include "impeller/renderer/render_target.h"

#ifdef FML_OS_ANDROID
#include <pthread.h>
#include <sys/resource.h>
#include <sys/time.h>
#endif  // FML_OS_ANDROID

#include <map>
#include <memory>
#include <optional>
#include <string>
#include <vector>

#include "flutter/fml/cpu_affinity.h"
#include "flutter/fml/trace_event.h"
#include "impeller/base/validation.h"
#include "impeller/renderer/backend/vulkan/allocator_vk.h"
#include "impeller/renderer/backend/vulkan/capabilities_vk.h"
#include "impeller/renderer/backend/vulkan/command_buffer_vk.h"
#include "impeller/renderer/backend/vulkan/command_pool_vk.h"
#include "impeller/renderer/backend/vulkan/command_queue_vk.h"
#include "impeller/renderer/backend/vulkan/debug_report_vk.h"
#include "impeller/renderer/backend/vulkan/descriptor_pool_vk.h"
#include "impeller/renderer/backend/vulkan/fence_waiter_vk.h"
#include "impeller/renderer/backend/vulkan/gpu_tracer_vk.h"
#include "impeller/renderer/backend/vulkan/resource_manager_vk.h"
#include "impeller/renderer/backend/vulkan/surface_context_vk.h"
#include "impeller/renderer/backend/vulkan/yuv_conversion_library_vk.h"
#include "impeller/renderer/capabilities.h"

VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE

namespace impeller {

static bool gHasValidationLayers = false;

bool HasValidationLayers() {
  return gHasValidationLayers;
}

static std::optional<vk::PhysicalDevice> PickPhysicalDevice(
    const CapabilitiesVK& caps,
    const vk::Instance& instance) {
  for (const auto& device : instance.enumeratePhysicalDevices().value) {
    if (caps.GetEnabledDeviceFeatures(device).has_value()) {
      return device;
    }
  }
  return std::nullopt;
}

static std::vector<vk::DeviceQueueCreateInfo> GetQueueCreateInfos(
    std::initializer_list<QueueIndexVK> queues) {
  std::map<size_t /* family */, size_t /* index */> family_index_map;
  for (const auto& queue : queues) {
    family_index_map[queue.family] = 0;
  }
  for (const auto& queue : queues) {
    auto value = family_index_map[queue.family];
    family_index_map[queue.family] = std::max(value, queue.index);
  }

  static float kQueuePriority = 1.0f;
  std::vector<vk::DeviceQueueCreateInfo> infos;
  for (const auto& item : family_index_map) {
    vk::DeviceQueueCreateInfo info;
    info.setQueueFamilyIndex(item.first);
    info.setQueueCount(item.second + 1);
    info.setQueuePriorities(kQueuePriority);
    infos.push_back(info);
  }
  return infos;
}

static std::optional<QueueIndexVK> 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();
  for (size_t i = 0u; i < families.size(); i++) {
    if (!(families[i].queueFlags & flags)) {
      continue;
    }
    return QueueIndexVK{.family = i, .index = 0};
  }
  return std::nullopt;
}

std::shared_ptr<ContextVK> ContextVK::Create(Settings settings) {
  auto context = std::shared_ptr<ContextVK>(new ContextVK());
  context->Setup(std::move(settings));
  if (!context->IsValid()) {
    return nullptr;
  }
  return context;
}

// static
size_t ContextVK::ChooseThreadCountForWorkers(size_t hardware_concurrency) {
  // Never create more than 4 worker threads. Attempt to use up to
  // half of the available concurrency.
  return std::clamp(hardware_concurrency / 2ull, /*lo=*/1ull, /*hi=*/4ull);
}

namespace {
thread_local uint64_t tls_context_count = 0;
uint64_t CalculateHash(void* ptr) {
  // You could make a context once per nanosecond for 584 years on one thread
  // before this overflows.
  return ++tls_context_count;
}
}  // namespace

ContextVK::ContextVK() : hash_(CalculateHash(this)) {}

ContextVK::~ContextVK() {
  if (device_holder_ && device_holder_->device) {
    [[maybe_unused]] auto result = device_holder_->device->waitIdle();
  }
  CommandPoolRecyclerVK::DestroyThreadLocalPools(this);
}

Context::BackendType ContextVK::GetBackendType() const {
  return Context::BackendType::kVulkan;
}

void ContextVK::Setup(Settings settings) {
  TRACE_EVENT0("impeller", "ContextVK::Setup");

  if (!settings.proc_address_callback) {
    return;
  }

  raster_message_loop_ = fml::ConcurrentMessageLoop::Create(
      ChooseThreadCountForWorkers(std::thread::hardware_concurrency()));
  raster_message_loop_->PostTaskToAllWorkers([]() {
    // Currently we only use the worker task pool for small parts of a frame
    // workload, if this changes this setting may need to be adjusted.
    fml::RequestAffinity(fml::CpuAffinity::kNotPerformance);
#ifdef FML_OS_ANDROID
    if (::setpriority(PRIO_PROCESS, gettid(), -5) != 0) {
      FML_LOG(ERROR) << "Failed to set Workers task runner priority";
    }
#endif  // FML_OS_ANDROID
  });

  auto& dispatcher = VULKAN_HPP_DEFAULT_DISPATCHER;
  dispatcher.init(settings.proc_address_callback);

  std::vector<std::string> embedder_instance_extensions;
  std::vector<std::string> embedder_device_extensions;
  if (settings.embedder_data.has_value()) {
    embedder_instance_extensions = settings.embedder_data->instance_extensions;
    embedder_device_extensions = settings.embedder_data->device_extensions;
  }
  auto caps = std::shared_ptr<CapabilitiesVK>(new CapabilitiesVK(
      settings.enable_validation,                                      //
      settings.fatal_missing_validations,                              //
      /*use_embedder_extensions=*/settings.embedder_data.has_value(),  //
      embedder_instance_extensions,                                    //
      embedder_device_extensions                                       //
      ));

  if (!caps->IsValid()) {
    VALIDATION_LOG << "Could not determine device capabilities.";
    return;
  }

  gHasValidationLayers = caps->AreValidationsEnabled();

  auto enabled_layers = caps->GetEnabledLayers();
  auto enabled_extensions = caps->GetEnabledInstanceExtensions();

  if (!enabled_layers.has_value() || !enabled_extensions.has_value()) {
    VALIDATION_LOG << "Device has insufficient capabilities.";
    return;
  }

  vk::InstanceCreateFlags instance_flags = {};

  if (std::find(enabled_extensions.value().begin(),
                enabled_extensions.value().end(),
                "VK_KHR_portability_enumeration") !=
      enabled_extensions.value().end()) {
    instance_flags |= vk::InstanceCreateFlagBits::eEnumeratePortabilityKHR;
  }

  std::vector<const char*> enabled_layers_c;
  std::vector<const char*> enabled_extensions_c;

  for (const auto& layer : enabled_layers.value()) {
    enabled_layers_c.push_back(layer.c_str());
  }

  for (const auto& ext : enabled_extensions.value()) {
    enabled_extensions_c.push_back(ext.c_str());
  }

  vk::ApplicationInfo application_info;
  application_info.setApplicationVersion(VK_API_VERSION_1_0);
  application_info.setApiVersion(VK_API_VERSION_1_1);
  application_info.setEngineVersion(VK_API_VERSION_1_0);
  application_info.setPEngineName("Impeller");
  application_info.setPApplicationName("Impeller");

  vk::StructureChain<vk::InstanceCreateInfo, vk::ValidationFeaturesEXT>
      instance_chain;

  if (!caps->AreValidationsEnabled()) {
    instance_chain.unlink<vk::ValidationFeaturesEXT>();
  }

  std::vector<vk::ValidationFeatureEnableEXT> enabled_validations = {
      vk::ValidationFeatureEnableEXT::eSynchronizationValidation,
  };

  auto validation = instance_chain.get<vk::ValidationFeaturesEXT>();
  validation.setEnabledValidationFeatures(enabled_validations);

  auto instance_info = instance_chain.get<vk::InstanceCreateInfo>();
  instance_info.setPEnabledLayerNames(enabled_layers_c);
  instance_info.setPEnabledExtensionNames(enabled_extensions_c);
  instance_info.setPApplicationInfo(&application_info);
  instance_info.setFlags(instance_flags);

  auto device_holder = std::make_shared<DeviceHolderImpl>();
  if (!settings.embedder_data.has_value()) {
    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);
  } else {
    device_holder->instance.reset(settings.embedder_data->instance);
    device_holder->owned = false;
  }
  dispatcher.init(device_holder->instance.get());

  //----------------------------------------------------------------------------
  /// Setup the debug report.
  ///
  /// Do this as early as possible since we could use the debug report from
  /// initialization issues.
  ///
  auto debug_report =
      std::make_unique<DebugReportVK>(*caps, device_holder->instance.get());

  if (!debug_report->IsValid()) {
    VALIDATION_LOG << "Could not set up debug report.";
    return;
  }

  //----------------------------------------------------------------------------
  /// Pick the physical device.
  ///
  if (!settings.embedder_data.has_value()) {
    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 = physical_device.value();
  } else {
    device_holder->physical_device = settings.embedder_data->physical_device;
  }

  //----------------------------------------------------------------------------
  /// Pick device queues.
  ///
  auto graphics_queue =
      PickQueue(device_holder->physical_device, vk::QueueFlagBits::eGraphics);
  auto transfer_queue =
      PickQueue(device_holder->physical_device, vk::QueueFlagBits::eTransfer);
  auto compute_queue =
      PickQueue(device_holder->physical_device, vk::QueueFlagBits::eCompute);

  if (!graphics_queue.has_value()) {
    VALIDATION_LOG << "Could not pick graphics queue.";
    return;
  }
  if (!transfer_queue.has_value()) {
    transfer_queue = graphics_queue.value();
  }
  if (!compute_queue.has_value()) {
    VALIDATION_LOG << "Could not pick compute queue.";
    return;
  }

  //----------------------------------------------------------------------------
  /// Create the logical device.
  ///
  auto enabled_device_extensions =
      caps->GetEnabledDeviceExtensions(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.
    return;
  }

  std::vector<const char*> enabled_device_extensions_c;
  for (const auto& ext : enabled_device_extensions.value()) {
    enabled_device_extensions_c.push_back(ext.c_str());
  }

  const auto queue_create_infos = GetQueueCreateInfos(
      {graphics_queue.value(), compute_queue.value(), transfer_queue.value()});

  const auto enabled_features =
      caps->GetEnabledDeviceFeatures(device_holder->physical_device);
  if (!enabled_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.
    return;
  }

  vk::DeviceCreateInfo device_info;

  device_info.setPNext(&enabled_features.value().get());
  device_info.setQueueCreateInfos(queue_create_infos);
  device_info.setPEnabledExtensionNames(enabled_device_extensions_c);
  // Device layers are deprecated and ignored.

  if (!settings.embedder_data.has_value()) {
    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);
  } else {
    device_holder->device.reset(settings.embedder_data->device);
  }

  if (!caps->SetPhysicalDevice(device_holder->physical_device,
                               *enabled_features)) {
    VALIDATION_LOG << "Capabilities could not be updated.";
    return;
  }

  //----------------------------------------------------------------------------
  /// Create the allocator.
  ///
  auto allocator = std::shared_ptr<AllocatorVK>(new AllocatorVK(
      weak_from_this(),                //
      application_info.apiVersion,     //
      device_holder->physical_device,  //
      device_holder,                   //
      device_holder->instance.get(),   //
      *caps                            //
      ));

  if (!allocator->IsValid()) {
    VALIDATION_LOG << "Could not create memory allocator.";
    return;
  }

  //----------------------------------------------------------------------------
  /// Setup the pipeline library.
  ///
  auto pipeline_library = std::shared_ptr<PipelineLibraryVK>(
      new PipelineLibraryVK(device_holder,                         //
                            caps,                                  //
                            std::move(settings.cache_directory),   //
                            raster_message_loop_->GetTaskRunner()  //
                            ));

  if (!pipeline_library->IsValid()) {
    VALIDATION_LOG << "Could not create pipeline library.";
    return;
  }

  auto sampler_library =
      std::shared_ptr<SamplerLibraryVK>(new SamplerLibraryVK(device_holder));

  auto shader_library = std::shared_ptr<ShaderLibraryVK>(
      new ShaderLibraryVK(device_holder,                   //
                          settings.shader_libraries_data)  //
  );

  if (!shader_library->IsValid()) {
    VALIDATION_LOG << "Could not create shader library.";
    return;
  }

  //----------------------------------------------------------------------------
  /// Create the fence waiter.
  ///
  auto fence_waiter =
      std::shared_ptr<FenceWaiterVK>(new FenceWaiterVK(device_holder));

  //----------------------------------------------------------------------------
  /// Create the resource manager and command pool recycler.
  ///
  auto resource_manager = ResourceManagerVK::Create();
  if (!resource_manager) {
    VALIDATION_LOG << "Could not create resource manager.";
    return;
  }

  auto command_pool_recycler =
      std::make_shared<CommandPoolRecyclerVK>(weak_from_this());
  if (!command_pool_recycler) {
    VALIDATION_LOG << "Could not create command pool recycler.";
    return;
  }

  auto descriptor_pool_recycler =
      std::make_shared<DescriptorPoolRecyclerVK>(weak_from_this());
  if (!descriptor_pool_recycler) {
    VALIDATION_LOG << "Could not create descriptor pool recycler.";
    return;
  }

  //----------------------------------------------------------------------------
  /// Fetch the queues.
  ///
  QueuesVK queues;
  if (!settings.embedder_data.has_value()) {
    queues = QueuesVK::FromQueueIndices(device_holder->device.get(),  //
                                        graphics_queue.value(),       //
                                        compute_queue.value(),        //
                                        transfer_queue.value()        //
    );
  } else {
    queues =
        QueuesVK::FromEmbedderQueue(settings.embedder_data->queue,
                                    settings.embedder_data->queue_family_index);
  }
  if (!queues.IsValid()) {
    VALIDATION_LOG << "Could not fetch device queues.";
    return;
  }

  VkPhysicalDeviceProperties physical_device_properties;
  dispatcher.vkGetPhysicalDeviceProperties(device_holder->physical_device,
                                           &physical_device_properties);

  //----------------------------------------------------------------------------
  /// All done!
  ///
  device_holder_ = std::move(device_holder);
  idle_waiter_vk_ = std::make_shared<IdleWaiterVK>(device_holder_);
  driver_info_ =
      std::make_unique<DriverInfoVK>(device_holder_->physical_device);
  debug_report_ = std::move(debug_report);
  allocator_ = std::move(allocator);
  shader_library_ = std::move(shader_library);
  sampler_library_ = std::move(sampler_library);
  pipeline_library_ = std::move(pipeline_library);
  yuv_conversion_library_ = std::shared_ptr<YUVConversionLibraryVK>(
      new YUVConversionLibraryVK(device_holder_));
  queues_ = std::move(queues);
  device_capabilities_ = std::move(caps);
  fence_waiter_ = std::move(fence_waiter);
  resource_manager_ = std::move(resource_manager);
  command_pool_recycler_ = std::move(command_pool_recycler);
  descriptor_pool_recycler_ = std::move(descriptor_pool_recycler);
  device_name_ = std::string(physical_device_properties.deviceName);
  command_queue_vk_ = std::make_shared<CommandQueueVK>(weak_from_this());
  should_disable_surface_control_ = settings.disable_surface_control;
  should_batch_cmd_buffers_ = driver_info_->CanBatchSubmitCommandBuffers();
  is_valid_ = true;

  // Create the GPU Tracer later because it depends on state from
  // the ContextVK.
  gpu_tracer_ = std::make_shared<GPUTracerVK>(weak_from_this(),
                                              settings.enable_gpu_tracing);
  gpu_tracer_->InitializeQueryPool(*this);

  //----------------------------------------------------------------------------
  /// Label all the relevant objects. This happens after setup so that the
  /// debug messengers have had a chance to be set up.
  ///
  SetDebugName(GetDevice(), device_holder_->device.get(), "ImpellerDevice");
}

void ContextVK::SetOffscreenFormat(PixelFormat pixel_format) {
  CapabilitiesVK::Cast(*device_capabilities_).SetOffscreenFormat(pixel_format);
}

// |Context|
std::string ContextVK::DescribeGpuModel() const {
  return device_name_;
}

bool ContextVK::IsValid() const {
  return is_valid_;
}

std::shared_ptr<Allocator> ContextVK::GetResourceAllocator() const {
  return allocator_;
}

std::shared_ptr<ShaderLibrary> ContextVK::GetShaderLibrary() const {
  return shader_library_;
}

std::shared_ptr<SamplerLibrary> ContextVK::GetSamplerLibrary() const {
  return sampler_library_;
}

std::shared_ptr<PipelineLibrary> ContextVK::GetPipelineLibrary() const {
  return pipeline_library_;
}

std::shared_ptr<CommandBuffer> ContextVK::CreateCommandBuffer() const {
  const auto& recycler = GetCommandPoolRecycler();
  auto tls_pool = recycler->Get();
  if (!tls_pool) {
    return nullptr;
  }

  // look up a cached descriptor pool for the current frame and reuse it
  // if it exists, otherwise create a new pool.
  std::shared_ptr<DescriptorPoolVK> descriptor_pool;
  {
    Lock lock(desc_pool_mutex_);
    DescriptorPoolMap::iterator current_pool =
        cached_descriptor_pool_.find(std::this_thread::get_id());
    if (current_pool == cached_descriptor_pool_.end()) {
      descriptor_pool =
          (cached_descriptor_pool_[std::this_thread::get_id()] =
               std::make_shared<DescriptorPoolVK>(weak_from_this()));
    } else {
      descriptor_pool = current_pool->second;
    }
  }

  auto tracked_objects = std::make_shared<TrackedObjectsVK>(
      weak_from_this(), std::move(tls_pool), std::move(descriptor_pool),
      GetGPUTracer()->CreateGPUProbe());
  auto queue = GetGraphicsQueue();

  if (!tracked_objects || !tracked_objects->IsValid() || !queue) {
    return nullptr;
  }

  vk::CommandBufferBeginInfo begin_info;
  begin_info.flags = vk::CommandBufferUsageFlagBits::eOneTimeSubmit;
  if (tracked_objects->GetCommandBuffer().begin(begin_info) !=
      vk::Result::eSuccess) {
    VALIDATION_LOG << "Could not begin command buffer.";
    return nullptr;
  }

  tracked_objects->GetGPUProbe().RecordCmdBufferStart(
      tracked_objects->GetCommandBuffer());

  return std::shared_ptr<CommandBufferVK>(new CommandBufferVK(
      shared_from_this(),         //
      GetDeviceHolder(),          //
      std::move(tracked_objects)  //
      ));
}

vk::Instance ContextVK::GetInstance() const {
  return *device_holder_->instance;
}

const vk::Device& ContextVK::GetDevice() const {
  return device_holder_->device.get();
}

const std::shared_ptr<fml::ConcurrentTaskRunner>
ContextVK::GetConcurrentWorkerTaskRunner() const {
  return raster_message_loop_->GetTaskRunner();
}

void ContextVK::Shutdown() {
  // There are multiple objects, for example |CommandPoolVK|, that in their
  // destructors make a strong reference to |ContextVK|. Resetting these shared
  // pointers ensures that cleanup happens in a correct order.
  //
  // tl;dr: Without it, we get thread::join failures on shutdown.
  fence_waiter_.reset();
  resource_manager_.reset();

  raster_message_loop_->Terminate();
}

std::shared_ptr<SurfaceContextVK> ContextVK::CreateSurfaceContext() {
  return std::make_shared<SurfaceContextVK>(shared_from_this());
}

const std::shared_ptr<const Capabilities>& ContextVK::GetCapabilities() const {
  return device_capabilities_;
}

const std::shared_ptr<QueueVK>& ContextVK::GetGraphicsQueue() const {
  return queues_.graphics_queue;
}

vk::PhysicalDevice ContextVK::GetPhysicalDevice() const {
  return device_holder_->physical_device;
}

std::shared_ptr<FenceWaiterVK> ContextVK::GetFenceWaiter() const {
  return fence_waiter_;
}

std::shared_ptr<ResourceManagerVK> ContextVK::GetResourceManager() const {
  return resource_manager_;
}

std::shared_ptr<CommandPoolRecyclerVK> ContextVK::GetCommandPoolRecycler()
    const {
  return command_pool_recycler_;
}

std::shared_ptr<GPUTracerVK> ContextVK::GetGPUTracer() const {
  return gpu_tracer_;
}

std::shared_ptr<DescriptorPoolRecyclerVK> ContextVK::GetDescriptorPoolRecycler()
    const {
  return descriptor_pool_recycler_;
}

std::shared_ptr<CommandQueue> ContextVK::GetCommandQueue() const {
  return command_queue_vk_;
}

bool ContextVK::EnqueueCommandBuffer(
    std::shared_ptr<CommandBuffer> command_buffer) {
  if (should_batch_cmd_buffers_) {
    pending_command_buffers_.push_back(std::move(command_buffer));
    return true;
  } else {
    return GetCommandQueue()->Submit({command_buffer}).ok();
  }
}

bool ContextVK::FlushCommandBuffers() {
  if (should_batch_cmd_buffers_) {
    bool result = GetCommandQueue()->Submit(pending_command_buffers_).ok();
    pending_command_buffers_.clear();
    return result;
  } else {
    return true;
  }
}

// Creating a render pass is observed to take an additional 6ms on a Pixel 7
// device as the driver will lazily bootstrap and compile shaders to do so.
// The render pass does not need to be begun or executed.
void ContextVK::InitializeCommonlyUsedShadersIfNeeded() const {
  RenderTargetAllocator rt_allocator(GetResourceAllocator());
  RenderTarget render_target =
      rt_allocator.CreateOffscreenMSAA(*this, {1, 1}, 1);

  RenderPassBuilderVK builder;

  render_target.IterateAllColorAttachments(
      [&builder](size_t index, const ColorAttachment& attachment) -> bool {
        builder.SetColorAttachment(
            index,                                                    //
            attachment.texture->GetTextureDescriptor().format,        //
            attachment.texture->GetTextureDescriptor().sample_count,  //
            attachment.load_action,                                   //
            attachment.store_action                                   //
        );
        return true;
      });

  if (auto depth = render_target.GetDepthAttachment(); depth.has_value()) {
    builder.SetDepthStencilAttachment(
        depth->texture->GetTextureDescriptor().format,        //
        depth->texture->GetTextureDescriptor().sample_count,  //
        depth->load_action,                                   //
        depth->store_action                                   //
    );
  } else if (auto stencil = render_target.GetStencilAttachment();
             stencil.has_value()) {
    builder.SetStencilAttachment(
        stencil->texture->GetTextureDescriptor().format,        //
        stencil->texture->GetTextureDescriptor().sample_count,  //
        stencil->load_action,                                   //
        stencil->store_action                                   //
    );
  }

  auto pass = builder.Build(GetDevice());
}

void ContextVK::DisposeThreadLocalCachedResources() {
  {
    Lock lock(desc_pool_mutex_);
    cached_descriptor_pool_.erase(std::this_thread::get_id());
  }
  command_pool_recycler_->Dispose();
}

const std::shared_ptr<YUVConversionLibraryVK>&
ContextVK::GetYUVConversionLibrary() const {
  return yuv_conversion_library_;
}

const std::unique_ptr<DriverInfoVK>& ContextVK::GetDriverInfo() const {
  return driver_info_;
}

bool ContextVK::GetShouldDisableSurfaceControlSwapchain() const {
  return should_disable_surface_control_;
}

RuntimeStageBackend ContextVK::GetRuntimeStageBackend() const {
  return RuntimeStageBackend::kVulkan;
}

}  // namespace impeller
