// 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 "dawn/native/d3d12/CommandRecordingContext.h"

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

#include <string>
#include <utility>

#include "dawn/common/Defer.h"
#include "dawn/native/d3d/D3DError.h"
#include "dawn/native/d3d12/DeviceD3D12.h"
#include "dawn/native/d3d12/HeapD3D12.h"
#include "dawn/native/d3d12/ResidencyManagerD3D12.h"
#include "dawn/platform/DawnPlatform.h"
#include "dawn/platform/tracing/TraceEvent.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 = 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
