// Copyright 2018 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/DynamicUploader.h"

#include <utility>

#include "dawn/common/Math.h"
#include "dawn/native/Device.h"

namespace dawn::native {

DynamicUploader::DynamicUploader(DeviceBase* device) : mDevice(device) {
    mRingBuffers.emplace_back(
        std::unique_ptr<RingBuffer>(new RingBuffer{nullptr, RingBufferAllocator(kRingBufferSize)}));
}

void DynamicUploader::ReleaseStagingBuffer(std::unique_ptr<StagingBufferBase> stagingBuffer) {
    mReleasedStagingBuffers.Enqueue(std::move(stagingBuffer), mDevice->GetPendingCommandSerial());
}

ResultOrError<UploadHandle> DynamicUploader::AllocateInternal(uint64_t allocationSize,
                                                              ExecutionSerial serial) {
    // Disable further sub-allocation should the request be too large.
    if (allocationSize > kRingBufferSize) {
        std::unique_ptr<StagingBufferBase> stagingBuffer;
        DAWN_TRY_ASSIGN(stagingBuffer, mDevice->CreateStagingBuffer(allocationSize));

        UploadHandle uploadHandle;
        uploadHandle.mappedBuffer = static_cast<uint8_t*>(stagingBuffer->GetMappedPointer());
        uploadHandle.stagingBuffer = stagingBuffer.get();

        ReleaseStagingBuffer(std::move(stagingBuffer));
        return uploadHandle;
    }

    // Note: Validation ensures size is already aligned.
    // First-fit: find next smallest buffer large enough to satisfy the allocation request.
    RingBuffer* targetRingBuffer = mRingBuffers.back().get();
    for (auto& ringBuffer : mRingBuffers) {
        const RingBufferAllocator& ringBufferAllocator = ringBuffer->mAllocator;
        // Prevent overflow.
        ASSERT(ringBufferAllocator.GetSize() >= ringBufferAllocator.GetUsedSize());
        const uint64_t remainingSize =
            ringBufferAllocator.GetSize() - ringBufferAllocator.GetUsedSize();
        if (allocationSize <= remainingSize) {
            targetRingBuffer = ringBuffer.get();
            break;
        }
    }

    uint64_t startOffset = RingBufferAllocator::kInvalidOffset;
    if (targetRingBuffer != nullptr) {
        startOffset = targetRingBuffer->mAllocator.Allocate(allocationSize, serial);
    }

    // Upon failure, append a newly created ring buffer to fulfill the
    // request.
    if (startOffset == RingBufferAllocator::kInvalidOffset) {
        mRingBuffers.emplace_back(std::unique_ptr<RingBuffer>(
            new RingBuffer{nullptr, RingBufferAllocator(kRingBufferSize)}));

        targetRingBuffer = mRingBuffers.back().get();
        startOffset = targetRingBuffer->mAllocator.Allocate(allocationSize, serial);
    }

    ASSERT(startOffset != RingBufferAllocator::kInvalidOffset);

    // Allocate the staging buffer backing the ringbuffer.
    // Note: the first ringbuffer will be lazily created.
    if (targetRingBuffer->mStagingBuffer == nullptr) {
        std::unique_ptr<StagingBufferBase> stagingBuffer;
        DAWN_TRY_ASSIGN(stagingBuffer,
                        mDevice->CreateStagingBuffer(targetRingBuffer->mAllocator.GetSize()));
        targetRingBuffer->mStagingBuffer = std::move(stagingBuffer);
    }

    ASSERT(targetRingBuffer->mStagingBuffer != nullptr);

    UploadHandle uploadHandle;
    uploadHandle.stagingBuffer = targetRingBuffer->mStagingBuffer.get();
    uploadHandle.mappedBuffer =
        static_cast<uint8_t*>(uploadHandle.stagingBuffer->GetMappedPointer()) + startOffset;
    uploadHandle.startOffset = startOffset;

    return uploadHandle;
}

void DynamicUploader::Deallocate(ExecutionSerial lastCompletedSerial) {
    // Reclaim memory within the ring buffers by ticking (or removing requests no longer
    // in-flight).
    for (size_t i = 0; i < mRingBuffers.size(); ++i) {
        mRingBuffers[i]->mAllocator.Deallocate(lastCompletedSerial);

        // Never erase the last buffer as to prevent re-creating smaller buffers
        // again. The last buffer is the largest.
        if (mRingBuffers[i]->mAllocator.Empty() && i < mRingBuffers.size() - 1) {
            mRingBuffers.erase(mRingBuffers.begin() + i);
        }
    }
    mReleasedStagingBuffers.ClearUpTo(lastCompletedSerial);
}

// TODO(dawn:512): Optimize this function so that it doesn't allocate additional memory
// when it's not necessary.
ResultOrError<UploadHandle> DynamicUploader::Allocate(uint64_t allocationSize,
                                                      ExecutionSerial serial,
                                                      uint64_t offsetAlignment) {
    ASSERT(offsetAlignment > 0);
    UploadHandle uploadHandle;
    DAWN_TRY_ASSIGN(uploadHandle, AllocateInternal(allocationSize + offsetAlignment - 1, serial));
    uint64_t additionalOffset =
        Align(uploadHandle.startOffset, offsetAlignment) - uploadHandle.startOffset;
    uploadHandle.mappedBuffer = static_cast<uint8_t*>(uploadHandle.mappedBuffer) + additionalOffset;
    uploadHandle.startOffset += additionalOffset;
    return uploadHandle;
}
}  // namespace dawn::native
