// Copyright 2017 The Dawn & Tint Authors
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this
//    list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice,
//    this list of conditions and the following disclaimer in the documentation
//    and/or other materials provided with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of its
//    contributors may be used to endorse or promote products derived from
//    this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#include "dawn/native/vulkan/DeviceVk.h"

#include <algorithm>

#include "dawn/common/Log.h"
#include "dawn/common/Math.h"
#include "dawn/common/NonCopyable.h"
#include "dawn/common/Platform.h"
#include "dawn/common/Version_autogen.h"
#include "dawn/native/BackendConnection.h"
#include "dawn/native/ChainUtils.h"
#include "dawn/native/CreatePipelineAsyncEvent.h"
#include "dawn/native/Error.h"
#include "dawn/native/ErrorData.h"
#include "dawn/native/Instance.h"
#include "dawn/native/IntegerTypes.h"
#include "dawn/native/SystemHandle.h"
#include "dawn/native/VulkanBackend.h"
#include "dawn/native/vulkan/BackendVk.h"
#include "dawn/native/vulkan/BindGroupLayoutVk.h"
#include "dawn/native/vulkan/BindGroupVk.h"
#include "dawn/native/vulkan/BufferVk.h"
#include "dawn/native/vulkan/CommandBufferVk.h"
#include "dawn/native/vulkan/ComputePipelineVk.h"
#include "dawn/native/vulkan/FencedDeleter.h"
#include "dawn/native/vulkan/FramebufferCache.h"
#include "dawn/native/vulkan/PhysicalDeviceVk.h"
#include "dawn/native/vulkan/PipelineCacheVk.h"
#include "dawn/native/vulkan/PipelineLayoutVk.h"
#include "dawn/native/vulkan/QuerySetVk.h"
#include "dawn/native/vulkan/QueueVk.h"
#include "dawn/native/vulkan/RenderPassCache.h"
#include "dawn/native/vulkan/RenderPipelineVk.h"
#include "dawn/native/vulkan/ResourceMemoryAllocatorVk.h"
#include "dawn/native/vulkan/SamplerVk.h"
#include "dawn/native/vulkan/ShaderModuleVk.h"
#include "dawn/native/vulkan/SharedFenceVk.h"
#include "dawn/native/vulkan/SharedTextureMemoryVk.h"
#include "dawn/native/vulkan/SwapChainVk.h"
#include "dawn/native/vulkan/TextureVk.h"
#include "dawn/native/vulkan/UtilsVulkan.h"
#include "dawn/native/vulkan/VulkanError.h"

namespace dawn::native::vulkan {
namespace {

template <typename F>
struct NoopDrawFunction;

template <typename R, typename... Args>
struct NoopDrawFunction<R(VKAPI_PTR*)(Args...)> {
    static R VKAPI_PTR Fun(Args...) {}
};

}  // namespace

// static
ResultOrError<Ref<Device>> Device::Create(AdapterBase* adapter,
                                          const UnpackedPtr<DeviceDescriptor>& descriptor,
                                          const TogglesState& deviceToggles,
                                          Ref<DeviceBase::DeviceLostEvent>&& lostEvent) {
    Ref<Device> device =
        AcquireRef(new Device(adapter, descriptor, deviceToggles, std::move(lostEvent)));
    DAWN_TRY(device->Initialize(descriptor));
    return device;
}

Device::Device(AdapterBase* adapter,
               const UnpackedPtr<DeviceDescriptor>& descriptor,
               const TogglesState& deviceToggles,
               Ref<DeviceBase::DeviceLostEvent>&& lostEvent)
    : DeviceBase(adapter, descriptor, deviceToggles, std::move(lostEvent)),
      mDebugPrefix(GetNextDeviceDebugPrefix()) {}

MaybeError Device::Initialize(const UnpackedPtr<DeviceDescriptor>& descriptor) {
    if (GetInstance()->IsBackendValidationEnabled() &&
        !IsToggleEnabled(Toggle::UseUserDefinedLabelsInBackend)) {
        // NOTE: If Vulkan backend validation is enabled then these labels must be set to associate
        // validation errors with a specific device. Backend validation errors will cause a crash
        // if labels are not set.
        EmitLog(wgpu::LoggingType::Warning,
                "Backend object labels are required to map Vulkan backend errors to a device.");
    }

    // Copy the adapter's device info to the device so that we can change the "knobs"
    mDeviceInfo = ToBackend(GetPhysicalDevice())->GetDeviceInfo();

    // Initialize the "instance" procs of our local function table.
    VulkanFunctions* functions = GetMutableFunctions();
    *functions = ToBackend(GetPhysicalDevice())->GetVulkanInstance()->GetFunctions();

    // Two things are crucial if device initialization fails: the function pointers to destroy
    // objects, and the fence deleter that calls these functions. Do not do anything before
    // these two are set up, so that a failed initialization doesn't cause a crash in
    // DestroyImpl()
    {
        VkPhysicalDevice vkPhysicalDevice = ToBackend(GetPhysicalDevice())->GetVkPhysicalDevice();

        VulkanDeviceKnobs usedDeviceKnobs = {};
        DAWN_TRY_ASSIGN(usedDeviceKnobs, CreateDevice(vkPhysicalDevice));
        *static_cast<VulkanDeviceKnobs*>(&mDeviceInfo) = usedDeviceKnobs;

        DAWN_TRY(functions->LoadDeviceProcs(GetVkInstance(), mVkDevice, mDeviceInfo));

        mDeleter = std::make_unique<MutexProtected<FencedDeleter>>(this);
    }

    if (IsToggleEnabled(Toggle::VulkanSkipDraw)) {
        // Chrome skips draw for some tests.
        functions->CmdDraw = NoopDrawFunction<PFN_vkCmdDraw>::Fun;
        functions->CmdDrawIndexed = NoopDrawFunction<PFN_vkCmdDrawIndexed>::Fun;
        functions->CmdDrawIndirect = NoopDrawFunction<PFN_vkCmdDrawIndirect>::Fun;
        functions->CmdDrawIndexedIndirect = NoopDrawFunction<PFN_vkCmdDrawIndexedIndirect>::Fun;
    }

    mFramebufferCache = std::make_unique<FramebufferCache>(this);
    mRenderPassCache = std::make_unique<RenderPassCache>(this);

    VkDeviceSize heapBlockSize =
        ResourceMemoryAllocator::GetHeapBlockSize(descriptor.Get<DawnDeviceAllocatorControl>());
    mResourceMemoryAllocator =
        std::make_unique<MutexProtected<ResourceMemoryAllocator>>(this, heapBlockSize);

    mExternalMemoryService = std::make_unique<external_memory::Service>(this);

    if (uint32_t(HasFeature(Feature::SharedFenceVkSemaphoreOpaqueFD)) +
            uint32_t(HasFeature(Feature::SharedFenceSyncFD)) +
            uint32_t(HasFeature(Feature::SharedFenceVkSemaphoreZirconHandle)) >
        1) {
        return DAWN_VALIDATION_ERROR("At most one of %s, %s, and %s may be enabled.",
                                     wgpu::FeatureName::SharedFenceVkSemaphoreOpaqueFD,
                                     wgpu::FeatureName::SharedFenceSyncFD,
                                     wgpu::FeatureName::SharedFenceVkSemaphoreZirconHandle);
    }
    if (HasFeature(Feature::SharedFenceVkSemaphoreOpaqueFD)) {
        mExternalSemaphoreService = std::make_unique<external_semaphore::Service>(
            this, VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT_KHR);
    } else if (HasFeature(Feature::SharedFenceSyncFD)) {
        mExternalSemaphoreService = std::make_unique<external_semaphore::Service>(
            this, VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT);
    } else if (HasFeature(Feature::SharedFenceVkSemaphoreZirconHandle)) {
        mExternalSemaphoreService = std::make_unique<external_semaphore::Service>(
            this, VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_ZIRCON_EVENT_BIT_FUCHSIA);
    } else {
#if DAWN_PLATFORM_IS(FUCHSIA)
        mExternalSemaphoreService = std::make_unique<external_semaphore::Service>(
            this, VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_ZIRCON_EVENT_BIT_FUCHSIA);
#elif DAWN_PLATFORM_IS(ANDROID) || DAWN_PLATFORM_IS(CHROMEOS)
        mExternalSemaphoreService = std::make_unique<external_semaphore::Service>(
            this, VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT);
#else
        mExternalSemaphoreService = std::make_unique<external_semaphore::Service>(
            this, VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT_KHR);
#endif
    }

    SetLabelImpl();

    ToBackend(GetPhysicalDevice())->GetVulkanInstance()->StartListeningForDeviceMessages(this);

    Ref<Queue> queue;
    DAWN_TRY_ASSIGN(queue, Queue::Create(this, &descriptor->defaultQueue, mMainQueueFamily));

    return DeviceBase::Initialize(descriptor, std::move(queue));
}

Device::~Device() {
    Destroy();
}

ResultOrError<Ref<BindGroupBase>> Device::CreateBindGroupImpl(
    const BindGroupDescriptor* descriptor) {
    return BindGroup::Create(this, descriptor);
}
ResultOrError<Ref<BindGroupLayoutInternalBase>> Device::CreateBindGroupLayoutImpl(
    const BindGroupLayoutDescriptor* descriptor) {
    return BindGroupLayout::Create(this, descriptor);
}
ResultOrError<Ref<BufferBase>> Device::CreateBufferImpl(
    const UnpackedPtr<BufferDescriptor>& descriptor) {
    return Buffer::Create(this, descriptor);
}
ResultOrError<Ref<CommandBufferBase>> Device::CreateCommandBuffer(
    CommandEncoder* encoder,
    const CommandBufferDescriptor* descriptor) {
    return CommandBuffer::Create(encoder, descriptor);
}
Ref<ComputePipelineBase> Device::CreateUninitializedComputePipelineImpl(
    const UnpackedPtr<ComputePipelineDescriptor>& descriptor) {
    return ComputePipeline::CreateUninitialized(this, descriptor);
}
ResultOrError<Ref<PipelineLayoutBase>> Device::CreatePipelineLayoutImpl(
    const UnpackedPtr<PipelineLayoutDescriptor>& descriptor) {
    return PipelineLayout::Create(this, descriptor);
}
ResultOrError<Ref<QuerySetBase>> Device::CreateQuerySetImpl(const QuerySetDescriptor* descriptor) {
    return QuerySet::Create(this, descriptor);
}
Ref<RenderPipelineBase> Device::CreateUninitializedRenderPipelineImpl(
    const UnpackedPtr<RenderPipelineDescriptor>& descriptor) {
    return RenderPipeline::CreateUninitialized(this, descriptor);
}
ResultOrError<Ref<SamplerBase>> Device::CreateSamplerImpl(const SamplerDescriptor* descriptor) {
    return Sampler::Create(this, descriptor);
}
ResultOrError<Ref<ShaderModuleBase>> Device::CreateShaderModuleImpl(
    const UnpackedPtr<ShaderModuleDescriptor>& descriptor,
    const std::vector<tint::wgsl::Extension>& internalExtensions,
    ShaderModuleParseResult* parseResult) {
    return ShaderModule::Create(this, descriptor, internalExtensions, parseResult);
}
ResultOrError<Ref<SwapChainBase>> Device::CreateSwapChainImpl(Surface* surface,
                                                              SwapChainBase* previousSwapChain,
                                                              const SurfaceConfiguration* config) {
    return SwapChain::Create(this, surface, previousSwapChain, config);
}
ResultOrError<Ref<TextureBase>> Device::CreateTextureImpl(
    const UnpackedPtr<TextureDescriptor>& descriptor) {
    return InternalTexture::Create(this, descriptor);
}
ResultOrError<Ref<TextureViewBase>> Device::CreateTextureViewImpl(
    TextureBase* texture,
    const UnpackedPtr<TextureViewDescriptor>& descriptor) {
    return TextureView::Create(texture, descriptor);
}
Ref<PipelineCacheBase> Device::GetOrCreatePipelineCacheImpl(const CacheKey& key) {
    if (IsToggleEnabled(Toggle::VulkanMonolithicPipelineCache)) {
        std::call_once(mMonolithicPipelineCacheFlag, [this]() {
            CacheKey cacheKey = GetCacheKey();
            // `pipelineCacheUUID` is supposed to change if anything in the driver changes such that
            // the serialized VkPipelineCache is no longer valid.
            auto& deviceProperties = GetDeviceInfo().properties;
            StreamIn(&cacheKey, deviceProperties.pipelineCacheUUID);

            mMonolithicPipelineCache = PipelineCache::CreateMonolithic(this, cacheKey);
        });

        return mMonolithicPipelineCache;
    }

    return PipelineCache::Create(this, key);
}
void Device::InitializeComputePipelineAsyncImpl(Ref<CreateComputePipelineAsyncEvent> event) {
    event->InitializeAsync();
}
void Device::InitializeRenderPipelineAsyncImpl(Ref<CreateRenderPipelineAsyncEvent> event) {
    event->InitializeAsync();
}

ResultOrError<Ref<SharedTextureMemoryBase>> Device::ImportSharedTextureMemoryImpl(
    const SharedTextureMemoryDescriptor* descriptor) {
    UnpackedPtr<SharedTextureMemoryDescriptor> unpacked;
    DAWN_TRY_ASSIGN(unpacked, ValidateAndUnpack(descriptor));

    wgpu::SType type;
    DAWN_TRY_ASSIGN(type,
                    (unpacked.ValidateBranches<Branch<SharedTextureMemoryDmaBufDescriptor>,
                                               Branch<SharedTextureMemoryAHardwareBufferDescriptor>,
                                               Branch<SharedTextureMemoryOpaqueFDDescriptor>>()));

    switch (type) {
        case wgpu::SType::SharedTextureMemoryDmaBufDescriptor:
            DAWN_INVALID_IF(!HasFeature(Feature::SharedTextureMemoryDmaBuf), "%s is not enabled.",
                            wgpu::FeatureName::SharedTextureMemoryDmaBuf);
            return SharedTextureMemory::Create(this, descriptor->label,
                                               unpacked.Get<SharedTextureMemoryDmaBufDescriptor>());
        case wgpu::SType::SharedTextureMemoryAHardwareBufferDescriptor:
            DAWN_INVALID_IF(!HasFeature(Feature::SharedTextureMemoryAHardwareBuffer),
                            "%s is not enabled.",
                            wgpu::FeatureName::SharedTextureMemoryAHardwareBuffer);
            return SharedTextureMemory::Create(
                this, descriptor->label,
                unpacked.Get<SharedTextureMemoryAHardwareBufferDescriptor>());
        case wgpu::SType::SharedTextureMemoryOpaqueFDDescriptor:
            DAWN_INVALID_IF(!HasFeature(Feature::SharedTextureMemoryOpaqueFD), "%s is not enabled.",
                            wgpu::FeatureName::SharedTextureMemoryOpaqueFD);
            return SharedTextureMemory::Create(
                this, descriptor->label, unpacked.Get<SharedTextureMemoryOpaqueFDDescriptor>());
        default:
            DAWN_UNREACHABLE();
    }
}

ResultOrError<Ref<SharedFenceBase>> Device::ImportSharedFenceImpl(
    const SharedFenceDescriptor* descriptor) {
    UnpackedPtr<SharedFenceDescriptor> unpacked;
    DAWN_TRY_ASSIGN(unpacked, ValidateAndUnpack(descriptor));

    wgpu::SType type;
    DAWN_TRY_ASSIGN(
        type, (unpacked.ValidateBranches<Branch<SharedFenceVkSemaphoreZirconHandleDescriptor>,
                                         Branch<SharedFenceSyncFDDescriptor>,
                                         Branch<SharedFenceVkSemaphoreOpaqueFDDescriptor>>()));

    switch (type) {
        case wgpu::SType::SharedFenceVkSemaphoreZirconHandleDescriptor:
            DAWN_INVALID_IF(!HasFeature(Feature::SharedFenceVkSemaphoreZirconHandle),
                            "%s is not enabled.",
                            wgpu::FeatureName::SharedFenceVkSemaphoreZirconHandle);
            return SharedFence::Create(
                this, descriptor->label,
                unpacked.Get<SharedFenceVkSemaphoreZirconHandleDescriptor>());
        case wgpu::SType::SharedFenceSyncFDDescriptor:
            DAWN_INVALID_IF(!HasFeature(Feature::SharedFenceSyncFD), "%s is not enabled.",
                            wgpu::FeatureName::SharedFenceSyncFD);
            return SharedFence::Create(this, descriptor->label,
                                       unpacked.Get<SharedFenceSyncFDDescriptor>());
        case wgpu::SType::SharedFenceVkSemaphoreOpaqueFDDescriptor:
            DAWN_INVALID_IF(!HasFeature(Feature::SharedFenceVkSemaphoreOpaqueFD),
                            "%s is not enabled.",
                            wgpu::FeatureName::SharedFenceVkSemaphoreOpaqueFD);
            return SharedFence::Create(this, descriptor->label,
                                       unpacked.Get<SharedFenceVkSemaphoreOpaqueFDDescriptor>());
        default:
            DAWN_UNREACHABLE();
    }
}

MaybeError Device::TickImpl() {
    Queue* queue = ToBackend(GetQueue());

    ExecutionSerial completedSerial = queue->GetCompletedCommandSerial();
    queue->RecycleCompletedCommands(completedSerial);

    mDescriptorAllocatorsPendingDeallocation.Use([&](auto pending) {
        for (Ref<DescriptorSetAllocator>& allocator : pending->IterateUpTo(completedSerial)) {
            allocator->FinishDeallocation(completedSerial);
        }
        pending->ClearUpTo(completedSerial);
    });

    GetResourceMemoryAllocator()->Tick(completedSerial);
    GetFencedDeleter()->Tick(completedSerial);

    DAWN_TRY(queue->SubmitPendingCommands());
    DAWN_TRY(CheckDebugLayerAndGenerateErrors());

    return {};
}

VkInstance Device::GetVkInstance() const {
    return ToBackend(GetPhysicalDevice())->GetVulkanInstance()->GetVkInstance();
}
const VulkanDeviceInfo& Device::GetDeviceInfo() const {
    return mDeviceInfo;
}

const VulkanGlobalInfo& Device::GetGlobalInfo() const {
    return ToBackend(GetPhysicalDevice())->GetVulkanInstance()->GetGlobalInfo();
}

VkDevice Device::GetVkDevice() const {
    return mVkDevice;
}

uint32_t Device::GetGraphicsQueueFamily() const {
    return mMainQueueFamily;
}

MutexProtected<FencedDeleter>& Device::GetFencedDeleter() const {
    return *mDeleter;
}

FramebufferCache* Device::GetFramebufferCache() const {
    return mFramebufferCache.get();
}

RenderPassCache* Device::GetRenderPassCache() const {
    return mRenderPassCache.get();
}

MutexProtected<ResourceMemoryAllocator>& Device::GetResourceMemoryAllocator() const {
    return *mResourceMemoryAllocator;
}

external_semaphore::Service* Device::GetExternalSemaphoreService() const {
    return mExternalSemaphoreService.get();
}

void Device::EnqueueDeferredDeallocation(DescriptorSetAllocator* allocator) {
    mDescriptorAllocatorsPendingDeallocation->Enqueue(allocator,
                                                      GetQueue()->GetPendingCommandSerial());
}

ResultOrError<VulkanDeviceKnobs> Device::CreateDevice(VkPhysicalDevice vkPhysicalDevice) {
    VulkanDeviceKnobs usedKnobs = {};

    // Default to asking for all available known extensions.
    usedKnobs.extensions = mDeviceInfo.extensions;

    // However only request the extensions that haven't been promoted in the device's apiVersion
    std::vector<const char*> extensionNames;
    for (DeviceExt ext : usedKnobs.extensions) {
        const DeviceExtInfo& info = GetDeviceExtInfo(ext);

        if (info.versionPromoted > mDeviceInfo.properties.apiVersion) {
            extensionNames.push_back(info.name);
        }
    }

    // Some device features can only be enabled using a VkPhysicalDeviceFeatures2 struct, which
    // is supported by the VK_EXT_get_physical_properties2 instance extension, which was
    // promoted as a core API in Vulkan 1.1.
    //
    // Prepare a VkPhysicalDeviceFeatures2 struct for this use case, it will only be populated
    // if HasExt(DeviceExt::GetPhysicalDeviceProperties2) is true.
    VkPhysicalDeviceFeatures2 features2 = {};
    features2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
    features2.pNext = nullptr;
    PNextChainBuilder featuresChain(&features2);

    // Required for core WebGPU features.
    if (HasFeature(Feature::CoreFeaturesAndLimits)) {
        usedKnobs.features.depthBiasClamp = VK_TRUE;
        usedKnobs.features.imageCubeArray = VK_TRUE;
        usedKnobs.features.independentBlend = VK_TRUE;
        usedKnobs.features.sampleRateShading = VK_TRUE;
    }
    // Required for core and compat WebGPU features.
    usedKnobs.features.fullDrawIndexUint32 = VK_TRUE;
    usedKnobs.features.fragmentStoresAndAtomics = VK_TRUE;
    usedKnobs.features.shaderUniformBufferArrayDynamicIndexing = VK_TRUE;
    usedKnobs.features.shaderStorageBufferArrayDynamicIndexing = VK_TRUE;
    usedKnobs.features.shaderSampledImageArrayDynamicIndexing = VK_TRUE;
    usedKnobs.features.shaderStorageImageArrayDynamicIndexing = VK_TRUE;

    if (IsRobustnessEnabled()) {
        usedKnobs.features.robustBufferAccess = VK_TRUE;
    }

    if (mDeviceInfo.HasExt(DeviceExt::SubgroupSizeControl)) {
        DAWN_ASSERT(usedKnobs.HasExt(DeviceExt::SubgroupSizeControl));

        // Always request all the features from VK_EXT_subgroup_size_control when available.
        usedKnobs.subgroupSizeControlFeatures = mDeviceInfo.subgroupSizeControlFeatures;
        featuresChain.Add(&usedKnobs.subgroupSizeControlFeatures);
    }

    if (mDeviceInfo.HasExt(DeviceExt::ZeroInitializeWorkgroupMemory)) {
        DAWN_ASSERT(usedKnobs.HasExt(DeviceExt::ZeroInitializeWorkgroupMemory));

        // Always allow initializing workgroup memory with OpConstantNull when available.
        // Note that the driver still won't initialize workgroup memory unless the workgroup
        // variable is explicitly initialized with OpConstantNull.
        usedKnobs.zeroInitializeWorkgroupMemoryFeatures =
            mDeviceInfo.zeroInitializeWorkgroupMemoryFeatures;
        featuresChain.Add(&usedKnobs.zeroInitializeWorkgroupMemoryFeatures);
    }

    if (mDeviceInfo.HasExt(DeviceExt::DemoteToHelperInvocation)) {
        DAWN_ASSERT(usedKnobs.HasExt(DeviceExt::DemoteToHelperInvocation));
        usedKnobs.demoteToHelperInvocationFeatures = mDeviceInfo.demoteToHelperInvocationFeatures;
        featuresChain.Add(&usedKnobs.demoteToHelperInvocationFeatures);
    }

    if (mDeviceInfo.HasExt(DeviceExt::ShaderIntegerDotProduct)) {
        DAWN_ASSERT(usedKnobs.HasExt(DeviceExt::ShaderIntegerDotProduct));

        usedKnobs.shaderIntegerDotProductFeatures = mDeviceInfo.shaderIntegerDotProductFeatures;
        featuresChain.Add(&usedKnobs.shaderIntegerDotProductFeatures);
    }

    if (mDeviceInfo.features.samplerAnisotropy == VK_TRUE) {
        usedKnobs.features.samplerAnisotropy = VK_TRUE;
    }

    if (IsToggleEnabled(Toggle::UseVulkanMemoryModel)) {
        DAWN_ASSERT(usedKnobs.HasExt(DeviceExt::VulkanMemoryModel));
        usedKnobs.vulkanMemoryModelFeatures = mDeviceInfo.vulkanMemoryModelFeatures;
        featuresChain.Add(&usedKnobs.vulkanMemoryModelFeatures);
    }

    if (HasFeature(Feature::TextureCompressionBC)) {
        DAWN_ASSERT(mDeviceInfo.features.textureCompressionBC == VK_TRUE);
        usedKnobs.features.textureCompressionBC = VK_TRUE;
    }

    if (HasFeature(Feature::TextureCompressionETC2)) {
        DAWN_ASSERT(mDeviceInfo.features.textureCompressionETC2 == VK_TRUE);
        usedKnobs.features.textureCompressionETC2 = VK_TRUE;
    }

    if (HasFeature(Feature::TextureCompressionASTC)) {
        DAWN_ASSERT(mDeviceInfo.features.textureCompressionASTC_LDR == VK_TRUE);
        usedKnobs.features.textureCompressionASTC_LDR = VK_TRUE;
    }

    if (HasFeature(Feature::DepthClipControl)) {
        usedKnobs.features.depthClamp = VK_TRUE;
    }

    if (HasFeature(Feature::ChromiumExperimentalPrimitiveId)) {
        DAWN_ASSERT(mDeviceInfo.features.geometryShader == VK_TRUE);
        usedKnobs.features.geometryShader = VK_TRUE;
    }

    bool shaderFloat16Int8FeaturesAdded = false;
    if (HasFeature(Feature::ShaderF16)) {
        DAWN_ASSERT(usedKnobs.HasExt(DeviceExt::ShaderFloat16Int8) &&
                    mDeviceInfo.shaderFloat16Int8Features.shaderFloat16 == VK_TRUE &&
                    usedKnobs.HasExt(DeviceExt::_16BitStorage) &&
                    mDeviceInfo._16BitStorageFeatures.storageBuffer16BitAccess == VK_TRUE &&
                    mDeviceInfo._16BitStorageFeatures.uniformAndStorageBuffer16BitAccess ==
                        VK_TRUE);

        usedKnobs.shaderFloat16Int8Features.shaderFloat16 = VK_TRUE;
        usedKnobs._16BitStorageFeatures.storageBuffer16BitAccess = VK_TRUE;
        usedKnobs._16BitStorageFeatures.uniformAndStorageBuffer16BitAccess = VK_TRUE;
        if (mDeviceInfo._16BitStorageFeatures.storageInputOutput16 == VK_TRUE) {
            usedKnobs._16BitStorageFeatures.storageInputOutput16 = VK_TRUE;
        }
        shaderFloat16Int8FeaturesAdded = true;

        featuresChain.Add(&usedKnobs.shaderFloat16Int8Features,
                          VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_FLOAT16_INT8_FEATURES_KHR);
        featuresChain.Add(&usedKnobs._16BitStorageFeatures,
                          VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_16BIT_STORAGE_FEATURES);
    }

    // Set device feature for subgroups with f16 types.
    if (HasFeature(Feature::ShaderF16) && HasFeature(Feature::Subgroups)) {
        DAWN_ASSERT(usedKnobs.HasExt(DeviceExt::ShaderSubgroupExtendedTypes) &&
                    mDeviceInfo.shaderSubgroupExtendedTypes.shaderSubgroupExtendedTypes == VK_TRUE);

        usedKnobs.shaderSubgroupExtendedTypes = mDeviceInfo.shaderSubgroupExtendedTypes;
        featuresChain.Add(&usedKnobs.shaderSubgroupExtendedTypes);
    }

    if (HasFeature(Feature::DualSourceBlending)) {
        usedKnobs.features.dualSrcBlend = VK_TRUE;
    }

    if (HasFeature(Feature::ClipDistances)) {
        usedKnobs.features.shaderClipDistance = VK_TRUE;
    }

    if (HasFeature(Feature::R8UnormStorage) || HasFeature(Feature::TextureFormatsTier1)) {
        usedKnobs.features.shaderStorageImageExtendedFormats = VK_TRUE;
    }

    if (IsRobustnessEnabled() && mDeviceInfo.HasExt(DeviceExt::Robustness2)) {
        DAWN_ASSERT(usedKnobs.HasExt(DeviceExt::Robustness2));

        usedKnobs.robustness2Features = mDeviceInfo.robustness2Features;
        featuresChain.Add(&usedKnobs.robustness2Features);
    }

    if (HasFeature(Feature::YCbCrVulkanSamplers) &&
        mDeviceInfo.HasExt(DeviceExt::SamplerYCbCrConversion) &&
        mDeviceInfo.HasExt(DeviceExt::ExternalMemoryAndroidHardwareBuffer)) {
        usedKnobs.samplerYCbCrConversionFeatures.samplerYcbcrConversion = VK_TRUE;
        featuresChain.Add(&usedKnobs.samplerYCbCrConversionFeatures,
                          VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_YCBCR_CONVERSION_FEATURES);
    }

    if (HasFeature(Feature::MultiDrawIndirect)) {
        DAWN_ASSERT(usedKnobs.HasExt(DeviceExt::DrawIndirectCount) &&
                    mDeviceInfo.features.multiDrawIndirect == VK_TRUE);
        usedKnobs.features.multiDrawIndirect = VK_TRUE;
    }

    if (HasFeature(Feature::ChromiumExperimentalSubgroupMatrix)) {
        DAWN_ASSERT(IsToggleEnabled(Toggle::UseVulkanMemoryModel));
        DAWN_ASSERT(usedKnobs.HasExt(DeviceExt::CooperativeMatrix));
        usedKnobs.cooperativeMatrixFeatures = mDeviceInfo.cooperativeMatrixFeatures;
        featuresChain.Add(&usedKnobs.cooperativeMatrixFeatures);

        // Using int8 and uint8 cooperative matrices requires `shaderInt8`.
        if (mDeviceInfo.shaderFloat16Int8Features.shaderInt8 == VK_TRUE) {
            usedKnobs.shaderFloat16Int8Features.shaderInt8 = VK_TRUE;
            if (!shaderFloat16Int8FeaturesAdded) {
                featuresChain.Add(
                    &usedKnobs.shaderFloat16Int8Features,
                    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_FLOAT16_INT8_FEATURES_KHR);
            }
        }
    }

    // Find a universal queue family
    {
        // Note that GRAPHICS and COMPUTE imply TRANSFER so we don't need to check for it.
        constexpr uint32_t kUniversalFlags = VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT;
        int universalQueueFamily = -1;
        for (unsigned int i = 0; i < mDeviceInfo.queueFamilies.size(); ++i) {
            if ((mDeviceInfo.queueFamilies[i].queueFlags & kUniversalFlags) == kUniversalFlags) {
                universalQueueFamily = i;
                break;
            }
        }

        if (universalQueueFamily == -1) {
            return DAWN_INTERNAL_ERROR("No universal queue family");
        }
        mMainQueueFamily = static_cast<uint32_t>(universalQueueFamily);
    }

    // Choose to create a single universal queue
    std::vector<VkDeviceQueueCreateInfo> queuesToRequest;
    float zero = 0.0f;
    {
        VkDeviceQueueCreateInfo queueCreateInfo;
        queueCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
        queueCreateInfo.pNext = nullptr;
        queueCreateInfo.flags = 0;
        queueCreateInfo.queueFamilyIndex = static_cast<uint32_t>(mMainQueueFamily);
        queueCreateInfo.queueCount = 1;
        queueCreateInfo.pQueuePriorities = &zero;

        queuesToRequest.push_back(queueCreateInfo);
    }

    VkDeviceCreateInfo createInfo;
    createInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
    createInfo.pNext = nullptr;
    createInfo.flags = 0;
    createInfo.queueCreateInfoCount = static_cast<uint32_t>(queuesToRequest.size());
    createInfo.pQueueCreateInfos = queuesToRequest.data();
    createInfo.enabledLayerCount = 0;
    createInfo.ppEnabledLayerNames = nullptr;
    createInfo.enabledExtensionCount = static_cast<uint32_t>(extensionNames.size());
    createInfo.ppEnabledExtensionNames = extensionNames.data();

    // When we have DeviceExt::GetPhysicalDeviceProperties2, use features2 so that features not
    // covered by VkPhysicalDeviceFeatures can be enabled.
    if (mDeviceInfo.HasExt(DeviceExt::GetPhysicalDeviceProperties2)) {
        features2.features = usedKnobs.features;
        createInfo.pNext = &features2;
        createInfo.pEnabledFeatures = nullptr;
    } else {
        DAWN_ASSERT(features2.pNext == nullptr);
        createInfo.pEnabledFeatures = &usedKnobs.features;
    }

    DAWN_TRY(CheckVkSuccess(fn.CreateDevice(vkPhysicalDevice, &createInfo, nullptr, &mVkDevice),
                            "vkCreateDevice"));

    return usedKnobs;
}

VulkanFunctions* Device::GetMutableFunctions() {
    return const_cast<VulkanFunctions*>(&fn);
}

MaybeError Device::CopyFromStagingToBuffer(BufferBase* source,
                                           uint64_t sourceOffset,
                                           BufferBase* destination,
                                           uint64_t destinationOffset,
                                           uint64_t size) {
    // It is a validation error to do a 0-sized copy in Vulkan, check it is skipped prior to
    // calling this function.
    DAWN_ASSERT(size != 0);

    CommandRecordingContext* recordingContext =
        ToBackend(GetQueue())->GetPendingRecordingContext(Queue::SubmitMode::Passive);

    ToBackend(destination)
        ->EnsureDataInitializedAsDestination(recordingContext, destinationOffset, size);

    // There is no need of a barrier to make host writes available and visible to the copy
    // operation for HOST_COHERENT memory. The Vulkan spec for vkQueueSubmit describes that it
    // does an implicit availability, visibility and domain operation.

    // Insert pipeline barrier to ensure correct ordering with previous memory operations on the
    // buffer.
    ToBackend(destination)->TransitionUsageNow(recordingContext, wgpu::BufferUsage::CopyDst);

    VkBufferCopy copy;
    copy.srcOffset = sourceOffset;
    copy.dstOffset = destinationOffset;
    copy.size = size;

    this->fn.CmdCopyBuffer(recordingContext->commandBuffer, ToBackend(source)->GetHandle(),
                           ToBackend(destination)->GetHandle(), 1, &copy);

    return {};
}

MaybeError Device::CopyFromStagingToTextureImpl(const BufferBase* source,
                                                const TexelCopyBufferLayout& src,
                                                const TextureCopy& dst,
                                                const Extent3D& copySizePixels) {
    // There is no need of a barrier to make host writes available and visible to the copy
    // operation for HOST_COHERENT memory. The Vulkan spec for vkQueueSubmit describes that it
    // does an implicit availability, visibility and domain operation.

    CommandRecordingContext* recordingContext =
        ToBackend(GetQueue())->GetPendingRecordingContext(Queue::SubmitMode::Passive);

    VkBufferImageCopy region = ComputeBufferImageCopyRegion(src, dst, copySizePixels);
    VkImageSubresourceLayers subresource = region.imageSubresource;

    SubresourceRange range = GetSubresourcesAffectedByCopy(dst, copySizePixels);

    if (IsCompleteSubresourceCopiedTo(dst.texture.Get(), copySizePixels, subresource.mipLevel,
                                      dst.aspect)) {
        // Since texture has been overwritten, it has been "initialized"
        dst.texture->SetIsSubresourceContentInitialized(true, range);
    } else {
        DAWN_TRY(
            ToBackend(dst.texture)->EnsureSubresourceContentInitialized(recordingContext, range));
    }
    // Insert pipeline barrier to ensure correct ordering with previous memory operations on the
    // texture.
    ToBackend(dst.texture)
        ->TransitionUsageNow(recordingContext, wgpu::TextureUsage::CopyDst, wgpu::ShaderStage::None,
                             range);
    VkImage dstImage = ToBackend(dst.texture)->GetHandle();

    // Dawn guarantees dstImage be in the TRANSFER_DST_OPTIMAL layout after the
    // copy command.
    this->fn.CmdCopyBufferToImage(recordingContext->commandBuffer, ToBackend(source)->GetHandle(),
                                  dstImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &region);
    return {};
}

MaybeError Device::ImportExternalImage(const ExternalImageDescriptorVk* descriptor,
                                       ExternalMemoryHandle memoryHandle,
                                       VkImage image,
                                       const std::vector<ExternalSemaphoreHandle>& waitHandles,
                                       VkDeviceMemory* outAllocation,
                                       std::vector<VkSemaphore>* outWaitSemaphores) {
    UnpackedPtr<TextureDescriptor> textureDescriptor;
    DAWN_TRY_ASSIGN(textureDescriptor, ValidateAndUnpack(FromAPI(descriptor->cTextureDescriptor)));

    wgpu::TextureUsage usage = textureDescriptor->usage;
    if (auto* internalUsageDesc = textureDescriptor.Get<DawnTextureInternalUsageDescriptor>()) {
        usage |= internalUsageDesc->internalUsage;
    }

    // Check services support this combination of handle type / image info
    DAWN_INVALID_IF(!mExternalSemaphoreService->Supported(),
                    "External semaphore usage not supported");

    DAWN_INVALID_IF(
        !mExternalMemoryService->SupportsImportMemory(
            descriptor->GetType(), VulkanImageFormat(this, textureDescriptor->format),
            VK_IMAGE_TYPE_2D, VK_IMAGE_TILING_OPTIMAL,
            VulkanImageUsage(this, usage, GetValidInternalFormat(textureDescriptor->format)),
            VK_IMAGE_CREATE_ALIAS_BIT_KHR),
        "External memory usage not supported");

    // Import the external image's memory
    external_memory::MemoryImportParams importParams;
    DAWN_TRY_ASSIGN(importParams, mExternalMemoryService->GetMemoryImportParams(descriptor, image));
    DAWN_TRY_ASSIGN(*outAllocation, mExternalMemoryService->ImportMemory(
                                        descriptor->GetType(), memoryHandle, importParams, image));

    // Import semaphores we have to wait on before using the texture
    for (const ExternalSemaphoreHandle& handle : waitHandles) {
        VkSemaphore semaphore = VK_NULL_HANDLE;
        DAWN_TRY_ASSIGN(semaphore, mExternalSemaphoreService->ImportSemaphore(handle));

        // The legacy import mechanism transfers ownership to Dawn.
        // The new import mechanism dups the semaphore handle.
        // Therefore, on success, because ImportSemaphore has dup'ed the handle,
        // we need to close the old handle by acquiring and dropping it.
        // TODO(dawn:1745): This entire code path will be deprecated and removed.
        SystemHandle::Acquire(handle);
        outWaitSemaphores->push_back(semaphore);
    }

    return {};
}

bool Device::SignalAndExportExternalTexture(
    Texture* texture,
    VkImageLayout desiredLayout,
    ExternalImageExportInfoVk* info,
    std::vector<ExternalSemaphoreHandle>* semaphoreHandles) {
    ExternalVkImageTexture* externalTexture = static_cast<ExternalVkImageTexture*>(texture);
    return !ConsumedError([&]() -> MaybeError {
        DAWN_TRY(ValidateObject(texture));

        ExternalSemaphoreHandle semaphoreHandle;
        VkImageLayout releasedOldLayout;
        VkImageLayout releasedNewLayout;
        DAWN_TRY(externalTexture->ExportExternalTexture(desiredLayout, &semaphoreHandle,
                                                        &releasedOldLayout, &releasedNewLayout));

        semaphoreHandles->push_back(semaphoreHandle);
        info->releasedOldLayout = releasedOldLayout;
        info->releasedNewLayout = releasedNewLayout;
        info->isInitialized =
            texture->IsSubresourceContentInitialized(texture->GetAllSubresources());

        return {};
    }());
}

Ref<TextureBase> Device::CreateTextureWrappingVulkanImage(
    const ExternalImageDescriptorVk* descriptor,
    ExternalMemoryHandle memoryHandle,
    const std::vector<ExternalSemaphoreHandle>& waitHandles) {
    // Initial validation
    if (ConsumedError(ValidateIsAlive())) {
        return nullptr;
    }
    TextureDescriptor reifiedDescriptor =
        FromAPI(descriptor->cTextureDescriptor)->WithTrivialFrontendDefaults();
    UnpackedPtr<TextureDescriptor> textureDescriptor;
    if (ConsumedError(ValidateAndUnpack(&reifiedDescriptor), &textureDescriptor)) {
        return nullptr;
    }
    if (ConsumedError(ValidateTextureDescriptor(this, textureDescriptor,
                                                AllowMultiPlanarTextureFormat::Yes))) {
        return nullptr;
    }
    if (ConsumedError(ValidateVulkanImageCanBeWrapped(this, textureDescriptor),
                      "validating that a Vulkan image can be wrapped with %s.",
                      textureDescriptor)) {
        return nullptr;
    }
    if (GetValidInternalFormat(textureDescriptor->format).IsMultiPlanar() &&
        !descriptor->isInitialized) {
        [[maybe_unused]] bool consumed = ConsumedError(DAWN_VALIDATION_ERROR(
            "External textures with multiplanar formats must be initialized."));
        return nullptr;
    }

    VkDeviceMemory allocation = VK_NULL_HANDLE;
    std::vector<VkSemaphore> waitSemaphores;
    waitSemaphores.reserve(waitHandles.size());

    // Cleanup in case of a failure, the image creation doesn't acquire the external objects
    // if a failure happems.
    Ref<ExternalVkImageTexture> result;
    // TODO(crbug.com/1026480): Consolidate this into a single CreateFromExternal call.
    if (ConsumedError(ExternalVkImageTexture::Create(this, descriptor, textureDescriptor,
                                                     mExternalMemoryService.get()),
                      &result) ||
        ConsumedError(ImportExternalImage(descriptor, memoryHandle, result->GetHandle(),
                                          waitHandles, &allocation, &waitSemaphores)) ||
        ConsumedError(result->BindExternalMemory(descriptor, allocation, waitSemaphores))) {
        // Delete the Texture if it was created
        result = nullptr;

        // Clear image memory
        fn.FreeMemory(GetVkDevice(), allocation, nullptr);

        // Clear any wait semaphores we were able to import
        for (VkSemaphore semaphore : waitSemaphores) {
            fn.DestroySemaphore(GetVkDevice(), semaphore, nullptr);
        }
    }

    return result;
}

uint32_t Device::GetComputeSubgroupSize() const {
    return ToBackend(GetPhysicalDevice())->GetDefaultComputeSubgroupSize();
}

void Device::OnDebugMessage(std::string message) {
    mDebugMessages.push_back(std::move(message));
}

MaybeError Device::CheckDebugLayerAndGenerateErrors() {
    if (!GetAdapter()->GetInstance()->IsBackendValidationEnabled() || mDebugMessages.empty()) {
        return {};
    }

    auto error = DAWN_INTERNAL_ERROR("The Vulkan validation layer reported uncaught errors.");

    AppendDebugLayerMessages(error.get());

    return std::move(error);
}

void Device::AppendDebugLayerMessages(ErrorData* error) {
    if (!GetAdapter()->GetInstance()->IsBackendValidationEnabled()) {
        return;
    }

    while (!mDebugMessages.empty()) {
        error->AppendBackendMessage(std::move(mDebugMessages.back()));
        mDebugMessages.pop_back();
    }
}

void Device::CheckDebugMessagesAfterDestruction() const {
    if (!GetAdapter()->GetInstance()->IsBackendValidationEnabled() || mDebugMessages.empty()) {
        return;
    }

    dawn::ErrorLog()
        << "Some VVL messages were not handled before dawn::native::vulkan::Device destruction:";
    for (const auto& message : mDebugMessages) {
        dawn::ErrorLog() << " - " << message;
    }

    // Crash in debug
    DAWN_ASSERT(false);
}

void Device::DestroyImpl() {
    DAWN_ASSERT(GetState() == State::Disconnected);

    // We failed during initialization so early that we don't even have a VkDevice. There is
    // nothing to do.
    if (mVkDevice == VK_NULL_HANDLE) {
        return;
    }

    // TODO(crbug.com/dawn/831): DestroyImpl is called from two places.
    // - It may be called if the device is explicitly destroyed with APIDestroy.
    //   This case is NOT thread-safe and needs proper synchronization with other
    //   simultaneous uses of the device.
    // - It may be called when the last ref to the device is dropped and the device
    //   is implicitly destroyed. This case is thread-safe because there are no
    //   other threads using the device since there are no other live refs.

    // The deleter is the second thing we initialize. If it is not present, it means that
    // only the VkDevice was created and nothing else. Destroy the device and do nothing else
    // because the function pointers might not have been loaded (and there is nothing to
    // destroy anyway).
    if (mDeleter == nullptr) {
        fn.DestroyDevice(mVkDevice, nullptr);
        mVkDevice = VK_NULL_HANDLE;
        return;
    }

    // Enough of the Device's initialization happened that we can now do regular robust
    // deinitialization.

    ToBackend(GetPhysicalDevice())->GetVulkanInstance()->StopListeningForDeviceMessages(this);

    mDescriptorAllocatorsPendingDeallocation.Use([&](auto pending) {
        for (Ref<DescriptorSetAllocator>& allocator : pending->IterateUpTo(kMaxExecutionSerial)) {
            allocator->FinishDeallocation(kMaxExecutionSerial);
        }
        pending->ClearUpTo(kMaxExecutionSerial);
    });

    // Releasing the uploader enqueues buffers to be released.
    // Call Tick() again to clear them before releasing the deleter.
    GetResourceMemoryAllocator()->Tick(kMaxExecutionSerial);

    // Allow recycled memory to be deleted.
    GetResourceMemoryAllocator()->FreeRecycledMemory();

    // The VkFramebuffers and VkRenderPasses in the cache can be destroyed immediately since all
    // commands referring to them are guaranteed to be finished executing.
    mFramebufferCache = nullptr;
    mRenderPassCache = nullptr;

    // Destroy the VkPipelineCache before VkDevice.
    mMonolithicPipelineCache = nullptr;

    // Delete all the remaining VkDevice child objects immediately since the GPU timeline is
    // finished.
    GetFencedDeleter()->Tick(kMaxExecutionSerial);
    mDeleter = nullptr;

    // VkQueues are destroyed when the VkDevice is destroyed
    // The VkDevice is needed to destroy child objects, so it must be destroyed last after all
    // child objects have been deleted.
    DAWN_ASSERT(mVkDevice != VK_NULL_HANDLE);
    fn.DestroyDevice(mVkDevice, nullptr);
    mVkDevice = VK_NULL_HANDLE;

    // No additonal Vulkan commands should be done by this device after this function. Check for any
    // remaining Vulkan Validation Layer messages that may have been added during destruction or not
    // handled prior to destruction.
    CheckDebugMessagesAfterDestruction();
}

MaybeError Device::GetAHardwareBufferPropertiesImpl(void* handle,
                                                    AHardwareBufferProperties* properties) const {
#if DAWN_PLATFORM_IS(ANDROID)
    auto* aHardwareBuffer = static_cast<struct AHardwareBuffer*>(handle);

    VkAndroidHardwareBufferPropertiesANDROID bufferProperties = {
        .sType = VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_PROPERTIES_ANDROID,
    };

    // Query the properties to find the appropriate VkFormat and memory type.
    VkAndroidHardwareBufferFormatPropertiesANDROID bufferFormatProperties;
    PNextChainBuilder bufferPropertiesChain(&bufferProperties);
    bufferPropertiesChain.Add(&bufferFormatProperties,
                              VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_FORMAT_PROPERTIES_ANDROID);

    DAWN_TRY(CheckVkSuccess(fn.GetAndroidHardwareBufferPropertiesANDROID(
                                GetVkDevice(), aHardwareBuffer, &bufferProperties),
                            "vkGetAndroidHardwareBufferPropertiesANDROID"));

    // Populate the YCbCr info.
    properties->yCbCrInfo.externalFormat = bufferFormatProperties.externalFormat;
    properties->yCbCrInfo.vkFormat = bufferFormatProperties.format;
    properties->yCbCrInfo.vkYCbCrModel = bufferFormatProperties.suggestedYcbcrModel;
    properties->yCbCrInfo.vkYCbCrRange = bufferFormatProperties.suggestedYcbcrRange;
    properties->yCbCrInfo.vkComponentSwizzleRed =
        bufferFormatProperties.samplerYcbcrConversionComponents.r;
    properties->yCbCrInfo.vkComponentSwizzleGreen =
        bufferFormatProperties.samplerYcbcrConversionComponents.g;
    properties->yCbCrInfo.vkComponentSwizzleBlue =
        bufferFormatProperties.samplerYcbcrConversionComponents.b;
    properties->yCbCrInfo.vkComponentSwizzleAlpha =
        bufferFormatProperties.samplerYcbcrConversionComponents.a;
    properties->yCbCrInfo.vkXChromaOffset = bufferFormatProperties.suggestedXChromaOffset;
    properties->yCbCrInfo.vkYChromaOffset = bufferFormatProperties.suggestedYChromaOffset;

    uint32_t formatFeatures = bufferFormatProperties.formatFeatures;
    properties->yCbCrInfo.vkChromaFilter =
        (formatFeatures & VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_LINEAR_FILTER_BIT)
            ? wgpu::FilterMode::Linear
            : wgpu::FilterMode::Nearest;
    properties->yCbCrInfo.forceExplicitReconstruction =
        formatFeatures &
        VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_BIT;

    return {};
#else
    return DeviceBase::GetAHardwareBufferPropertiesImpl(handle, properties);
#endif
}

uint32_t Device::GetOptimalBytesPerRowAlignment() const {
    return mDeviceInfo.properties.limits.optimalBufferCopyRowPitchAlignment;
}

uint64_t Device::GetOptimalBufferToTextureCopyOffsetAlignment() const {
    return mDeviceInfo.properties.limits.optimalBufferCopyOffsetAlignment;
}

float Device::GetTimestampPeriodInNS() const {
    return mDeviceInfo.properties.limits.timestampPeriod;
}

AllocatorMemoryInfo Device::GetAllocatorMemoryInfo() const {
    DAWN_ASSERT(IsLockedByCurrentThreadIfNeeded());
    AllocatorMemoryInfo info = {};
    info.totalAllocatedMemory = GetResourceMemoryAllocator()->GetTotalAllocatedMemory();
    info.totalUsedMemory = GetResourceMemoryAllocator()->GetTotalUsedMemory();
    info.totalLazyAllocatedMemory = GetResourceMemoryAllocator()->GetTotalLazyAllocatedMemory();
    info.totalLazyUsedMemory = GetResourceMemoryAllocator()->GetTotalLazyUsedMemory();
    return info;
}

void Device::SetLabelImpl() {
    SetDebugName(this, VK_OBJECT_TYPE_DEVICE, mVkDevice, "Dawn_Device", GetLabel());
}

bool Device::ReduceMemoryUsageImpl() {
    GetResourceMemoryAllocator()->FreeRecycledMemory();

    GetFramebufferCache()->Clear();

    auto GetLastPendingDeletionSerial = [this]() {
        // Only hold the lock for one of these objects at a time to avoid lock-order-inversion.
        auto deleterSerial = GetFencedDeleter()->GetLastPendingDeletionSerial();
        auto allocatorSerial = GetResourceMemoryAllocator()->GetLastPendingDeletionSerial();
        return std::max(deleterSerial, allocatorSerial);
    };
    ExecutionSerial deletionSerial = GetLastPendingDeletionSerial();

    if (deletionSerial == kBeginningOfGPUTime) {
        // Nothing pending deletion.
        return false;
    }

    Queue* queue = ToBackend(GetQueue());

    if (deletionSerial > queue->GetLastSubmittedCommandSerial()) {
        // Submit any pending commands to ensure that the pending deletion serial completes. One
        // complication here is that there might not be any pending commands and the queue would
        // skip commit. Getting the recording context works makes it look like there is work to
        // submit in all cases.
        // TODO(crbug.com/398193014): If there is no work in the queue to submit then the device
        // should be able to immediately delete objects enqueued for deletion after tick completes.
        queue->GetPendingRecordingContext();
    }

    if (ConsumedError(TickImpl())) {
        return false;
    }
    DAWN_ASSERT(deletionSerial <= queue->GetLastSubmittedCommandSerial());

    // Check again if there is anything left to delete as tick might have deleted objects.
    return GetLastPendingDeletionSerial() != kBeginningOfGPUTime;
}

void Device::PerformIdleTasksImpl() {
    if (mMonolithicPipelineCache) {
        MaybeError maybeError = mMonolithicPipelineCache->StoreOnIdle();
        if (maybeError.IsError()) {
            std::unique_ptr<ErrorData> error = maybeError.AcquireError();
            EmitLog(wgpu::LoggingType::Error, error->GetFormattedMessage().c_str());
            return;
        }
    }
}

bool Device::CanAddStorageUsageToBufferWithoutSideEffects(wgpu::BufferUsage storageUsage,
                                                          wgpu::BufferUsage originalUsage,
                                                          size_t bufferSize) const {
    DAWN_ASSERT(IsSubset(storageUsage, wgpu::BufferUsage::Storage | kInternalStorageBuffer |
                                           kReadOnlyStorageBuffer));
    if (originalUsage & kMappableBufferUsages) {
        return HasFeature(Feature::BufferMapExtendedUsages);
    }
    return true;
}

// Gets or creates an occlusion Query object for use with Toggle::VulkanAddWorkToEmptyResolvePass.
QuerySetBase* Device::GetEmptyPassQuerySet() {
    DAWN_ASSERT(IsToggleEnabled(Toggle::VulkanAddWorkToEmptyResolvePass));

    if (!mEmptyPassQuerySet) {
        QuerySetDescriptor descriptor;
        descriptor.type = wgpu::QueryType::Occlusion;
        descriptor.count = 1;
        mEmptyPassQuerySet = APICreateQuerySet(&descriptor);
    }
    return mEmptyPassQuerySet.Get();
}

}  // namespace dawn::native::vulkan
