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

    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()) {
        Release();
        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);

    Release();
    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
