/*
 * 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/GrD3DCpuDescriptorManager.h"

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

GrD3DCpuDescriptorManager::GrD3DCpuDescriptorManager(GrD3DGpu* gpu)
    : fRTVDescriptorPool(gpu, D3D12_DESCRIPTOR_HEAP_TYPE_RTV)
    , fDSVDescriptorPool(gpu, D3D12_DESCRIPTOR_HEAP_TYPE_DSV)
    , fCBVSRVDescriptorPool(gpu, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV)
    , fSamplerDescriptorPool(gpu, D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER) {}

GrD3DDescriptorHeap::CPUHandle GrD3DCpuDescriptorManager::createRenderTargetView(
        GrD3DGpu* gpu, ID3D12Resource* textureResource) {
    const GrD3DDescriptorHeap::CPUHandle& descriptor = fRTVDescriptorPool.allocateHandle(gpu);
    gpu->device()->CreateRenderTargetView(textureResource, nullptr, descriptor.fHandle);
    return descriptor;
}

void GrD3DCpuDescriptorManager::recycleRenderTargetView(
        const GrD3DDescriptorHeap::CPUHandle& rtvDescriptor) {
    fRTVDescriptorPool.releaseHandle(rtvDescriptor);
}

GrD3DDescriptorHeap::CPUHandle GrD3DCpuDescriptorManager::createDepthStencilView(
        GrD3DGpu* gpu, ID3D12Resource* textureResource) {
    const GrD3DDescriptorHeap::CPUHandle& descriptor = fDSVDescriptorPool.allocateHandle(gpu);
    gpu->device()->CreateDepthStencilView(textureResource, nullptr, descriptor.fHandle);
    return descriptor;
}

void GrD3DCpuDescriptorManager::recycleDepthStencilView(
        const GrD3DDescriptorHeap::CPUHandle& dsvDescriptor) {
    fDSVDescriptorPool.releaseHandle(dsvDescriptor);
}

GrD3DDescriptorHeap::CPUHandle GrD3DCpuDescriptorManager::createConstantBufferView(
        GrD3DGpu* gpu, ID3D12Resource* bufferResource, size_t offset, size_t size) {
    const GrD3DDescriptorHeap::CPUHandle& descriptor = fCBVSRVDescriptorPool.allocateHandle(gpu);
    D3D12_CONSTANT_BUFFER_VIEW_DESC desc = {};
    desc.BufferLocation = bufferResource->GetGPUVirtualAddress() + offset;
    desc.SizeInBytes = size;
    gpu->device()->CreateConstantBufferView(&desc, descriptor.fHandle);
    return descriptor;
}

GrD3DDescriptorHeap::CPUHandle GrD3DCpuDescriptorManager::createShaderResourceView(
        GrD3DGpu* gpu, ID3D12Resource* resource) {
    const GrD3DDescriptorHeap::CPUHandle& descriptor = fCBVSRVDescriptorPool.allocateHandle(gpu);
    // TODO: for 4:2:0 YUV formats we'll need to map two different views, one for Y and one for UV.
    // For now map the entire resource.
    gpu->device()->CreateShaderResourceView(resource, nullptr, descriptor.fHandle);
    return descriptor;
}

void GrD3DCpuDescriptorManager::recycleConstantOrShaderView(
        const GrD3DDescriptorHeap::CPUHandle& view) {
    fCBVSRVDescriptorPool.releaseHandle(view);
}

GrD3DDescriptorHeap::CPUHandle GrD3DCpuDescriptorManager::createSampler(
        GrD3DGpu* gpu, D3D12_FILTER filter, D3D12_TEXTURE_ADDRESS_MODE addressModeU,
        D3D12_TEXTURE_ADDRESS_MODE addressModeV) {
    const GrD3DDescriptorHeap::CPUHandle& descriptor = fSamplerDescriptorPool.allocateHandle(gpu);
    D3D12_SAMPLER_DESC desc = {};
    desc.Filter = filter;
    desc.AddressU = addressModeU;
    desc.AddressV = addressModeV;
    desc.AddressW = D3D12_TEXTURE_ADDRESS_MODE_CLAMP;
    desc.MipLODBias = 0;
    desc.MaxAnisotropy = 1;
    desc.ComparisonFunc = D3D12_COMPARISON_FUNC_ALWAYS;
    // desc.BorderColor initialized to { 0, 0, 0, 0 } by default initializer, above.
    desc.MinLOD = 0;
    desc.MaxLOD = SK_ScalarMax;

    gpu->device()->CreateSampler(&desc, descriptor.fHandle);
    return descriptor;
}

void GrD3DCpuDescriptorManager::recycleSampler(
        const GrD3DDescriptorHeap::CPUHandle& samplerDescriptor) {
    fSamplerDescriptorPool.releaseHandle(samplerDescriptor);
}

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

std::unique_ptr<GrD3DCpuDescriptorManager::Heap> GrD3DCpuDescriptorManager::Heap::Make(
        GrD3DGpu* gpu, D3D12_DESCRIPTOR_HEAP_TYPE type, unsigned int numDescriptors) {
    std::unique_ptr<GrD3DDescriptorHeap> heap =
            GrD3DDescriptorHeap::Make(gpu, type, numDescriptors, D3D12_DESCRIPTOR_HEAP_FLAG_NONE);
    if (!heap) {
        return nullptr;
    }

    return std::unique_ptr<Heap>(new Heap(heap, numDescriptors));
}

GrD3DDescriptorHeap::CPUHandle GrD3DCpuDescriptorManager::Heap::allocateCPUHandle() {
    SkBitSet::OptionalIndex freeBlock = fFreeBlocks.findFirst();
    SkASSERT(freeBlock);
    fFreeBlocks.reset(*freeBlock);
    --fFreeCount;
    return fHeap->getCPUHandle(*freeBlock);
}

void GrD3DCpuDescriptorManager::Heap::freeCPUHandle(const GrD3DDescriptorHeap::CPUHandle& handle) {
    SkASSERT(this->ownsHandle(handle));
    size_t index = fHeap->getIndex(handle);
    fFreeBlocks.set(index);
    ++fFreeCount;
}

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

GrD3DCpuDescriptorManager::HeapPool::HeapPool(GrD3DGpu* gpu, D3D12_DESCRIPTOR_HEAP_TYPE heapType)
    : fMaxAvailableDescriptors(32)
    , fHeapType(heapType) {
    std::unique_ptr<GrD3DCpuDescriptorManager::Heap> heap =
            GrD3DCpuDescriptorManager::Heap::Make(gpu, fHeapType, fMaxAvailableDescriptors);
    fDescriptorHeaps.push_back(std::move(heap));
}

GrD3DDescriptorHeap::CPUHandle GrD3DCpuDescriptorManager::HeapPool::allocateHandle(
        GrD3DGpu* gpu) {
    for (unsigned int i = 0; i < fDescriptorHeaps.size(); ++i) {
        if (fDescriptorHeaps[i]->canAllocate()) {
            GrD3DDescriptorHeap::CPUHandle handle = fDescriptorHeaps[i]->allocateCPUHandle();
            return handle;
        }
    }

    // need to allocate more space
    std::unique_ptr<GrD3DCpuDescriptorManager::Heap> heap =
        GrD3DCpuDescriptorManager::Heap::Make(gpu, fHeapType, fMaxAvailableDescriptors);

    fDescriptorHeaps.push_back(std::move(heap));
    fMaxAvailableDescriptors *= 2;
    GrD3DDescriptorHeap::CPUHandle handle =
            fDescriptorHeaps[fDescriptorHeaps.size() - 1]->allocateCPUHandle();
    return handle;
}

void GrD3DCpuDescriptorManager::HeapPool::releaseHandle(
        const GrD3DDescriptorHeap::CPUHandle& dsvDescriptor) {
    for (unsigned int i = 0; i < fDescriptorHeaps.size(); ++i) {
        if (fDescriptorHeaps[i]->ownsHandle(dsvDescriptor)) {
            fDescriptorHeaps[i]->freeCPUHandle(dsvDescriptor);
            return;
        }
    }
    SkASSERT(false);
}
