// 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
