// 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 { namespace 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
