// Copyright 2020 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/metal/QuerySetMTL.h"

#include "common/Math.h"
#include "common/Platform.h"
#include "dawn_native/metal/DeviceMTL.h"

namespace dawn_native::metal {

    namespace {

        ResultOrError<id<MTLCounterSampleBuffer>> CreateCounterSampleBuffer(
            Device* device,
            MTLCommonCounterSet counterSet,
            uint32_t count) API_AVAILABLE(macos(10.15), ios(14.0)) {
            NSRef<MTLCounterSampleBufferDescriptor> descriptorRef =
                AcquireNSRef([MTLCounterSampleBufferDescriptor new]);
            MTLCounterSampleBufferDescriptor* descriptor = descriptorRef.Get();

            // To determine which counters are available from a device, we need to iterate through
            // the counterSets property of a MTLDevice. Then configure which counters will be
            // sampled by creating a MTLCounterSampleBufferDescriptor and setting its counterSet
            // property to the matched one of the available set.
            for (id<MTLCounterSet> set in device->GetMTLDevice().counterSets) {
                if ([set.name isEqualToString:counterSet]) {
                    descriptor.counterSet = set;
                    break;
                }
            }
            ASSERT(descriptor.counterSet != nullptr);

            descriptor.sampleCount = static_cast<NSUInteger>(std::max(count, uint32_t(1u)));
            descriptor.storageMode = MTLStorageModePrivate;
            if (device->IsToggleEnabled(Toggle::MetalUseSharedModeForCounterSampleBuffer)) {
                descriptor.storageMode = MTLStorageModeShared;
            }

            NSError* error = nullptr;
            id<MTLCounterSampleBuffer> counterSampleBuffer =
                [device->GetMTLDevice() newCounterSampleBufferWithDescriptor:descriptor
                                                                       error:&error];
            if (error != nullptr) {
                return DAWN_OUT_OF_MEMORY_ERROR(std::string("Error creating query set: ") +
                                                [error.localizedDescription UTF8String]);
            }

            return counterSampleBuffer;
        }
    }

    // static
    ResultOrError<Ref<QuerySet>> QuerySet::Create(Device* device,
                                                  const QuerySetDescriptor* descriptor) {
        Ref<QuerySet> queryset = AcquireRef(new QuerySet(device, descriptor));
        DAWN_TRY(queryset->Initialize());
        return queryset;
    }

    MaybeError QuerySet::Initialize() {
        Device* device = ToBackend(GetDevice());

        switch (GetQueryType()) {
            case wgpu::QueryType::Occlusion: {
                // Create buffer for writing 64-bit results.
                NSUInteger bufferSize = static_cast<NSUInteger>(
                    std::max(GetQueryCount() * sizeof(uint64_t), size_t(4u)));
                mVisibilityBuffer = AcquireNSPRef([device->GetMTLDevice()
                    newBufferWithLength:bufferSize
                                options:MTLResourceStorageModePrivate]);

                if (mVisibilityBuffer == nil) {
                    return DAWN_OUT_OF_MEMORY_ERROR("Failed to allocate query set.");
                }
                break;
            }
            case wgpu::QueryType::PipelineStatistics:
                if (@available(macOS 10.15, iOS 14.0, *)) {
                    DAWN_TRY_ASSIGN(mCounterSampleBuffer,
                                    CreateCounterSampleBuffer(device, MTLCommonCounterSetStatistic,
                                                              GetQueryCount()));
                } else {
                    UNREACHABLE();
                }
                break;
            case wgpu::QueryType::Timestamp:
                if (@available(macOS 10.15, iOS 14.0, *)) {
                    DAWN_TRY_ASSIGN(mCounterSampleBuffer,
                                    CreateCounterSampleBuffer(device, MTLCommonCounterSetTimestamp,
                                                              GetQueryCount()));
                } else {
                    UNREACHABLE();
                }
                break;
            default:
                UNREACHABLE();
                break;
        }

        return {};
    }

    id<MTLBuffer> QuerySet::GetVisibilityBuffer() const {
        return mVisibilityBuffer.Get();
    }

    id<MTLCounterSampleBuffer> QuerySet::GetCounterSampleBuffer() const
        API_AVAILABLE(macos(10.15), ios(14.0)) {
        return mCounterSampleBuffer;
    }

    QuerySet::~QuerySet() = default;

    void QuerySet::DestroyImpl() {
        QuerySetBase::DestroyImpl();

        mVisibilityBuffer = nullptr;

        // mCounterSampleBuffer isn't an NSRef because API_AVAILABLE doesn't work will with
        // templates.
        if (@available(macOS 10.15, iOS 14.0, *)) {
            [mCounterSampleBuffer release];
            mCounterSampleBuffer = nullptr;
        }
    }

}  // namespace dawn_native::metal
