// Copyright 2020 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/StagingDescriptorAllocatorD3D12.h"

#include <utility>

#include "dawn/common/Math.h"
#include "dawn/native/d3d/D3DError.h"
#include "dawn/native/d3d12/DeviceD3D12.h"

namespace dawn::native::d3d12 {

StagingDescriptorAllocator::StagingDescriptorAllocator(Device* device,
                                                       uint32_t descriptorCount,
                                                       uint32_t heapSize,
                                                       D3D12_DESCRIPTOR_HEAP_TYPE heapType)
    : mDevice(device),
      mSizeIncrement(device->GetD3D12Device()->GetDescriptorHandleIncrementSize(heapType)),
      mBlockSize(descriptorCount * mSizeIncrement),
      mHeapSize(RoundUp(heapSize, descriptorCount)),
      mHeapType(heapType) {
    ASSERT(descriptorCount <= heapSize);
}

StagingDescriptorAllocator::~StagingDescriptorAllocator() {
    const Index freeBlockIndicesSize = GetFreeBlockIndicesSize();
    for (auto& buffer : mPool) {
        ASSERT(buffer.freeBlockIndices.size() == freeBlockIndicesSize);
    }
    ASSERT(mAvailableHeaps.size() == mPool.size());
}

ResultOrError<CPUDescriptorHeapAllocation> StagingDescriptorAllocator::AllocateCPUDescriptors() {
    if (mAvailableHeaps.empty()) {
        DAWN_TRY(AllocateCPUHeap());
    }

    ASSERT(!mAvailableHeaps.empty());

    const uint32_t heapIndex = mAvailableHeaps.back();
    NonShaderVisibleBuffer& buffer = mPool[heapIndex];

    ASSERT(!buffer.freeBlockIndices.empty());

    const Index blockIndex = buffer.freeBlockIndices.back();

    buffer.freeBlockIndices.pop_back();

    if (buffer.freeBlockIndices.empty()) {
        mAvailableHeaps.pop_back();
    }

    const D3D12_CPU_DESCRIPTOR_HANDLE baseCPUDescriptor = {
        buffer.heap->GetCPUDescriptorHandleForHeapStart().ptr + (blockIndex * mBlockSize)};

    return CPUDescriptorHeapAllocation{baseCPUDescriptor, heapIndex};
}

MaybeError StagingDescriptorAllocator::AllocateCPUHeap() {
    D3D12_DESCRIPTOR_HEAP_DESC heapDescriptor;
    heapDescriptor.Type = mHeapType;
    heapDescriptor.NumDescriptors = mHeapSize;
    heapDescriptor.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE;
    heapDescriptor.NodeMask = 0;

    ComPtr<ID3D12DescriptorHeap> heap;
    DAWN_TRY(CheckHRESULT(
        mDevice->GetD3D12Device()->CreateDescriptorHeap(&heapDescriptor, IID_PPV_ARGS(&heap)),
        "ID3D12Device::CreateDescriptorHeap"));

    NonShaderVisibleBuffer newBuffer;
    newBuffer.heap = std::move(heap);

    const Index freeBlockIndicesSize = GetFreeBlockIndicesSize();
    newBuffer.freeBlockIndices.reserve(freeBlockIndicesSize);

    for (Index blockIndex = 0; blockIndex < freeBlockIndicesSize; blockIndex++) {
        newBuffer.freeBlockIndices.push_back(blockIndex);
    }

    mAvailableHeaps.push_back(mPool.size());
    mPool.emplace_back(std::move(newBuffer));

    return {};
}

void StagingDescriptorAllocator::Deallocate(CPUDescriptorHeapAllocation* allocation) {
    ASSERT(allocation->IsValid());

    const uint32_t heapIndex = allocation->GetHeapIndex();

    ASSERT(heapIndex < mPool.size());

    // Insert the deallocated block back into the free-list. Order does not matter. However,
    // having blocks be non-contigious could slow down future allocations due to poor cache
    // locality.
    // TODO(dawn:155): Consider more optimization.
    std::vector<Index>& freeBlockIndices = mPool[heapIndex].freeBlockIndices;
    if (freeBlockIndices.empty()) {
        mAvailableHeaps.emplace_back(heapIndex);
    }

    const D3D12_CPU_DESCRIPTOR_HANDLE heapStart =
        mPool[heapIndex].heap->GetCPUDescriptorHandleForHeapStart();

    const D3D12_CPU_DESCRIPTOR_HANDLE baseDescriptor = allocation->OffsetFrom(0, 0);

    const Index blockIndex = (baseDescriptor.ptr - heapStart.ptr) / mBlockSize;

    freeBlockIndices.emplace_back(blockIndex);

    // Invalidate the handle in case the developer accidentally uses it again.
    allocation->Invalidate();
}

uint32_t StagingDescriptorAllocator::GetSizeIncrement() const {
    return mSizeIncrement;
}

StagingDescriptorAllocator::Index StagingDescriptorAllocator::GetFreeBlockIndicesSize() const {
    return ((mHeapSize * mSizeIncrement) / mBlockSize);
}

ResultOrError<CPUDescriptorHeapAllocation>
StagingDescriptorAllocator::AllocateTransientCPUDescriptors() {
    CPUDescriptorHeapAllocation allocation;
    DAWN_TRY_ASSIGN(allocation, AllocateCPUDescriptors());
    mAllocationsToDelete.Enqueue(allocation, mDevice->GetPendingCommandSerial());
    return allocation;
}

void StagingDescriptorAllocator::Tick(ExecutionSerial completedSerial) {
    for (CPUDescriptorHeapAllocation& allocation :
         mAllocationsToDelete.IterateUpTo(completedSerial)) {
        Deallocate(&allocation);
    }

    mAllocationsToDelete.ClearUpTo(completedSerial);
}

}  // namespace dawn::native::d3d12
