/*
 * 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 recycleShaderView(const GrD3DDescriptorHeap::CPUHandle&);

    D3D12_CPU_DESCRIPTOR_HANDLE findOrCreateCompatibleSampler(const GrSamplerState& params);

    sk_sp<GrD3DDescriptorTable> findOrCreateShaderViewTable(
            const std::vector<D3D12_CPU_DESCRIPTOR_HANDLE>& shaderViews);
    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
