blob: 37ad5da2fe595f0fc59d21dd45586226bbec34a8 [file] [log] [blame]
//
// Copyright © 2017,2022-2024 Arm Ltd and Contributors. All rights reserved.
// SPDX-License-Identifier: MIT
//
#include <armnn/BackendHelper.hpp>
#include <armnn/BackendId.hpp>
#include <armnn/BackendOptions.hpp>
#include <armnn/BackendRegistry.hpp>
#include <armnn/LstmParams.hpp>
#include <armnn/QuantizedLstmParams.hpp>
#include <armnn/Tensor.hpp>
#include <armnn/Types.hpp>
#include <armnn/backends/ILayerSupport.hpp>
#include <armnn/backends/IBackendInternal.hpp>
#include <stddef.h>
namespace armnn
{
// Return LayerSupportHandle instead of the previous pointer to ILayerSupport.
LayerSupportHandle GetILayerSupportByBackendId(const armnn::BackendId& backend)
{
BackendRegistry& backendRegistry = armnn::BackendRegistryInstance();
if (!backendRegistry.IsBackendRegistered(backend))
{
return LayerSupportHandle(nullptr);
}
auto factoryFunc = backendRegistry.GetFactory(backend);
auto backendObject = factoryFunc();
return LayerSupportHandle(backendObject->GetLayerSupport(), backend);
}
Optional<const BackendOptions::BackendOption> GetCapability(const std::string& backendCapabilityName,
const BackendCapabilities& capabilities)
{
for (size_t i=0; i < capabilities.GetOptionCount(); i++)
{
const auto& capability = capabilities.GetOption(i);
if (backendCapabilityName == capability.GetName())
{
return capability;
}
}
return EmptyOptional();
}
Optional<const BackendOptions::BackendOption> GetCapability(const std::string& backendCapabilityName,
const armnn::BackendId& backend)
{
auto const& backendRegistry = armnn::BackendRegistryInstance();
if (backendRegistry.IsBackendRegistered(backend))
{
auto factoryFunc = backendRegistry.GetFactory(backend);
auto backendObject = factoryFunc();
auto capabilities = backendObject->GetCapabilities();
return GetCapability(backendCapabilityName, capabilities);
}
return EmptyOptional();
}
bool HasCapability(const std::string& name, const BackendCapabilities& capabilities)
{
return GetCapability(name, capabilities).has_value();
}
bool HasCapability(const std::string& name, const armnn::BackendId& backend)
{
return GetCapability(name, backend).has_value();
}
bool HasCapability(const BackendOptions::BackendOption& capability, const BackendCapabilities& capabilities)
{
return HasMatchingCapability(capability, capabilities);
}
bool HasCapability(const BackendOptions::BackendOption& backendOption, const armnn::BackendId& backend)
{
return HasMatchingCapability(backendOption, backend);
}
bool HasMatchingCapability(const BackendOptions::BackendOption& capability, const BackendCapabilities& capabilities)
{
for (size_t i=0; i < capabilities.GetOptionCount(); i++)
{
const auto& backendCapability = capabilities.GetOption(i);
if (capability.GetName() == backendCapability.GetName())
{
if (capability.GetValue().IsBool() && backendCapability.GetValue().IsBool())
{
return capability.GetValue().AsBool() == backendCapability.GetValue().AsBool();
}
else if (capability.GetValue().IsFloat() && backendCapability.GetValue().IsFloat())
{
return capability.GetValue().AsFloat() == backendCapability.GetValue().AsFloat();
}
else if (capability.GetValue().IsInt() && backendCapability.GetValue().IsInt())
{
return capability.GetValue().AsInt() == backendCapability.GetValue().AsInt();
}
else if (capability.GetValue().IsString() && backendCapability.GetValue().IsString())
{
return capability.GetValue().AsString() == backendCapability.GetValue().AsString();
}
else if (capability.GetValue().IsUnsignedInt() && backendCapability.GetValue().IsUnsignedInt())
{
return capability.GetValue().AsUnsignedInt() == backendCapability.GetValue().AsUnsignedInt();
}
}
}
return false;
}
bool HasMatchingCapability(const BackendOptions::BackendOption& backendOption, const armnn::BackendId& backend)
{
auto const& backendRegistry = armnn::BackendRegistryInstance();
if (backendRegistry.IsBackendRegistered(backend))
{
auto factoryFunc = backendRegistry.GetFactory(backend);
auto backendObject = factoryFunc();
auto capabilities = backendObject->GetCapabilities();
return HasMatchingCapability(backendOption, capabilities);
}
return false;
}
unsigned int GetNumberOfCacheFiles(const armnn::BackendId& backend)
{
auto const& backendRegistry = armnn::BackendRegistryInstance();
if (backendRegistry.IsBackendRegistered(backend))
{
auto factoryFunc = backendRegistry.GetFactory(backend);
auto backendObject = factoryFunc();
return backendObject->GetNumberOfCacheFiles();
}
return 0;
}
bool LayerSupportHandle::IsBackendRegistered() const
{
if (m_LayerSupport)
{
return true;
}
return false;
}
using TensorInfos = std::vector<TensorInfo>;
bool LayerSupportHandle::IsActivationSupported(const TensorInfo& input,
const TensorInfo& output,
const ActivationDescriptor& descriptor,
Optional<std::string&> reasonIfUnsupported)
{
TensorInfos infos{input, output};
return m_LayerSupport->IsLayerSupported(LayerType::Activation,
infos,
descriptor,
EmptyOptional(),
EmptyOptional(),
reasonIfUnsupported);
}
bool LayerSupportHandle::IsAdditionSupported(const TensorInfo& input0,
const TensorInfo& input1,
const TensorInfo& output,
Optional<std::string&> reasonIfUnsupported)
{
TensorInfos infos{input0, input1, output};
return m_LayerSupport->IsLayerSupported(LayerType::Addition,
infos,
BaseDescriptor(),
EmptyOptional(),
EmptyOptional(),
reasonIfUnsupported);
}
bool LayerSupportHandle::IsArgMinMaxSupported(const TensorInfo& input,
const TensorInfo& output,
const ArgMinMaxDescriptor& descriptor,
Optional<std::string&> reasonIfUnsupported)
{
TensorInfos infos{input, output};
return m_LayerSupport->IsLayerSupported(LayerType::ArgMinMax,
infos,
descriptor,
EmptyOptional(),
EmptyOptional(),
reasonIfUnsupported);
}
bool LayerSupportHandle::IsBatchMatMulSupported(const TensorInfo& input0,
const TensorInfo& input1,
const TensorInfo& output,
const BatchMatMulDescriptor& descriptor,
Optional<std::string&> reasonIfUnsupported)
{
TensorInfos infos{input0, input1, output};
return m_LayerSupport->IsLayerSupported(LayerType::BatchMatMul,
infos,
descriptor,
EmptyOptional(),
EmptyOptional(),
reasonIfUnsupported);
}
bool LayerSupportHandle::IsBatchNormalizationSupported(const TensorInfo& input,
const TensorInfo& output,
const TensorInfo& mean,
const TensorInfo& var,
const TensorInfo& beta,
const TensorInfo& gamma,
const BatchNormalizationDescriptor& descriptor,
Optional<std::string&> reasonIfUnsupported)
{
TensorInfos infos{input, output, mean, var, beta, gamma};
return m_LayerSupport->IsLayerSupported(LayerType::BatchNormalization,
infos,
descriptor,
EmptyOptional(),
EmptyOptional(),
reasonIfUnsupported);
}
bool LayerSupportHandle::IsBatchToSpaceNdSupported(const TensorInfo& input,
const TensorInfo& output,
const BatchToSpaceNdDescriptor& descriptor,
Optional<std::string&> reasonIfUnsupported)
{
TensorInfos infos{input, output};
return m_LayerSupport->IsLayerSupported(LayerType::BatchToSpaceNd,
infos,
descriptor,
EmptyOptional(),
EmptyOptional(),
reasonIfUnsupported);
}
bool LayerSupportHandle::IsBroadcastToSupported(const TensorInfo& input,
const TensorInfo& output,
const armnn::BroadcastToDescriptor& descriptor,
Optional<std::string&> reasonIfUnsupported)
{
TensorInfos infos{input, output};
return m_LayerSupport->IsLayerSupported(LayerType::BroadcastTo,
infos,
descriptor,
EmptyOptional(),
EmptyOptional(),
reasonIfUnsupported.value());
}
bool LayerSupportHandle::IsCastSupported(const TensorInfo& input,
const TensorInfo& output,
Optional<std::string&> reasonIfUnsupported)
{
TensorInfos infos{input, output};
return m_LayerSupport->IsLayerSupported(LayerType::Cast,
infos,
BaseDescriptor(),
EmptyOptional(),
EmptyOptional(),
reasonIfUnsupported);
}
bool LayerSupportHandle::IsChannelShuffleSupported(const TensorInfo &input,
const TensorInfo &output,
const ChannelShuffleDescriptor &descriptor,
Optional<std::string &> reasonIfUnsupported)
{
TensorInfos infos{input, output};
return m_LayerSupport->IsLayerSupported(LayerType::ChannelShuffle,
infos,
descriptor,
EmptyOptional(),
EmptyOptional(),
reasonIfUnsupported);
}
bool LayerSupportHandle::IsComparisonSupported(const TensorInfo& input0,
const TensorInfo& input1,
const TensorInfo& output,
const ComparisonDescriptor& descriptor,
Optional<std::string&> reasonIfUnsupported)
{
TensorInfos infos{input0, input1, output};
return m_LayerSupport->IsLayerSupported(LayerType::Comparison,
infos,
descriptor,
EmptyOptional(),
EmptyOptional(),
reasonIfUnsupported);
}
bool LayerSupportHandle::IsConcatSupported(const std::vector<const TensorInfo*> inputs,
const TensorInfo& output,
const OriginsDescriptor& descriptor,
Optional<std::string&> reasonIfUnsupported)
{
TensorInfos infos;
for (const TensorInfo* inputInfo : inputs)
{
infos.push_back(*inputInfo);
}
infos.push_back(output);
return m_LayerSupport->IsLayerSupported(LayerType::Concat,
infos,
descriptor,
EmptyOptional(),
EmptyOptional(),
reasonIfUnsupported);
}
bool LayerSupportHandle::IsConstantSupported(const TensorInfo& output,
Optional<std::string&> reasonIfUnsupported)
{
TensorInfos infos{output};
return m_LayerSupport->IsLayerSupported(LayerType::Constant,
infos,
BaseDescriptor(),
EmptyOptional(),
EmptyOptional(),
reasonIfUnsupported);
}
bool LayerSupportHandle::IsConvertFp16ToFp32Supported(const TensorInfo& input,
const TensorInfo& output,
Optional<std::string&> reasonIfUnsupported)
{
TensorInfos infos{input, output};
return m_LayerSupport->IsLayerSupported(LayerType::ConvertFp16ToFp32,
infos,
BaseDescriptor(),
EmptyOptional(),
EmptyOptional(),
reasonIfUnsupported);
}
bool LayerSupportHandle::IsConvertFp32ToFp16Supported(const TensorInfo& input,
const TensorInfo& output,
Optional<std::string&> reasonIfUnsupported)
{
TensorInfos infos{input, output};
return m_LayerSupport->IsLayerSupported(LayerType::ConvertFp32ToFp16,
infos,
BaseDescriptor(),
EmptyOptional(),
EmptyOptional(),
reasonIfUnsupported);
}
bool LayerSupportHandle::IsConvolution2dSupported(const TensorInfo& input,
const TensorInfo& output,
const Convolution2dDescriptor& descriptor,
const TensorInfo& weights,
const Optional<TensorInfo>& biases,
Optional<std::string&> reasonIfUnsupported)
{
TensorInfo biasesVal = biases.has_value() ? biases.value() : TensorInfo();
TensorInfos infos{input, output, weights, biasesVal};
Optional<const BackendOptions::BackendOption> capability ;
if (!m_BackendId.IsUndefined())
{
capability = GetCapability("NonConstWeights", m_BackendId);
if (!capability.has_value() || capability.value().GetValue().AsBool() == false)
{
if (!weights.IsConstant())
{
if (reasonIfUnsupported.has_value())
{
reasonIfUnsupported.value() =
"Backend is not capable of supporting dynamic weights (NonConstWeights) and "
"Convolution2d weights are set as dynamic (non constant). ";
}
return false;
}
if (descriptor.m_BiasEnabled && !biasesVal.IsConstant())
{
if (reasonIfUnsupported.has_value())
{
reasonIfUnsupported.value() =
"Backend is not capable of supporting dynamic biases (NonConstWeights) and "
"Convolution2d biases are set as dynamic (non constant). ";
}
return false;
}
// At the first stage we will only print a warning. this is to give
// backend developers a chance to adopt and read weights from input slots.
ARMNN_LOG(warning) << "The backend makes use of a deprecated interface to read constant tensors. "
"If you are a backend developer please find more information in our "
"doxygen documentation on github https://github.com/ARM-software/armnn "
"under the keyword 'ConstTensorsAsInputs'.";
}
}
return m_LayerSupport->IsLayerSupported(LayerType::Convolution2d,
infos,
descriptor,
EmptyOptional(),
EmptyOptional(),
reasonIfUnsupported);
}
bool LayerSupportHandle::IsConvolution3dSupported(const TensorInfo& input,
const TensorInfo& output,
const Convolution3dDescriptor& descriptor,
const TensorInfo& weights,
const Optional<TensorInfo>& biases,
Optional<std::string&> reasonIfUnsupported)
{
TensorInfo biasesVal = biases.has_value() ? biases.value() : TensorInfo();
TensorInfos infos{input, output, weights, biasesVal};
return m_LayerSupport->IsLayerSupported(LayerType::Convolution3d,
infos,
descriptor,
EmptyOptional(),
EmptyOptional(),
reasonIfUnsupported);
}
bool LayerSupportHandle::IsDebugSupported(const TensorInfo& input,
const TensorInfo& output,
Optional<std::string&> reasonIfUnsupported)
{
TensorInfos infos{input, output};
return m_LayerSupport->IsLayerSupported(LayerType::Debug,
infos,
BaseDescriptor(),
EmptyOptional(),
EmptyOptional(),
reasonIfUnsupported);
}
bool LayerSupportHandle::IsDepthToSpaceSupported(const TensorInfo& input,
const TensorInfo& output,
const DepthToSpaceDescriptor& descriptor,
Optional<std::string&> reasonIfUnsupported)
{
TensorInfos infos{input, output};
return m_LayerSupport->IsLayerSupported(LayerType::DepthToSpace,
infos,
descriptor,
EmptyOptional(),
EmptyOptional(),
reasonIfUnsupported);
}
bool LayerSupportHandle::IsDepthwiseConvolutionSupported(
const TensorInfo& input,
const TensorInfo& output,
const DepthwiseConvolution2dDescriptor& descriptor,
const TensorInfo& weights,
const Optional<TensorInfo>& biases,
Optional<std::string&> reasonIfUnsupported)
{
TensorInfo biasesVal = biases.has_value() ? biases.value() : TensorInfo();
TensorInfos infos{input, output, weights, biasesVal};
Optional<const BackendOptions::BackendOption> capability ;
if (!m_BackendId.IsUndefined())
{
capability = GetCapability("NonConstWeights", m_BackendId);
if (!capability.has_value() || capability.value().GetValue().AsBool() == false)
{
if (!weights.IsConstant())
{
if (reasonIfUnsupported.has_value())
{
reasonIfUnsupported.value() =
"Backend is not capable of supporting dynamic weights (NonConstWeights) and "
"DepthwiseConvolution2d weights are set as dynamic (non constant). ";
}
return false;
}
if (descriptor.m_BiasEnabled && !biasesVal.IsConstant())
{
if (reasonIfUnsupported.has_value())
{
reasonIfUnsupported.value() =
"Backend is not capable of supporting dynamic biases (NonConstWeights) and "
"DepthwiseConvolution2d biases are set as dynamic (non constant). ";
}
return false;
}
// At the first stage we will only print a warning. this is to give
// backend developers a chance to adopt and read weights from input slots.
ARMNN_LOG(warning) << "The backend makes use of a deprecated interface to read constant tensors. "
"If you are a backend developer please find more information in our "
"doxygen documentation on github https://github.com/ARM-software/armnn "
"under the keyword 'ConstTensorsAsInputs'.";
}
}
return m_LayerSupport->IsLayerSupported(LayerType::DepthwiseConvolution2d,
infos,
descriptor,
EmptyOptional(),
EmptyOptional(),
reasonIfUnsupported);
}
bool LayerSupportHandle::IsDequantizeSupported(const TensorInfo& input,
const TensorInfo& output,
Optional<std::string&> reasonIfUnsupported)
{
TensorInfos infos{input, output};
return m_LayerSupport->IsLayerSupported(LayerType::Dequantize,
infos,
BaseDescriptor(),
EmptyOptional(),
EmptyOptional(),
reasonIfUnsupported);
}
bool LayerSupportHandle::IsDetectionPostProcessSupported(const TensorInfo& boxEncodings,
const TensorInfo& scores,
const TensorInfo& anchors,
const TensorInfo& detectionBoxes,
const TensorInfo& detectionClasses,
const TensorInfo& detectionScores,
const TensorInfo& numDetections,
const DetectionPostProcessDescriptor& descriptor,
Optional<std::string&> reasonIfUnsupported)
{
TensorInfos infos{boxEncodings, scores, anchors, detectionBoxes, detectionClasses, detectionScores, numDetections};
return m_LayerSupport->IsLayerSupported(LayerType::DetectionPostProcess,
infos,
descriptor,
EmptyOptional(),
EmptyOptional(),
reasonIfUnsupported);
}
bool LayerSupportHandle::IsDilatedDepthwiseConvolutionSupported(
const TensorInfo& input,
const TensorInfo& output,
const DepthwiseConvolution2dDescriptor& descriptor,
const TensorInfo& weights,
const Optional<TensorInfo>& biases,
Optional<std::string&> reasonIfUnsupported)
{
TensorInfo biasesVal = biases.has_value() ? biases.value() : TensorInfo();
TensorInfos infos{input, output, weights, biasesVal};
Optional<const BackendOptions::BackendOption> capability ;
if (!m_BackendId.IsUndefined())
{
capability = GetCapability("NonConstWeights", m_BackendId);
if (!capability.has_value() || capability.value().GetValue().AsBool() == false)
{
if (!weights.IsConstant())
{
if (reasonIfUnsupported.has_value())
{
reasonIfUnsupported.value() =
"Backend is not capable of supporting dynamic weights (NonConstWeights) and "
"DilatedDepthwiseConvolution2d weights are set as dynamic (non constant). ";
}
return false;
}
if (descriptor.m_BiasEnabled && !biasesVal.IsConstant())
{
if (reasonIfUnsupported.has_value())
{
reasonIfUnsupported.value() =
"Backend is not capable of supporting dynamic biases (NonConstWeights) and "
"DilatedDepthwiseConvolution2d biases are set as dynamic (non constant). ";
}
return false;
}
// At the first stage we will only print a warning. this is to give
// backend developers a chance to adopt and read weights from input slots.
ARMNN_LOG(warning) << "The backend makes use of a deprecated interface to read constant tensors. "
"If you are a backend developer please find more information in our "
"doxygen documentation on github https://github.com/ARM-software/armnn "
"under the keyword 'ConstTensorsAsInputs'.";
}
}
return m_LayerSupport->IsLayerSupported(LayerType::DepthwiseConvolution2d,
infos,
descriptor,
EmptyOptional(),
EmptyOptional(),
reasonIfUnsupported);
}
bool LayerSupportHandle::IsDivisionSupported(const TensorInfo& input0,
const TensorInfo& input1,
const TensorInfo& output,
Optional<std::string&> reasonIfUnsupported)
{
TensorInfos infos{input0, input1, output};
return m_LayerSupport->IsLayerSupported(LayerType::Division,
infos,
BaseDescriptor(),
EmptyOptional(),
EmptyOptional(),
reasonIfUnsupported);
}
bool LayerSupportHandle::IsElementwiseBinarySupported(const TensorInfo &input0,
const TensorInfo &input1,
const TensorInfo &output,
const ElementwiseBinaryDescriptor &descriptor,
Optional<std::string &> reasonIfUnsupported)
{
TensorInfos infos{input0, input1, output};
return m_LayerSupport->IsLayerSupported(LayerType::ElementwiseBinary,
infos,
descriptor,
EmptyOptional(),
EmptyOptional(),
reasonIfUnsupported);
}
bool LayerSupportHandle::IsElementwiseUnarySupported(const TensorInfo& input,
const TensorInfo& output,
const ElementwiseUnaryDescriptor& descriptor,
Optional<std::string&> reasonIfUnsupported)
{
TensorInfos infos{input, output};
return m_LayerSupport->IsLayerSupported(LayerType::ElementwiseUnary,
infos,
descriptor,
EmptyOptional(),
EmptyOptional(),
reasonIfUnsupported);
}
bool LayerSupportHandle::IsFakeQuantizationSupported(const TensorInfo& input,
const FakeQuantizationDescriptor& descriptor,
Optional<std::string&> reasonIfUnsupported)
{
TensorInfos infos{input};
return m_LayerSupport->IsLayerSupported(LayerType::FakeQuantization,
infos,
descriptor,
EmptyOptional(),
EmptyOptional(),
reasonIfUnsupported);
}
bool LayerSupportHandle::IsFillSupported(const TensorInfo& input,
const TensorInfo& output,
const FillDescriptor& descriptor,
Optional<std::string&> reasonIfUnsupported)
{
TensorInfos infos{input, output};
return m_LayerSupport->IsLayerSupported(LayerType::Fill,
infos,
descriptor,
EmptyOptional(),
EmptyOptional(),
reasonIfUnsupported);
}
bool LayerSupportHandle::IsFloorSupported(const TensorInfo& input,
const TensorInfo& output,
Optional<std::string&> reasonIfUnsupported)
{
TensorInfos infos{input, output};
return m_LayerSupport->IsLayerSupported(LayerType::Floor,
infos,
BaseDescriptor(),
EmptyOptional(),
EmptyOptional(),
reasonIfUnsupported);
}
bool LayerSupportHandle::IsFullyConnectedSupported(const TensorInfo& input,
const TensorInfo& output,
const TensorInfo& weights,
const TensorInfo& biases,
const FullyConnectedDescriptor& descriptor,
Optional<std::string&> reasonIfUnsupported)
{
TensorInfos infos{input, output, weights, biases};
Optional<const BackendOptions::BackendOption> capability;
if (!m_BackendId.IsUndefined())
{
capability = GetCapability("NonConstWeights", m_BackendId);
if (!capability.has_value() || capability.value().GetValue().AsBool() == false)
{
if (!descriptor.m_ConstantWeights)
{
if (reasonIfUnsupported.has_value())
{
reasonIfUnsupported.value() =
"Backend is not capable of supporting dynamic weights (NonConstWeights) and "
"FullyConnected descriptor indicates that weights are dynamic (non constant). ";
}
return false;
}
if (!weights.IsConstant())
{
if (reasonIfUnsupported.has_value())
{
reasonIfUnsupported.value() =
"Backend is not capable of supporting dynamic weights (NonConstWeights) and "
"FullyConnected weights are set as dynamic (non constant). ";
}
return false;
}
if (descriptor.m_BiasEnabled && !biases.IsConstant())
{
if (reasonIfUnsupported.has_value())
{
reasonIfUnsupported.value() =
"Backend is not capable of supporting dynamic biases (NonConstWeights) and "
"FullyConnected biases are set as dynamic (non constant). ";
}
return false;
}
// At the first stage we will only print a warning. this is to give
// backend developers a chance to adopt and read weights from input slots.
ARMNN_LOG(warning) << "The backend makes use of a deprecated interface to read constant tensors. "
"If you are a backend developer please find more information in our "
"doxygen documentation on github https://github.com/ARM-software/armnn "
"under the keyword 'ConstTensorsAsInputs'.";
}
}
return m_LayerSupport->IsLayerSupported(LayerType::FullyConnected,
infos,
descriptor,
EmptyOptional(),
EmptyOptional(),
reasonIfUnsupported);
}
bool LayerSupportHandle::IsFusedSupported(const std::vector<std::reference_wrapper<TensorInfo>>& inputs,
const std::vector<std::reference_wrapper<TensorInfo>>& outputs,
const FusedDescriptor& descriptor,
Optional<std::string&> reasonIfUnsupported)
{
TensorInfos infos;
infos.reserve(inputs.size() + outputs.size());
for (TensorInfo inInfo : inputs)
{
infos.emplace_back(inInfo);
}
for (TensorInfo outInfo : outputs)
{
infos.emplace_back(outInfo);
}
return m_LayerSupport->IsLayerSupported(LayerType::Fused,
infos,
descriptor,
EmptyOptional(),
EmptyOptional(),
reasonIfUnsupported);
}
bool LayerSupportHandle::IsGatherSupported(const TensorInfo& input0,
const TensorInfo& input1,
const TensorInfo& output,
const GatherDescriptor& descriptor,
Optional<std::string&> reasonIfUnsupported)
{
TensorInfos infos{input0, input1, output};
return m_LayerSupport->IsLayerSupported(LayerType::Gather,
infos,
descriptor,
EmptyOptional(),
EmptyOptional(),
reasonIfUnsupported);
}
bool LayerSupportHandle::IsGatherNdSupported(const TensorInfo& input0,
const TensorInfo& input1,
const TensorInfo& output,
Optional<std::string&> reasonIfUnsupported)
{
TensorInfos infos{input0, input1, output};
return m_LayerSupport->IsLayerSupported(LayerType::GatherNd,
infos,
BaseDescriptor(),
EmptyOptional(),
EmptyOptional(),
reasonIfUnsupported);
}
bool LayerSupportHandle::IsInputSupported(const TensorInfo& input,
Optional<std::string&> reasonIfUnsupported)
{
TensorInfos infos{input};
return m_LayerSupport->IsLayerSupported(LayerType::Input,
infos,
BaseDescriptor(),
EmptyOptional(),
EmptyOptional(),
reasonIfUnsupported);
}
bool LayerSupportHandle::IsInstanceNormalizationSupported(
const TensorInfo& input,
const TensorInfo& output,
const InstanceNormalizationDescriptor& descriptor,
Optional<std::string&> reasonIfUnsupported)
{
TensorInfos infos{input, output};
return m_LayerSupport->IsLayerSupported(LayerType::InstanceNormalization,
infos,
descriptor,
EmptyOptional(),
EmptyOptional(),
reasonIfUnsupported);
}
bool LayerSupportHandle::IsL2NormalizationSupported(const TensorInfo& input,
const TensorInfo& output,
const L2NormalizationDescriptor& descriptor,
Optional<std::string&> reasonIfUnsupported)
{
TensorInfos infos{input, output};
return m_LayerSupport->IsLayerSupported(LayerType::L2Normalization,
infos,
descriptor,
EmptyOptional(),
EmptyOptional(),
reasonIfUnsupported);
}
bool LayerSupportHandle::IsLogicalBinarySupported(const TensorInfo& input0,
const TensorInfo& input1,
const TensorInfo& output,
const LogicalBinaryDescriptor& descriptor,
Optional<std::string&> reasonIfUnsupported)
{
TensorInfos infos{input0, input1, output};
return m_LayerSupport->IsLayerSupported(LayerType::LogicalBinary,
infos,
descriptor,
EmptyOptional(),
EmptyOptional(),
reasonIfUnsupported);
}
bool LayerSupportHandle::IsLogicalUnarySupported(const TensorInfo& input,
const TensorInfo& output,
const ElementwiseUnaryDescriptor& descriptor,
Optional<std::string&> reasonIfUnsupported)
{
TensorInfos infos{input, output};
return m_LayerSupport->IsLayerSupported(LayerType::ElementwiseUnary,
infos,
descriptor,
EmptyOptional(),
EmptyOptional(),
reasonIfUnsupported);
}
bool LayerSupportHandle::IsLogSoftmaxSupported(const TensorInfo& input,
const TensorInfo& output,
const LogSoftmaxDescriptor& descriptor,
Optional<std::string&> reasonIfUnsupported)
{
TensorInfos infos{input, output};
return m_LayerSupport->IsLayerSupported(LayerType::LogSoftmax,
infos,
descriptor,
EmptyOptional(),
EmptyOptional(),
reasonIfUnsupported);
}
bool LayerSupportHandle::IsLstmSupported(const TensorInfo& input,
const TensorInfo& outputStateIn,
const TensorInfo& cellStateIn,
const TensorInfo& scratchBuffer,
const TensorInfo& outputStateOut,
const TensorInfo& cellStateOut,
const TensorInfo& output,
const LstmDescriptor& descriptor,
const LstmInputParamsInfo& paramsInfo,
Optional<std::string&> reasonIfUnsupported)
{
TensorInfos infos{input, outputStateIn, cellStateIn, scratchBuffer, outputStateOut, cellStateOut, output};
return m_LayerSupport->IsLayerSupported(LayerType::Lstm,
infos,
descriptor,
paramsInfo,
EmptyOptional(),
reasonIfUnsupported);
}
bool LayerSupportHandle::IsMaximumSupported(const TensorInfo& input0,
const TensorInfo& input1,
const TensorInfo& output,
Optional<std::string&> reasonIfUnsupported)
{
TensorInfos infos{input0, input1, output};
return m_LayerSupport->IsLayerSupported(LayerType::Maximum,
infos,
BaseDescriptor(),
EmptyOptional(),
EmptyOptional(),
reasonIfUnsupported);
}
bool LayerSupportHandle::IsMeanSupported(const TensorInfo& input,
const TensorInfo& output,
const MeanDescriptor& descriptor,
Optional<std::string&> reasonIfUnsupported)
{
TensorInfos infos{input, output};
return m_LayerSupport->IsLayerSupported(LayerType::Mean,
infos,
descriptor,
EmptyOptional(),
EmptyOptional(),
reasonIfUnsupported);
}
bool LayerSupportHandle::IsMemCopySupported(const TensorInfo& input,
const TensorInfo& output,
Optional<std::string&> reasonIfUnsupported)
{
TensorInfos infos{input, output};
return m_LayerSupport->IsLayerSupported(LayerType::MemCopy,
infos,
BaseDescriptor(),
EmptyOptional(),
EmptyOptional(),
reasonIfUnsupported);
}
bool LayerSupportHandle::IsMemImportSupported(const TensorInfo& input,
const TensorInfo& output,
Optional<std::string&> reasonIfUnsupported)
{
TensorInfos infos{input, output};
return m_LayerSupport->IsLayerSupported(LayerType::MemImport,
infos,
BaseDescriptor(),
EmptyOptional(),
EmptyOptional(),
reasonIfUnsupported);
}
bool LayerSupportHandle::IsMergeSupported(const TensorInfo& input0,
const TensorInfo& input1,
const TensorInfo& output,
Optional<std::string&> reasonIfUnsupported)
{
TensorInfos infos{input0, input1, output};
return m_LayerSupport->IsLayerSupported(LayerType::Merge,
infos,
BaseDescriptor(),
EmptyOptional(),
EmptyOptional(),
reasonIfUnsupported);
}
bool LayerSupportHandle::IsMinimumSupported(const TensorInfo& input0,
const TensorInfo& input1,
const TensorInfo& output,
Optional<std::string&> reasonIfUnsupported)
{
TensorInfos infos{input0, input1, output};
return m_LayerSupport->IsLayerSupported(LayerType::Minimum,
infos,
BaseDescriptor(),
EmptyOptional(),
EmptyOptional(),
reasonIfUnsupported);
}
bool LayerSupportHandle::IsMultiplicationSupported(const TensorInfo& input0,
const TensorInfo& input1,
const TensorInfo& output,
Optional<std::string&> reasonIfUnsupported)
{
TensorInfos infos{input0, input1, output};
return m_LayerSupport->IsLayerSupported(LayerType::Multiplication,
infos,
BaseDescriptor(),
EmptyOptional(),
EmptyOptional(),
reasonIfUnsupported);
}
bool LayerSupportHandle::IsNormalizationSupported(const TensorInfo& input,
const TensorInfo& output,
const NormalizationDescriptor& descriptor,
Optional<std::string&> reasonIfUnsupported)
{
TensorInfos infos{input, output};
return m_LayerSupport->IsLayerSupported(LayerType::Normalization,
infos,
descriptor,
EmptyOptional(),
EmptyOptional(),
reasonIfUnsupported);
}
bool LayerSupportHandle::IsOutputSupported(const TensorInfo& output,
Optional<std::string&> reasonIfUnsupported)
{
TensorInfos infos{output};
return m_LayerSupport->IsLayerSupported(LayerType::Output,
infos,
BaseDescriptor(),
EmptyOptional(),
EmptyOptional(),
reasonIfUnsupported);
}
bool LayerSupportHandle::IsPadSupported(const TensorInfo& input,
const TensorInfo& output,
const PadDescriptor& descriptor,
Optional<std::string&> reasonIfUnsupported)
{
TensorInfos infos{input, output};
return m_LayerSupport->IsLayerSupported(LayerType::Pad,
infos,
descriptor,
EmptyOptional(),
EmptyOptional(),
reasonIfUnsupported);
}
bool LayerSupportHandle::IsPermuteSupported(const TensorInfo& input,
const TensorInfo& output,
const PermuteDescriptor& descriptor,
Optional<std::string&> reasonIfUnsupported)
{
TensorInfos infos{input, output};
return m_LayerSupport->IsLayerSupported(LayerType::Permute,
infos,
descriptor,
EmptyOptional(),
EmptyOptional(),
reasonIfUnsupported);
}
bool LayerSupportHandle::IsPooling2dSupported(const TensorInfo& input,
const TensorInfo& output,
const Pooling2dDescriptor& descriptor,
Optional<std::string&> reasonIfUnsupported)
{
TensorInfos infos{input, output};
return m_LayerSupport->IsLayerSupported(LayerType::Pooling2d,
infos,
descriptor,
EmptyOptional(),
EmptyOptional(),
reasonIfUnsupported);
}
bool LayerSupportHandle::IsPooling3dSupported(const TensorInfo& input,
const TensorInfo& output,
const Pooling3dDescriptor& descriptor,
Optional<std::string&> reasonIfUnsupported)
{
TensorInfos infos{input, output};
return m_LayerSupport->IsLayerSupported(LayerType::Pooling3d,
infos,
descriptor,
EmptyOptional(),
EmptyOptional(),
reasonIfUnsupported);
}
bool LayerSupportHandle::IsPreCompiledSupported(const TensorInfo& input,
const PreCompiledDescriptor& descriptor,
Optional<std::string&> reasonIfUnsupported)
{
TensorInfos infos{input};
return m_LayerSupport->IsLayerSupported(LayerType::PreCompiled,
infos,
descriptor,
EmptyOptional(),
EmptyOptional(),
reasonIfUnsupported);
}
bool LayerSupportHandle::IsPreluSupported(const TensorInfo& input,
const TensorInfo& alpha,
const TensorInfo& output,
Optional<std::string&> reasonIfUnsupported)
{
TensorInfos infos{input, alpha, output};
return m_LayerSupport->IsLayerSupported(LayerType::Prelu,
infos,
BaseDescriptor(),
EmptyOptional(),
EmptyOptional(),
reasonIfUnsupported);
}
bool LayerSupportHandle::IsQuantizeSupported(const TensorInfo& input,
const TensorInfo& output,
Optional<std::string&> reasonIfUnsupported)
{
TensorInfos infos{input, output};
return m_LayerSupport->IsLayerSupported(LayerType::Quantize,
infos,
BaseDescriptor(),
EmptyOptional(),
EmptyOptional(),
reasonIfUnsupported);
}
bool LayerSupportHandle::IsQLstmSupported(const TensorInfo& input,
const TensorInfo& previousOutputIn,
const TensorInfo& previousCellStateIn,
const TensorInfo& outputStateOut,
const TensorInfo& cellStateOut,
const TensorInfo& output,
const QLstmDescriptor& descriptor,
const LstmInputParamsInfo& paramsInfo,
Optional<std::string&> reasonIfUnsupported)
{
TensorInfos infos{input, previousOutputIn, previousCellStateIn, outputStateOut, cellStateOut, output};
return m_LayerSupport->IsLayerSupported(LayerType::QLstm,
infos,
descriptor,
paramsInfo,
EmptyOptional(),
reasonIfUnsupported);
}
bool LayerSupportHandle::IsQuantizedLstmSupported(const TensorInfo& input,
const TensorInfo& previousCellStateIn,
const TensorInfo& previousOutputIn,
const TensorInfo& cellStateOut,
const TensorInfo& output,
const QuantizedLstmInputParamsInfo& paramsInfo,
Optional<std::string&> reasonIfUnsupported)
{
TensorInfos infos{input, previousCellStateIn, previousOutputIn, cellStateOut, output};
return m_LayerSupport->IsLayerSupported(LayerType::QuantizedLstm,
infos,
BaseDescriptor(),
EmptyOptional(),
paramsInfo,
reasonIfUnsupported);
}
bool LayerSupportHandle::IsRankSupported(const TensorInfo& input,
const TensorInfo& output,
Optional<std::string&> reasonIfUnsupported)
{
TensorInfos infos{input, output};
return m_LayerSupport->IsLayerSupported(LayerType::Rank,
infos,
BaseDescriptor(),
EmptyOptional(),
EmptyOptional(),
reasonIfUnsupported);
}
bool LayerSupportHandle::IsReduceSupported(const TensorInfo& input,
const TensorInfo& output,
const ReduceDescriptor& descriptor,
Optional<std::string&> reasonIfUnsupported)
{
TensorInfos infos{input, output};
return m_LayerSupport->IsLayerSupported(LayerType::Reduce,
infos,
descriptor,
EmptyOptional(),
EmptyOptional(),
reasonIfUnsupported);
}
bool LayerSupportHandle::IsReshapeSupported(const TensorInfo& input,
const TensorInfo& output,
const ReshapeDescriptor& descriptor,
Optional<std::string&> reasonIfUnsupported)
{
TensorInfos infos{input, output};
return m_LayerSupport->IsLayerSupported(LayerType::Reshape,
infos,
descriptor,
EmptyOptional(),
EmptyOptional(),
reasonIfUnsupported);
}
bool LayerSupportHandle::IsResizeSupported(const TensorInfo& input,
const TensorInfo& output,
const ResizeDescriptor& descriptor,
Optional<std::string&> reasonIfUnsupported)
{
TensorInfos infos{input, output};
return m_LayerSupport->IsLayerSupported(LayerType::Resize,
infos,
descriptor,
EmptyOptional(),
EmptyOptional(),
reasonIfUnsupported);
}
bool LayerSupportHandle::IsReverseV2Supported(const armnn::TensorInfo &input0,
const armnn::TensorInfo &input1,
const armnn::TensorInfo &output,
Optional<std::string &> reasonIfUnsupported)
{
TensorInfos infos{input0, input1, output};
return m_LayerSupport->IsLayerSupported(LayerType::ReverseV2,
infos,
BaseDescriptor(),
EmptyOptional(),
EmptyOptional(),
reasonIfUnsupported);
}
bool LayerSupportHandle::IsScatterNdSupported(const TensorInfo& input,
const TensorInfo& indices,
const TensorInfo& updates,
const TensorInfo& output,
const armnn::ScatterNdDescriptor &descriptor,
Optional<std::string&> reasonIfUnsupported)
{
TensorInfos infos{input, indices, updates, output};
return m_LayerSupport->IsLayerSupported(LayerType::ScatterNd,
infos,
descriptor,
EmptyOptional(),
EmptyOptional(),
reasonIfUnsupported);
}
bool LayerSupportHandle::IsShapeSupported(const TensorInfo& input,
const TensorInfo& output,
Optional<std::string&> reasonIfUnsupported)
{
TensorInfos infos{input, output};
return m_LayerSupport->IsLayerSupported(LayerType::Shape,
infos,
BaseDescriptor(),
EmptyOptional(),
EmptyOptional(),
reasonIfUnsupported);
}
bool LayerSupportHandle::IsSliceSupported(const TensorInfo& input,
const TensorInfo& output,
const SliceDescriptor& descriptor,
Optional<std::string&> reasonIfUnsupported)
{
TensorInfos infos{input, output};
return m_LayerSupport->IsLayerSupported(LayerType::Slice,
infos,
descriptor,
EmptyOptional(),
EmptyOptional(),
reasonIfUnsupported);
}
bool LayerSupportHandle::IsSoftmaxSupported(const TensorInfo& input,
const TensorInfo& output,
const SoftmaxDescriptor& descriptor,
Optional<std::string&> reasonIfUnsupported)
{
TensorInfos infos{input, output};
return m_LayerSupport->IsLayerSupported(LayerType::Softmax,
infos,
descriptor,
EmptyOptional(),
EmptyOptional(),
reasonIfUnsupported);
}
bool LayerSupportHandle::IsSpaceToBatchNdSupported(const TensorInfo& input,
const TensorInfo& output,
const SpaceToBatchNdDescriptor& descriptor,
Optional<std::string&> reasonIfUnsupported)
{
TensorInfos infos{input, output};
return m_LayerSupport->IsLayerSupported(LayerType::SpaceToBatchNd,
infos,
descriptor,
EmptyOptional(),
EmptyOptional(),
reasonIfUnsupported);
}
bool LayerSupportHandle::IsSpaceToDepthSupported(const TensorInfo& input,
const TensorInfo& output,
const SpaceToDepthDescriptor& descriptor,
Optional<std::string&> reasonIfUnsupported)
{
TensorInfos infos{input, output};
return m_LayerSupport->IsLayerSupported(LayerType::SpaceToDepth,
infos,
descriptor,
EmptyOptional(),
EmptyOptional(),
reasonIfUnsupported);
}
bool LayerSupportHandle::IsSplitterSupported(const TensorInfo& input,
const std::vector<std::reference_wrapper<TensorInfo>>& outputs,
const ViewsDescriptor& descriptor,
Optional<std::string&> reasonIfUnsupported)
{
TensorInfos infos{input};
for (TensorInfo outInfo : outputs)
{
infos.push_back(outInfo);
}
return m_LayerSupport->IsLayerSupported(LayerType::Splitter,
infos,
descriptor,
EmptyOptional(),
EmptyOptional(),
reasonIfUnsupported);
}
bool LayerSupportHandle::IsStackSupported(const std::vector<const TensorInfo*>& inputs,
const TensorInfo& output,
const StackDescriptor& descriptor,
Optional<std::string&> reasonIfUnsupported)
{
TensorInfos infos;
for (const TensorInfo* inputInfo : inputs)
{
infos.push_back(*inputInfo);
}
infos.push_back(output);
return m_LayerSupport->IsLayerSupported(LayerType::Stack,
infos,
descriptor,
EmptyOptional(),
EmptyOptional(),
reasonIfUnsupported);
}
bool LayerSupportHandle::IsStandInSupported(const std::vector<const TensorInfo*>& inputs,
const std::vector<const TensorInfo*>& outputs,
const StandInDescriptor& descriptor,
Optional<std::string&> reasonIfUnsupported)
{
TensorInfos infos;
for (const TensorInfo* inputInfo : inputs)
{
infos.push_back(*inputInfo);
}
for (const TensorInfo* outputInfo : outputs)
{
infos.push_back(*outputInfo);
}
return m_LayerSupport->IsLayerSupported(LayerType::StandIn,
infos,
descriptor,
EmptyOptional(),
EmptyOptional(),
reasonIfUnsupported);
}
bool LayerSupportHandle::IsStridedSliceSupported(const TensorInfo& input,
const TensorInfo& output,
const StridedSliceDescriptor& descriptor,
Optional<std::string&> reasonIfUnsupported)
{
TensorInfos infos{input, output};
return m_LayerSupport->IsLayerSupported(LayerType::StridedSlice,
infos,
descriptor,
EmptyOptional(),
EmptyOptional(),
reasonIfUnsupported);
}
bool LayerSupportHandle::IsSubtractionSupported(const TensorInfo& input0,
const TensorInfo& input1,
const TensorInfo& output,
Optional<std::string&> reasonIfUnsupported)
{
TensorInfos infos{input0, input1, output};
return m_LayerSupport->IsLayerSupported(LayerType::Subtraction,
infos,
BaseDescriptor(),
EmptyOptional(),
EmptyOptional(),
reasonIfUnsupported);
}
bool LayerSupportHandle::IsSwitchSupported(const TensorInfo& input0,
const TensorInfo& input1,
const TensorInfo& output0,
const TensorInfo& output1,
Optional<std::string&> reasonIfUnsupported)
{
TensorInfos infos{input0, input1, output0, output1};
return m_LayerSupport->IsLayerSupported(LayerType::Switch,
infos,
BaseDescriptor(),
EmptyOptional(),
EmptyOptional(),
reasonIfUnsupported);
}
bool LayerSupportHandle::IsTileSupported(const TensorInfo& input,
const TensorInfo& output,
const armnn::TileDescriptor &descriptor,
Optional<std::string&> reasonIfUnsupported)
{
TensorInfos infos{input, output};
return m_LayerSupport->IsLayerSupported(LayerType::Tile,
infos,
descriptor,
EmptyOptional(),
EmptyOptional(),
reasonIfUnsupported);
}
bool LayerSupportHandle::IsTransposeConvolution2dSupported(
const TensorInfo& input,
const TensorInfo& output,
const TransposeConvolution2dDescriptor& descriptor,
const TensorInfo& weights,
const Optional<TensorInfo>& biases,
Optional<std::string&> reasonIfUnsupported)
{
TensorInfo biasesVal = biases.has_value() ? biases.value() : TensorInfo();
TensorInfos infos{input, output, weights, biasesVal};
return m_LayerSupport->IsLayerSupported(LayerType::TransposeConvolution2d,
infos,
descriptor,
EmptyOptional(),
EmptyOptional(),
reasonIfUnsupported);
}
bool LayerSupportHandle::IsTransposeSupported(const TensorInfo& input,
const TensorInfo& output,
const TransposeDescriptor& descriptor,
Optional<std::string&> reasonIfUnsupported)
{
TensorInfos infos{input, output};
return m_LayerSupport->IsLayerSupported(LayerType::Transpose,
infos,
descriptor,
EmptyOptional(),
EmptyOptional(),
reasonIfUnsupported);
}
bool LayerSupportHandle::IsUnidirectionalSequenceLstmSupported(const TensorInfo& input,
const TensorInfo& outputStateIn,
const TensorInfo& cellStateIn,
const TensorInfo& outputStateOut,
const TensorInfo& cellStateOut,
const TensorInfo& output,
const LstmDescriptor& descriptor,
const LstmInputParamsInfo& paramsInfo,
Optional<std::string&> reasonIfUnsupported)
{
TensorInfos infos{input, outputStateIn, cellStateIn, outputStateOut, cellStateOut, output};
return m_LayerSupport->IsLayerSupported(LayerType::UnidirectionalSequenceLstm,
infos,
descriptor,
paramsInfo,
EmptyOptional(),
reasonIfUnsupported);
}
}