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

#ifndef GrD3DResourceProvider_DEFINED
#define GrD3DResourceProvider_DEFINED

#include "include/gpu/d3d/GrD3DTypes.h"
#include "include/private/SkTArray.h"
#include "include/private/SkTHash.h"
#include "src/core/SkLRUCache.h"
#include "src/gpu/GrProgramDesc.h"
#include "src/gpu/GrRingBuffer.h"
#include "src/gpu/d3d/GrD3DCommandSignature.h"
#include "src/gpu/d3d/GrD3DCpuDescriptorManager.h"
#include "src/gpu/d3d/GrD3DDescriptorTableManager.h"
#include "src/gpu/d3d/GrD3DPipeline.h"
#include "src/gpu/d3d/GrD3DRootSignature.h"
#include "src/gpu/d3d/GrD3DUtil.h"

#include <memory>

class GrD3DCommandSignature;
class GrD3DDirectCommandList;
class GrD3DGpu;
class GrD3DPipelineState;
class GrSamplerState;

class GrD3DResourceProvider {
public:
    GrD3DResourceProvider(GrD3DGpu*);

    void destroyResources();

    std::unique_ptr<GrD3DDirectCommandList> findOrCreateDirectCommandList();

    void recycleDirectCommandList(std::unique_ptr<GrD3DDirectCommandList>);

    sk_sp<GrD3DRootSignature> findOrCreateRootSignature(int numTextureSamplers);

    sk_sp<GrD3DCommandSignature> findOrCreateCommandSignature(GrD3DCommandSignature::ForIndexed,
                                                              unsigned int slot);

    GrD3DDescriptorHeap::CPUHandle createRenderTargetView(ID3D12Resource* textureResource);
    void recycleRenderTargetView(const GrD3DDescriptorHeap::CPUHandle&);

    GrD3DDescriptorHeap::CPUHandle createDepthStencilView(ID3D12Resource* textureResource);
    void recycleDepthStencilView(const GrD3DDescriptorHeap::CPUHandle&);

    GrD3DDescriptorHeap::CPUHandle createConstantBufferView(ID3D12Resource* bufferResource,
                                                            size_t offset,
                                                            size_t size);
    GrD3DDescriptorHeap::CPUHandle createShaderResourceView(ID3D12Resource* resource);
    GrD3DDescriptorHeap::CPUHandle createUnorderedAccessView(ID3D12Resource* resource);
    void recycleCBVSRVUAV(const GrD3DDescriptorHeap::CPUHandle&);

    D3D12_CPU_DESCRIPTOR_HANDLE findOrCreateCompatibleSampler(const GrSamplerState& params);

    sk_sp<GrD3DDescriptorTable> findOrCreateShaderResourceTable(
            const std::vector<D3D12_CPU_DESCRIPTOR_HANDLE>& shaderResourceViews);
    sk_sp<GrD3DDescriptorTable> findOrCreateSamplerTable(
            const std::vector<D3D12_CPU_DESCRIPTOR_HANDLE>& samplers);
    GrD3DDescriptorTableManager* descriptorTableMgr() {
        return &fDescriptorTableManager;
    }

    GrD3DPipelineState* findOrCreateCompatiblePipelineState(GrRenderTarget*,
                                                            const GrProgramInfo&);

    D3D12_GPU_VIRTUAL_ADDRESS uploadConstantData(void* data, size_t size);
    void prepForSubmit();

    void markPipelineStateUniformsDirty() { fPipelineStateCache->markPipelineStateUniformsDirty(); }

#if GR_TEST_UTILS
    void resetShaderCacheForTesting() const { fPipelineStateCache->release(); }
#endif

private:
#ifdef SK_DEBUG
#define GR_PIPELINE_STATE_CACHE_STATS
#endif

    class PipelineStateCache : public ::SkNoncopyable {
    public:
        PipelineStateCache(GrD3DGpu* gpu);
        ~PipelineStateCache();

        void release();
        GrD3DPipelineState* refPipelineState(GrRenderTarget*, const GrProgramInfo&);

        void markPipelineStateUniformsDirty();

    private:
        struct Entry;

        struct DescHash {
            uint32_t operator()(const GrProgramDesc& desc) const {
                return SkOpts::hash_fn(desc.asKey(), desc.keyLength(), 0);
            }
        };

        SkLRUCache<const GrProgramDesc, std::unique_ptr<Entry>, DescHash> fMap;

        GrD3DGpu* fGpu;

#ifdef GR_PIPELINE_STATE_CACHE_STATS
        int fTotalRequests;
        int fCacheMisses;
#endif
    };

    class DescriptorTableCache : public ::SkNoncopyable {
    public:
        DescriptorTableCache(GrD3DGpu* gpu) : fGpu(gpu), fMap(64) {
            // Initialize the array we pass into CopyDescriptors for ranges.
            // At the moment any descriptor we pass into CopyDescriptors is only itself,
            // not the beginning of a range, so each range size is always 1.
            for (int i = 0; i < kRangeSizesCount; ++i) {
                fRangeSizes[i] = 1;
            }
        }
        ~DescriptorTableCache() = default;

        void release();
        typedef std::function<sk_sp<GrD3DDescriptorTable>(GrD3DGpu*, unsigned int)> CreateFunc;
        sk_sp<GrD3DDescriptorTable> findOrCreateDescTable(
                const std::vector<D3D12_CPU_DESCRIPTOR_HANDLE>&, CreateFunc);

    private:
        GrD3DGpu* fGpu;

        typedef std::vector<D3D12_CPU_DESCRIPTOR_HANDLE> DescTableKey;
        typedef sk_sp<GrD3DDescriptorTable> DescTableValue;
        struct DescTableHash {
            uint32_t operator()(DescTableKey key) const {
                return SkOpts::hash_fn(key.data(),
                                       key.size()*sizeof(D3D12_CPU_DESCRIPTOR_HANDLE), 0);
            }
        };
        SkLRUCache<DescTableKey, DescTableValue, DescTableHash> fMap;
        static constexpr int kRangeSizesCount = 8;
        unsigned int fRangeSizes[kRangeSizesCount];
    };

    GrD3DGpu* fGpu;

    SkSTArray<4, std::unique_ptr<GrD3DDirectCommandList>> fAvailableDirectCommandLists;
    SkSTArray<4, sk_sp<GrD3DRootSignature>> fRootSignatures;
    SkSTArray<2, sk_sp<GrD3DCommandSignature>> fCommandSignatures;

    GrD3DCpuDescriptorManager fCpuDescriptorManager;
    GrD3DDescriptorTableManager fDescriptorTableManager;

    std::unique_ptr<PipelineStateCache> fPipelineStateCache;

    SkTHashMap<uint32_t, D3D12_CPU_DESCRIPTOR_HANDLE> fSamplers;

    DescriptorTableCache fShaderResourceDescriptorTableCache;
    DescriptorTableCache fSamplerDescriptorTableCache;
};

#endif
