/*
 * Copyright 2020 Google LLC
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "src/gpu/d3d/GrD3DDescriptorTableManager.h"

#include "src/gpu/d3d/GrD3DGpu.h"

GrD3DDescriptorTableManager::GrD3DDescriptorTableManager(GrD3DGpu* gpu)
    : fShaderViewDescriptorPool(gpu, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV)
    , fSamplerDescriptorPool(gpu, D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER) {}

sk_sp<GrD3DDescriptorTable>
        GrD3DDescriptorTableManager::createShaderViewTable(GrD3DGpu* gpu,
                                                                         unsigned int size) {
    sk_sp<GrD3DDescriptorTable> table = fShaderViewDescriptorPool.allocateTable(gpu, size);
    this->setHeaps(gpu);
    return table;
}

sk_sp<GrD3DDescriptorTable> GrD3DDescriptorTableManager::createSamplerTable(
        GrD3DGpu* gpu, unsigned int size) {
    sk_sp<GrD3DDescriptorTable> table = fSamplerDescriptorPool.allocateTable(gpu, size);
    this->setHeaps(gpu);
    return table;
}

void GrD3DDescriptorTableManager::setHeaps(GrD3DGpu* gpu) {
    sk_sp<Heap>& currentCBVSRVHeap = fShaderViewDescriptorPool.currentDescriptorHeap();
    sk_sp<Heap>& currentSamplerHeap = fSamplerDescriptorPool.currentDescriptorHeap();
    GrD3DDirectCommandList* commandList = gpu->currentCommandList();
    commandList->setDescriptorHeaps(currentCBVSRVHeap,
                                    currentCBVSRVHeap->d3dDescriptorHeap(),
                                    currentSamplerHeap,
                                    currentSamplerHeap->d3dDescriptorHeap());
}

void GrD3DDescriptorTableManager::prepForSubmit(GrD3DGpu* gpu) {
    fShaderViewDescriptorPool.prepForSubmit(gpu);
    fSamplerDescriptorPool.prepForSubmit(gpu);
}

void GrD3DDescriptorTableManager::recycle(Heap* heap) {
    // wrap the heap in an sk_sp and take ownership of it
    sk_sp<Heap> wrappedHeap(heap);

    SkASSERT(heap);
    switch (heap->type()) {
        case D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV:
            fShaderViewDescriptorPool.recycle(std::move(wrappedHeap));
            break;
        case D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER:
            fSamplerDescriptorPool.recycle(std::move(wrappedHeap));
            break;
        default:
            SkUNREACHABLE;
    }
}

////////////////////////////////////////////////////////////////////////////////////////////////

sk_sp<GrD3DDescriptorTableManager::Heap> GrD3DDescriptorTableManager::Heap::Make(
        GrD3DGpu* gpu, D3D12_DESCRIPTOR_HEAP_TYPE type, unsigned int descriptorCount) {
    std::unique_ptr<GrD3DDescriptorHeap> heap =
            GrD3DDescriptorHeap::Make(gpu, type, descriptorCount,
                                      D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE);
    if (!heap) {
        return nullptr;
    }

    return sk_sp< GrD3DDescriptorTableManager::Heap>(new Heap(gpu, heap, type, descriptorCount));
}

sk_sp<GrD3DDescriptorTable> GrD3DDescriptorTableManager::Heap::allocateTable(
        unsigned int count) {
    SkASSERT(fDescriptorCount - fNextAvailable >= count);
    unsigned int startIndex = fNextAvailable;
    fNextAvailable += count;
    return sk_sp<GrD3DDescriptorTable>(
            new GrD3DDescriptorTable(fHeap->getCPUHandle(startIndex).fHandle,
                                     fHeap->getGPUHandle(startIndex).fHandle, fType));
}

void GrD3DDescriptorTableManager::Heap::onRecycle() const {
    fGpu->resourceProvider().descriptorTableMgr()->recycle(const_cast<Heap*>(this));
}

////////////////////////////////////////////////////////////////////////////////////////////////

GrD3DDescriptorTableManager::HeapPool::HeapPool(GrD3DGpu* gpu, D3D12_DESCRIPTOR_HEAP_TYPE heapType)
    : fHeapType(heapType)
    , fCurrentHeapDescriptorCount(kInitialHeapDescriptorCount) {
    sk_sp<Heap> heap = Heap::Make(gpu, fHeapType, fCurrentHeapDescriptorCount);
    fDescriptorHeaps.push_back(heap);
}

sk_sp<GrD3DDescriptorTable> GrD3DDescriptorTableManager::HeapPool::allocateTable(
        GrD3DGpu* gpu, unsigned int count) {
    // In back-to-front order, iterate through heaps until we find one we can allocate from.
    // Any heap we can't allocate from gets removed from the list.
    // If it was already used, it will have been added to the commandlist,
    // and then later recycled back to us.
    while (fDescriptorHeaps.size() > 0) {
        if (fDescriptorHeaps[fDescriptorHeaps.size() - 1]->canAllocate(count)) {
            return fDescriptorHeaps[fDescriptorHeaps.size() - 1]->allocateTable(count);
        }
        // No space in current heap, pop off list
        fDescriptorHeaps.pop_back();
    }

    // Out of available heaps, need to allocate a new one
    fCurrentHeapDescriptorCount = std::min(2*fCurrentHeapDescriptorCount, 2048u);
    sk_sp<GrD3DDescriptorTableManager::Heap> heap =
            GrD3DDescriptorTableManager::Heap::Make(gpu, fHeapType, fCurrentHeapDescriptorCount);
    fDescriptorHeaps.push_back(heap);
    return fDescriptorHeaps[fDescriptorHeaps.size() - 1]->allocateTable(count);
}

sk_sp<GrD3DDescriptorTableManager::Heap>&
        GrD3DDescriptorTableManager::HeapPool::currentDescriptorHeap() {
    SkASSERT(fDescriptorHeaps.size() > 0);
    return fDescriptorHeaps[fDescriptorHeaps.size() - 1];
}

void GrD3DDescriptorTableManager::HeapPool::prepForSubmit(GrD3DGpu* gpu) {
    // Pop off the current descriptor heap
    if (fDescriptorHeaps[fDescriptorHeaps.size() - 1]->used()) {
        fDescriptorHeaps.pop_back();
    }

    if (fDescriptorHeaps.size() == 0) {
        fCurrentHeapDescriptorCount = std::min(fCurrentHeapDescriptorCount, 2048u);
        sk_sp<GrD3DDescriptorTableManager::Heap> heap =
            GrD3DDescriptorTableManager::Heap::Make(gpu, fHeapType, fCurrentHeapDescriptorCount);
        fDescriptorHeaps.push_back(heap);
    }
}

void GrD3DDescriptorTableManager::HeapPool::recycle(sk_sp<Heap> heap) {
    SkASSERT(heap);
    // only add heaps back if they match our current size
    // this purges any smaller heaps we no longer need
    if (heap->descriptorCount() == fCurrentHeapDescriptorCount) {
        heap->reset();
        fDescriptorHeaps.push_back(heap);
    }
}
