// Copyright 2022 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/tests/DawnTest.h"

#include "dawn/native/Buffer.h"
#include "dawn/native/CommandEncoder.h"
#include "dawn/native/d3d12/DeviceD3D12.h"
#include "dawn/utils/WGPUHelpers.h"

namespace {
    class ExpectBetweenTimestamps : public detail::Expectation {
      public:
        ~ExpectBetweenTimestamps() override = default;

        ExpectBetweenTimestamps(uint64_t value0, uint64_t value1) {
            mValue0 = value0;
            mValue1 = value1;
        }

        // Expect the actual results are between mValue0 and mValue1.
        testing::AssertionResult Check(const void* data, size_t size) override {
            const uint64_t* actual = static_cast<const uint64_t*>(data);
            for (size_t i = 0; i < size / sizeof(uint64_t); ++i) {
                if (actual[i] < mValue0 || actual[i] > mValue1) {
                    return testing::AssertionFailure()
                           << "Expected data[" << i << "] to be between " << mValue0 << " and "
                           << mValue1 << ", actual " << actual[i] << std::endl;
                }
            }

            return testing::AssertionSuccess();
        }

      private:
        uint64_t mValue0;
        uint64_t mValue1;
    };

}  // anonymous namespace

using namespace dawn::native::d3d12;

class D3D12GPUTimestampCalibrationTests : public DawnTest {
  protected:
    void SetUp() override {
        DawnTest::SetUp();

        DAWN_TEST_UNSUPPORTED_IF(UsesWire());
        // Requires that timestamp query feature is enabled and timestamp query conversion is
        // disabled.
        DAWN_TEST_UNSUPPORTED_IF(!SupportsFeatures({wgpu::FeatureName::TimestampQuery}) ||
                                 !HasToggleEnabled("disable_timestamp_query_conversion"));
    }

    std::vector<wgpu::FeatureName> GetRequiredFeatures() override {
        std::vector<wgpu::FeatureName> requiredFeatures = {};
        if (SupportsFeatures({wgpu::FeatureName::TimestampQuery})) {
            requiredFeatures.push_back(wgpu::FeatureName::TimestampQuery);
        }
        return requiredFeatures;
    }
};

// Check that the timestamps got by timestamp query are between the two timestamps from
// GetClockCalibration() after the timestamp conversion is disabled.
TEST_P(D3D12GPUTimestampCalibrationTests, TimestampsInOrder) {
    constexpr uint32_t kQueryCount = 2;

    wgpu::QuerySetDescriptor querySetDescriptor;
    querySetDescriptor.count = kQueryCount;
    querySetDescriptor.type = wgpu::QueryType::Timestamp;
    wgpu::QuerySet querySet = device.CreateQuerySet(&querySetDescriptor);

    wgpu::BufferDescriptor bufferDescriptor;
    bufferDescriptor.size = kQueryCount * sizeof(uint64_t);
    bufferDescriptor.usage =
        wgpu::BufferUsage::QueryResolve | wgpu::BufferUsage::CopySrc | wgpu::BufferUsage::CopyDst;
    wgpu::Buffer destination = device.CreateBuffer(&bufferDescriptor);

    wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
    encoder.WriteTimestamp(querySet, 0);
    encoder.WriteTimestamp(querySet, 1);
    wgpu::CommandBuffer commands = encoder.Finish();

    Device* d3DDevice = reinterpret_cast<Device*>(device.Get());
    uint64_t gpuTimestamp0, gpuTimestamp1;
    uint64_t cpuTimestamp0, cpuTimestamp1;
    d3DDevice->GetCommandQueue()->GetClockCalibration(&gpuTimestamp0, &cpuTimestamp0);
    queue.Submit(1, &commands);
    WaitForAllOperations();
    d3DDevice->GetCommandQueue()->GetClockCalibration(&gpuTimestamp1, &cpuTimestamp1);

    // Separate resolve queryset to reduce the execution time of the queue with WriteTimestamp,
    // so that the timestamp in the querySet will be closer to both gpuTimestamps from
    // GetClockCalibration.
    wgpu::CommandEncoder resolveEncoder = device.CreateCommandEncoder();
    resolveEncoder.ResolveQuerySet(querySet, 0, kQueryCount, destination, 0);
    wgpu::CommandBuffer resolveCommands = resolveEncoder.Finish();
    queue.Submit(1, &resolveCommands);

    EXPECT_BUFFER(destination, 0, kQueryCount * sizeof(uint64_t),
                  new ExpectBetweenTimestamps(gpuTimestamp0, gpuTimestamp1));
}

DAWN_INSTANTIATE_TEST(D3D12GPUTimestampCalibrationTests,
                      D3D12Backend({"disable_timestamp_query_conversion"}));
