// 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 "dawn/common/HashUtils.h"
#include "dawn/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
