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

#include "dawn/common/HashUtils.h"
#include "dawn/common/Log.h"
#include "dawn/native/D3D12Backend.h"
#include "dawn/native/d3d12/D3D12Error.h"
#include "dawn/native/d3d12/DeviceD3D12.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
