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

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

GrD3DCpuDescriptorManager::GrD3DCpuDescriptorManager(GrD3DGpu* gpu)
    : fRTVDescriptorPool(gpu, D3D12_DESCRIPTOR_HEAP_TYPE_RTV)
    , fDSVDescriptorPool(gpu, D3D12_DESCRIPTOR_HEAP_TYPE_DSV)
    , fShaderViewDescriptorPool(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 =
            fShaderViewDescriptorPool.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,
        unsigned int mostDetailedMip, unsigned int mipLevels) {
    const GrD3DDescriptorHeap::CPUHandle& descriptor =
            fShaderViewDescriptorPool.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.
    D3D12_SHADER_RESOURCE_VIEW_DESC desc = {};
    desc.Format = resource->GetDesc().Format;
    desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D;
    desc.Texture2D.MostDetailedMip = mostDetailedMip;
    desc.Texture2D.MipLevels = mipLevels;
    desc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
    gpu->device()->CreateShaderResourceView(resource, &desc, descriptor.fHandle);
    return descriptor;
}

GrD3DDescriptorHeap::CPUHandle GrD3DCpuDescriptorManager::createUnorderedAccessView(
        GrD3DGpu* gpu, ID3D12Resource* resource, unsigned int mipSlice) {
    const GrD3DDescriptorHeap::CPUHandle& descriptor =
            fShaderViewDescriptorPool.allocateHandle(gpu);
    if (resource->GetDesc().Dimension == D3D12_RESOURCE_DIMENSION_BUFFER) {
        // TODO: figure out buffer setup
        gpu->device()->CreateUnorderedAccessView(resource, nullptr, nullptr, descriptor.fHandle);
    } else {
        D3D12_UNORDERED_ACCESS_VIEW_DESC desc = {};
        desc.Format = resource->GetDesc().Format;
        desc.ViewDimension = D3D12_UAV_DIMENSION_TEXTURE2D;
        desc.Texture2D.MipSlice = mipSlice;
        gpu->device()->CreateUnorderedAccessView(resource, nullptr, &desc, descriptor.fHandle);
    }
    return descriptor;
}

void GrD3DCpuDescriptorManager::recycleShaderView(
        const GrD3DDescriptorHeap::CPUHandle& view) {
    fShaderViewDescriptorPool.releaseHandle(view);
}

GrD3DDescriptorHeap::CPUHandle GrD3DCpuDescriptorManager::createSampler(
        GrD3DGpu* gpu,
        D3D12_FILTER filter,
        float maxLOD,
        unsigned int maxAnisotropy,
        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 = maxAnisotropy;
    desc.ComparisonFunc = D3D12_COMPARISON_FUNC_ALWAYS;
    // desc.BorderColor initialized to { 0, 0, 0, 0 } by default initializer, above.
    desc.MinLOD = 0;
    desc.MaxLOD = maxLOD;

    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.has_value());
    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);
    // TODO: handle failed heap creation and/or memory restrictions better
    // skbug.com/40043048
    SkASSERT(heap);

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