// Copyright 2017 The Dawn Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "dawn_native/d3d12/DeviceD3D12.h"

#include "common/GPUInfo.h"
#include "dawn_native/DynamicUploader.h"
#include "dawn_native/Instance.h"
#include "dawn_native/d3d12/AdapterD3D12.h"
#include "dawn_native/d3d12/BackendD3D12.h"
#include "dawn_native/d3d12/BindGroupD3D12.h"
#include "dawn_native/d3d12/BindGroupLayoutD3D12.h"
#include "dawn_native/d3d12/CommandAllocatorManager.h"
#include "dawn_native/d3d12/CommandBufferD3D12.h"
#include "dawn_native/d3d12/ComputePipelineD3D12.h"
#include "dawn_native/d3d12/D3D11on12Util.h"
#include "dawn_native/d3d12/D3D12Error.h"
#include "dawn_native/d3d12/PipelineLayoutD3D12.h"
#include "dawn_native/d3d12/PlatformFunctions.h"
#include "dawn_native/d3d12/QuerySetD3D12.h"
#include "dawn_native/d3d12/QueueD3D12.h"
#include "dawn_native/d3d12/RenderPipelineD3D12.h"
#include "dawn_native/d3d12/ResidencyManagerD3D12.h"
#include "dawn_native/d3d12/ResourceAllocatorManagerD3D12.h"
#include "dawn_native/d3d12/SamplerD3D12.h"
#include "dawn_native/d3d12/SamplerHeapCacheD3D12.h"
#include "dawn_native/d3d12/ShaderModuleD3D12.h"
#include "dawn_native/d3d12/ShaderVisibleDescriptorAllocatorD3D12.h"
#include "dawn_native/d3d12/StagingBufferD3D12.h"
#include "dawn_native/d3d12/StagingDescriptorAllocatorD3D12.h"
#include "dawn_native/d3d12/SwapChainD3D12.h"
#include "dawn_native/d3d12/UtilsD3D12.h"

#include <sstream>

namespace dawn_native { namespace d3d12 {

    // TODO(dawn:155): Figure out these values.
    static constexpr uint16_t kShaderVisibleDescriptorHeapSize = 1024;
    static constexpr uint8_t kAttachmentDescriptorHeapSize = 64;

    // Value may change in the future to better accomodate large clears.
    static constexpr uint64_t kZeroBufferSize = 1024 * 1024 * 4;  // 4 Mb

    static constexpr uint64_t kMaxDebugMessagesToPrint = 5;

    // static
    ResultOrError<Ref<Device>> Device::Create(Adapter* adapter,
                                              const DeviceDescriptor* descriptor) {
        Ref<Device> device = AcquireRef(new Device(adapter, descriptor));
        DAWN_TRY(device->Initialize());
        return device;
    }

    MaybeError Device::Initialize() {
        InitTogglesFromDriver();

        mD3d12Device = ToBackend(GetAdapter())->GetDevice();

        ASSERT(mD3d12Device != nullptr);

        // Create device-global objects
        D3D12_COMMAND_QUEUE_DESC queueDesc = {};
        queueDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE;
        queueDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT;
        DAWN_TRY(
            CheckHRESULT(mD3d12Device->CreateCommandQueue(&queueDesc, IID_PPV_ARGS(&mCommandQueue)),
                         "D3D12 create command queue"));

        if (IsFeatureEnabled(Feature::TimestampQuery)) {
            // Get GPU timestamp counter frequency (in ticks/second). This fails if the specified
            // command queue doesn't support timestamps. D3D12_COMMAND_LIST_TYPE_DIRECT queues
            // always support timestamps except where there are bugs in Windows container and vGPU
            // implementations.
            uint64_t frequency;
            DAWN_TRY(CheckHRESULT(mCommandQueue->GetTimestampFrequency(&frequency),
                                  "D3D12 get timestamp frequency"));
            // Calculate the period in nanoseconds by the frequency.
            mTimestampPeriod = static_cast<float>(1e9) / frequency;
        }

        // If PIX is not attached, the QueryInterface fails. Hence, no need to check the return
        // value.
        mCommandQueue.As(&mD3d12SharingContract);

        DAWN_TRY(
            CheckHRESULT(mD3d12Device->CreateFence(uint64_t(GetLastSubmittedCommandSerial()),
                                                   D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&mFence)),
                         "D3D12 create fence"));

        mFenceEvent = CreateEvent(nullptr, FALSE, FALSE, nullptr);
        ASSERT(mFenceEvent != nullptr);

        // Initialize backend services
        mCommandAllocatorManager = std::make_unique<CommandAllocatorManager>(this);

        // Zero sized allocator is never requested and does not need to exist.
        for (uint32_t countIndex = 0; countIndex < kNumViewDescriptorAllocators; countIndex++) {
            mViewAllocators[countIndex + 1] = std::make_unique<StagingDescriptorAllocator>(
                this, 1u << countIndex, kShaderVisibleDescriptorHeapSize,
                D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);
        }

        for (uint32_t countIndex = 0; countIndex < kNumSamplerDescriptorAllocators; countIndex++) {
            mSamplerAllocators[countIndex + 1] = std::make_unique<StagingDescriptorAllocator>(
                this, 1u << countIndex, kShaderVisibleDescriptorHeapSize,
                D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER);
        }

        mRenderTargetViewAllocator = std::make_unique<StagingDescriptorAllocator>(
            this, 1, kAttachmentDescriptorHeapSize, D3D12_DESCRIPTOR_HEAP_TYPE_RTV);

        mDepthStencilViewAllocator = std::make_unique<StagingDescriptorAllocator>(
            this, 1, kAttachmentDescriptorHeapSize, D3D12_DESCRIPTOR_HEAP_TYPE_DSV);

        mSamplerHeapCache = std::make_unique<SamplerHeapCache>(this);

        mResidencyManager = std::make_unique<ResidencyManager>(this);
        mResourceAllocatorManager = std::make_unique<ResourceAllocatorManager>(this);

        // ShaderVisibleDescriptorAllocators use the ResidencyManager and must be initialized after.
        DAWN_TRY_ASSIGN(
            mSamplerShaderVisibleDescriptorAllocator,
            ShaderVisibleDescriptorAllocator::Create(this, D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER));

        DAWN_TRY_ASSIGN(
            mViewShaderVisibleDescriptorAllocator,
            ShaderVisibleDescriptorAllocator::Create(this, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV));

        // Initialize indirect commands
        D3D12_INDIRECT_ARGUMENT_DESC argumentDesc = {};
        argumentDesc.Type = D3D12_INDIRECT_ARGUMENT_TYPE_DISPATCH;

        D3D12_COMMAND_SIGNATURE_DESC programDesc = {};
        programDesc.ByteStride = 3 * sizeof(uint32_t);
        programDesc.NumArgumentDescs = 1;
        programDesc.pArgumentDescs = &argumentDesc;

        GetD3D12Device()->CreateCommandSignature(&programDesc, NULL,
                                                 IID_PPV_ARGS(&mDispatchIndirectSignature));

        argumentDesc.Type = D3D12_INDIRECT_ARGUMENT_TYPE_DRAW;
        programDesc.ByteStride = 4 * sizeof(uint32_t);

        GetD3D12Device()->CreateCommandSignature(&programDesc, NULL,
                                                 IID_PPV_ARGS(&mDrawIndirectSignature));

        argumentDesc.Type = D3D12_INDIRECT_ARGUMENT_TYPE_DRAW_INDEXED;
        programDesc.ByteStride = 5 * sizeof(uint32_t);

        GetD3D12Device()->CreateCommandSignature(&programDesc, NULL,
                                                 IID_PPV_ARGS(&mDrawIndexedIndirectSignature));

        DAWN_TRY(DeviceBase::Initialize(new Queue(this)));
        // Device shouldn't be used until after DeviceBase::Initialize so we must wait until after
        // device initialization to call NextSerial
        DAWN_TRY(NextSerial());

        // The environment can only use DXC when it's available. Override the decision if it is not
        // applicable.
        DAWN_TRY(ApplyUseDxcToggle());

        DAWN_TRY(CreateZeroBuffer());

        return {};
    }

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

    ID3D12Device* Device::GetD3D12Device() const {
        return mD3d12Device.Get();
    }

    ComPtr<ID3D12CommandQueue> Device::GetCommandQueue() const {
        return mCommandQueue;
    }

    ID3D12SharingContract* Device::GetSharingContract() const {
        return mD3d12SharingContract.Get();
    }

    ComPtr<ID3D12CommandSignature> Device::GetDispatchIndirectSignature() const {
        return mDispatchIndirectSignature;
    }

    ComPtr<ID3D12CommandSignature> Device::GetDrawIndirectSignature() const {
        return mDrawIndirectSignature;
    }

    ComPtr<ID3D12CommandSignature> Device::GetDrawIndexedIndirectSignature() const {
        return mDrawIndexedIndirectSignature;
    }

    ComPtr<IDXGIFactory4> Device::GetFactory() const {
        return ToBackend(GetAdapter())->GetBackend()->GetFactory();
    }

    MaybeError Device::ApplyUseDxcToggle() {
        if (!ToBackend(GetAdapter())->GetBackend()->GetFunctions()->IsDXCAvailable()) {
            ForceSetToggle(Toggle::UseDXC, false);
        } else if (IsFeatureEnabled(Feature::ShaderFloat16)) {
            // Currently we can only use DXC to compile HLSL shaders using float16.
            ForceSetToggle(Toggle::UseDXC, true);
        }

        if (IsToggleEnabled(Toggle::UseDXC)) {
            DAWN_TRY(ToBackend(GetAdapter())->GetBackend()->EnsureDxcCompiler());
            DAWN_TRY(ToBackend(GetAdapter())->GetBackend()->EnsureDxcLibrary());
            DAWN_TRY(ToBackend(GetAdapter())->GetBackend()->EnsureDxcValidator());
        }

        return {};
    }

    ComPtr<IDxcLibrary> Device::GetDxcLibrary() const {
        return ToBackend(GetAdapter())->GetBackend()->GetDxcLibrary();
    }

    ComPtr<IDxcCompiler> Device::GetDxcCompiler() const {
        return ToBackend(GetAdapter())->GetBackend()->GetDxcCompiler();
    }

    ComPtr<IDxcValidator> Device::GetDxcValidator() const {
        return ToBackend(GetAdapter())->GetBackend()->GetDxcValidator();
    }

    const PlatformFunctions* Device::GetFunctions() const {
        return ToBackend(GetAdapter())->GetBackend()->GetFunctions();
    }

    CommandAllocatorManager* Device::GetCommandAllocatorManager() const {
        return mCommandAllocatorManager.get();
    }

    ResidencyManager* Device::GetResidencyManager() const {
        return mResidencyManager.get();
    }

    ResultOrError<CommandRecordingContext*> Device::GetPendingCommandContext() {
        // Callers of GetPendingCommandList do so to record commands. Only reserve a command
        // allocator when it is needed so we don't submit empty command lists
        if (!mPendingCommands.IsOpen()) {
            DAWN_TRY(mPendingCommands.Open(mD3d12Device.Get(), mCommandAllocatorManager.get()));
        }
        return &mPendingCommands;
    }

    MaybeError Device::CreateZeroBuffer() {
        BufferDescriptor zeroBufferDescriptor;
        zeroBufferDescriptor.usage = wgpu::BufferUsage::CopySrc | wgpu::BufferUsage::CopyDst;
        zeroBufferDescriptor.size = kZeroBufferSize;
        zeroBufferDescriptor.label = "ZeroBuffer_Internal";
        DAWN_TRY_ASSIGN(mZeroBuffer, Buffer::Create(this, &zeroBufferDescriptor));

        return {};
    }

    MaybeError Device::ClearBufferToZero(CommandRecordingContext* commandContext,
                                         BufferBase* destination,
                                         uint64_t offset,
                                         uint64_t size) {
        // TODO(crbug.com/dawn/852): It would be ideal to clear the buffer in CreateZeroBuffer, but
        // the allocation of the staging buffer causes various end2end tests that monitor heap usage
        // to fail if it's done during device creation. Perhaps ClearUnorderedAccessView*() can be
        // used to avoid that.
        if (!mZeroBuffer->IsDataInitialized()) {
            DynamicUploader* uploader = GetDynamicUploader();
            UploadHandle uploadHandle;
            DAWN_TRY_ASSIGN(uploadHandle,
                            uploader->Allocate(kZeroBufferSize, GetPendingCommandSerial(),
                                               kCopyBufferToBufferOffsetAlignment));

            memset(uploadHandle.mappedBuffer, 0u, kZeroBufferSize);

            CopyFromStagingToBufferImpl(commandContext, uploadHandle.stagingBuffer,
                                        uploadHandle.startOffset, mZeroBuffer.Get(), 0,
                                        kZeroBufferSize);

            mZeroBuffer->SetIsDataInitialized();
        }

        Buffer* dstBuffer = ToBackend(destination);

        // Necessary to ensure residency of the zero buffer.
        mZeroBuffer->TrackUsageAndTransitionNow(commandContext, wgpu::BufferUsage::CopySrc);
        dstBuffer->TrackUsageAndTransitionNow(commandContext, wgpu::BufferUsage::CopyDst);

        while (size > 0) {
            uint64_t copySize = std::min(kZeroBufferSize, size);
            commandContext->GetCommandList()->CopyBufferRegion(
                dstBuffer->GetD3D12Resource(), offset, mZeroBuffer->GetD3D12Resource(), 0,
                copySize);

            offset += copySize;
            size -= copySize;
        }

        return {};
    }

    MaybeError Device::TickImpl() {
        // Perform cleanup operations to free unused objects
        ExecutionSerial completedSerial = GetCompletedCommandSerial();

        mResourceAllocatorManager->Tick(completedSerial);
        DAWN_TRY(mCommandAllocatorManager->Tick(completedSerial));
        mViewShaderVisibleDescriptorAllocator->Tick(completedSerial);
        mSamplerShaderVisibleDescriptorAllocator->Tick(completedSerial);
        mRenderTargetViewAllocator->Tick(completedSerial);
        mDepthStencilViewAllocator->Tick(completedSerial);
        mUsedComObjectRefs.ClearUpTo(completedSerial);

        if (mPendingCommands.IsOpen()) {
            DAWN_TRY(ExecutePendingCommandContext());
            DAWN_TRY(NextSerial());
        }

        DAWN_TRY(CheckDebugLayerAndGenerateErrors());

        return {};
    }

    MaybeError Device::NextSerial() {
        IncrementLastSubmittedCommandSerial();

        return CheckHRESULT(
            mCommandQueue->Signal(mFence.Get(), uint64_t(GetLastSubmittedCommandSerial())),
            "D3D12 command queue signal fence");
    }

    MaybeError Device::WaitForSerial(ExecutionSerial serial) {
        DAWN_TRY(CheckPassedSerials());
        if (GetCompletedCommandSerial() < serial) {
            DAWN_TRY(CheckHRESULT(mFence->SetEventOnCompletion(uint64_t(serial), mFenceEvent),
                                  "D3D12 set event on completion"));
            WaitForSingleObject(mFenceEvent, INFINITE);
            DAWN_TRY(CheckPassedSerials());
        }
        return {};
    }

    ResultOrError<ExecutionSerial> Device::CheckAndUpdateCompletedSerials() {
        ExecutionSerial completedSerial = ExecutionSerial(mFence->GetCompletedValue());
        if (DAWN_UNLIKELY(completedSerial == ExecutionSerial(UINT64_MAX))) {
            // GetCompletedValue returns UINT64_MAX if the device was removed.
            // Try to query the failure reason.
            DAWN_TRY(CheckHRESULT(mD3d12Device->GetDeviceRemovedReason(),
                                  "ID3D12Device::GetDeviceRemovedReason"));
            // Otherwise, return a generic device lost error.
            return DAWN_DEVICE_LOST_ERROR("Device lost");
        }

        if (completedSerial <= GetCompletedCommandSerial()) {
            return ExecutionSerial(0);
        }

        return completedSerial;
    }

    void Device::ReferenceUntilUnused(ComPtr<IUnknown> object) {
        mUsedComObjectRefs.Enqueue(object, GetPendingCommandSerial());
    }

    MaybeError Device::ExecutePendingCommandContext() {
        return mPendingCommands.ExecuteCommandList(this);
    }

    ResultOrError<Ref<BindGroupBase>> Device::CreateBindGroupImpl(
        const BindGroupDescriptor* descriptor) {
        return BindGroup::Create(this, descriptor);
    }
    ResultOrError<Ref<BindGroupLayoutBase>> Device::CreateBindGroupLayoutImpl(
        const BindGroupLayoutDescriptor* descriptor,
        PipelineCompatibilityToken pipelineCompatibilityToken) {
        return BindGroupLayout::Create(this, descriptor, pipelineCompatibilityToken);
    }
    ResultOrError<Ref<BufferBase>> Device::CreateBufferImpl(const 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 ComputePipelineDescriptor* descriptor) {
        return ComputePipeline::CreateUninitialized(this, descriptor);
    }
    ResultOrError<Ref<PipelineLayoutBase>> Device::CreatePipelineLayoutImpl(
        const 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 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 ShaderModuleDescriptor* descriptor,
        ShaderModuleParseResult* parseResult) {
        return ShaderModule::Create(this, descriptor, parseResult);
    }
    ResultOrError<Ref<SwapChainBase>> Device::CreateSwapChainImpl(
        const SwapChainDescriptor* descriptor) {
        return OldSwapChain::Create(this, descriptor);
    }
    ResultOrError<Ref<NewSwapChainBase>> Device::CreateSwapChainImpl(
        Surface* surface,
        NewSwapChainBase* previousSwapChain,
        const SwapChainDescriptor* descriptor) {
        return SwapChain::Create(this, surface, previousSwapChain, descriptor);
    }
    ResultOrError<Ref<TextureBase>> Device::CreateTextureImpl(const TextureDescriptor* descriptor) {
        return Texture::Create(this, descriptor);
    }
    ResultOrError<Ref<TextureViewBase>> Device::CreateTextureViewImpl(
        TextureBase* texture,
        const TextureViewDescriptor* descriptor) {
        return TextureView::Create(texture, descriptor);
    }
    void Device::InitializeComputePipelineAsyncImpl(Ref<ComputePipelineBase> computePipeline,
                                                    WGPUCreateComputePipelineAsyncCallback callback,
                                                    void* userdata) {
        ComputePipeline::InitializeAsync(std::move(computePipeline), callback, userdata);
    }
    void Device::InitializeRenderPipelineAsyncImpl(Ref<RenderPipelineBase> renderPipeline,
                                                   WGPUCreateRenderPipelineAsyncCallback callback,
                                                   void* userdata) {
        RenderPipeline::InitializeAsync(std::move(renderPipeline), callback, userdata);
    }

    ResultOrError<std::unique_ptr<StagingBufferBase>> Device::CreateStagingBuffer(size_t size) {
        std::unique_ptr<StagingBufferBase> stagingBuffer =
            std::make_unique<StagingBuffer>(size, this);
        DAWN_TRY(stagingBuffer->Initialize());
        return std::move(stagingBuffer);
    }

    MaybeError Device::CopyFromStagingToBuffer(StagingBufferBase* source,
                                               uint64_t sourceOffset,
                                               BufferBase* destination,
                                               uint64_t destinationOffset,
                                               uint64_t size) {
        CommandRecordingContext* commandRecordingContext;
        DAWN_TRY_ASSIGN(commandRecordingContext, GetPendingCommandContext());

        Buffer* dstBuffer = ToBackend(destination);

        bool cleared;
        DAWN_TRY_ASSIGN(cleared, dstBuffer->EnsureDataInitializedAsDestination(
                                     commandRecordingContext, destinationOffset, size));
        DAWN_UNUSED(cleared);

        CopyFromStagingToBufferImpl(commandRecordingContext, source, sourceOffset, destination,
                                    destinationOffset, size);

        return {};
    }

    void Device::CopyFromStagingToBufferImpl(CommandRecordingContext* commandContext,
                                             StagingBufferBase* source,
                                             uint64_t sourceOffset,
                                             BufferBase* destination,
                                             uint64_t destinationOffset,
                                             uint64_t size) {
        ASSERT(commandContext != nullptr);
        Buffer* dstBuffer = ToBackend(destination);
        StagingBuffer* srcBuffer = ToBackend(source);
        dstBuffer->TrackUsageAndTransitionNow(commandContext, wgpu::BufferUsage::CopyDst);

        commandContext->GetCommandList()->CopyBufferRegion(
            dstBuffer->GetD3D12Resource(), destinationOffset, srcBuffer->GetResource(),
            sourceOffset, size);
    }

    MaybeError Device::CopyFromStagingToTexture(const StagingBufferBase* source,
                                                const TextureDataLayout& src,
                                                TextureCopy* dst,
                                                const Extent3D& copySizePixels) {
        CommandRecordingContext* commandContext;
        DAWN_TRY_ASSIGN(commandContext, GetPendingCommandContext());
        Texture* texture = ToBackend(dst->texture.Get());
        ASSERT(texture->GetDimension() != wgpu::TextureDimension::e1D);

        SubresourceRange range = GetSubresourcesAffectedByCopy(*dst, copySizePixels);

        if (IsCompleteSubresourceCopiedTo(texture, copySizePixels, dst->mipLevel)) {
            texture->SetIsSubresourceContentInitialized(true, range);
        } else {
            texture->EnsureSubresourceContentInitialized(commandContext, range);
        }

        texture->TrackUsageAndTransitionNow(commandContext, wgpu::TextureUsage::CopyDst, range);

        RecordCopyBufferToTexture(commandContext, *dst, ToBackend(source)->GetResource(),
                                  src.offset, src.bytesPerRow, src.rowsPerImage, copySizePixels,
                                  texture, range.aspects);

        return {};
    }

    void Device::DeallocateMemory(ResourceHeapAllocation& allocation) {
        mResourceAllocatorManager->DeallocateMemory(allocation);
    }

    ResultOrError<ResourceHeapAllocation> Device::AllocateMemory(
        D3D12_HEAP_TYPE heapType,
        const D3D12_RESOURCE_DESC& resourceDescriptor,
        D3D12_RESOURCE_STATES initialUsage) {
        return mResourceAllocatorManager->AllocateMemory(heapType, resourceDescriptor,
                                                         initialUsage);
    }

    Ref<TextureBase> Device::CreateExternalTexture(
        const TextureDescriptor* descriptor,
        ComPtr<ID3D12Resource> d3d12Texture,
        Ref<D3D11on12ResourceCacheEntry> d3d11on12Resource,
        ExternalMutexSerial acquireMutexKey,
        ExternalMutexSerial releaseMutexKey,
        bool isSwapChainTexture,
        bool isInitialized) {
        Ref<Texture> dawnTexture;
        if (ConsumedError(
                Texture::CreateExternalImage(this, descriptor, std::move(d3d12Texture),
                                             std::move(d3d11on12Resource), acquireMutexKey,
                                             releaseMutexKey, isSwapChainTexture, isInitialized),
                &dawnTexture)) {
            return nullptr;
        }
        return {dawnTexture};
    }

    ComPtr<ID3D11On12Device> Device::GetOrCreateD3D11on12Device() {
        if (mD3d11On12Device == nullptr) {
            ComPtr<ID3D11Device> d3d11Device;
            D3D_FEATURE_LEVEL d3dFeatureLevel;
            IUnknown* const iUnknownQueue = mCommandQueue.Get();
            if (FAILED(GetFunctions()->d3d11on12CreateDevice(mD3d12Device.Get(), 0, nullptr, 0,
                                                             &iUnknownQueue, 1, 1, &d3d11Device,
                                                             nullptr, &d3dFeatureLevel))) {
                return nullptr;
            }

            ComPtr<ID3D11On12Device> d3d11on12Device;
            HRESULT hr = d3d11Device.As(&d3d11on12Device);
            ASSERT(SUCCEEDED(hr));

            mD3d11On12Device = std::move(d3d11on12Device);
        }
        return mD3d11On12Device;
    }

    const D3D12DeviceInfo& Device::GetDeviceInfo() const {
        return ToBackend(GetAdapter())->GetDeviceInfo();
    }

    void Device::InitTogglesFromDriver() {
        const bool useResourceHeapTier2 = (GetDeviceInfo().resourceHeapTier >= 2);
        SetToggle(Toggle::UseD3D12ResourceHeapTier2, useResourceHeapTier2);
        SetToggle(Toggle::UseD3D12RenderPass, GetDeviceInfo().supportsRenderPass);
        SetToggle(Toggle::UseD3D12ResidencyManagement, true);
        SetToggle(Toggle::UseDXC, false);

        // Disable optimizations when using FXC
        // See https://crbug.com/dawn/1203
        SetToggle(Toggle::FxcOptimizations, false);

        // By default use the maximum shader-visible heap size allowed.
        SetToggle(Toggle::UseD3D12SmallShaderVisibleHeapForTesting, false);

        PCIInfo pciInfo = GetAdapter()->GetPCIInfo();

        // Currently this workaround is only needed on Intel Gen9 and Gen9.5 GPUs.
        // See http://crbug.com/1161355 for more information.
        if (gpu_info::IsIntel(pciInfo.vendorId) &&
            (gpu_info::IsSkylake(pciInfo.deviceId) || gpu_info::IsKabylake(pciInfo.deviceId) ||
             gpu_info::IsCoffeelake(pciInfo.deviceId))) {
            constexpr gpu_info::D3DDriverVersion kFirstDriverVersionWithFix = {30, 0, 100, 9864};
            if (gpu_info::CompareD3DDriverVersion(pciInfo.vendorId,
                                                  ToBackend(GetAdapter())->GetDriverVersion(),
                                                  kFirstDriverVersionWithFix) < 0) {
                SetToggle(
                    Toggle::UseTempBufferInSmallFormatTextureToTextureCopyFromGreaterToLessMipLevel,
                    true);
            }
        }
    }

    MaybeError Device::WaitForIdleForDestruction() {
        // Immediately forget about all pending commands
        mPendingCommands.Release();

        DAWN_TRY(NextSerial());
        // Wait for all in-flight commands to finish executing
        DAWN_TRY(WaitForSerial(GetLastSubmittedCommandSerial()));

        return {};
    }

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

        ComPtr<ID3D12InfoQueue> infoQueue;
        DAWN_TRY(CheckHRESULT(mD3d12Device.As(&infoQueue),
                              "D3D12 QueryInterface ID3D12Device to ID3D12InfoQueue"));
        uint64_t totalErrors = infoQueue->GetNumStoredMessagesAllowedByRetrievalFilter();

        // Check if any errors have occurred otherwise we would be creating an empty error. Note
        // that we use GetNumStoredMessagesAllowedByRetrievalFilter instead of GetNumStoredMessages
        // because we only convert WARNINGS or higher messages to dawn errors.
        if (totalErrors == 0) {
            return {};
        }

        std::ostringstream messages;
        uint64_t errorsToPrint = std::min(kMaxDebugMessagesToPrint, totalErrors);
        for (uint64_t i = 0; i < errorsToPrint; ++i) {
            SIZE_T messageLength = 0;
            HRESULT hr = infoQueue->GetMessage(i, nullptr, &messageLength);
            if (FAILED(hr)) {
                messages << " ID3D12InfoQueue::GetMessage failed with " << hr << '\n';
                continue;
            }

            std::unique_ptr<uint8_t[]> messageData(new uint8_t[messageLength]);
            D3D12_MESSAGE* message = reinterpret_cast<D3D12_MESSAGE*>(messageData.get());
            hr = infoQueue->GetMessage(i, message, &messageLength);
            if (FAILED(hr)) {
                messages << " ID3D12InfoQueue::GetMessage failed with " << hr << '\n';
                continue;
            }

            messages << message->pDescription << " (" << message->ID << ")\n";
        }
        if (errorsToPrint < totalErrors) {
            messages << (totalErrors - errorsToPrint) << " messages silenced\n";
        }
        // We only print up to the first kMaxDebugMessagesToPrint errors
        infoQueue->ClearStoredMessages();

        return DAWN_INTERNAL_ERROR(messages.str());
    }

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

        // Immediately forget about all pending commands for the case where device is lost on its
        // own and WaitForIdleForDestruction isn't called.
        mPendingCommands.Release();

        if (mFenceEvent != nullptr) {
            ::CloseHandle(mFenceEvent);
        }

        // Release recycled resource heaps.
        if (mResourceAllocatorManager != nullptr) {
            mResourceAllocatorManager->DestroyPool();
        }

        // We need to handle clearing up com object refs that were enqeued after TickImpl
        mUsedComObjectRefs.ClearUpTo(std::numeric_limits<ExecutionSerial>::max());

        ASSERT(mUsedComObjectRefs.Empty());
        ASSERT(!mPendingCommands.IsOpen());
    }

    ShaderVisibleDescriptorAllocator* Device::GetViewShaderVisibleDescriptorAllocator() const {
        return mViewShaderVisibleDescriptorAllocator.get();
    }

    ShaderVisibleDescriptorAllocator* Device::GetSamplerShaderVisibleDescriptorAllocator() const {
        return mSamplerShaderVisibleDescriptorAllocator.get();
    }

    StagingDescriptorAllocator* Device::GetViewStagingDescriptorAllocator(
        uint32_t descriptorCount) const {
        ASSERT(descriptorCount <= kMaxViewDescriptorsPerBindGroup);
        // This is Log2 of the next power of two, plus 1.
        uint32_t allocatorIndex = descriptorCount == 0 ? 0 : Log2Ceil(descriptorCount) + 1;
        return mViewAllocators[allocatorIndex].get();
    }

    StagingDescriptorAllocator* Device::GetSamplerStagingDescriptorAllocator(
        uint32_t descriptorCount) const {
        ASSERT(descriptorCount <= kMaxSamplerDescriptorsPerBindGroup);
        // This is Log2 of the next power of two, plus 1.
        uint32_t allocatorIndex = descriptorCount == 0 ? 0 : Log2Ceil(descriptorCount) + 1;
        return mSamplerAllocators[allocatorIndex].get();
    }

    StagingDescriptorAllocator* Device::GetRenderTargetViewAllocator() const {
        return mRenderTargetViewAllocator.get();
    }

    StagingDescriptorAllocator* Device::GetDepthStencilViewAllocator() const {
        return mDepthStencilViewAllocator.get();
    }

    SamplerHeapCache* Device::GetSamplerHeapCache() {
        return mSamplerHeapCache.get();
    }

    uint32_t Device::GetOptimalBytesPerRowAlignment() const {
        return D3D12_TEXTURE_DATA_PITCH_ALIGNMENT;
    }

    // TODO(dawn:512): Once we optimize DynamicUploader allocation with offsets we
    // should make this return D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT = 512.
    // Current implementations would try to allocate additional 511 bytes,
    // so we return 1 and let ComputeTextureCopySplits take care of the alignment.
    uint64_t Device::GetOptimalBufferToTextureCopyOffsetAlignment() const {
        return 1;
    }

    float Device::GetTimestampPeriodInNS() const {
        return mTimestampPeriod;
    }

    bool Device::ShouldDuplicateNumWorkgroupsForDispatchIndirect(
        ComputePipelineBase* computePipeline) const {
        return ToBackend(computePipeline)->UsesNumWorkgroups();
    }

}}  // namespace dawn_native::d3d12
