/*
 * Copyright (c) 2022 Arm Limited.
 *
 * SPDX-License-Identifier: MIT
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to
 * deal in the Software without restriction, including without limitation the
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
 * sell copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */
#include "src/gpu/cl/operators/ClIndirectConv2d.h"

#include "arm_compute/core/KernelDescriptors.h"
#include "arm_compute/core/Types.h"
#include "arm_compute/core/utils/misc/ShapeCalculator.h"
#include "arm_compute/runtime/CL/CLScheduler.h"
#include "src/gpu/cl/kernels/ClIndirectConv2dAddressPrecalculationKernel.h"
#include "src/gpu/cl/kernels/ClIndirectConv2dKernel.h"
#include "src/runtime/heuristics/indirect_conv/ClIndirectConvKernelConfig.h"
#include "src/runtime/heuristics/indirect_conv/IClIndirectConvKernelConfig.h"

#include "src/core/helpers/MemoryHelpers.h"
#include "src/gpu/cl/utils/ClAuxTensorHandler.h"

#include "src/common/utils/Log.h"

using namespace arm_compute::cl_indirect_conv;

namespace arm_compute
{
namespace opencl
{
using namespace arm_compute::experimental;

namespace
{
DirectConvComputeKernelInfo config_indirect_convolution_nhwc(const ITensorInfo *src, const ITensorInfo *weights, const PadStrideInfo &conv_info)
{
    // Get GPU target
    GPUTarget gpu_target = CLScheduler::get().target();

    std::unique_ptr<IClIndirectConvKernelConfig> t = ClIndirectConvKernelConfigurationFactory::create(gpu_target);

    return t->configure(src, weights, conv_info);
}

} // namespace

void ClIndirectConv2d::configure(const CLCompileContext &compile_context, ITensorInfo *src, ITensorInfo *weights, ITensorInfo *biases, ITensorInfo *dst,
                                 const PadStrideInfo &conv_info, const ActivationLayerInfo &act_info)
{
    ARM_COMPUTE_ERROR_ON_NULLPTR(src);
    ARM_COMPUTE_LOG_PARAMS(src, weights, biases, dst, conv_info, act_info);

    // Reuse the direct convolution descriptor
    const DirectConvComputeKernelInfo desc = config_indirect_convolution_nhwc(src, weights, conv_info);

    // Configure indirect convolution kernels
    auto k0 = std::make_unique<kernels::ClIndirectConv2dAddressPrecalculationKernel>();
    auto k1 = std::make_unique<kernels::ClIndirectConv2dKernel>();

    k0->set_target(CLScheduler::get().target());
    k1->set_target(CLScheduler::get().target());

    k0->configure(compile_context, src, weights, &_indirect_buffer, conv_info, desc);
    k1->configure(compile_context, src, weights, biases, &_indirect_buffer, dst, conv_info, act_info, desc);

    _addr_precalculation_kernel = std::move(k0);
    _indirect_conv_kernel       = std::move(k1);
    _is_prepared                = false;

    // Tune kernels
    CLScheduler::get().tune_kernel_static(*_indirect_conv_kernel);

    // Request memory for the indirect buffer
    _aux_mem[IndirectBuffer] = MemoryInfo(offset_int_vec(IndirectBuffer), MemoryLifetime::Persistent, _indirect_buffer.total_size());
}

Status ClIndirectConv2d::validate(const ITensorInfo *src, const ITensorInfo *weights, const ITensorInfo *biases, const ITensorInfo *dst,
                                  const PadStrideInfo &conv_info, const ActivationLayerInfo &act_info)
{
    // Initialize the direct convolution descriptor
    const DirectConvComputeKernelInfo desc = config_indirect_convolution_nhwc(src, weights, conv_info);

    TensorShape ind_buffer_shape = misc::shape_calculator::compute_indirect_buffer_shape(src->tensor_shape(),
                                                                                         src->data_layout(),
                                                                                         weights->tensor_shape(),
                                                                                         conv_info,
                                                                                         desc);

    TensorInfo indirect_buffer(ind_buffer_shape, 1, DataType::S32);

    ARM_COMPUTE_RETURN_ON_ERROR(kernels::ClIndirectConv2dAddressPrecalculationKernel::validate(src, weights, &indirect_buffer, conv_info, desc));
    ARM_COMPUTE_RETURN_ON_ERROR(kernels::ClIndirectConv2dKernel::validate(src, weights, biases, &indirect_buffer, dst, conv_info, act_info, desc));

    return Status{};
}

void ClIndirectConv2d::run(ITensorPack &tensors)
{
    CLAuxTensorHandler indirect_buffer(offset_int_vec(IndirectBuffer), _indirect_buffer, tensors, true);

    prepare(tensors);

    ITensorPack indirect_conv2d_pack(tensors);
    indirect_conv2d_pack.add_const_tensor(ACL_SRC_3, indirect_buffer.get());

    // Run indirect convolution
    CLScheduler::get().enqueue_op(*_indirect_conv_kernel, indirect_conv2d_pack, true);
}

void ClIndirectConv2d::prepare(ITensorPack &constants)
{
    if(!_is_prepared)
    {
        ICLTensor *indirect_buffer_aux = utils::cast::polymorphic_downcast<ICLTensor *>(constants.get_tensor(offset_int_vec(IndirectBuffer)));
        ARM_COMPUTE_ERROR_ON(indirect_buffer_aux == nullptr);

        ARM_COMPUTE_LOG_INFO_WITH_FUNCNAME_ACL("Preparing indirect buffer");

        CLAuxTensorHandler indirect_buffer(_indirect_buffer, *indirect_buffer_aux);
        ARM_COMPUTE_ERROR_ON(indirect_buffer.get()->cl_buffer().get() == nullptr);

        ITensorPack indirect_buffer_pack{ { ACL_DST, indirect_buffer.get() } };
        CLScheduler::get().enqueue_op(*_addr_precalculation_kernel, indirect_buffer_pack, true);

        _is_prepared = true;
    }
}

experimental::MemoryRequirements ClIndirectConv2d::workspace() const
{
    return _aux_mem;
}
} // namespace opencl
} // namespace arm_compute
