// 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 "src/dawn/native/d3d12/DeviceD3D12.h"

#include <algorithm>
#include <limits>
#include <memory>
#include <sstream>
#include <utility>

#include "dawn/native/D3D12Backend.h"
#include "dawn/platform/DawnPlatform.h"
#include "src/dawn/common/GPUInfo.h"
#include "src/dawn/native/ChainUtils.h"
#include "src/dawn/native/DynamicUploader.h"
#include "src/dawn/native/Instance.h"
#include "src/dawn/native/d3d/D3DError.h"
#include "src/dawn/native/d3d/KeyedMutex.h"
#include "src/dawn/native/d3d12/BackendD3D12.h"
#include "src/dawn/native/d3d12/BindGroupD3D12.h"
#include "src/dawn/native/d3d12/BindGroupLayoutD3D12.h"
#include "src/dawn/native/d3d12/CommandBufferD3D12.h"
#include "src/dawn/native/d3d12/ComputePipelineD3D12.h"
#include "src/dawn/native/d3d12/PhysicalDeviceD3D12.h"
#include "src/dawn/native/d3d12/PipelineLayoutD3D12.h"
#include "src/dawn/native/d3d12/PlatformFunctionsD3D12.h"
#include "src/dawn/native/d3d12/QuerySetD3D12.h"
#include "src/dawn/native/d3d12/QueueD3D12.h"
#include "src/dawn/native/d3d12/RenderPipelineD3D12.h"
#include "src/dawn/native/d3d12/ResidencyManagerD3D12.h"
#include "src/dawn/native/d3d12/ResourceTableD3D12.h"
#include "src/dawn/native/d3d12/SamplerD3D12.h"
#include "src/dawn/native/d3d12/SamplerHeapCacheD3D12.h"
#include "src/dawn/native/d3d12/ShaderModuleD3D12.h"
#include "src/dawn/native/d3d12/ShaderVisibleDescriptorAllocatorD3D12.h"
#include "src/dawn/native/d3d12/SharedBufferMemoryD3D12.h"
#include "src/dawn/native/d3d12/SharedFenceD3D12.h"
#include "src/dawn/native/d3d12/SharedTextureMemoryD3D12.h"
#include "src/dawn/native/d3d12/StagingDescriptorAllocatorD3D12.h"
#include "src/dawn/native/d3d12/SwapChainD3D12.h"
#include "src/dawn/native/d3d12/UtilsD3D12.h"
#include "src/dawn/platform/tracing/TraceEvent.h"
#include "src/utils/compiler.h"

namespace dawn::native::d3d12 {
namespace {
// 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 accommodate large clears.
static constexpr uint64_t kZeroBufferSize = 1024 * 1024 * 4;  // 4 Mb

static constexpr uint64_t kMaxDebugMessagesToPrint = 5;
}  // 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;
}

MaybeError Device::Initialize(const UnpackedPtr<DeviceDescriptor>& descriptor) {
    mD3d12Device = ToBackend(GetPhysicalDevice())->GetDevice();

    // Querying for the ID3D12DebugDevice interface will tell us whether the debug layer
    // is enabled. The debug layer can be enabled internally via command line flags or externally
    // via dxcpl.exe or d3dconfig.exe.
    ComPtr<ID3D12DebugDevice> d3d12DebugDevice;
    mIsDebugLayerEnabled = SUCCEEDED(mD3d12Device.As(&d3d12DebugDevice));

    DAWN_ASSERT(mD3d12Device != nullptr);

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

    if ((HasFeature(Feature::TimestampQuery) ||
         HasFeature(Feature::ChromiumExperimentalTimestampQueryInsidePasses)) &&
        !IsToggleEnabled(Toggle::DisableTimestampQueryConversion)) {
        // 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(queue->GetCommandQueue()->GetTimestampFrequency(&frequency),
                              "D3D12 get timestamp frequency"));
        // Calculate the period in nanoseconds by the frequency.
        mTimestampPeriod = static_cast<float>(1e9) / frequency;
    }

    // Initialize backend services

    // 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<MutexProtected<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<MutexProtected<StagingDescriptorAllocator>>(
                this, 1u << countIndex, kShaderVisibleDescriptorHeapSize,
                D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER);
    }

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

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

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

    mResidencyManager = std::make_unique<MutexProtected<ResidencyManager>>(this);
    mResourceAllocatorManager =
        std::make_unique<MutexProtected<ResourceAllocatorManager>>(this, queue.Get());

    // 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, nullptr,
                                             IID_PPV_ARGS(&mDispatchIndirectSignature));

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

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

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

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

    DAWN_TRY(DeviceBase::Initialize(descriptor, std::move(queue)));
    DAWN_TRY(EnsureCompilerLibraries());

    // Set up shader profile for DXC.
    if (IsToggleEnabled(Toggle::UseDXC)) {
        uint32_t appliedShaderModel =
            ToBackend(GetPhysicalDevice())->GetAppliedShaderModelUnderToggles(GetTogglesState());

        uint32_t shaderModelMajor = 0;
        uint32_t shaderModelMinor = 0;

        // TODO(crbug.com/513251803): Don't use shader model as decimal value
        DAWN_ASSERT(appliedShaderModel <= 76);
        if (appliedShaderModel >= 70 && appliedShaderModel <= 76) {
            shaderModelMajor = 6;
            shaderModelMinor = appliedShaderModel - 60;
        } else {
            shaderModelMajor = appliedShaderModel / 10;
            shaderModelMinor = appliedShaderModel % 10;
        }

        // Profiles are always <stage>s_<minor>_<major> so we build the s_<minor>_major and add
        // it to each of the stage's suffix.
        std::wstring profileSuffix = std::format(L"s_{}_{}", shaderModelMajor, shaderModelMinor);
        mDxcShaderProfiles[SingleShaderStage::Vertex] = L"v" + profileSuffix;
        mDxcShaderProfiles[SingleShaderStage::Fragment] = L"p" + profileSuffix;
        mDxcShaderProfiles[SingleShaderStage::Compute] = L"c" + profileSuffix;
    }

    // The device guard isn't needed for thread safety exactly, since device creation should happen
    // on a single thread, but it's required to satisfy assertions.
    auto deviceGuard = GetGuard();
    DAWN_TRY(CreateZeroBuffer());

    SetLabelImpl();

    return {};
}

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

Device::~Device() = default;

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

ComPtr<ID3D11On12Device> Device::GetOrCreateD3D11On12Device() {
    ComPtr<ID3D11On12Device> d3d11On12Device;
    // Use std::addressof to avoid ComPtr's overloaded operator& returning ComPtrRef type.
    if (ConsumedError(GetOrCreateD3D11On12DeviceInternal(), std::addressof(d3d11On12Device))) {
        return nullptr;
    }
    return d3d11On12Device;
}

ComPtr<ID3D12CommandQueue> Device::GetD3D12CommandQueue() const {
    return ToBackend(GetQueue())->GetCommandQueue();
}

ResultOrError<ComPtr<ID3D11On12Device>> Device::GetOrCreateD3D11On12DeviceInternal() {
    if (mD3d11On12Device == nullptr) {
        ComPtr<ID3D11Device> d3d11Device;
        D3D_FEATURE_LEVEL d3dFeatureLevel;
        IUnknown* const iUnknownQueue = ToBackend(GetQueue())->GetCommandQueue();
        DAWN_TRY(CheckHRESULT(
            GetFunctions()->d3d11on12CreateDevice(mD3d12Device.Get(), 0, nullptr, 0, &iUnknownQueue,
                                                  1, 1, &d3d11Device, nullptr, &d3dFeatureLevel),
            "D3D11on12CreateDevice"));

        ComPtr<ID3D11On12Device> d3d11on12Device;
        d3d11Device.As(&d3d11on12Device);
        DAWN_ASSERT(d3d11on12Device);

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

void Device::Flush11On12DeviceToAvoidLeaks() {
    DAWN_ASSERT(mD3d11On12Device);

    ComPtr<ID3D11Device> d3d11Device;
    mD3d11On12Device.As(&d3d11Device);
    DAWN_ASSERT(d3d11Device);

    ComPtr<ID3D11DeviceContext> d3d11DeviceContext;
    d3d11Device->GetImmediateContext(&d3d11DeviceContext);
    DAWN_ASSERT(d3d11DeviceContext);

    // 11on12 has a bug where D3D12 resources used only for keyed shared mutexes are not released
    // until work is submitted to the device context and flushed. The most minimal work we can get
    // away with is issuing a TiledResourceBarrier.
    ComPtr<ID3D11DeviceContext2> d3d11DeviceContext2;
    d3d11DeviceContext.As(&d3d11DeviceContext2);
    DAWN_ASSERT(d3d11DeviceContext2);

    d3d11DeviceContext2->TiledResourceBarrier(nullptr, nullptr);
    d3d11DeviceContext2->Flush();
}

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

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

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

// Ensure DXC if use_dxc toggles are set and validated.
MaybeError Device::EnsureCompilerLibraries() {
    if (IsToggleEnabled(Toggle::UseDXC)) {
        DAWN_TRY(ToBackend(GetPhysicalDevice())->GetBackend()->EnsureDXC());
    } else {
        DAWN_TRY(ToBackend(GetPhysicalDevice())->GetBackend()->EnsureFXC());
    }

    return {};
}

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

MutexProtected<ResidencyManager>& Device::GetResidencyManager() const {
    return *mResidencyManager;
}

MaybeError Device::CreateZeroBuffer() {
    BufferDescriptor zeroBufferDescriptor;
    zeroBufferDescriptor.size = kZeroBufferSize;
    zeroBufferDescriptor.label = "ZeroBuffer_Internal";

    Ref<BufferBase> zeroBufferBase;

    // Clear zero buffer from CPU when `Feature::BufferMapExtendedUsages` is supported.
    if (ToBackend(GetPhysicalDevice())->SupportsBufferMapExtendedUsages()) {
        zeroBufferDescriptor.mappedAtCreation = true;
        zeroBufferDescriptor.usage = wgpu::BufferUsage::CopySrc | wgpu::BufferUsage::MapWrite;

        DAWN_TRY_ASSIGN(zeroBufferBase, CreateBuffer(&zeroBufferDescriptor));

        auto mapping = zeroBufferBase->GetCurrentMapping();
        DAWN_ASSERT(!mapping.mappedSpan.empty());
        std::ranges::fill(mapping.mappedSpan, std::byte{0});
        DAWN_TRY(zeroBufferBase->Unmap());
    } else {
        zeroBufferDescriptor.usage = wgpu::BufferUsage::CopySrc | wgpu::BufferUsage::CopyDst;

        DAWN_TRY_ASSIGN(zeroBufferBase, CreateBuffer(&zeroBufferDescriptor));

        auto scopedUseZeroBuffer = zeroBufferBase->UseInternal();
        CommandRecordingContext* commandContext =
            ToBackend(GetQueue())->GetPendingCommandContext(QueueBase::SubmitMode::Passive);

        DAWN_TRY(GetDynamicUploader()->WithUploadReservation(
            kZeroBufferSize, kCopyBufferToBufferOffsetAlignment,
            [&](UploadReservation reservation) -> MaybeError {
                DAWN_UNSAFE_TODO(memset(reservation.mappedPointer, 0u, kZeroBufferSize));

                CopyFromStagingToBufferHelper(commandContext, reservation.buffer.Get(),
                                              reservation.offsetInBuffer, zeroBufferBase.Get(), 0,
                                              kZeroBufferSize);

                zeroBufferBase->SetInitialized(true);
                return {};
            }));
    }

    mZeroBuffer = ToBackend(zeroBufferBase);
    return {};
}

MaybeError Device::ClearBufferToZero(CommandRecordingContext* commandContext,
                                     BufferBase* destination,
                                     uint64_t offset,
                                     uint64_t size) {
    Buffer* dstBuffer = ToBackend(destination);

    // Necessary to ensure residency of the zero buffer.
    auto scopedUseZeroBuffer = mZeroBuffer->UseInternal();
    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 = GetQueue()->GetCompletedCommandSerial();

    (*mResourceAllocatorManager)->Tick(completedSerial);
    mViewShaderVisibleDescriptorAllocator->Tick(completedSerial);
    mSamplerShaderVisibleDescriptorAllocator->Tick(completedSerial);
    (*mRenderTargetViewAllocator)->Tick(completedSerial);
    (*mDepthStencilViewAllocator)->Tick(completedSerial);
    mUsedComObjectRefs->ClearUpTo(completedSerial);

    DAWN_TRY(ToBackend(GetQueue())->SubmitPendingCommands());

    DAWN_TRY(CheckDebugLayerAndGenerateErrors());

    return {};
}

void Device::ReferenceUntilUnused(ComPtr<IUnknown> object) {
    mUsedComObjectRefs->Enqueue(std::move(object), GetQueue()->GetPendingCommandSerial());
}

ResultOrError<Ref<BindGroupBase>> Device::CreateBindGroupImpl(
    const UnpackedPtr<BindGroupDescriptor>& descriptor) {
    return BindGroup::Create(this, descriptor);
}
ResultOrError<Ref<BindGroupLayoutInternalBase>> Device::CreateBindGroupLayoutImpl(
    const UnpackedPtr<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<ResourceTableBase>> Device::CreateResourceTableImpl(
    const ResourceTableDescriptor* descriptor) {
    return ResourceTable::Create(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) {
    return ShaderModule::Create(this, descriptor, internalExtensions);
}
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 Texture::Create(this, descriptor);
}
ResultOrError<Ref<TextureViewBase>> Device::CreateTextureViewImpl(
    TextureBase* texture,
    const UnpackedPtr<TextureViewDescriptor>& descriptor) {
    return TextureView::Create(texture, descriptor);
}
void Device::InitializeComputePipelineAsyncImpl(Ref<CreateComputePipelineAsyncEvent> event) {
    event->InitializeAsync();
}
void Device::InitializeRenderPipelineAsyncImpl(Ref<CreateRenderPipelineAsyncEvent> event) {
    event->InitializeAsync();
}

ResultOrError<Ref<SharedBufferMemoryBase>> Device::ImportSharedBufferMemoryImpl(
    const SharedBufferMemoryDescriptor* descriptor) {
    UnpackedPtr<SharedBufferMemoryDescriptor> unpacked;
    DAWN_TRY_ASSIGN(unpacked, ValidateAndUnpack(descriptor));

    wgpu::SType type;
    DAWN_TRY_ASSIGN(
        type, (unpacked.ValidateBranches<Branch<SharedBufferMemoryD3D12ResourceDescriptor>,
                                         Branch<SharedBufferMemoryFromWindowsHandleDescriptor>>()));

    switch (type) {
        case wgpu::SType::SharedBufferMemoryD3D12ResourceDescriptor:
            DAWN_INVALID_IF(!HasFeature(Feature::SharedBufferMemoryD3D12Resource),
                            "%s is not enabled.",
                            wgpu::FeatureName::SharedBufferMemoryD3D12Resource);
            return SharedBufferMemory::Create(
                this, descriptor->label, unpacked.Get<SharedBufferMemoryD3D12ResourceDescriptor>());
        case wgpu::SType::SharedBufferMemoryFromWindowsHandleDescriptor:
            DAWN_INVALID_IF(!HasFeature(Feature::SharedBufferMemoryFromWindowsHandle),
                            "%s is not enabled.",
                            wgpu::FeatureName::SharedBufferMemoryFromWindowsHandle);
            return SharedBufferMemory::Create(
                this, descriptor->label,
                unpacked.Get<SharedBufferMemoryFromWindowsHandleDescriptor>());
        default:
            DAWN_UNREACHABLE();
    }
}

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<SharedTextureMemoryDXGISharedHandleDescriptor>,
                                         Branch<SharedTextureMemoryD3D12ResourceDescriptor>>()));

    switch (type) {
        case wgpu::SType::SharedTextureMemoryDXGISharedHandleDescriptor:
            DAWN_INVALID_IF(!HasFeature(Feature::SharedTextureMemoryDXGISharedHandle),
                            "%s is not enabled.",
                            wgpu::FeatureName::SharedTextureMemoryDXGISharedHandle);
            return SharedTextureMemory::Create(
                this, descriptor->label,
                unpacked.Get<SharedTextureMemoryDXGISharedHandleDescriptor>());
        case wgpu::SType::SharedTextureMemoryD3D12ResourceDescriptor:
            DAWN_INVALID_IF(!HasFeature(Feature::SharedTextureMemoryD3D12Resource),
                            "%s is not enabled.",
                            wgpu::FeatureName::SharedTextureMemoryD3D12Resource);
            return SharedTextureMemory::Create(
                this, descriptor->label,
                unpacked.Get<SharedTextureMemoryD3D12ResourceDescriptor>());
        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<SharedFenceDXGISharedHandleDescriptor>>()));

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

MaybeError Device::CopyFromStagingToBuffer(BufferBase* source,
                                           uint64_t sourceOffset,
                                           BufferBase* destination,
                                           uint64_t destinationOffset,
                                           uint64_t size) {
    CommandRecordingContext* commandRecordingContext =
        ToBackend(GetQueue())->GetPendingCommandContext(QueueBase::SubmitMode::Passive);

    Buffer* dstBuffer = ToBackend(destination);

    [[maybe_unused]] bool cleared;
    DAWN_TRY_ASSIGN(cleared, dstBuffer->EnsureDataInitializedAsDestination(
                                 commandRecordingContext, destinationOffset, size));

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

    return {};
}

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

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

MaybeError Device::CopyFromStagingToTextureImpl(BufferBase* source,
                                                const TexelCopyBufferLayout& src,
                                                const TextureCopy& dst,
                                                const Extent3D& copySizePixels) {
    CommandRecordingContext* commandContext =
        ToBackend(GetQueue())->GetPendingCommandContext(QueueBase::SubmitMode::Passive);

    Texture* texture = ToBackend(dst.texture.Get());
    DAWN_TRY(texture->SynchronizeTextureBeforeUse(commandContext));

    SubresourceRange range = GetSubresourcesAffectedByCopy(dst, copySizePixels);
    if (IsCompleteSubresourceCopiedTo(texture, copySizePixels, dst.mipLevel, dst.aspect)) {
        texture->SetIsSubresourceContentInitialized(true, range);
    } else {
        DAWN_TRY(texture->EnsureSubresourceContentInitialized(commandContext, range));
    }

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

    const TypedTexelBlockInfo& blockInfo = GetBlockInfo(dst);
    BlockCount blocksPerRow = blockInfo.BytesToBlocks(src.bytesPerRow);
    BlockCount rowsPerImage{src.rowsPerImage};
    BlockExtent3D copySizePixelsInBlocks = blockInfo.ToBlock(copySizePixels);

    RecordBufferTextureCopyWithBufferHandle(
        BufferTextureCopyDirection::B2T, commandContext->GetCommandList(),
        ToBackend(source)->GetD3D12Resource(), src.offset, blocksPerRow, rowsPerImage, dst,
        copySizePixelsInBlocks);
    return {};
}

uint32_t Device::GetResourceHeapTier() const {
    return IsToggleEnabled(Toggle::UseD3D12ResourceHeapTier2) ? 2u : 1u;
}

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

ResultOrError<ResourceHeapAllocation> Device::AllocateMemory(
    ResourceHeapKind resourceHeapKind,
    const D3D12_RESOURCE_DESC& resourceDescriptor,
    D3D12_RESOURCE_STATES initialUsage,
    uint32_t formatBytesPerBlock,
    bool forceAllocateAsCommittedResource) {
    // formatBytesPerBlock is needed only for color non-compressed formats for a workaround.
    return (*mResourceAllocatorManager)
        ->AllocateMemory(resourceHeapKind, resourceDescriptor, initialUsage, formatBytesPerBlock,
                         forceAllocateAsCommittedResource);
}

MaybeError Device::ImportSharedHandleResource(HANDLE handle,
                                              bool useKeyedMutex,
                                              ComPtr<ID3D12Resource>& d3d12Resource,
                                              Ref<d3d::KeyedMutex>& keyedMutex) {
    DAWN_TRY(CheckHRESULT(GetD3D12Device()->OpenSharedHandle(handle, IID_PPV_ARGS(&d3d12Resource)),
                          "D3D12 opening shared handle"));

    if (useKeyedMutex) {
        ComPtr<ID3D11On12Device> d3d11on12Device;
        DAWN_TRY_ASSIGN(d3d11on12Device, GetOrCreateD3D11On12DeviceInternal());

        // Since D3D12 does not directly support keyed mutexes, we need to wrap the D3D12 resource
        // using 11on12 and QueryInterface the D3D11 representation for the keyed mutex.
        ComPtr<ID3D11Texture2D> d3d11Texture;
        D3D11_RESOURCE_FLAGS resourceFlags;
        resourceFlags.BindFlags = 0;
        resourceFlags.MiscFlags = D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX;
        resourceFlags.CPUAccessFlags = 0;
        resourceFlags.StructureByteStride = 0;
        DAWN_TRY(CheckHRESULT(d3d11on12Device->CreateWrappedResource(
                                  d3d12Resource.Get(), &resourceFlags, D3D12_RESOURCE_STATE_COMMON,
                                  D3D12_RESOURCE_STATE_COMMON, IID_PPV_ARGS(&d3d11Texture)),
                              "Failed to create wrapped D3D11on12 resource"));

        ComPtr<IDXGIKeyedMutex> dxgiKeyedMutex;
        d3d11Texture.As(&dxgiKeyedMutex);
        DAWN_INVALID_IF(!dxgiKeyedMutex, "Failed to retrieve DXGI keyed mutex when expected");

        keyedMutex = AcquireRef(new d3d::KeyedMutex(this, std::move(dxgiKeyedMutex)));
    }

    return {};
}

void Device::DisposeKeyedMutex(ComPtr<IDXGIKeyedMutex> dxgiKeyedMutex) {
    ComPtr<ID3D11Resource> d3d11Resource;
    dxgiKeyedMutex.As(&d3d11Resource);
    DAWN_ASSERT(d3d11Resource);

    ID3D11Resource* d3d11ResourcePtr = d3d11Resource.Get();
    mD3d11On12Device->ReleaseWrappedResources(&d3d11ResourcePtr, 1);

    // Release the resource and keyed mutex before calling Flush11on12DeviceToAvoidLeaks below.
    dxgiKeyedMutex.Reset();
    d3d11Resource.Reset();

    Flush11On12DeviceToAvoidLeaks();
}

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

void AppendDebugLayerMessagesToError(ID3D12InfoQueue* infoQueue,
                                     uint64_t totalErrors,
                                     ErrorData* error) {
    DAWN_ASSERT(totalErrors > 0);
    DAWN_ASSERT(error != nullptr);

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

        HeapArray<uint8_t> messageData(messageLength);
        D3D12_MESSAGE* message = reinterpret_cast<D3D12_MESSAGE*>(messageData.data());
        hr = infoQueue->GetMessage(i, message, &messageLength);
        if (FAILED(hr)) {
            messageStream << " ID3D12InfoQueue::GetMessage failed with " << hr;
            error->AppendBackendMessage(messageStream.str());
            continue;
        }

        messageStream << message->pDescription << " (" << message->ID << ")";
        error->AppendBackendMessage(messageStream.str());
    }
    if (errorsToPrint < totalErrors) {
        std::ostringstream messages;
        messages << (totalErrors - errorsToPrint) << " messages silenced";
        error->AppendBackendMessage(messages.str());
    }

    // We only print up to the first kMaxDebugMessagesToPrint errors
    infoQueue->ClearStoredMessages();
}

MaybeError Device::CheckDebugLayerAndGenerateErrors() {
    if (!mIsDebugLayerEnabled) {
        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 {};
    }

    auto error = DAWN_INTERNAL_ERROR("The D3D12 debug layer reported uncaught errors.");

    AppendDebugLayerMessagesToError(infoQueue.Get(), totalErrors, error.get());

    return error;
}

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

    ComPtr<ID3D12InfoQueue> infoQueue;
    if (FAILED(mD3d12Device.As(&infoQueue))) {
        return;
    }
    uint64_t totalErrors = infoQueue->GetNumStoredMessagesAllowedByRetrievalFilter();

    if (totalErrors == 0) {
        return;
    }

    AppendDebugLayerMessagesToError(infoQueue.Get(), totalErrors, error);
}

void Device::AppendDeviceLostMessage(ErrorData* error) {
    if (mD3d12Device) {
        HRESULT result = mD3d12Device->GetDeviceRemovedReason();
        error->AppendBackendMessage("Device removed reason: %s (0x%08X)",
                                    d3d::HRESULTAsString(result), result);
        RecordDeviceRemovedReason(result);
    }
}

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

    // 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.

    Base::DestroyImpl(reason);

    mZeroBuffer = nullptr;

    // Release recycled resource heaps and all other objects waiting for deletion in the resource
    // allocation manager.
    mResourceAllocatorManager.reset();

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

    DAWN_ASSERT(mUsedComObjectRefs->Empty());
}

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

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

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

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

MutexProtected<StagingDescriptorAllocator>& Device::GetRenderTargetViewAllocator() const {
    return *mRenderTargetViewAllocator.get();
}

MutexProtected<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;
}

bool Device::CanTextureLoadResolveTargetInTheSameRenderpass() const {
    return true;
}

bool Device::CanResolveSubRect() const {
    return true;
}

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

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

void Device::SetLabelImpl() {
    SetDebugName(this, mD3d12Device.Get(), "Dawn_Device", GetLabel());
}

bool Device::MayRequireDuplicationOfIndirectParameters() const {
    return true;
}

bool Device::ShouldDuplicateParametersForDrawIndirect(
    const RenderPipelineBase* renderPipelineBase) const {
    return renderPipelineBase->UsesVertexIndex() || renderPipelineBase->UsesInstanceIndex();
}

uint64_t Device::GetBufferCopyOffsetAlignmentForDepthStencil() const {
    // On the D3D12 platforms where programmable MSAA is not supported, the source box specifying a
    // portion of the depth texture must all be 0, or an error and a device lost will occur, so on
    // these platforms the buffer copy offset must be a multiple of 512 when the texture is created
    // with D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL. See https://crbug.com/dawn/727 for more
    // details.
    if (IsToggleEnabled(
            Toggle::D3D12UseTempBufferInDepthStencilTextureAndBufferCopyWithNonZeroBufferOffset)) {
        return D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT;
    }
    return DeviceBase::GetBufferCopyOffsetAlignmentForDepthStencil();
}

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

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

const PerStage<std::wstring>& Device::GetDxcShaderProfiles() const {
    return mDxcShaderProfiles;
}

AllocatorMemoryInfo Device::GetAllocatorMemoryInfo() const {
    DAWN_ASSERT(IsLockedByCurrentThreadIfNeeded());
    AllocatorMemoryInfo info = {};
    info.totalAllocatedMemory = (*mResourceAllocatorManager)->GetTotalAllocatedMemory();
    info.totalUsedMemory = (*mResourceAllocatorManager)->GetTotalUsedMemory();
    // D3D12 has no lazy memory concept, leave lazy fields as zero.
    return info;
}

}  // namespace dawn::native::d3d12
