/*
 * Copyright (C) 2019 Apple Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 * THE POSSIBILITY OF SUCH DAMAGE.
 */

#import "config.h"
#import "GPUBindGroupAllocator.h"

#if ENABLE(WEBGPU)

#import "GPUErrorScopes.h"
#import <Metal/Metal.h>
#import <wtf/BlockObjCExceptions.h>
#import <wtf/CheckedArithmetic.h>

namespace WebCore {

Ref<GPUBindGroupAllocator> GPUBindGroupAllocator::create(GPUErrorScopes& errors)
{
    return adoptRef(*new GPUBindGroupAllocator(errors));
}

GPUBindGroupAllocator::GPUBindGroupAllocator(GPUErrorScopes& errors)
    : m_errorScopes(makeRef(errors))
{
}

#if USE(METAL)

Optional<GPUBindGroupAllocator::ArgumentBufferOffsets> GPUBindGroupAllocator::allocateAndSetEncoders(MTLArgumentEncoder *vertex, MTLArgumentEncoder *fragment, MTLArgumentEncoder *compute)
{
    id<MTLDevice> device = nil;
    auto checkedOffset = Checked<NSUInteger>(m_lastOffset);

    if (vertex) {
        device = vertex.device;
        checkedOffset += vertex.encodedLength;
    }
    if (fragment) {
        device = fragment.device;
        checkedOffset += fragment.encodedLength;
    }
    if (compute) {
        device = compute.device;
        checkedOffset += compute.encodedLength;
    }

    // No arguments; nothing to be done.
    if (!device)
        return { };

    if (checkedOffset.hasOverflowed()) {
        m_errorScopes->generateError("", GPUErrorFilter::OutOfMemory);
        return { };
    }

    auto newOffset = checkedOffset.unsafeGet();

    if (m_argumentBuffer && newOffset > m_argumentBuffer.get().length) {
        if (!reallocate(newOffset))
            return { };
    } else if (!m_argumentBuffer) {
        // Based off mimimum allocation for a shared-memory MTLBuffer on macOS.
        NSUInteger minimumSize = 4096;
        if (minimumSize < newOffset)
            minimumSize = newOffset;

        BEGIN_BLOCK_OBJC_EXCEPTIONS;
        m_argumentBuffer = adoptNS([device newBufferWithLength:minimumSize options:0]);
        END_BLOCK_OBJC_EXCEPTIONS;

        if (!m_argumentBuffer) {
            m_errorScopes->generateError("", GPUErrorFilter::OutOfMemory);
            return { };
        }
    }

    ArgumentBufferOffsets offsets;

    // Math in the following section is guarded against overflow by newOffset calculation.
    BEGIN_BLOCK_OBJC_EXCEPTIONS;

    if (vertex) {
        offsets.vertex = m_lastOffset;
        [vertex setArgumentBuffer:m_argumentBuffer.get() offset:*offsets.vertex];
    }
    if (fragment) {
        offsets.fragment = (vertex ? vertex.encodedLength : 0) + m_lastOffset;
        [fragment setArgumentBuffer:m_argumentBuffer.get() offset:*offsets.fragment];
    }
    if (compute) {
        offsets.compute = (vertex ? vertex.encodedLength : 0) + (fragment ? fragment.encodedLength : 0) + m_lastOffset;
        [compute setArgumentBuffer:m_argumentBuffer.get() offset:*offsets.compute];
    }

    END_BLOCK_OBJC_EXCEPTIONS;

    m_lastOffset = newOffset;

    return offsets;
}

// FIXME: https://bugs.webkit.org/show_bug.cgi?id=200657, https://bugs.webkit.org/show_bug.cgi?id=200658 Optimize reallocation and reset behavior.
bool GPUBindGroupAllocator::reallocate(NSUInteger newOffset)
{
    MTLBuffer *newBuffer = nil;

    auto newLength = Checked<NSUInteger>(m_argumentBuffer.get().length);
    while (newLength < newOffset) {
        newLength *= 1.25;

        if (newLength.hasOverflowed()) {
            newLength = std::numeric_limits<NSUInteger>::max();
            break;
        }
    }

    BEGIN_BLOCK_OBJC_EXCEPTIONS;

    newBuffer = [m_argumentBuffer.get().device newBufferWithLength:newLength.unsafeGet() options:0];
    memcpy(newBuffer.contents, m_argumentBuffer.get().contents, m_argumentBuffer.get().length);

    END_BLOCK_OBJC_EXCEPTIONS;

    if (!newBuffer) {
        m_errorScopes->generateError("", GPUErrorFilter::OutOfMemory);
        return false;
    }

    m_argumentBuffer = adoptNS(newBuffer);
    return true;
}

void GPUBindGroupAllocator::tryReset()
{
    if (!hasOneRef())
        return;

    m_argumentBuffer = nullptr;
    m_lastOffset = 0;
}

#endif // USE(METAL)

} // namespace WebCore

#endif // ENABLE(WEBGPU)
