// Copyright 2019 The Dawn & Tint Authors
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this
//    list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice,
//    this list of conditions and the following disclaimer in the documentation
//    and/or other materials provided with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of its
//    contributors may be used to endorse or promote products derived from
//    this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#include "src/dawn/native/d3d12/CommandRecordingContext.h"

#include <profileapi.h>
#include <sysinfoapi.h>

#include <string>
#include <utility>

#include "dawn/platform/DawnPlatform.h"
#include "src/dawn/common/Defer.h"
#include "src/dawn/native/d3d/D3DError.h"
#include "src/dawn/native/d3d12/DeviceD3D12.h"
#include "src/dawn/native/d3d12/HeapD3D12.h"
#include "src/dawn/native/d3d12/ResidencyManagerD3D12.h"
#include "src/dawn/platform/tracing/TraceEvent.h"
#include "src/utils/numeric.h"

namespace dawn::native::d3d12 {

void CommandRecordingContext::AddToSharedBufferList(Buffer* buffer) {
    mSharedBuffers.insert(buffer);
}

void CommandRecordingContext::AddToSharedTextureList(Texture* texture) {
    mSharedTextures.insert(texture);
}

void CommandRecordingContext::Open(ComPtr<ID3D12GraphicsCommandList> commandList) {
    mD3d12CommandList = std::move(commandList);
    mD3d12CommandList.As(&mD3d12CommandList1);
    mD3d12CommandList.As(&mD3d12CommandList4);
    mNeedsSubmit = false;
}

MaybeError CommandRecordingContext::ExecuteCommandList(Device* device,
                                                       ID3D12CommandQueue* commandQueue) {
    DAWN_ASSERT(mD3d12CommandList != nullptr);

    // Make sure to always Release when this call completes. This is especially important for
    // KeyedMutexes to ensure other users of SharedTextureMemory can rely on them being unlocked
    // after submit.
    Defer defer;
    defer.Append([this] { Release(); });

    for (Buffer* buffer : mSharedBuffers) {
        DAWN_TRY(buffer->SynchronizeBufferBeforeUseOnGPU());
    }

    for (Texture* texture : mSharedTextures) {
        DAWN_TRY(texture->SynchronizeTextureBeforeUse(this));
    }

    MaybeError error =
        CheckHRESULT(mD3d12CommandList->Close(), "D3D12 closing pending command list");
    if (error.IsError()) {
        DAWN_TRY(std::move(error));
    }
    DAWN_TRY(device->GetResidencyManager()->EnsureHeapsAreResident(mHeapsPendingUsage.data(),
                                                                   mHeapsPendingUsage.size()));

    if (device->IsToggleEnabled(Toggle::RecordDetailedTimingInTraceEvents)) {
        uint64_t gpuTimestamp;
        uint64_t cpuTimestamp;
        FILETIME fileTimeNonPrecise;
        SYSTEMTIME systemTimeNonPrecise;

        // Both supported since Windows 2000, have a accuracy of 1ms
        GetSystemTimeAsFileTime(&fileTimeNonPrecise);
        GetSystemTime(&systemTimeNonPrecise);
        // Query CPU and GPU timestamps at almost the same time
        commandQueue->GetClockCalibration(&gpuTimestamp, &cpuTimestamp);

        uint64_t gpuFrequency;
        uint64_t cpuFrequency;
        LARGE_INTEGER cpuFrequencyLargeInteger;
        commandQueue->GetTimestampFrequency(&gpuFrequency);
        QueryPerformanceFrequency(&cpuFrequencyLargeInteger);  // Supported since Windows 2000
        cpuFrequency = sign_cast(cpuFrequencyLargeInteger.QuadPart);

        std::string timingInfo = absl::StrFormat(
            "UTC Time: %u/%u/%u %02u:%02u:%02u.%03u, File Time: %u, CPU "
            "Timestamp: %u, GPU Timestamp: %u, CPU Tick Frequency: %u, GPU Tick Frequency: "
            "%u",
            systemTimeNonPrecise.wYear, systemTimeNonPrecise.wMonth, systemTimeNonPrecise.wDay,
            systemTimeNonPrecise.wHour, systemTimeNonPrecise.wMinute, systemTimeNonPrecise.wSecond,
            systemTimeNonPrecise.wMilliseconds,
            (static_cast<uint64_t>(fileTimeNonPrecise.dwHighDateTime) << 32) +
                fileTimeNonPrecise.dwLowDateTime,
            cpuTimestamp, gpuTimestamp, cpuFrequency, gpuFrequency);

        TRACE_EVENT_INSTANT1(device->GetPlatform(), General,
                             "d3d12::CommandRecordingContext::ExecuteCommandList Detailed Timing",
                             "Timing", timingInfo.c_str());
    }

    ID3D12CommandList* d3d12CommandList = GetCommandList();
    commandQueue->ExecuteCommandLists(1, &d3d12CommandList);

    return {};
}

void CommandRecordingContext::TrackHeapUsage(Heap* heap, ExecutionSerial serial) {
    // Before tracking the heap, check the last serial it was recorded on to ensure we aren't
    // tracking it more than once.
    if (heap->GetLastUsage() < serial) {
        heap->SetLastUsage(serial);
        mHeapsPendingUsage.push_back(heap);
    }
}

ID3D12GraphicsCommandList* CommandRecordingContext::GetCommandList() const {
    DAWN_ASSERT(mD3d12CommandList != nullptr);
    return mD3d12CommandList.Get();
}

ID3D12GraphicsCommandList1* CommandRecordingContext::GetCommandList1() const {
    DAWN_ASSERT(mD3d12CommandList != nullptr);
    return mD3d12CommandList1.Get();
}

// This function will fail on Windows versions prior to 1809. Support must be queried through
// the device before calling.
ID3D12GraphicsCommandList4* CommandRecordingContext::GetCommandList4() const {
    DAWN_ASSERT(mD3d12CommandList != nullptr);
    return mD3d12CommandList4.Get();
}

void CommandRecordingContext::Release() {
    mD3d12CommandList.Reset();
    mD3d12CommandList1.Reset();
    mD3d12CommandList4.Reset();

    mNeedsSubmit = false;

    mSharedBuffers.clear();
    mSharedTextures.clear();
    mHeapsPendingUsage.clear();
    mTempBuffers.clear();

    ReleaseKeyedMutexes();
}

bool CommandRecordingContext::NeedsSubmit() const {
    return mNeedsSubmit;
}

void CommandRecordingContext::SetNeedsSubmit() {
    mNeedsSubmit = true;
}

void CommandRecordingContext::AddToTempBuffers(Ref<Buffer> tempBuffer) {
    mTempBuffers.emplace_back(tempBuffer);
}

MaybeError CommandRecordingContext::AcquireKeyedMutex(Ref<d3d::KeyedMutex> keyedMutex) {
    if (!mAcquiredKeyedMutexes.contains(keyedMutex)) {
        DAWN_TRY(keyedMutex->AcquireKeyedMutex());
        mAcquiredKeyedMutexes.emplace(std::move(keyedMutex));
    }
    return {};
}

void CommandRecordingContext::ReleaseKeyedMutexes() {
    for (auto& keyedMutex : mAcquiredKeyedMutexes) {
        keyedMutex->ReleaseKeyedMutex();
    }
    mAcquiredKeyedMutexes.clear();
}

}  // namespace dawn::native::d3d12
