// Copyright 2021 The Dawn Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// D3D12Backend.cpp: contains the definition of symbols exported by D3D12Backend.h so that they
// can be compiled twice: once export (shared library), once not exported (static library)

#include "dawn_native/d3d12/D3D11on12Util.h"

#include "common/HashUtils.h"
#include "common/Log.h"
#include "dawn_native/d3d12/D3D12Error.h"
#include "dawn_native/d3d12/DeviceD3D12.h"

#include <dawn_native/D3D12Backend.h>

namespace dawn::native::d3d12 {

    void Flush11On12DeviceToAvoidLeaks(ComPtr<ID3D11On12Device> d3d11on12Device) {
        if (d3d11on12Device == nullptr) {
            return;
        }

        ComPtr<ID3D11Device> d3d11Device;
        if (FAILED(d3d11on12Device.As(&d3d11Device))) {
            return;
        }

        ComPtr<ID3D11DeviceContext> d3d11DeviceContext;
        d3d11Device->GetImmediateContext(&d3d11DeviceContext);

        ASSERT(d3d11DeviceContext != nullptr);

        // 11on12 has a bug where D3D12 resources used only for keyed shared mutexes
        // are not released until work is submitted to the device context and flushed.
        // The most minimal work we can get away with is issuing a TiledResourceBarrier.

        // ID3D11DeviceContext2 is available in Win8.1 and above. This suffices for a
        // D3D12 backend since both D3D12 and 11on12 first appeared in Windows 10.
        ComPtr<ID3D11DeviceContext2> d3d11DeviceContext2;
        if (FAILED(d3d11DeviceContext.As(&d3d11DeviceContext2))) {
            return;
        }

        d3d11DeviceContext2->TiledResourceBarrier(nullptr, nullptr);
        d3d11DeviceContext2->Flush();
    }

    D3D11on12ResourceCacheEntry::D3D11on12ResourceCacheEntry(
        ComPtr<IDXGIKeyedMutex> dxgiKeyedMutex,
        ComPtr<ID3D11On12Device> d3d11On12Device)
        : mDXGIKeyedMutex(std::move(dxgiKeyedMutex)), mD3D11on12Device(std::move(d3d11On12Device)) {
    }

    D3D11on12ResourceCacheEntry::D3D11on12ResourceCacheEntry(
        ComPtr<ID3D11On12Device> d3d11On12Device)
        : mD3D11on12Device(std::move(d3d11On12Device)) {
    }

    D3D11on12ResourceCacheEntry::~D3D11on12ResourceCacheEntry() {
        if (mDXGIKeyedMutex == nullptr) {
            return;
        }

        if (mAcquireCount > 0) {
            mDXGIKeyedMutex->ReleaseSync(kDXGIKeyedMutexAcquireReleaseKey);
        }

        ComPtr<ID3D11Resource> d3d11Resource;
        if (FAILED(mDXGIKeyedMutex.As(&d3d11Resource))) {
            return;
        }

        ASSERT(mD3D11on12Device != nullptr);

        ID3D11Resource* d3d11ResourceRaw = d3d11Resource.Get();
        mD3D11on12Device->ReleaseWrappedResources(&d3d11ResourceRaw, 1);

        d3d11Resource.Reset();
        mDXGIKeyedMutex.Reset();

        Flush11On12DeviceToAvoidLeaks(std::move(mD3D11on12Device));
    }

    MaybeError D3D11on12ResourceCacheEntry::AcquireKeyedMutex() {
        ASSERT(mDXGIKeyedMutex != nullptr);
        ASSERT(mAcquireCount >= 0);
        if (mAcquireCount == 0) {
            DAWN_TRY(CheckHRESULT(
                mDXGIKeyedMutex->AcquireSync(kDXGIKeyedMutexAcquireReleaseKey, INFINITE),
                "D3D12 acquiring shared mutex"));
        }
        mAcquireCount++;
        return {};
    }

    void D3D11on12ResourceCacheEntry::ReleaseKeyedMutex() {
        ASSERT(mDXGIKeyedMutex != nullptr);
        ASSERT(mAcquireCount > 0);
        mAcquireCount--;
        if (mAcquireCount == 0) {
            mDXGIKeyedMutex->ReleaseSync(kDXGIKeyedMutexAcquireReleaseKey);
        }
    }

    size_t D3D11on12ResourceCacheEntry::HashFunc::operator()(
        const Ref<D3D11on12ResourceCacheEntry> a) const {
        size_t hash = 0;
        HashCombine(&hash, a->mD3D11on12Device.Get());
        return hash;
    }

    bool D3D11on12ResourceCacheEntry::EqualityFunc::operator()(
        const Ref<D3D11on12ResourceCacheEntry> a,
        const Ref<D3D11on12ResourceCacheEntry> b) const {
        return a->mD3D11on12Device == b->mD3D11on12Device;
    }

    D3D11on12ResourceCache::D3D11on12ResourceCache() = default;

    D3D11on12ResourceCache::~D3D11on12ResourceCache() = default;

    Ref<D3D11on12ResourceCacheEntry> D3D11on12ResourceCache::GetOrCreateD3D11on12Resource(
        WGPUDevice device,
        ID3D12Resource* d3d12Resource) {
        Device* backendDevice = reinterpret_cast<Device*>(device);
        // The Dawn and 11on12 device share the same D3D12 command queue whereas this external image
        // could be accessed/produced with multiple Dawn devices. To avoid cross-queue sharing
        // restrictions, the 11 wrapped resource is forbidden to be shared between Dawn devices by
        // using the 11on12 device as the cache key.
        ComPtr<ID3D11On12Device> d3d11on12Device = backendDevice->GetOrCreateD3D11on12Device();
        if (d3d11on12Device == nullptr) {
            dawn::ErrorLog() << "Unable to create 11on12 device for external image";
            return nullptr;
        }

        D3D11on12ResourceCacheEntry blueprint(d3d11on12Device);
        auto iter = mCache.find(&blueprint);
        if (iter != mCache.end()) {
            return *iter;
        }

        // We use IDXGIKeyedMutexes to synchronize access between D3D11 and D3D12. D3D11/12 fences
        // are a viable alternative but are, unfortunately, not available on all versions of Windows
        // 10. Since D3D12 does not directly support keyed mutexes, we need to wrap the D3D12
        // resource using 11on12 and QueryInterface the D3D11 representation for the keyed mutex.
        ComPtr<ID3D11Texture2D> d3d11Texture;
        D3D11_RESOURCE_FLAGS resourceFlags;
        resourceFlags.BindFlags = 0;
        resourceFlags.MiscFlags = D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX;
        resourceFlags.CPUAccessFlags = 0;
        resourceFlags.StructureByteStride = 0;
        if (FAILED(d3d11on12Device->CreateWrappedResource(
                d3d12Resource, &resourceFlags, D3D12_RESOURCE_STATE_COMMON,
                D3D12_RESOURCE_STATE_COMMON, IID_PPV_ARGS(&d3d11Texture)))) {
            return nullptr;
        }

        ComPtr<IDXGIKeyedMutex> dxgiKeyedMutex;
        if (FAILED(d3d11Texture.As(&dxgiKeyedMutex))) {
            return nullptr;
        }

        // Keep this cache from growing unbounded.
        // TODO(dawn:625): Consider using a replacement policy based cache.
        if (mCache.size() > kMaxD3D11on12ResourceCacheSize) {
            mCache.clear();
        }

        Ref<D3D11on12ResourceCacheEntry> entry =
            AcquireRef(new D3D11on12ResourceCacheEntry(dxgiKeyedMutex, std::move(d3d11on12Device)));
        mCache.insert(entry);

        return entry;
    }

}  // namespace dawn::native::d3d12
