// Copyright 2019 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.

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

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

#include <string>
#include <utility>

#include "dawn/native/d3d12/CommandAllocatorManager.h"
#include "dawn/native/d3d12/D3D12Error.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::AddToSharedTextureList(Texture* texture) {
    ASSERT(IsOpen());
    mSharedTextures.insert(texture);
}

MaybeError CommandRecordingContext::Open(ID3D12Device* d3d12Device,
                                         CommandAllocatorManager* commandAllocationManager) {
    ASSERT(!IsOpen());
    ID3D12CommandAllocator* commandAllocator;
    DAWN_TRY_ASSIGN(commandAllocator, commandAllocationManager->ReserveCommandAllocator());
    if (mD3d12CommandList != nullptr) {
        MaybeError error = CheckHRESULT(mD3d12CommandList->Reset(commandAllocator, nullptr),
                                        "D3D12 resetting command list");
        if (error.IsError()) {
            mD3d12CommandList.Reset();
            DAWN_TRY(std::move(error));
        }
    } else {
        ComPtr<ID3D12GraphicsCommandList> d3d12GraphicsCommandList;
        DAWN_TRY(CheckHRESULT(
            d3d12Device->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, commandAllocator,
                                           nullptr, IID_PPV_ARGS(&d3d12GraphicsCommandList)),
            "D3D12 creating direct command list"));
        mD3d12CommandList = std::move(d3d12GraphicsCommandList);
        // Store a cast to ID3D12GraphicsCommandList4. This is required to use the D3D12 render
        // pass APIs introduced in Windows build 1809.
        mD3d12CommandList.As(&mD3d12CommandList4);
    }

    mIsOpen = true;

    return {};
}

MaybeError CommandRecordingContext::ExecuteCommandList(Device* device) {
    if (IsOpen()) {
        // Shared textures must be transitioned to common state after the last usage in order
        // for them to be used by other APIs like D3D11. We ensure this by transitioning to the
        // common state right before command list submission. TransitionUsageNow itself ensures
        // no unnecessary transitions happen if the resources is already in the common state.
        for (Texture* texture : mSharedTextures) {
            DAWN_TRY(texture->SynchronizeImportedTextureBeforeUse());
            texture->TrackAllUsageAndTransitionNow(this, D3D12_RESOURCE_STATE_COMMON);
        }

        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
            device->GetCommandQueue()->GetClockCalibration(&gpuTimestamp, &cpuTimestamp);

            uint64_t gpuFrequency;
            uint64_t cpuFrequency;
            LARGE_INTEGER cpuFrequencyLargeInteger;
            device->GetCommandQueue()->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();
        device->GetCommandQueue()->ExecuteCommandLists(1, &d3d12CommandList);

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

        mIsOpen = false;
        mSharedTextures.clear();
        mHeapsPendingUsage.clear();
        mTempBuffers.clear();
    }
    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 {
    ASSERT(mD3d12CommandList != nullptr);
    ASSERT(IsOpen());
    return mD3d12CommandList.Get();
}

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

void CommandRecordingContext::Release() {
    mD3d12CommandList.Reset();
    mD3d12CommandList4.Reset();
    mIsOpen = false;
    mSharedTextures.clear();
    mHeapsPendingUsage.clear();
    mTempBuffers.clear();
}

bool CommandRecordingContext::IsOpen() const {
    return mIsOpen;
}

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

}  // namespace dawn::native::d3d12
