diff options
-rw-r--r-- | ArmnnPreparedModel_1_3.cpp | 10 | ||||
-rw-r--r-- | ConversionUtils.hpp | 648 | ||||
-rw-r--r-- | ConversionUtils_1_2.hpp | 611 | ||||
-rw-r--r-- | ConversionUtils_1_3.hpp | 5 | ||||
-rw-r--r-- | Utils.cpp | 5 |
5 files changed, 806 insertions, 473 deletions
diff --git a/ArmnnPreparedModel_1_3.cpp b/ArmnnPreparedModel_1_3.cpp index a27c7a39..386cc174 100644 --- a/ArmnnPreparedModel_1_3.cpp +++ b/ArmnnPreparedModel_1_3.cpp @@ -451,6 +451,8 @@ Return<V1_3::ErrorStatus> ArmnnPreparedModel_1_3<HalVersion>::PrepareMemoryForOu return V1_3::ErrorStatus::GENERAL_FAILURE; } + const size_t outputSize = outputTensorInfo.GetNumBytes(); + unsigned int count = 0; std::for_each(outputArg.dimensions.begin(), outputArg.dimensions.end(), [&](auto dim) { @@ -466,14 +468,13 @@ Return<V1_3::ErrorStatus> ArmnnPreparedModel_1_3<HalVersion>::PrepareMemoryForOu count++; }); - const size_t outputSize = outputTensorInfo.GetNumBytes(); - outputs.emplace_back(i, outputTensor); outputShapes[i] = ComputeShape(outputTensorInfo); if (outputArg.location.length < outputSize) { - ALOGW("ArmnnPreparedModel_1_3::Execute failed"); + ALOGW("ArmnnPreparedModel_1_3::Execute failed outputArg.location.length (%s) < outputSize (%s)", + std::to_string(outputArg.location.length).c_str(), std::to_string(outputSize).c_str()); outputShapes[i].isSufficient = false; return V1_3::ErrorStatus::OUTPUT_INSUFFICIENT_SIZE; } @@ -481,7 +482,8 @@ Return<V1_3::ErrorStatus> ArmnnPreparedModel_1_3<HalVersion>::PrepareMemoryForOu const size_t bufferSize = memPools.at(outputArg.location.poolIndex).getHidlMemory().size(); if (bufferSize < outputSize) { - ALOGW("ArmnnPreparedModel_1_3::Execute failed"); + ALOGW("ArmnnPreparedModel_1_3::Execute failed bufferSize (%s) < outputSize (%s)", + std::to_string(bufferSize).c_str(), std::to_string(outputSize).c_str()); outputShapes[i].isSufficient = false; return V1_3::ErrorStatus::OUTPUT_INSUFFICIENT_SIZE; } diff --git a/ConversionUtils.hpp b/ConversionUtils.hpp index 474d1a58..f2f95ac8 100644 --- a/ConversionUtils.hpp +++ b/ConversionUtils.hpp @@ -1,5 +1,5 @@ // -// Copyright © 2017 Arm Ltd. All rights reserved. +// Copyright © 2017 Arm Ltd and Contributors. All rights reserved. // SPDX-License-Identifier: MIT // @@ -1395,12 +1395,30 @@ bool SetupAndTrackLayerOutputSlot(const HalOperation& operation, armnn::IOutputSlot& outputSlot = layer.GetOutputSlot(layerOutputIndex); + if (overrideOutputInfo == nullptr) + { + outputSlot.SetTensorInfo(GetTensorInfoForOperand(*outputOperand)); + } + else + { + outputSlot.SetTensorInfo(*overrideOutputInfo); + } + + // Type one dynamic tensors require the previous layer's output shape for inference + if (!layer.GetInputSlot(0).GetConnection() && + IsDynamicTensor(outputSlot.GetTensorInfo())) + { + return false; + } + bool isSupported = false; if (validateFunc && layer.GetInputSlot(0).GetConnection() && IsDynamicTensor(outputSlot.GetTensorInfo())) { + // IsTensorInfoSet will infer the dynamic output shape outputSlot.IsTensorInfoSet(); + // Once the shape is inferred we can validate it validateFunc(outputSlot.GetTensorInfo(), isSupported); if(!isSupported) @@ -1413,17 +1431,6 @@ bool SetupAndTrackLayerOutputSlot(const HalOperation& operation, return false; } } - else - { - if (overrideOutputInfo == nullptr) - { - outputSlot.SetTensorInfo(GetTensorInfoForOperand(*outputOperand)); - } - else - { - outputSlot.SetTensorInfo(*overrideOutputInfo); - } - } const uint32_t operandIndex = operation.outputs[operationOutputIndex]; data.m_OutputSlotForOperand[operandIndex] = &outputSlot; @@ -1810,19 +1817,28 @@ bool ConvertAdd(const HalOperation& operation, const HalModel& model, Conversion const armnn::TensorInfo& inputInfo1 = input1.GetTensorInfo(); const armnn::TensorInfo& outputInfo = GetTensorInfoForOperand(*outputOperand); - if (IsDynamicTensor(outputInfo)) + + bool isSupported = false; + auto validateFunc = [&](const armnn::TensorInfo& outputInfo, bool& isSupported) { - return Fail("%s: Dynamic output tensors are not supported", __func__); + FORWARD_LAYER_SUPPORT_FUNC(__func__, + IsAdditionSupported, + data.m_Backends, + isSupported, + inputInfo0, + inputInfo1, + outputInfo); + }; + + if(!IsDynamicTensor(outputInfo)) + { + validateFunc(outputInfo, isSupported); + } + else + { + isSupported = AreDynamicTensorsSupported(); } - bool isSupported = false; - FORWARD_LAYER_SUPPORT_FUNC(__func__, - IsAdditionSupported, - data.m_Backends, - isSupported, - inputInfo0, - inputInfo1, - outputInfo); if (!isSupported) { return false; @@ -1839,7 +1855,7 @@ bool ConvertAdd(const HalOperation& operation, const HalModel& model, Conversion return false; } - return SetupAndTrackLayerOutputSlot<HalPolicy>(operation, 0, *endLayer, model, data); + return SetupAndTrackLayerOutputSlot<HalPolicy>(operation, 0, *endLayer, model, data, nullptr, validateFunc); } else { @@ -1962,7 +1978,6 @@ bool ConvertConcatenation(const HalOperation& operation, const HalModel& model, return Fail("%s: Operation has no outputs", __func__); } - armnn::TensorInfo outputInfo = GetTensorInfoForOperand(*outputOperand); armnn::TensorShape outputShape = outputInfo.GetShape(); @@ -2247,11 +2262,6 @@ bool ConvertConv2d(const HalOperation& operation, const HalModel& model, Convers const armnn::TensorInfo& inputInfo = input.GetTensorInfo(); const armnn::TensorInfo& outputInfo = GetTensorInfoForOperand(*output); - if (IsDynamicTensor(outputInfo)) - { - return Fail("%s: Dynamic output tensors are not supported", __func__); - } - // ArmNN does not currently support non-fixed weights or bias const ConstTensorPin weightsPin = ConvertOperationInputToConstTensorPin<HalPolicy>(operation, 1, model, data); const ConstTensorPin biasPin = ConvertOperationInputToConstTensorPin<HalPolicy>(operation, 2, model, data); @@ -2310,15 +2320,28 @@ bool ConvertConv2d(const HalOperation& operation, const HalModel& model, Convers armnn::Optional<armnn::TensorInfo> biases(bias.GetInfo()); bool isSupported = false; - FORWARD_LAYER_SUPPORT_FUNC(__func__, - IsConvolution2dSupported, - data.m_Backends, - isSupported, - inputInfo, - outputInfo, - desc, - weights.GetInfo(), - biases); + auto validateFunc = [&](const armnn::TensorInfo& outputInfo, bool& isSupported) + { + FORWARD_LAYER_SUPPORT_FUNC(__func__, + IsConvolution2dSupported, + data.m_Backends, + isSupported, + inputInfo, + outputInfo, + desc, + weights.GetInfo(), + biases); + }; + + if(!IsDynamicTensor(outputInfo)) + { + validateFunc(outputInfo, isSupported); + } + else + { + isSupported = AreDynamicTensorsSupported(); + } + if (!isSupported) { return false; @@ -2341,7 +2364,7 @@ bool ConvertConv2d(const HalOperation& operation, const HalModel& model, Convers input.Connect(startLayer->GetInputSlot(0)); - return SetupAndTrackLayerOutputSlot<HalPolicy>(operation, 0, *endLayer, model, data); + return SetupAndTrackLayerOutputSlot<HalPolicy>(operation, 0, *endLayer, model, data, nullptr, validateFunc); } template<typename HalPolicy, @@ -2372,10 +2395,6 @@ bool ConvertDepthToSpace(const HalOperation& operation, const HalModel& model, C } const armnn::TensorInfo& outputInfo = GetTensorInfoForOperand(*output); - if (IsDynamicTensor(outputInfo)) - { - return Fail("%s: Dynamic output tensors are not supported", __func__); - } armnn::DepthToSpaceDescriptor descriptor; @@ -2392,13 +2411,26 @@ bool ConvertDepthToSpace(const HalOperation& operation, const HalModel& model, C } bool isSupported = false; - FORWARD_LAYER_SUPPORT_FUNC(__func__, - IsDepthToSpaceSupported, - data.m_Backends, - isSupported, - inputInfo, - outputInfo, - descriptor); + auto validateFunc = [&](const armnn::TensorInfo& outputInfo, bool& isSupported) + { + FORWARD_LAYER_SUPPORT_FUNC(__func__, + IsDepthToSpaceSupported, + data.m_Backends, + isSupported, + inputInfo, + outputInfo, + descriptor); + }; + + if(!IsDynamicTensor(outputInfo)) + { + validateFunc(outputInfo, isSupported); + } + else + { + isSupported = AreDynamicTensorsSupported(); + } + if (!isSupported) { return false; @@ -2408,7 +2440,7 @@ bool ConvertDepthToSpace(const HalOperation& operation, const HalModel& model, C assert(layer != nullptr); input.Connect(layer->GetInputSlot(0)); - return SetupAndTrackLayerOutputSlot<HalPolicy>(operation, 0, *layer, model, data); + return SetupAndTrackLayerOutputSlot<HalPolicy>(operation, 0, *layer, model, data, nullptr, validateFunc); } template<typename HalPolicy, @@ -2436,11 +2468,6 @@ bool ConvertDepthwiseConv2d(const HalOperation& operation, const HalModel& model const armnn::TensorInfo& inputInfo = input.GetTensorInfo(); const armnn::TensorInfo& outputInfo = GetTensorInfoForOperand(*output); - if (IsDynamicTensor(outputInfo)) - { - return Fail("%s: Dynamic output tensors are not supported", __func__); - } - // ArmNN does not currently support non-fixed weights or bias // Find the shape of the weights tensor. In AndroidNN this will be [ 1, H, W, I * M ] const HalOperand* weightsOperand = GetInputOperand<HalPolicy>(operation, 1, model); @@ -2524,15 +2551,29 @@ bool ConvertDepthwiseConv2d(const HalOperation& operation, const HalModel& model armnn::Optional<armnn::TensorInfo> biases(bias.GetInfo()); bool isSupported = false; - FORWARD_LAYER_SUPPORT_FUNC(__func__, - IsDepthwiseConvolutionSupported, - data.m_Backends, - isSupported, - inputInfo, - outputInfo, - desc, - weights.GetInfo(), - biases); + auto validateFunc = [&](const armnn::TensorInfo& outputInfo, bool& isSupported) + { + FORWARD_LAYER_SUPPORT_FUNC(__func__, + IsDepthwiseConvolutionSupported, + data.m_Backends, + isSupported, + inputInfo, + outputInfo, + desc, + weights.GetInfo(), + biases); + }; + + if(!IsDynamicTensor(outputInfo)) + { + validateFunc(outputInfo, isSupported); + } + else + { + isSupported = AreDynamicTensorsSupported(); + } + + if (!isSupported) { return false; @@ -2553,7 +2594,7 @@ bool ConvertDepthwiseConv2d(const HalOperation& operation, const HalModel& model input.Connect(startLayer->GetInputSlot(0)); - return SetupAndTrackLayerOutputSlot<HalPolicy>(operation, 0, *endLayer, model, data); + return SetupAndTrackLayerOutputSlot<HalPolicy>(operation, 0, *endLayer, model, data, nullptr, validateFunc); } template<typename HalPolicy, @@ -2583,18 +2624,27 @@ bool ConvertDequantize(const HalOperation& operation, const HalModel& model, Con } const armnn::TensorInfo& outputInfo = GetTensorInfoForOperand(*outputOperand); - if (IsDynamicTensor(outputInfo)) + + bool isSupported = false; + auto validateFunc = [&](const armnn::TensorInfo& outputInfo, bool& isSupported) { - return Fail("%s: Dynamic output tensors are not supported", __func__); + FORWARD_LAYER_SUPPORT_FUNC(__func__, + IsDequantizeSupported, + data.m_Backends, + isSupported, + inputInfo, + outputInfo); + }; + + if(IsDynamicTensor(outputInfo)) + { + isSupported = AreDynamicTensorsSupported(); + } + else + { + validateFunc(outputInfo, isSupported); } - bool isSupported = false; - FORWARD_LAYER_SUPPORT_FUNC(__func__, - IsDequantizeSupported, - data.m_Backends, - isSupported, - inputInfo, - outputInfo); if (!isSupported) { return false; @@ -2604,7 +2654,7 @@ bool ConvertDequantize(const HalOperation& operation, const HalModel& model, Con assert(layer != nullptr); input.Connect(layer->GetInputSlot(0)); - return SetupAndTrackLayerOutputSlot<HalPolicy>(operation, 0, *layer, model, data); + return SetupAndTrackLayerOutputSlot<HalPolicy>(operation, 0, *layer, model, data, nullptr, validateFunc); } template<typename HalPolicy, @@ -2637,19 +2687,28 @@ bool ConvertDiv(const HalOperation& operation, const HalModel& model, Conversion } const armnn::TensorInfo& outputInfo = GetTensorInfoForOperand(*output); - if (IsDynamicTensor(outputInfo)) + + bool isSupported = false; + auto validateFunc = [&](const armnn::TensorInfo& outputInfo, bool& isSupported) { - return Fail("%s: Dynamic output tensors are not supported", __func__); + FORWARD_LAYER_SUPPORT_FUNC(__func__, + IsDivisionSupported, + data.m_Backends, + isSupported, + input0.GetTensorInfo(), + input1.GetTensorInfo(), + outputInfo); + }; + + if(!IsDynamicTensor(outputInfo)) + { + validateFunc(outputInfo, isSupported); + } + else + { + isSupported = AreDynamicTensorsSupported(); } - bool isSupported = false; - FORWARD_LAYER_SUPPORT_FUNC(__func__, - IsDivisionSupported, - data.m_Backends, - isSupported, - input0.GetTensorInfo(), - input1.GetTensorInfo(), - outputInfo); if (!isSupported) { return false; @@ -2666,7 +2725,7 @@ bool ConvertDiv(const HalOperation& operation, const HalModel& model, Conversion return false; } - return SetupAndTrackLayerOutputSlot<HalPolicy>(operation, 0, *endLayer, model, data); + return SetupAndTrackLayerOutputSlot<HalPolicy>(operation, 0, *endLayer, model, data, nullptr, validateFunc); } return Fail("%s: ProcessActivation failed", __func__); } @@ -2691,18 +2750,27 @@ bool ConvertFloor(const HalOperation& operation, const HalModel& model, Conversi } const armnn::TensorInfo& outputInfo = GetTensorInfoForOperand(*outputOperand); - if (IsDynamicTensor(outputInfo)) + + bool isSupported = false; + auto validateFunc = [&](const armnn::TensorInfo& outputInfo, bool& isSupported) { - return Fail("%s: Dynamic output tensors are not supported", __func__); + FORWARD_LAYER_SUPPORT_FUNC(__func__, + IsFloorSupported, + data.m_Backends, + isSupported, + input.GetTensorInfo(), + outputInfo); + }; + + if(!IsDynamicTensor(outputInfo)) + { + validateFunc(outputInfo, isSupported); + } + else + { + isSupported = AreDynamicTensorsSupported(); } - bool isSupported = false; - FORWARD_LAYER_SUPPORT_FUNC(__func__, - IsFloorSupported, - data.m_Backends, - isSupported, - input.GetTensorInfo(), - outputInfo); if (!isSupported) { return false; @@ -2712,7 +2780,7 @@ bool ConvertFloor(const HalOperation& operation, const HalModel& model, Conversi assert(layer != nullptr); input.Connect(layer->GetInputSlot(0)); - return SetupAndTrackLayerOutputSlot<HalPolicy>(operation, 0, *layer, model, data); + return SetupAndTrackLayerOutputSlot<HalPolicy>(operation, 0, *layer, model, data, nullptr, validateFunc); } inline bool IsQSymm8(const V1_0::Operand&) @@ -2891,11 +2959,6 @@ bool ConvertFullyConnected(const HalOperation& operation, const HalModel& model, const armnn::TensorInfo& inputInfo = input.GetTensorInfo(); const armnn::TensorInfo& outputInfo = GetTensorInfoForOperand(*output); - if (IsDynamicTensor(outputInfo)) - { - return Fail("%s: Dynamic output tensors are not supported", __func__); - } - ConstTensorPin weightsPin = DequantizeAndMakeConstTensorPin<HalPolicy>(operation, model, data, 1); ConstTensorPin biasPin = ConvertOperationInputToConstTensorPin<HalPolicy>(operation, 2, model, data); // 1D @@ -2944,7 +3007,9 @@ bool ConvertFullyConnected(const HalOperation& operation, const HalModel& model, } bool isSupported = false; - FORWARD_LAYER_SUPPORT_FUNC(__func__, + auto validateFunc = [&](const armnn::TensorInfo& outputInfo, bool& isSupported) + { + FORWARD_LAYER_SUPPORT_FUNC(__func__, IsFullyConnectedSupported, data.m_Backends, isSupported, @@ -2953,6 +3018,17 @@ bool ConvertFullyConnected(const HalOperation& operation, const HalModel& model, weights.GetInfo(), bias.GetInfo(), desc); + }; + + if(!IsDynamicTensor(outputInfo)) + { + validateFunc(outputInfo, isSupported); + } + else + { + isSupported = AreDynamicTensorsSupported(); + } + if (!isSupported) { return false; @@ -2980,7 +3056,7 @@ bool ConvertFullyConnected(const HalOperation& operation, const HalModel& model, input.Connect(startLayer->GetInputSlot(0)); } - return SetupAndTrackLayerOutputSlot<HalPolicy>(operation, 0, *endLayer, model, data); + return SetupAndTrackLayerOutputSlot<HalPolicy>(operation, 0, *endLayer, model, data, nullptr, validateFunc); } else { @@ -3015,10 +3091,6 @@ bool ConvertL2Normalization(const HalOperation& operation, const HalModel& model const armnn::TensorInfo& inputInfo = input.GetTensorInfo(); const armnn::TensorInfo& outputInfo = GetTensorInfoForOperand(*output); - if (IsDynamicTensor(outputInfo)) - { - return Fail("%s: Dynamic output tensors are not supported", __func__); - } if (outputInfo.GetNumDimensions() != 4u) { return Fail("%s: Tensor Rank other than 4 is not supported", __func__); @@ -3028,13 +3100,26 @@ bool ConvertL2Normalization(const HalOperation& operation, const HalModel& model desc.m_DataLayout = armnn::DataLayout::NHWC; bool isSupported = false; - FORWARD_LAYER_SUPPORT_FUNC(__func__, - IsL2NormalizationSupported, - data.m_Backends, - isSupported, - inputInfo, - outputInfo, - desc); + auto validateFunc = [&](const armnn::TensorInfo& outputInfo, bool& isSupported) + { + FORWARD_LAYER_SUPPORT_FUNC(__func__, + IsL2NormalizationSupported, + data.m_Backends, + isSupported, + inputInfo, + outputInfo, + desc); + }; + + if(!IsDynamicTensor(outputInfo)) + { + validateFunc(outputInfo, isSupported); + } + else + { + isSupported = AreDynamicTensorsSupported(); + } + if (!isSupported) { return false; @@ -3044,7 +3129,7 @@ bool ConvertL2Normalization(const HalOperation& operation, const HalModel& model assert(layer != nullptr); input.Connect(layer->GetInputSlot(0)); - return SetupAndTrackLayerOutputSlot<HalPolicy>(operation, 0, *layer, model, data); + return SetupAndTrackLayerOutputSlot<HalPolicy>(operation, 0, *layer, model, data, nullptr, validateFunc); } template<typename HalPolicy, @@ -3077,10 +3162,6 @@ bool ConvertLocalResponseNormalization(const HalOperation& operation, const armnn::TensorInfo& inputInfo = input.GetTensorInfo(); const armnn::TensorInfo& outputInfo = GetTensorInfoForOperand(*output); - if (IsDynamicTensor(outputInfo)) - { - return Fail("%s: Dynamic output tensors are not supported", __func__); - } if (outputInfo.GetNumDimensions() != 4u) { return Fail("%s: Tensor Rank other than 4 is not supported", __func__); @@ -3105,13 +3186,26 @@ bool ConvertLocalResponseNormalization(const HalOperation& operation, descriptor.m_NormSize = 1 + (2 * descriptor.m_NormSize); bool isSupported = false; - FORWARD_LAYER_SUPPORT_FUNC(__func__, - IsNormalizationSupported, - data.m_Backends, - isSupported, - inputInfo, - outputInfo, - descriptor); + auto validateFunc = [&](const armnn::TensorInfo& outputInfo, bool& isSupported) + { + FORWARD_LAYER_SUPPORT_FUNC(__func__, + IsNormalizationSupported, + data.m_Backends, + isSupported, + inputInfo, + outputInfo, + descriptor); + }; + + if(!IsDynamicTensor(outputInfo)) + { + validateFunc(outputInfo, isSupported); + } + else + { + isSupported = AreDynamicTensorsSupported(); + } + if (!isSupported) { return false; @@ -3122,7 +3216,7 @@ bool ConvertLocalResponseNormalization(const HalOperation& operation, assert(layer != nullptr); input.Connect(layer->GetInputSlot(0)); - return SetupAndTrackLayerOutputSlot<HalPolicy>(operation, 0, *layer, model, data); + return SetupAndTrackLayerOutputSlot<HalPolicy>(operation, 0, *layer, model, data, nullptr, validateFunc); } template<typename HalPolicy, @@ -3156,10 +3250,6 @@ bool ConvertMean(const HalOperation& operation, const HalModel& model, Conversio } const armnn::TensorInfo& outputInfo = GetTensorInfoForOperand(*output); - if (IsDynamicTensor(outputInfo)) - { - return Fail("%s: Dynamic output tensors are not supported", __func__); - } const HalOperand* axisOperand = GetInputOperand<HalPolicy>(operation, 1, model); if (!axisOperand) @@ -3194,13 +3284,26 @@ bool ConvertMean(const HalOperation& operation, const HalModel& model, Conversio descriptor.m_KeepDims = keepDims > 0; bool isSupported = false; - FORWARD_LAYER_SUPPORT_FUNC(__func__, - IsMeanSupported, - data.m_Backends, - isSupported, - inputInfo, - outputInfo, - descriptor); + auto validateFunc = [&](const armnn::TensorInfo& outputInfo, bool& isSupported) + { + FORWARD_LAYER_SUPPORT_FUNC(__func__, + IsMeanSupported, + data.m_Backends, + isSupported, + inputInfo, + outputInfo, + descriptor); + }; + + if(!IsDynamicTensor(outputInfo)) + { + validateFunc(outputInfo, isSupported); + } + else + { + isSupported = AreDynamicTensorsSupported(); + } + if (!isSupported) { return false; @@ -3210,7 +3313,7 @@ bool ConvertMean(const HalOperation& operation, const HalModel& model, Conversio assert(layer != nullptr); input.Connect(layer->GetInputSlot(0)); - return SetupAndTrackLayerOutputSlot<HalPolicy>(operation, 0, *layer, model, data); + return SetupAndTrackLayerOutputSlot<HalPolicy>(operation, 0, *layer, model, data, nullptr, validateFunc); } template<typename HalPolicy, @@ -3244,19 +3347,28 @@ bool ConvertMul(const HalOperation& operation, const HalModel& model, Conversion } const armnn::TensorInfo& outputInfo = GetTensorInfoForOperand(*outputOperand); - if (IsDynamicTensor(outputInfo)) + + bool isSupported = false; + auto validateFunc = [&](const armnn::TensorInfo& outputInfo, bool& isSupported) { - return Fail("%s: Dynamic output tensors are not supported", __func__); + FORWARD_LAYER_SUPPORT_FUNC(__func__, + IsMultiplicationSupported, + data.m_Backends, + isSupported, + input0.GetTensorInfo(), + input1.GetTensorInfo(), + outputInfo); + }; + + if(!IsDynamicTensor(outputInfo)) + { + validateFunc(outputInfo, isSupported); + } + else + { + isSupported = AreDynamicTensorsSupported(); } - bool isSupported = false; - FORWARD_LAYER_SUPPORT_FUNC(__func__, - IsMultiplicationSupported, - data.m_Backends, - isSupported, - input0.GetTensorInfo(), - input1.GetTensorInfo(), - outputInfo); if (!isSupported) { return false; @@ -3276,7 +3388,7 @@ bool ConvertMul(const HalOperation& operation, const HalModel& model, Conversion return false; } - return SetupAndTrackLayerOutputSlot<HalPolicy>(operation, 0, *endLayer, model, data); + return SetupAndTrackLayerOutputSlot<HalPolicy>(operation, 0, *endLayer, model, data, nullptr, validateFunc); } else { @@ -3323,19 +3435,28 @@ bool ConvertPad(HalOperation& operation, const HalModel& model, ConversionData& } const armnn::TensorInfo& outputInfo = GetTensorInfoForOperand(*output); - if (IsDynamicTensor(outputInfo)) + + bool isSupported = false; + auto validateFunc = [&](const armnn::TensorInfo& outputInfo, bool& isSupported) { - return Fail("%s: Dynamic output tensors are not supported", __func__); + FORWARD_LAYER_SUPPORT_FUNC(__func__, + IsPadSupported, + data.m_Backends, + isSupported, + inputInfo, + outputInfo, + descriptor); + }; + + if(!IsDynamicTensor(outputInfo)) + { + validateFunc(outputInfo, isSupported); + } + else + { + isSupported = AreDynamicTensorsSupported(); } - bool isSupported = false; - FORWARD_LAYER_SUPPORT_FUNC(__func__, - IsPadSupported, - data.m_Backends, - isSupported, - inputInfo, - outputInfo, - descriptor); if (!isSupported) { return false; @@ -3344,9 +3465,8 @@ bool ConvertPad(HalOperation& operation, const HalModel& model, ConversionData& armnn::IConnectableLayer* const layer = data.m_Network->AddPadLayer(descriptor); assert(layer != nullptr); input.Connect(layer->GetInputSlot(0)); - layer->GetOutputSlot(0).SetTensorInfo(outputInfo); - return SetupAndTrackLayerOutputSlot<HalPolicy>(operation, 0, *layer, model, data); + return SetupAndTrackLayerOutputSlot<HalPolicy>(operation, 0, *layer, model, data, nullptr, validateFunc); } template<typename HalPolicy, @@ -3389,12 +3509,6 @@ bool ConvertReshape(const HalOperation& operation, const HalModel& model, Conver return Fail("%s: Failed to resolve the requested shape", __func__); } - const Shape outputOperandShape = GetOperandShape(*outputOperand); - if (!SameShape(requestedShape, outputOperandShape)) - { - return Fail("%s: Shape of output operand does not match resolved requested shape", __func__); - } - LayerInputHandle input = ConvertToLayerInputHandle<HalPolicy>(operation, 0, model, data); if (!input.IsValid()) { @@ -3405,14 +3519,29 @@ bool ConvertReshape(const HalOperation& operation, const HalModel& model, Conver reshapeDescriptor.m_TargetShape = armnn::TensorShape(requestedShape.dimensions.size(), requestedShape.dimensions.data()); + const armnn::TensorInfo& outputInfo = GetTensorInfoForOperand(*outputOperand); + bool isSupported = false; - FORWARD_LAYER_SUPPORT_FUNC(__func__, - IsReshapeSupported, - data.m_Backends, - isSupported, - input.GetTensorInfo(), - GetTensorInfoForOperand(*outputOperand), - reshapeDescriptor); + auto validateFunc = [&](const armnn::TensorInfo& outputInfo, bool& isSupported) + { + FORWARD_LAYER_SUPPORT_FUNC(__func__, + IsReshapeSupported, + data.m_Backends, + isSupported, + input.GetTensorInfo(), + outputInfo, + reshapeDescriptor); + }; + + if(!IsDynamicTensor(outputInfo)) + { + validateFunc(outputInfo, isSupported); + } + else + { + isSupported = AreDynamicTensorsSupported(); + } + if (!isSupported) { return false; @@ -3422,7 +3551,7 @@ bool ConvertReshape(const HalOperation& operation, const HalModel& model, Conver assert(layer != nullptr); input.Connect(layer->GetInputSlot(0)); - return SetupAndTrackLayerOutputSlot<HalPolicy>(operation, 0, *layer, model, data); + return SetupAndTrackLayerOutputSlot<HalPolicy>(operation, 0, *layer, model, data, nullptr, validateFunc); } template<typename HalPolicy, @@ -3455,19 +3584,28 @@ bool ConvertSub(const HalOperation& operation, const HalModel& model, Conversion } const armnn::TensorInfo& outputInfo = GetTensorInfoForOperand(*output); - if (IsDynamicTensor(outputInfo)) + + bool isSupported = false; + auto validateFunc = [&](const armnn::TensorInfo& outputInfo, bool& isSupported) { - return Fail("%s: Dynamic output tensors are not supported", __func__); + FORWARD_LAYER_SUPPORT_FUNC(__func__, + IsSubtractionSupported, + data.m_Backends, + isSupported, + input0.GetTensorInfo(), + input1.GetTensorInfo(), + outputInfo); + }; + + if(IsDynamicTensor(outputInfo)) + { + isSupported = AreDynamicTensorsSupported(); + } + else + { + validateFunc(outputInfo, isSupported); } - bool isSupported = false; - FORWARD_LAYER_SUPPORT_FUNC(__func__, - IsSubtractionSupported, - data.m_Backends, - isSupported, - input0.GetTensorInfo(), - input1.GetTensorInfo(), - outputInfo); if (!isSupported) { return false; @@ -3486,7 +3624,7 @@ bool ConvertSub(const HalOperation& operation, const HalModel& model, Conversion { return false; } - return SetupAndTrackLayerOutputSlot<HalPolicy>(operation, 0, *endLayer, model, data); + return SetupAndTrackLayerOutputSlot<HalPolicy>(operation, 0, *endLayer, model, data, nullptr, validateFunc); } return Fail("%s: ProcessActivation failed", __func__); @@ -3517,7 +3655,6 @@ bool ConvertSqueeze(const HalOperation& operation, const HalModel& model, Conver { return Fail("%s: Could not read output 0", __func__); } - if (IsDynamicTensor(GetTensorInfoForOperand(*output))) { return Fail("%s: Dynamic output tensors are not supported", __func__); @@ -3567,6 +3704,7 @@ bool ConvertSqueeze(const HalOperation& operation, const HalModel& model, Conver inputInfo, outputInfo, reshapeDesc); + if (!isSupported) { return false; @@ -3606,10 +3744,6 @@ bool ConvertStridedSlice(const HalOperation& operation, const HalModel& model, C } const armnn::TensorInfo& outputInfo = GetTensorInfoForOperand(*output); - if (IsDynamicTensor(outputInfo)) - { - return Fail("%s: Dynamic output tensors are not supported", __func__); - } const HalOperand* beginOperand = GetInputOperand<HalPolicy>(operation, 1, model); const HalOperand* endOperand = GetInputOperand<HalPolicy>(operation, 2, model); @@ -3663,13 +3797,26 @@ bool ConvertStridedSlice(const HalOperation& operation, const HalModel& model, C } bool isSupported = false; - FORWARD_LAYER_SUPPORT_FUNC(__func__, - IsStridedSliceSupported, - data.m_Backends, - isSupported, - inputInfo, - outputInfo, - descriptor); + auto validateFunc = [&](const armnn::TensorInfo& outputInfo, bool& isSupported) + { + FORWARD_LAYER_SUPPORT_FUNC(__func__, + IsStridedSliceSupported, + data.m_Backends, + isSupported, + inputInfo, + outputInfo, + descriptor); + }; + + if(IsDynamicTensor(outputInfo)) + { + isSupported = AreDynamicTensorsSupported(); + } + else + { + validateFunc(outputInfo, isSupported); + } + if (!isSupported) { return false; @@ -3704,7 +3851,7 @@ bool ConvertStridedSlice(const HalOperation& operation, const HalModel& model, C assert(layer != nullptr); input.Connect(layer->GetInputSlot(0)); - return SetupAndTrackLayerOutputSlot<HalPolicy>(operation, 0, *layer, model, data); + return SetupAndTrackLayerOutputSlot<HalPolicy>(operation, 0, *layer, model, data, nullptr, validateFunc); } template<typename HalPolicy, @@ -3757,20 +3904,28 @@ bool ConvertTranspose(const HalOperation& operation, const HalModel& model, Conv } const armnn::TensorInfo& outputInfo = GetTensorInfoForOperand(*output); - if (IsDynamicTensor(outputInfo)) + + bool isSupported = false; + auto validateFunc = [&](const armnn::TensorInfo& outputInfo, bool& isSupported) { - return Fail("%s: Dynamic output tensors are not supported", __func__); - } + FORWARD_LAYER_SUPPORT_FUNC(__func__, + IsTransposeSupported, + data.m_Backends, + isSupported, + inputInfo, + outputInfo, + transposeDesc); + }; + if(IsDynamicTensor(outputInfo)) + { + isSupported = AreDynamicTensorsSupported(); + } + else + { + validateFunc(outputInfo, isSupported); + } - bool isSupported = false; - FORWARD_LAYER_SUPPORT_FUNC(__func__, - IsTransposeSupported, - data.m_Backends, - isSupported, - inputInfo, - outputInfo, - transposeDesc); if (!isSupported) { return false; @@ -3780,7 +3935,7 @@ bool ConvertTranspose(const HalOperation& operation, const HalModel& model, Conv assert(layer != nullptr); input.Connect(layer->GetInputSlot(0)); - return SetupAndTrackLayerOutputSlot<HalPolicy>(operation, 0, *layer, model, data); + return SetupAndTrackLayerOutputSlot<HalPolicy>(operation, 0, *layer, model, data, nullptr, validateFunc); } template<typename HalPolicy, @@ -3805,10 +3960,6 @@ bool ConvertBatchToSpaceNd(const HalOperation& operation, } const armnn::TensorInfo& outputInfo = GetTensorInfoForOperand(*output); - if (IsDynamicTensor(outputInfo)) - { - return Fail("%s: Dynamic output tensors are not supported", __func__); - } const HalOperand* blockOperand = GetInputOperand<HalPolicy>(operation, 1, model); if (!blockOperand) @@ -3849,13 +4000,27 @@ bool ConvertBatchToSpaceNd(const HalOperation& operation, batchToSpaceNdDesc.m_Crops = {{0, 0}, {0, 0}}; bool isSupported = false; - FORWARD_LAYER_SUPPORT_FUNC(__func__, - IsBatchToSpaceNdSupported, - data.m_Backends, - isSupported, - inputInfo, - outputInfo, - batchToSpaceNdDesc); + auto validateFunc = [&](const armnn::TensorInfo& outputInfo, bool& isSupported) + { + FORWARD_LAYER_SUPPORT_FUNC(__func__, + IsBatchToSpaceNdSupported, + data.m_Backends, + isSupported, + inputInfo, + outputInfo, + batchToSpaceNdDesc); + }; + + if(!IsDynamicTensor(outputInfo)) + { + validateFunc(outputInfo, isSupported); + } + else + { + isSupported = AreDynamicTensorsSupported(); + } + + if (!isSupported) { return false; @@ -3865,7 +4030,7 @@ bool ConvertBatchToSpaceNd(const HalOperation& operation, assert(layer != nullptr); input.Connect(layer->GetInputSlot(0)); - return SetupAndTrackLayerOutputSlot<HalPolicy>(operation, 0, *layer, model, data); + return SetupAndTrackLayerOutputSlot<HalPolicy>(operation, 0, *layer, model, data, nullptr, validateFunc); } template<typename HalPolicy, @@ -3896,10 +4061,6 @@ bool ConvertSpaceToBatchNd(const HalOperation& operation, const HalModel& model, } const armnn::TensorInfo& outputInfo = GetTensorInfoForOperand(*output); - if (IsDynamicTensor(outputInfo)) - { - return Fail("%s: Dynamic output tensors are not supported", __func__); - } const HalOperand* blockShapeOperand = GetInputOperand<HalPolicy>(operation, 1, model); const HalOperand* paddingsOperand = GetInputOperand<HalPolicy>(operation, 2, model); @@ -3955,13 +4116,26 @@ bool ConvertSpaceToBatchNd(const HalOperation& operation, const HalModel& model, } bool isSupported = false; - FORWARD_LAYER_SUPPORT_FUNC(__func__, - IsSpaceToBatchNdSupported, - data.m_Backends, - isSupported, - inputInfo, - outputInfo, - descriptor); + auto validateFunc = [&](const armnn::TensorInfo& outputInfo, bool& isSupported) + { + FORWARD_LAYER_SUPPORT_FUNC(__func__, + IsSpaceToBatchNdSupported, + data.m_Backends, + isSupported, + inputInfo, + outputInfo, + descriptor); + }; + + if(IsDynamicTensor(outputInfo)) + { + isSupported = AreDynamicTensorsSupported(); + } + else + { + validateFunc(outputInfo, isSupported); + } + if (!isSupported) { return false; @@ -3971,7 +4145,7 @@ bool ConvertSpaceToBatchNd(const HalOperation& operation, const HalModel& model, assert(layer != nullptr); input.Connect(layer->GetInputSlot(0)); - return SetupAndTrackLayerOutputSlot<HalPolicy>(operation, 0, *layer, model, data); + return SetupAndTrackLayerOutputSlot<HalPolicy>(operation, 0, *layer, model, data, nullptr, validateFunc); } } // namespace armnn_driver diff --git a/ConversionUtils_1_2.hpp b/ConversionUtils_1_2.hpp index 824a8f4a..0f47ad31 100644 --- a/ConversionUtils_1_2.hpp +++ b/ConversionUtils_1_2.hpp @@ -1,5 +1,5 @@ // -// Copyright © 2020 Arm Ltd. All rights reserved. +// Copyright © 2020 Arm Ltd and Contributors. All rights reserved. // SPDX-License-Identifier: MIT // @@ -138,22 +138,30 @@ bool ConvertComparison_1_2(const HalOperation& operation, const TensorInfo& inputInfo1 = input1.GetTensorInfo(); const TensorInfo& outputInfo = GetTensorInfoForOperand(*output); - if (IsDynamicTensor(outputInfo)) - { - return Fail("%s: Dynamic output tensors are not supported", __func__); - } - ComparisonDescriptor descriptor(comparisonOperation); bool isSupported = false; - FORWARD_LAYER_SUPPORT_FUNC(__func__, - IsComparisonSupported, - data.m_Backends, - isSupported, - inputInfo0, - inputInfo1, - outputInfo, - descriptor); + auto validateFunc = [&](const armnn::TensorInfo& outputInfo, bool& isSupported) + { + FORWARD_LAYER_SUPPORT_FUNC(__func__, + IsComparisonSupported, + data.m_Backends, + isSupported, + inputInfo0, + inputInfo1, + outputInfo, + descriptor); + + }; + + if(!IsDynamicTensor(outputInfo)) + { + validateFunc(outputInfo, isSupported); + } + else + { + isSupported = AreDynamicTensorsSupported(); + } if (!isSupported) { @@ -169,7 +177,10 @@ bool ConvertComparison_1_2(const HalOperation& operation, return false; } - return SetupAndTrackLayerOutputSlot<HalPolicy>(operation, 0, *layer, model, data); + input0.Connect(layer->GetInputSlot(0)); + input1.Connect(layer->GetInputSlot(1)); + + return SetupAndTrackLayerOutputSlot<HalPolicy>(operation, 0, *layer, model, data, nullptr, validateFunc); } template<typename HalPolicy, @@ -198,11 +209,6 @@ bool ConvertConv2d_1_2(const HalOperation& operation, const HalModel& model, Con const TensorInfo& inputInfo = input.GetTensorInfo(); const TensorInfo& outputInfo = GetTensorInfoForOperand(*output); - if (IsDynamicTensor(outputInfo)) - { - return Fail("%s: Dynamic output tensors are not supported", __func__); - } - Convolution2dDescriptor desc; desc.m_DataLayout = DataLayout::NHWC; @@ -297,15 +303,27 @@ bool ConvertConv2d_1_2(const HalOperation& operation, const HalModel& model, Con Optional<TensorInfo> biases(bias.GetInfo()); bool isSupported = false; - FORWARD_LAYER_SUPPORT_FUNC(__func__, - IsConvolution2dSupported, - data.m_Backends, - isSupported, - inputInfo, - outputInfo, - desc, - weights.GetInfo(), - biases); + auto validateFunc = [&](const armnn::TensorInfo& outputInfo, bool& isSupported) + { + FORWARD_LAYER_SUPPORT_FUNC(__func__, + IsConvolution2dSupported, + data.m_Backends, + isSupported, + inputInfo, + outputInfo, + desc, + weights.GetInfo(), + biases); + }; + + if(!IsDynamicTensor(outputInfo)) + { + validateFunc(outputInfo, isSupported); + } + else + { + isSupported = AreDynamicTensorsSupported(); + } if (!isSupported) { @@ -329,7 +347,7 @@ bool ConvertConv2d_1_2(const HalOperation& operation, const HalModel& model, Con input.Connect(startLayer->GetInputSlot(0)); - return SetupAndTrackLayerOutputSlot<HalPolicy>(operation, 0, *endLayer, model, data); + return SetupAndTrackLayerOutputSlot<HalPolicy>(operation, 0, *endLayer, model, data, nullptr, validateFunc); } template<typename HalPolicy, @@ -359,11 +377,6 @@ bool ConvertDepthwiseConv2d_1_2(const HalOperation& operation, const HalModel& m const TensorInfo& inputInfo = input.GetTensorInfo(); const TensorInfo& outputInfo = GetTensorInfoForOperand(*output); - if (IsDynamicTensor(outputInfo)) - { - return Fail("%s: Dynamic output tensors are not supported", __func__); - } - // ArmNN does not currently support non-fixed weights or bias // Find the shape of the weights tensor. In AndroidNN this will be [ 1, H, W, I * M ] const HalOperand* weightsOperand = GetInputOperand<HalPolicy>(operation, 1, model); @@ -476,15 +489,27 @@ bool ConvertDepthwiseConv2d_1_2(const HalOperation& operation, const HalModel& m Optional<TensorInfo> biases(bias.GetInfo()); bool isSupported = false; - FORWARD_LAYER_SUPPORT_FUNC(__func__, - IsDepthwiseConvolutionSupported, - data.m_Backends, - isSupported, - inputInfo, - outputInfo, - desc, - weights.GetInfo(), - biases); + auto validateFunc = [&](const armnn::TensorInfo& outputInfo, bool& isSupported) + { + FORWARD_LAYER_SUPPORT_FUNC(__func__, + IsDepthwiseConvolutionSupported, + data.m_Backends, + isSupported, + inputInfo, + outputInfo, + desc, + weights.GetInfo(), + biases); + }; + + if(!IsDynamicTensor(outputInfo)) + { + validateFunc(outputInfo, isSupported); + } + else + { + isSupported = AreDynamicTensorsSupported(); + } if (!isSupported) { @@ -556,21 +581,29 @@ bool ConvertElementwiseUnary(const HalOperation& operation, const TensorInfo& inputInfo = input.GetTensorInfo(); const TensorInfo& outputInfo = GetTensorInfoForOperand(*output); - if (IsDynamicTensor(outputInfo)) - { - return Fail("%s: Dynamic output tensors are not supported", __func__); - } - ElementwiseUnaryDescriptor descriptor(unaryOperation); bool isSupported = false; - FORWARD_LAYER_SUPPORT_FUNC(__func__, - IsElementwiseUnarySupported, - data.m_Backends, - isSupported, - inputInfo, - outputInfo, - descriptor); + + auto validateFunc = [&](const armnn::TensorInfo& outputInfo, bool& isSupported) + { + FORWARD_LAYER_SUPPORT_FUNC(__func__, + IsElementwiseUnarySupported, + data.m_Backends, + isSupported, + inputInfo, + outputInfo, + descriptor); + }; + + if(!IsDynamicTensor(outputInfo)) + { + validateFunc(outputInfo, isSupported); + } + else + { + isSupported = AreDynamicTensorsSupported(); + } if (!isSupported) { @@ -579,10 +612,9 @@ bool ConvertElementwiseUnary(const HalOperation& operation, IConnectableLayer* layer = data.m_Network->AddElementwiseUnaryLayer(descriptor); assert(layer != nullptr); - input.Connect(layer->GetInputSlot(0)); - return SetupAndTrackLayerOutputSlot<HalPolicy>(operation, 0, *layer, model, data); + return SetupAndTrackLayerOutputSlot<HalPolicy>(operation, 0, *layer, model, data, nullptr, validateFunc); } template<typename HalPolicy, @@ -609,10 +641,6 @@ bool ConvertExpandDims(const HalOperation& operation, const HalModel& model, Con } const TensorInfo& outputInfo = GetTensorInfoForOperand(*output); - if (IsDynamicTensor(outputInfo)) - { - return Fail("%s: Dynamic output tensors are not supported", __func__); - } int32_t axis; if (!GetInputScalar<HalPolicy>(operation, 1, HalOperandType::INT32, axis, model, data)) @@ -640,13 +668,25 @@ bool ConvertExpandDims(const HalOperation& operation, const HalModel& model, Con reshapeDescriptor.m_TargetShape = targetShape; bool isSupported = false; - FORWARD_LAYER_SUPPORT_FUNC(__func__, - IsReshapeSupported, - data.m_Backends, - isSupported, - input.GetTensorInfo(), - outputInfo, - reshapeDescriptor); + auto validateFunc = [&](const armnn::TensorInfo& outputInfo, bool& isSupported) + { + FORWARD_LAYER_SUPPORT_FUNC(__func__, + IsReshapeSupported, + data.m_Backends, + isSupported, + input.GetTensorInfo(), + outputInfo, + reshapeDescriptor); + }; + + if(!IsDynamicTensor(outputInfo)) + { + validateFunc(outputInfo, isSupported); + } + else + { + isSupported = AreDynamicTensorsSupported(); + } if (!isSupported) { @@ -657,7 +697,7 @@ bool ConvertExpandDims(const HalOperation& operation, const HalModel& model, Con assert(layer != nullptr); input.Connect(layer->GetInputSlot(0)); - return SetupAndTrackLayerOutputSlot<HalPolicy>(operation, 0, *layer, model, data); + return SetupAndTrackLayerOutputSlot<HalPolicy>(operation, 0, *layer, model, data, nullptr, validateFunc); } template<typename HalPolicy, @@ -691,10 +731,6 @@ bool ConvertGather(const HalOperation& operation, const HalModel& model, Convers } const TensorInfo& outputInfo = GetTensorInfoForOperand(*output); auto outputDimensions = outputInfo.GetNumDimensions(); - if (IsDynamicTensor(outputInfo)) - { - return Fail("%s: Dynamic output tensors are not supported", __func__); - } if (outputDimensions != inputDimensions + indicesDimensions - 1) { return Fail("%s: Operation has invalid output dimensions: %d. Output must be an (%d + %d - 1)-D tensor", @@ -716,14 +752,27 @@ bool ConvertGather(const HalOperation& operation, const HalModel& model, Convers desc.m_Axis = axis; bool isSupported = false; - FORWARD_LAYER_SUPPORT_FUNC(__func__, - IsGatherSupported, - data.m_Backends, - isSupported, - input.GetTensorInfo(), - indices.GetTensorInfo(), - outputInfo, - desc); + auto validateFunc = [&](const armnn::TensorInfo& outputInfo, bool& isSupported) + { + FORWARD_LAYER_SUPPORT_FUNC(__func__, + IsGatherSupported, + data.m_Backends, + isSupported, + input.GetTensorInfo(), + indices.GetTensorInfo(), + outputInfo, + desc); + }; + + if(!IsDynamicTensor(outputInfo)) + { + validateFunc(outputInfo, isSupported); + } + else + { + isSupported = AreDynamicTensorsSupported(); + } + if (!isSupported) { return false; @@ -734,7 +783,7 @@ bool ConvertGather(const HalOperation& operation, const HalModel& model, Convers input.Connect(layer->GetInputSlot(0)); indices.Connect(layer->GetInputSlot(1)); - return SetupAndTrackLayerOutputSlot<HalPolicy>(operation, 0, *layer, model, data); + return SetupAndTrackLayerOutputSlot<HalPolicy>(operation, 0, *layer, model, data, nullptr, validateFunc); } template<typename HalPolicy, @@ -763,10 +812,6 @@ bool ConvertGroupedConv2d(const HalOperation& operation, const HalModel& model, return Fail("%s: Could not read output 0", __func__); } const TensorInfo& outputInfo = GetTensorInfoForOperand(*output); - if (IsDynamicTensor(outputInfo)) - { - return Fail("%s: Dynamic output tensors are not supported", __func__); - } // Look ahead to determine data layout DataLayout dataLayout = DataLayout::NHWC; @@ -1035,13 +1080,26 @@ bool ConvertGroupedConv2d(const HalOperation& operation, const HalModel& model, } isSupported = false; - FORWARD_LAYER_SUPPORT_FUNC(__func__, - IsConcatSupported, - data.m_Backends, - isSupported, - std::vector<const TensorInfo*>(numGroups * channelMultiplier, &groupOutputInfo), - outputInfo, - concatDescriptor); + auto validateFunc = [&](const armnn::TensorInfo& outputInfo, bool& isSupported) + { + FORWARD_LAYER_SUPPORT_FUNC(__func__, + IsConcatSupported, + data.m_Backends, + isSupported, + std::vector<const TensorInfo*>(numGroups * channelMultiplier, &groupOutputInfo), + outputInfo, + concatDescriptor); + }; + + if(!IsDynamicTensor(outputInfo)) + { + validateFunc(outputInfo, isSupported); + } + else + { + isSupported = AreDynamicTensorsSupported(); + } + if (!isSupported) { return false; @@ -1072,7 +1130,7 @@ bool ConvertGroupedConv2d(const HalOperation& operation, const HalModel& model, return Fail("%s: ProcessActivation failed", __func__); } - return SetupAndTrackLayerOutputSlot<HalPolicy>(operation, 0, *endLayer, model, data); + return SetupAndTrackLayerOutputSlot<HalPolicy>(operation, 0, *endLayer, model, data, nullptr, validateFunc); } template<typename HalPolicy, @@ -1098,10 +1156,6 @@ bool ConvertInstanceNormalization(const HalOperation& operation, const HalModel& } const TensorInfo& outputInfo = GetTensorInfoForOperand(*output); - if (IsDynamicTensor(outputInfo)) - { - return Fail("%s: Dynamic output tensors are not supported", __func__); - } // Determine data type of input tensor HalOperandType inputType; @@ -1147,13 +1201,26 @@ bool ConvertInstanceNormalization(const HalOperation& operation, const HalModel& desc.m_DataLayout = OptionalDataLayout<HalPolicy>(operation, 4, model, data); bool isSupported = false; - FORWARD_LAYER_SUPPORT_FUNC(__func__, - IsInstanceNormalizationSupported, - data.m_Backends, - isSupported, - input.GetTensorInfo(), - outputInfo, - desc); + auto validateFunc = [&](const armnn::TensorInfo& outputInfo, bool& isSupported) + { + FORWARD_LAYER_SUPPORT_FUNC(__func__, + IsInstanceNormalizationSupported, + data.m_Backends, + isSupported, + input.GetTensorInfo(), + outputInfo, + desc); + }; + + if(IsDynamicTensor(outputInfo)) + { + isSupported = AreDynamicTensorsSupported(); + } + else + { + validateFunc(outputInfo, isSupported); + } + if (!isSupported) { return false; @@ -1162,7 +1229,7 @@ bool ConvertInstanceNormalization(const HalOperation& operation, const HalModel& IConnectableLayer* layer = data.m_Network->AddInstanceNormalizationLayer(desc); input.Connect(layer->GetInputSlot(0)); - return SetupAndTrackLayerOutputSlot<HalPolicy>(operation, 0, *layer, model, data); + return SetupAndTrackLayerOutputSlot<HalPolicy>(operation, 0, *layer, model, data, nullptr, validateFunc); } template<typename HalPolicy, @@ -1188,10 +1255,6 @@ bool ConvertLogSoftmax(const HalOperation& operation, const HalModel& model, Con } const TensorInfo& outputInfo = GetTensorInfoForOperand(*output); - if (IsDynamicTensor(outputInfo)) - { - return Fail("%s: Dynamic output tensors are not supported", __func__); - } // Determine data type of input tensor HalOperandType inputType; @@ -1232,13 +1295,26 @@ bool ConvertLogSoftmax(const HalOperation& operation, const HalModel& model, Con } bool isSupported = false; - FORWARD_LAYER_SUPPORT_FUNC(__func__, - IsLogSoftmaxSupported, - data.m_Backends, - isSupported, - input.GetTensorInfo(), - outputInfo, - descriptor); + auto validateFunc = [&](const armnn::TensorInfo& outputInfo, bool& isSupported) + { + FORWARD_LAYER_SUPPORT_FUNC(__func__, + IsLogSoftmaxSupported, + data.m_Backends, + isSupported, + input.GetTensorInfo(), + outputInfo, + descriptor); + }; + + if(IsDynamicTensor(outputInfo)) + { + isSupported = AreDynamicTensorsSupported(); + } + else + { + validateFunc(outputInfo, isSupported); + } + if (!isSupported) { return false; @@ -1252,7 +1328,7 @@ bool ConvertLogSoftmax(const HalOperation& operation, const HalModel& model, Con input.Connect(layer->GetInputSlot(0)); - return SetupAndTrackLayerOutputSlot<HalPolicy>(operation, 0, *layer, model, data); + return SetupAndTrackLayerOutputSlot<HalPolicy>(operation, 0, *layer, model, data, nullptr, validateFunc); } template<typename HalPolicy, @@ -1279,19 +1355,27 @@ bool ConvertMaximum(const HalOperation& operation, const HalModel& model, Conver } const TensorInfo& outInfo = GetTensorInfoForOperand(*outputOperand); - if (IsDynamicTensor(outInfo)) - { - return Fail("%s: Dynamic output tensors are not supported", __func__); - } bool isSupported = false; - FORWARD_LAYER_SUPPORT_FUNC(__func__, - IsMaximumSupported, - data.m_Backends, - isSupported, - input0.GetTensorInfo(), - input1.GetTensorInfo(), - outInfo); + auto validateFunc = [&](const armnn::TensorInfo& outInfo, bool& isSupported) + { + FORWARD_LAYER_SUPPORT_FUNC(__func__, + IsMaximumSupported, + data.m_Backends, + isSupported, + input0.GetTensorInfo(), + input1.GetTensorInfo(), + outInfo); + }; + + if(IsDynamicTensor(outInfo)) + { + isSupported = AreDynamicTensorsSupported(); + } + else + { + validateFunc(outInfo, isSupported); + } if (!isSupported) { @@ -1306,7 +1390,7 @@ bool ConvertMaximum(const HalOperation& operation, const HalModel& model, Conver return false; } - return SetupAndTrackLayerOutputSlot<HalPolicy>(operation, 0, *layer, model, data); + return SetupAndTrackLayerOutputSlot<HalPolicy>(operation, 0, *layer, model, data, nullptr, validateFunc); } template<typename HalPolicy, @@ -1333,19 +1417,27 @@ bool ConvertMinimum(const HalOperation& operation, const HalModel& model, Conver } const TensorInfo& outputInfo = GetTensorInfoForOperand(*output); - if (IsDynamicTensor(outputInfo)) - { - return Fail("%s: Dynamic output tensors are not supported", __func__); - } bool isSupported = false; - FORWARD_LAYER_SUPPORT_FUNC(__func__, - IsMinimumSupported, - data.m_Backends, - isSupported, - input0.GetTensorInfo(), - input1.GetTensorInfo(), - outputInfo); + auto validateFunc = [&](const armnn::TensorInfo& outputInfo, bool& isSupported) + { + FORWARD_LAYER_SUPPORT_FUNC(__func__, + IsMinimumSupported, + data.m_Backends, + isSupported, + input0.GetTensorInfo(), + input1.GetTensorInfo(), + outputInfo); + }; + + if(IsDynamicTensor(outputInfo)) + { + isSupported = AreDynamicTensorsSupported(); + } + else + { + validateFunc(outputInfo, isSupported); + } if (!isSupported) { @@ -1360,7 +1452,7 @@ bool ConvertMinimum(const HalOperation& operation, const HalModel& model, Conver return false; } - return SetupAndTrackLayerOutputSlot<HalPolicy>(operation, 0, *layer, model, data); + return SetupAndTrackLayerOutputSlot<HalPolicy>(operation, 0, *layer, model, data, nullptr, validateFunc); } template<typename HalPolicy, @@ -1395,10 +1487,6 @@ bool ConvertPadV2(const HalOperation& operation, const HalModel& model, Conversi } const TensorInfo& outputInfo = GetTensorInfoForOperand(*output); - if (IsDynamicTensor(outputInfo)) - { - return Fail("%s: Dynamic output tensors are not supported", __func__); - } // Determine type of padding value HalOperandType operandType0; @@ -1443,13 +1531,26 @@ bool ConvertPadV2(const HalOperation& operation, const HalModel& model, Conversi } bool isSupported = false; - FORWARD_LAYER_SUPPORT_FUNC(__func__, - IsPadSupported, - data.m_Backends, - isSupported, - inputInfo, - outputInfo, - descriptor); + auto validateFunc = [&](const armnn::TensorInfo& outputInfo, bool& isSupported) + { + FORWARD_LAYER_SUPPORT_FUNC(__func__, + IsPadSupported, + data.m_Backends, + isSupported, + inputInfo, + outputInfo, + descriptor); + }; + + if(IsDynamicTensor(outputInfo)) + { + isSupported = AreDynamicTensorsSupported(); + } + else + { + validateFunc(outputInfo, isSupported); + } + if (!isSupported) { return false; @@ -1458,9 +1559,8 @@ bool ConvertPadV2(const HalOperation& operation, const HalModel& model, Conversi IConnectableLayer* const layer = data.m_Network->AddPadLayer(descriptor); assert(layer != nullptr); input.Connect(layer->GetInputSlot(0)); - layer->GetOutputSlot(0).SetTensorInfo(outputInfo); - return SetupAndTrackLayerOutputSlot<HalPolicy>(operation, 0, *layer, model, data); + return SetupAndTrackLayerOutputSlot<HalPolicy>(operation, 0, *layer, model, data, nullptr, validateFunc); } template<typename HalPolicy, @@ -1491,19 +1591,27 @@ bool ConvertPrelu(const HalOperation& operation, const HalModel& model, Conversi const TensorInfo& alphaInfo = alpha.GetTensorInfo(); const TensorInfo& outputInfo = GetTensorInfoForOperand(*output); - if (IsDynamicTensor(outputInfo)) + bool isSupported = false; + auto validateFunc = [&](const armnn::TensorInfo& outputInfo, bool& isSupported) { - return Fail("%s: Dynamic output tensors are not supported", __func__); + FORWARD_LAYER_SUPPORT_FUNC(__func__, + IsPreluSupported, + data.m_Backends, + isSupported, + inputInfo, + alphaInfo, + outputInfo); + }; + + if(IsDynamicTensor(outputInfo)) + { + isSupported = AreDynamicTensorsSupported(); + } + else + { + validateFunc(outputInfo, isSupported); } - bool isSupported = false; - FORWARD_LAYER_SUPPORT_FUNC(__func__, - IsPreluSupported, - data.m_Backends, - isSupported, - inputInfo, - alphaInfo, - outputInfo); if (!isSupported) { return false; @@ -1522,7 +1630,7 @@ bool ConvertPrelu(const HalOperation& operation, const HalModel& model, Conversi return false; } - return SetupAndTrackLayerOutputSlot<HalPolicy>(operation, 0, *layer, model, data); + return SetupAndTrackLayerOutputSlot<HalPolicy>(operation, 0, *layer, model, data, nullptr, validateFunc); } template<typename HalPolicy, @@ -1547,18 +1655,27 @@ bool ConvertQuantize(const HalOperation& operation, const HalModel& model, Conve } const TensorInfo& outputInfo = GetTensorInfoForOperand(*outputOperand); - if (IsDynamicTensor(outputInfo)) + + bool isSupported = false; + auto validateFunc = [&](const armnn::TensorInfo& outputInfo, bool& isSupported) { - return Fail("%s: Dynamic output tensors are not supported", __func__); + FORWARD_LAYER_SUPPORT_FUNC(__func__, + IsQuantizeSupported, + data.m_Backends, + isSupported, + input.GetTensorInfo(), + outputInfo); + }; + + if(IsDynamicTensor(outputInfo)) + { + isSupported = AreDynamicTensorsSupported(); + } + else + { + validateFunc(outputInfo, isSupported); } - bool isSupported = false; - FORWARD_LAYER_SUPPORT_FUNC(__func__, - IsQuantizeSupported, - data.m_Backends, - isSupported, - input.GetTensorInfo(), - outputInfo); if (!isSupported) { return false; @@ -1568,7 +1685,7 @@ bool ConvertQuantize(const HalOperation& operation, const HalModel& model, Conve assert(layer != nullptr); input.Connect(layer->GetInputSlot(0)); - return SetupAndTrackLayerOutputSlot<HalPolicy>(operation, 0, *layer, model, data); + return SetupAndTrackLayerOutputSlot<HalPolicy>(operation, 0, *layer, model, data, nullptr, validateFunc); } template<typename HalPolicy, @@ -1812,11 +1929,6 @@ bool ConvertResize(const HalOperation& operation, const TensorInfo& inputInfo = input.GetTensorInfo(); const TensorInfo& outputInfo = GetTensorInfoForOperand(*output); - if (IsDynamicTensor(outputInfo)) - { - return Fail("%s: Dynamic output tensors are not supported", __func__); - } - ResizeDescriptor descriptor; descriptor.m_Method = resizeMethod; descriptor.m_DataLayout = OptionalDataLayout<HalPolicy>(operation, 3, model, data); @@ -1906,13 +2018,25 @@ bool ConvertResize(const HalOperation& operation, descriptor.m_HalfPixelCenters = GetOptionalBool<HalPolicy>(operation, 5, model, data); bool isSupported = false; - FORWARD_LAYER_SUPPORT_FUNC(__func__, - IsResizeSupported, - data.m_Backends, - isSupported, - inputInfo, - outputInfo, - descriptor); + auto validateFunc = [&](const armnn::TensorInfo& outputInfo, bool& isSupported) + { + FORWARD_LAYER_SUPPORT_FUNC(__func__, + IsResizeSupported, + data.m_Backends, + isSupported, + inputInfo, + outputInfo, + descriptor); + }; + + if(IsDynamicTensor(outputInfo)) + { + isSupported = AreDynamicTensorsSupported(); + } + else + { + validateFunc(outputInfo, isSupported); + } if (!isSupported) { @@ -1920,12 +2044,10 @@ bool ConvertResize(const HalOperation& operation, } IConnectableLayer* layer = data.m_Network->AddResizeLayer(descriptor); - assert(layer != nullptr); - input.Connect(layer->GetInputSlot(0)); - return SetupAndTrackLayerOutputSlot<HalPolicy>(operation, 0, *layer, model, data); + return SetupAndTrackLayerOutputSlot<HalPolicy>(operation, 0, *layer, model, data, nullptr, validateFunc); } template<typename HalPolicy, @@ -1958,10 +2080,6 @@ bool ConvertSpaceToDepth(const HalOperation& operation, const HalModel& model, C } const TensorInfo& outputInfo = GetTensorInfoForOperand(*output); - if (IsDynamicTensor(outputInfo)) - { - return Fail("%s: Dynamic output tensors are not supported", __func__); - } SpaceToDepthDescriptor desc; @@ -1975,13 +2093,26 @@ bool ConvertSpaceToDepth(const HalOperation& operation, const HalModel& model, C desc.m_DataLayout = OptionalDataLayout<HalPolicy>(operation, 2, model, data); bool isSupported = false; - FORWARD_LAYER_SUPPORT_FUNC(__func__, - IsSpaceToDepthSupported, - data.m_Backends, - isSupported, - inputInfo, - outputInfo, - desc); + auto validateFunc = [&](const armnn::TensorInfo& outputInfo, bool& isSupported) + { + FORWARD_LAYER_SUPPORT_FUNC(__func__, + IsSpaceToDepthSupported, + data.m_Backends, + isSupported, + inputInfo, + outputInfo, + desc); + }; + + if(IsDynamicTensor(outputInfo)) + { + isSupported = AreDynamicTensorsSupported(); + } + else + { + validateFunc(outputInfo, isSupported); + } + if (!isSupported) { return false; @@ -1991,7 +2122,7 @@ bool ConvertSpaceToDepth(const HalOperation& operation, const HalModel& model, C assert(layer != nullptr); input.Connect(layer->GetInputSlot(0)); - return SetupAndTrackLayerOutputSlot<HalPolicy>(operation, 0, *layer, model, data); + return SetupAndTrackLayerOutputSlot<HalPolicy>(operation, 0, *layer, model, data, nullptr, validateFunc); } template<typename HalPolicy, @@ -2017,10 +2148,6 @@ bool ConvertSoftmax(const HalOperation& operation, const HalModel& model, Conver } const TensorInfo& outputInfo = GetTensorInfoForOperand(*outputOperand); - if (IsDynamicTensor(outputInfo)) - { - return Fail("%s: Dynamic output tensors are not supported", __func__); - } SoftmaxDescriptor desc; HalOperandType outputType = outputOperand->type; @@ -2056,13 +2183,26 @@ bool ConvertSoftmax(const HalOperation& operation, const HalModel& model, Conver } bool isSupported = false; - FORWARD_LAYER_SUPPORT_FUNC(__func__, - IsSoftmaxSupported, - data.m_Backends, - isSupported, - input.GetTensorInfo(), - outputInfo, - desc); + auto validateFunc = [&](const armnn::TensorInfo& outputInfo, bool& isSupported) + { + FORWARD_LAYER_SUPPORT_FUNC(__func__, + IsSoftmaxSupported, + data.m_Backends, + isSupported, + input.GetTensorInfo(), + outputInfo, + desc); + }; + + if(IsDynamicTensor(outputInfo)) + { + isSupported = AreDynamicTensorsSupported(); + } + else + { + validateFunc(outputInfo, isSupported); + } + if (!isSupported) { return false; @@ -2072,7 +2212,7 @@ bool ConvertSoftmax(const HalOperation& operation, const HalModel& model, Conver assert(layer != nullptr); input.Connect(layer->GetInputSlot(0)); - return SetupAndTrackLayerOutputSlot<HalPolicy>(operation, 0, *layer, model, data); + return SetupAndTrackLayerOutputSlot<HalPolicy>(operation, 0, *layer, model, data, nullptr, validateFunc); } template<typename HalPolicy, @@ -2460,6 +2600,7 @@ bool ConvertLstm(const HalOperation& operation, const HalModel& model, Conversio } bool isSupported = false; + FORWARD_LAYER_SUPPORT_FUNC(__func__, IsLstmSupported, data.m_Backends, @@ -2473,6 +2614,7 @@ bool ConvertLstm(const HalOperation& operation, const HalModel& model, Conversio outputInfo, desc, paramsInfo); + if (!isSupported) { return false; @@ -2485,7 +2627,6 @@ bool ConvertLstm(const HalOperation& operation, const HalModel& model, Conversio outputStateIn.Connect(layer->GetInputSlot(1)); cellStateIn.Connect(layer->GetInputSlot(2)); - return ( (IsDynamicTensor(scratchBufferInfo)? SetupAndTrackLayerOutputSlotAndOverrideTensorInfo<HalPolicy>( @@ -2521,10 +2662,6 @@ bool ConvertTransposeConv2d(const HalOperation& operation, const HalModel& model const TensorInfo& inputInfo = input.GetTensorInfo(); const TensorInfo& outputInfo = GetTensorInfoForOperand(*output); - if (IsDynamicTensor(outputInfo)) - { - return Fail("%s: Dynamic output tensors are not supported", __func__); - } // ArmNN does not currently support non-fixed weights or bias // Find the shape of the weights tensor. In AndroidNN this will be [ 1, H, W, I * M ] @@ -2658,15 +2795,27 @@ bool ConvertTransposeConv2d(const HalOperation& operation, const HalModel& model Optional<TensorInfo> biases(bias.GetInfo()); bool isSupported = false; - FORWARD_LAYER_SUPPORT_FUNC(__func__, - IsTransposeConvolution2dSupported, - data.m_Backends, - isSupported, - inputInfo, - outputInfo, - desc, - weights.GetInfo(), - biases); + auto validateFunc = [&](const armnn::TensorInfo& outputInfo, bool& isSupported) + { + FORWARD_LAYER_SUPPORT_FUNC(__func__, + IsTransposeConvolution2dSupported, + data.m_Backends, + isSupported, + inputInfo, + outputInfo, + desc, + weights.GetInfo(), + biases); + }; + + if(IsDynamicTensor(outputInfo)) + { + isSupported = AreDynamicTensorsSupported(); + } + else + { + validateFunc(outputInfo, isSupported); + } if (!isSupported) { return false; @@ -2687,7 +2836,7 @@ bool ConvertTransposeConv2d(const HalOperation& operation, const HalModel& model input.Connect(startLayer->GetInputSlot(0)); - return SetupAndTrackLayerOutputSlot<HalPolicy>(operation, 0, *endLayer, model, data); + return SetupAndTrackLayerOutputSlot<HalPolicy>(operation, 0, *endLayer, model, data, nullptr, validateFunc); } } // armnn_driver namespace
\ No newline at end of file diff --git a/ConversionUtils_1_3.hpp b/ConversionUtils_1_3.hpp index d5d89df1..e6961253 100644 --- a/ConversionUtils_1_3.hpp +++ b/ConversionUtils_1_3.hpp @@ -146,7 +146,6 @@ bool ConvertFill(const HalOperation& operation, const HalModel& model, Conversio IConnectableLayer* const layer = data.m_Network->AddFillLayer(descriptor); assert(layer != nullptr); input.Connect(layer->GetInputSlot(0)); - layer->GetOutputSlot(0).SetTensorInfo(outputInfo); return SetupAndTrackLayerOutputSlot<HalPolicy>(operation, 0, *layer, model, data); } @@ -667,6 +666,10 @@ bool ConvertRank(const HalOperation& operation, const HalModel& model, Conversio } armnn::TensorInfo outInfo = GetTensorInfoForOperand(*outputOperand); + if (IsDynamicTensor(outInfo)) + { + return Fail("%s: Dynamic output tensors are not supported", __func__); + } bool isSupported = false; FORWARD_LAYER_SUPPORT_FUNC(__func__, @@ -577,6 +577,11 @@ bool IsDynamicTensor(const armnn::TensorInfo& tensorInfo) { return true; } + // Account for the usage of the TensorShape empty constructor + if (tensorInfo.GetNumDimensions() == 0) + { + return true; + } return !tensorInfo.GetShape().AreAllDimensionsSpecified(); } |