/*
 * Copyright (c) 2021-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/ClDirectConv2d.h"

#include "arm_compute/core/KernelDescriptors.h"
#include "arm_compute/core/utils/misc/ShapeCalculator.h"
#include "arm_compute/runtime/CL/CLScheduler.h"
#include "src/core/CL/kernels/CLFillBorderKernel.h"
#include "src/core/helpers/AutoConfiguration.h"
#include "src/gpu/cl/kernels/ClActivationKernel.h"
#include "src/gpu/cl/kernels/ClDirectConv2dKernel.h"
#include "src/gpu/cl/kernels/direct_conv/ClDirectConvDefaultConfigBifrost.h"
#include "src/gpu/cl/kernels/direct_conv/ClDirectConvDefaultConfigValhall.h"
#include "src/gpu/cl/kernels/direct_conv/ClDirectConvKernelConfig.h"
#include "src/gpu/cl/kernels/direct_conv/IClDirectConvKernelConfig.h"

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

using namespace arm_compute::cl_direct_conv;

namespace arm_compute
{
namespace opencl
{
namespace
{
ITensorPack select_activation_src_dst(ITensorPack &tensors)
{
    ITensorPack pack;
    pack.add_tensor(TensorType::ACL_SRC, tensors.get_tensor(TensorType::ACL_DST));
    pack.add_tensor(TensorType::ACL_DST, tensors.get_tensor(TensorType::ACL_DST));
    return pack;
}

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

    std::unique_ptr<IClDirectConvKernelConfig> t = ClDirectConvKernelConfigurationFactory::create(gpu_target);

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

} // namespace

void ClDirectConv2d::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);

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

    // Configure direct convolution kernel
    const ActivationLayerInfo conv2d_act_info = (src->data_layout() == DataLayout::NHWC && is_data_type_float(src->data_type())) ? act_info : ActivationLayerInfo();
    auto                      k               = std::make_unique<kernels::ClDirectConv2dKernel>();
    k->set_target(CLScheduler::get().target());
    k->configure(compile_context, src, weights, biases, dst, conv_info, conv2d_act_info, desc);
    _direct_conv_kernel = std::move(k);

    // Configure border handler
    PixelValue zero_value(0.f);
    if(is_data_type_quantized_asymmetric(src->data_type()))
    {
        zero_value = PixelValue(0, src->data_type(), src->quantization_info());
    }
    auto b = std::make_unique<CLFillBorderKernel>();
    b->configure(compile_context, src, _direct_conv_kernel->border_size(), BorderMode::CONSTANT, zero_value);
    _src_border_handler = std::move(b);

    // Fused activation is currently supported for NHWC and floating point types
    if(act_info.enabled() && !conv2d_act_info.enabled())
    {
        auto a = std::make_unique<kernels::ClActivationKernel>();
        a->configure(compile_context, dst, dst, act_info);
        _activation_kernel = std::move(a);
    }

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

Status ClDirectConv2d::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_direct_convolution_nhwc(src, weights, conv_info);

    ARM_COMPUTE_RETURN_ON_ERROR(kernels::ClDirectConv2dKernel::validate(src, weights, biases, dst, conv_info, ActivationLayerInfo(), desc));
    if(act_info.enabled())
    {
        ARM_COMPUTE_RETURN_ON_ERROR(kernels::ClActivationKernel::validate(dst, dst, act_info));
    }
    return Status{};
}

void ClDirectConv2d::run(ITensorPack &tensors)
{
    // Run border handler
    CLScheduler::get().enqueue_op(*_src_border_handler.get(), tensors, false);
    // Run direct convolution
    CLScheduler::get().enqueue_op(*_direct_conv_kernel.get(), tensors, false);
    // Run activation kernel
    if(_activation_kernel)
    {
        auto act_pack = select_activation_src_dst(tensors);
        CLScheduler::get().enqueue_op(*_activation_kernel.get(), act_pack, false);
    }
}
} // namespace opencl
} // namespace arm_compute
