IVGCVSW-2019 : replace Compute enum in the Layer object

Change-Id: I76551d511ef718eac36e5b8e5fe426ec3a402855
diff --git a/include/armnn/BackendId.hpp b/include/armnn/BackendId.hpp
index af3b799..711833d 100644
--- a/include/armnn/BackendId.hpp
+++ b/include/armnn/BackendId.hpp
@@ -70,9 +70,12 @@
     return os;
 }
 
+struct UninitializedBackendId {};
+
 class BackendId final
 {
 public:
+    BackendId(UninitializedBackendId) { GetComputeDeviceAsCString(Compute::Undefined); }
     BackendId(const std::string& id) : m_Id{id} {}
     BackendId(const char* id) : m_Id{id} {}
 
@@ -102,6 +105,21 @@
         return m_Id == other.m_Id;
     }
 
+    // comparison against objects from which the
+    // BackendId can be constructed
+    template <typename O>
+    bool operator==(const O& other) const
+    {
+        BackendId temp{other};
+        return *this == temp;
+    }
+
+    template <typename O>
+    bool operator!=(const O& other) const
+    {
+        return !(*this == other);
+    }
+
     bool operator<(const BackendId& other) const
     {
         return m_Id < other.m_Id;
diff --git a/src/armnn/Graph.cpp b/src/armnn/Graph.cpp
index 0ba2d06..83d82a5 100644
--- a/src/armnn/Graph.cpp
+++ b/src/armnn/Graph.cpp
@@ -67,7 +67,7 @@
     for (auto&& it : TopologicalSort())
     {
         BOOST_LOG_TRIVIAL(info) << it->GetName() << ":" << GetLayerTypeAsCString(it->GetType())
-                                << ":" << GetComputeDeviceAsCString(it->GetComputeDevice());
+                                << ":" << it->GetBackendId().Get();
     }
     BOOST_LOG_TRIVIAL(info) << "\n\n";
 
@@ -260,7 +260,7 @@
     auto MayNeedCopyLayer = [](const Layer& layer)
         {
             // All layers should have been associated with a valid compute device at this point.
-            BOOST_ASSERT(layer.GetComputeDevice() != Compute::Undefined);
+            BOOST_ASSERT(layer.GetBackendId() != Compute::Undefined);
             // Does not need another copy layer if a copy layer is already present.
             return layer.GetType() != LayerType::MemCopy;
         };
@@ -276,7 +276,7 @@
                 for (auto&& dstInput : connectionCopy)
                 {
                     Layer& dstLayer = dstInput->GetOwningLayer();
-                    if (MayNeedCopyLayer(dstLayer) && (dstLayer.GetComputeDevice() != srcLayer->GetComputeDevice()))
+                    if (MayNeedCopyLayer(dstLayer) && (dstLayer.GetBackendId() != srcLayer->GetBackendId()))
                     {
                         // A copy layer is needed in between the source and destination layers.
                         // Record the operation rather than attempting to modify the graph as we go.
@@ -288,7 +288,7 @@
                                                                      % dstInput->GetSlotIndex());
 
                         MemCopyLayer* const copyLayer = InsertNewLayer<MemCopyLayer>(*dstInput, copyLayerName.c_str());
-                        copyLayer->SetComputeDevice(dstLayer.GetComputeDevice());
+                        copyLayer->SetBackendId(dstLayer.GetBackendId());
                     }
                 }
                 ++srcOutputIndex;
diff --git a/src/armnn/Layer.cpp b/src/armnn/Layer.cpp
index d922920..08a8bc3 100644
--- a/src/armnn/Layer.cpp
+++ b/src/armnn/Layer.cpp
@@ -133,7 +133,7 @@
 , m_LayerName(name ? name : "")
 , m_Type(type)
 , m_DataLayout(layout)
-, m_ComputeDevice(Compute::Undefined)
+, m_BackendId(UninitializedBackendId())
 , m_Guid(GenerateLayerGuid())
 {
     m_InputSlots.reserve(numInputSlots);
diff --git a/src/armnn/Layer.hpp b/src/armnn/Layer.hpp
index d897b25..a969607 100644
--- a/src/armnn/Layer.hpp
+++ b/src/armnn/Layer.hpp
@@ -237,8 +237,8 @@
 
     DataLayout GetDataLayout() const { return m_DataLayout; }
 
-    Compute GetComputeDevice() const { return m_ComputeDevice; }
-    void SetComputeDevice(Compute device) { m_ComputeDevice = device; }
+    const BackendId& GetBackendId() const { return m_BackendId; }
+    void SetBackendId(const BackendId& id) { m_BackendId = id; }
 
     // Virtuals
 
@@ -345,7 +345,7 @@
 
     const LayerType m_Type;
     const DataLayout m_DataLayout;
-    Compute m_ComputeDevice;
+    BackendId m_BackendId;
 
     /// Used for sorting.
     mutable LayerPriority m_Priority = 0;
diff --git a/src/armnn/LoadedNetwork.cpp b/src/armnn/LoadedNetwork.cpp
index ce9f76c..4f73bda 100644
--- a/src/armnn/LoadedNetwork.cpp
+++ b/src/armnn/LoadedNetwork.cpp
@@ -122,7 +122,7 @@
                     const char* const layerName = layer->GetNameStr().length() != 0 ? layer->GetName() : "<Unnamed>";
                     throw InvalidArgumentException(boost::str(
                         boost::format("No workload created for layer (name: '%1%' type: '%2%') (compute '%3%')")
-                        % layerName % static_cast<int>(layer->GetType()) % layer->GetComputeDevice()
+                        % layerName % static_cast<int>(layer->GetType()) % layer->GetBackendId().Get()
                     ));
                 }
 
@@ -176,27 +176,17 @@
 {
     const IWorkloadFactory* workloadFactory = nullptr;
 
-    switch (layer.GetComputeDevice())
+    if (layer.GetBackendId() == Compute::CpuAcc)
     {
-        case Compute::CpuAcc:
-        {
-            workloadFactory = &m_CpuAcc;
-            break;
-        }
-        case Compute::GpuAcc:
-        {
-            workloadFactory = &m_GpuAcc;
-            break;
-        }
-        case Compute::CpuRef:
-        {
-            workloadFactory = &m_CpuRef;
-            break;
-        }
-        default:
-        {
-            break;
-        }
+        workloadFactory = &m_CpuAcc;
+    }
+    else if (layer.GetBackendId() == Compute::GpuAcc)
+    {
+        workloadFactory = &m_GpuAcc;
+    }
+    else if (layer.GetBackendId() == Compute::CpuRef)
+    {
+        workloadFactory = &m_CpuRef;
     }
 
     BOOST_ASSERT_MSG(workloadFactory, "No workload factory");
diff --git a/src/armnn/Network.cpp b/src/armnn/Network.cpp
index 51490e3..c43f336 100644
--- a/src/armnn/Network.cpp
+++ b/src/armnn/Network.cpp
@@ -187,7 +187,7 @@
         {
             // need to set the compute device on the layer
             // before we can check if it is supported
-            layer->SetComputeDevice(backend);
+            layer->SetBackendId(backend);
             if (!IWorkloadFactory::IsLayerSupported(*layer, dataType, reasonIfUnsupported))
             {
                 if (dataType == DataType::Float16)
@@ -211,7 +211,7 @@
                             std::string reasonIfUnsupported;
 
                             // Try preferred backend first
-                            layer->SetComputeDevice(preferredBackend);
+                            layer->SetBackendId(preferredBackend);
                             if (IWorkloadFactory::IsLayerSupported(*layer, boost::none, reasonIfUnsupported))
                             {
                                 supportedBackendFound = true;
@@ -226,7 +226,7 @@
                                         continue;
                                     }
 
-                                    layer->SetComputeDevice(backend);
+                                    layer->SetBackendId(backend);
                                     if (IWorkloadFactory::IsLayerSupported(*layer, boost::none, reasonIfUnsupported))
                                     {
                                         supportedBackendFound = true;
@@ -260,7 +260,7 @@
                 }
                 std::stringstream warningMsg;
                 warningMsg << "WARNING: Layer of type " << GetLayerTypeAsCString(layer->GetType())
-                           << " is not supported on requested backend " << layer->GetComputeDevice()
+                           << " is not supported on requested backend " << layer->GetBackendId().Get()
                            << " for data type " << GetDataTypeName(dataType)
                            << " (reason: " << reasonIfUnsupported
                            << "), falling back to the next backend.";
@@ -287,7 +287,7 @@
                                 layerType == armnn::LayerType::Constant ||
                                 layerType == armnn::LayerType::Permute))
             {
-                layer->SetComputeDevice(armnn::Compute::CpuRef);
+                layer->SetBackendId(armnn::Compute::CpuRef);
             }
             else
             {
diff --git a/src/armnn/layers/LayerCloneBase.hpp b/src/armnn/layers/LayerCloneBase.hpp
index 9b9e1ea..3671d66 100644
--- a/src/armnn/layers/LayerCloneBase.hpp
+++ b/src/armnn/layers/LayerCloneBase.hpp
@@ -15,7 +15,7 @@
 {
     LayerType* const layer = graph.AddLayer<LayerType>(std::forward<Params>(params)...);
 
-    layer->SetComputeDevice(m_ComputeDevice);
+    layer->SetBackendId(GetBackendId());
     layer->SetGuid(GetGuid());
 
     return layer;
diff --git a/src/armnn/test/CreateWorkload.hpp b/src/armnn/test/CreateWorkload.hpp
index 21385d7..db1773a 100644
--- a/src/armnn/test/CreateWorkload.hpp
+++ b/src/armnn/test/CreateWorkload.hpp
@@ -32,7 +32,7 @@
     BOOST_TEST(workload.get() == boost::polymorphic_downcast<Workload*>(workload.get()),
                "Cannot convert to derived class");
     std::string reasonIfUnsupported;
-    layer.SetComputeDevice(factory.GetCompute());
+    layer.SetBackendId(factory.GetCompute());
     BOOST_TEST(factory.IsLayerSupported(layer, layer.GetDataType(), reasonIfUnsupported));
     return std::unique_ptr<Workload>(static_cast<Workload*>(workload.release()));
 }
diff --git a/src/armnn/test/GraphTests.cpp b/src/armnn/test/GraphTests.cpp
index b297a74..e99cb15 100644
--- a/src/armnn/test/GraphTests.cpp
+++ b/src/armnn/test/GraphTests.cpp
@@ -336,7 +336,7 @@
             // Both layers must have the same compute device.
             if (srcLayer && dstLayer)
             {
-                BOOST_TEST((srcLayer->GetComputeDevice() == dstLayer->GetComputeDevice()));
+                BOOST_TEST((srcLayer->GetBackendId() == dstLayer->GetBackendId()));
             }
 
             // Marks edge in original graph as observed (by deleting it).
@@ -418,7 +418,7 @@
                 }
 
                 // Both layers must have different compute devices.
-                BOOST_TEST((nonCopyLayer->GetComputeDevice() != adjLayer->GetComputeDevice()));
+                BOOST_TEST((nonCopyLayer->GetBackendId() != adjLayer->GetBackendId()));
 
                 // There must exist an edge connecting both layers directly in the original graph.
                 {
@@ -453,40 +453,40 @@
         using namespace std;
 
         Layer* const inputLayer = AddLayer<InputLayer>(0, "input");
-        inputLayer->SetComputeDevice(Compute::CpuRef);
+        inputLayer->SetBackendId(Compute::CpuRef);
 
         Convolution2dDescriptor convolutionDefaults;
         Layer* const convLayer1 = AddLayer<Convolution2dLayer>(convolutionDefaults, "conv1");
-        convLayer1->SetComputeDevice(Compute::CpuRef);
+        convLayer1->SetBackendId(Compute::CpuRef);
 
         inputLayer->GetOutputSlot(0).Connect(convLayer1->GetInputSlot(0));
 
         Layer* const convLayer2 = AddLayer<Convolution2dLayer>(convolutionDefaults, "conv2");
-        convLayer2->SetComputeDevice(Compute::CpuRef);
+        convLayer2->SetBackendId(Compute::CpuRef);
 
         convLayer1->GetOutputSlot(0).Connect(convLayer2->GetInputSlot(0));
 
         armnn::OriginsDescriptor mergerDefaults(2);
         Layer* const mergerLayer = AddLayer<MergerLayer>(mergerDefaults, "merger");
-        mergerLayer->SetComputeDevice(armnn::Compute::CpuRef);
+        mergerLayer->SetBackendId(armnn::Compute::CpuRef);
 
         convLayer1->GetOutputSlot(0).Connect(mergerLayer->GetInputSlot(0));
         convLayer2->GetOutputSlot(0).Connect(mergerLayer->GetInputSlot(1));
 
         armnn::ActivationDescriptor activationDefaults;
         Layer* const actLayer = AddLayer<ActivationLayer>(activationDefaults, "act");
-        actLayer->SetComputeDevice(armnn::Compute::CpuRef);
+        actLayer->SetBackendId(armnn::Compute::CpuRef);
 
         mergerLayer->GetOutputSlot(0).Connect(actLayer->GetInputSlot(0));
 
         armnn::SoftmaxDescriptor softmaxDefaults;
         Layer* const softmaxLayer = AddLayer<SoftmaxLayer>(softmaxDefaults, "softmax");
-        softmaxLayer->SetComputeDevice(armnn::Compute::CpuRef);
+        softmaxLayer->SetBackendId(armnn::Compute::CpuRef);
 
         actLayer->GetOutputSlot(0).Connect(softmaxLayer->GetInputSlot(0));
 
         Layer* const outputLayer = AddLayer<OutputLayer>(0, "output");
-        outputLayer->SetComputeDevice(armnn::Compute::CpuRef);
+        outputLayer->SetBackendId(armnn::Compute::CpuRef);
 
         softmaxLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
     }
@@ -537,17 +537,17 @@
     armnn::Graph graph;
 
     armnn::InputLayer* const inputLayer = graph.AddLayer<armnn::InputLayer>(0, "input");
-    inputLayer->SetComputeDevice(armnn::Compute::CpuRef);
+    inputLayer->SetBackendId(armnn::Compute::CpuRef);
 
     armnn::ViewsDescriptor splitterDesc(2);
     armnn::SplitterLayer* const splitterLayer = graph.AddLayer<armnn::SplitterLayer>(splitterDesc, "splitter");
-    splitterLayer->SetComputeDevice(armnn::Compute::GpuAcc);
+    splitterLayer->SetBackendId(armnn::Compute::GpuAcc);
 
     armnn::AdditionLayer* const additionLayer = graph.AddLayer<armnn::AdditionLayer>("addition");
-    additionLayer->SetComputeDevice(armnn::Compute::CpuRef);
+    additionLayer->SetBackendId(armnn::Compute::CpuRef);
 
     armnn::OutputLayer* const outputLayer = graph.AddLayer<armnn::OutputLayer>(0, "output");
-    outputLayer->SetComputeDevice(armnn::Compute::CpuRef);
+    outputLayer->SetBackendId(armnn::Compute::CpuRef);
 
     inputLayer->GetOutputSlot(0).Connect(splitterLayer->GetInputSlot(0));
     splitterLayer->GetOutputSlot(0).Connect(additionLayer->GetInputSlot(0));
@@ -568,10 +568,10 @@
     armnn::Graph graph;
 
     armnn::InputLayer* const inputLayer = graph.AddLayer<armnn::InputLayer>(0, "layer");
-    inputLayer->SetComputeDevice(armnn::Compute::CpuRef);
+    inputLayer->SetBackendId(armnn::Compute::CpuRef);
 
     armnn::OutputLayer* const outputLayer = graph.AddLayer<armnn::OutputLayer>(0, "layer");
-    outputLayer->SetComputeDevice(armnn::Compute::CpuRef);
+    outputLayer->SetBackendId(armnn::Compute::CpuRef);
 
     inputLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
 
diff --git a/src/armnn/test/NetworkTests.cpp b/src/armnn/test/NetworkTests.cpp
index f131946..3b426fa 100644
--- a/src/armnn/test/NetworkTests.cpp
+++ b/src/armnn/test/NetworkTests.cpp
@@ -510,7 +510,7 @@
     armnn::NeonWorkloadFactory fact;
     for (auto&& layer : static_cast<armnn::OptimizedNetwork*>(optNet.get())->GetGraph())
     {
-        BOOST_CHECK_EQUAL(armnn::Compute::CpuAcc, layer->GetComputeDevice());
+        BOOST_CHECK(layer->GetBackendId() == armnn::Compute::CpuAcc);
         BOOST_CHECK_NO_THROW(
             layer->CreateWorkload(static_cast<armnn::OptimizedNetwork*>(optNet.get())->GetGraph(), fact));
     }
@@ -541,7 +541,7 @@
     armnn::ClWorkloadFactory fact;
     for (auto&& layer : static_cast<armnn::OptimizedNetwork*>(optNet.get())->GetGraph())
     {
-        BOOST_CHECK_EQUAL(armnn::Compute::GpuAcc, layer->GetComputeDevice());
+        BOOST_CHECK(layer->GetBackendId() == armnn::Compute::GpuAcc);
         BOOST_CHECK_NO_THROW(
             layer->CreateWorkload(static_cast<armnn::OptimizedNetwork*>(optNet.get())->GetGraph(), fact));
     }
@@ -609,14 +609,14 @@
 #if ARMCOMPUTENEON_ENABLED
         if (layer->GetType() == armnn::LayerType::Input || layer->GetType() == armnn::LayerType::Output)
         {
-            BOOST_CHECK_EQUAL(armnn::Compute::CpuAcc, layer->GetComputeDevice());
+            BOOST_CHECK(layer->GetBackendId() == armnn::Compute::CpuAcc);
         }
         else if (layer->GetType() == armnn::LayerType::Normalization)
         {
-            BOOST_CHECK_EQUAL(armnn::Compute::CpuRef, layer->GetComputeDevice());
+            BOOST_CHECK(layer->GetBackendId() == armnn::Compute::CpuRef);
         }
 #else
-        BOOST_CHECK_EQUAL(armnn::Compute::CpuRef, layer->GetComputeDevice());
+        BOOST_CHECK(layer->GetBackendId() == armnn::Compute::CpuRef);
 #endif
     }
 }
@@ -747,7 +747,7 @@
     armnn::RefWorkloadFactory fact;
     for (auto&& layer : static_cast<armnn::OptimizedNetwork*>(optNet.get())->GetGraph())
     {
-        BOOST_CHECK_EQUAL(armnn::Compute::CpuRef, layer->GetComputeDevice());
+        BOOST_CHECK(layer->GetBackendId() == armnn::Compute::CpuRef);
         BOOST_CHECK_NO_THROW(
             layer->CreateWorkload(static_cast<armnn::OptimizedNetwork*>(optNet.get())->GetGraph(), fact));
     }
@@ -791,23 +791,23 @@
 #if ARMCOMPUTENEON_ENABLED
         if (layer->GetType() == armnn::LayerType::Input || layer->GetType() == armnn::LayerType::Output)
         {
-            BOOST_CHECK_EQUAL(armnn::Compute::CpuAcc, layer->GetComputeDevice());
+            BOOST_CHECK(layer->GetBackendId() == armnn::Compute::CpuAcc);
         }
         else if (layer->GetType() == armnn::LayerType::Normalization)
         {
-            BOOST_CHECK_EQUAL(armnn::Compute::CpuRef, layer->GetComputeDevice());
+            BOOST_CHECK(layer->GetBackendId() == armnn::Compute::CpuRef);
         }
 #elif ARMCOMPUTECL_ENABLED
         if (layer->GetType() == armnn::LayerType::Input || layer->GetType() == armnn::LayerType::Output)
         {
-            BOOST_CHECK_EQUAL(armnn::Compute::GpuAcc, layer->GetComputeDevice());
+            BOOST_CHECK(layer->GetBackendId() == armnn::Compute::GpuAcc);
         }
         else if (layer->GetType() == armnn::LayerType::Normalization)
         {
-            BOOST_CHECK_EQUAL(armnn::Compute::CpuRef, layer->GetComputeDevice());
+            BOOST_CHECK(layer->GetBackendId() == armnn::Compute::CpuRef);
         }
 #else
-        BOOST_CHECK_EQUAL(armnn::Compute::CpuRef, layer->GetComputeDevice());
+        BOOST_CHECK(layer->GetBackendId() == armnn::Compute::CpuRef);
 #endif
     }
 }
@@ -841,7 +841,7 @@
 
     for (auto&& layer : static_cast<armnn::OptimizedNetwork*>(optNet.get())->GetGraph())
     {
-        BOOST_CHECK_EQUAL(armnn::Compute::CpuRef, layer->GetComputeDevice());
+        BOOST_CHECK(layer->GetBackendId() == armnn::Compute::CpuRef);
     }
 }
 
@@ -874,7 +874,7 @@
 
     for (auto&& layer : static_cast<armnn::OptimizedNetwork*>(optNet.get())->GetGraph())
     {
-        BOOST_CHECK_EQUAL(armnn::Compute::CpuRef, layer->GetComputeDevice());
+        BOOST_CHECK(layer->GetBackendId() == armnn::Compute::CpuRef);
     }
 }
 
diff --git a/src/backends/WorkloadFactory.cpp b/src/backends/WorkloadFactory.cpp
index 05919d6..e7dec49 100644
--- a/src/backends/WorkloadFactory.cpp
+++ b/src/backends/WorkloadFactory.cpp
@@ -3,6 +3,7 @@
 // SPDX-License-Identifier: MIT
 //
 #include <backends/WorkloadFactory.hpp>
+#include <backends/LayerSupportRegistry.hpp>
 
 #include <backends/reference/RefWorkloadFactory.hpp>
 #include <backends/neon/NeonWorkloadFactory.hpp>
@@ -54,16 +55,19 @@
     }
 }
 
-bool IWorkloadFactory::IsLayerSupported(Compute compute,
+bool IWorkloadFactory::IsLayerSupported(const BackendId& backendId,
                                         const IConnectableLayer& connectableLayer,
                                         boost::optional<DataType> dataType,
                                         std::string& outReasonIfUnsupported)
 {
-    constexpr size_t reasonCapacity = 1024;
-    char reason[reasonCapacity];
+    Optional<std::string&> reason = outReasonIfUnsupported;
     bool result;
     const Layer& layer = *(boost::polymorphic_downcast<const Layer*>(&connectableLayer));
 
+    auto const& layerSupportRegistry = LayerSupportRegistryInstance();
+    auto layerSupportFactory = layerSupportRegistry.GetFactory(backendId);
+    auto layerSupportObject = layerSupportFactory();
+
     switch(layer.GetType())
     {
         case LayerType::Activation:
@@ -71,12 +75,11 @@
             auto cLayer = boost::polymorphic_downcast<const ActivationLayer*>(&layer);
             const TensorInfo& input = layer.GetInputSlot(0).GetConnection()->GetTensorInfo();
             const TensorInfo& output = layer.GetOutputSlot(0).GetTensorInfo();
-            result = IsActivationSupported(compute,
+            result = layerSupportObject->IsActivationSupported(
                                            OverrideDataType(input, dataType),
                                            OverrideDataType(output, dataType),
                                            cLayer->GetParameters(),
-                                           reason,
-                                           reasonCapacity);
+                                           reason);
             break;
         }
         case LayerType::Addition:
@@ -84,12 +87,11 @@
             const TensorInfo& input0 = layer.GetInputSlot(0).GetConnection()->GetTensorInfo();
             const TensorInfo& input1 = layer.GetInputSlot(1).GetConnection()->GetTensorInfo();
             const TensorInfo& output = layer.GetOutputSlot(0).GetTensorInfo();
-            result = IsAdditionSupported(compute,
+            result = layerSupportObject->IsAdditionSupported(
                                         OverrideDataType(input0, dataType),
                                         OverrideDataType(input1, dataType),
                                         OverrideDataType(output, dataType),
-                                        reason,
-                                        reasonCapacity);
+                                        reason);
             break;
         }
         case LayerType::BatchNormalization:
@@ -101,7 +103,7 @@
             const TensorInfo& var = cLayer->m_Variance->GetTensorInfo();
             const TensorInfo& beta = cLayer->m_Beta->GetTensorInfo();
             const TensorInfo& gamma = cLayer->m_Gamma->GetTensorInfo();
-            result = IsBatchNormalizationSupported(compute,
+            result = layerSupportObject->IsBatchNormalizationSupported(
                                                    OverrideDataType(input, dataType),
                                                    OverrideDataType(output, dataType),
                                                    OverrideDataType(mean, dataType),
@@ -109,27 +111,27 @@
                                                    OverrideDataType(beta, dataType),
                                                    OverrideDataType(gamma, dataType),
                                                    cLayer->GetParameters(),
-                                                   reason, reasonCapacity);
+                                                   reason);
             break;
         }
         case LayerType::Constant:
         {
             const TensorInfo& output = layer.GetOutputSlot(0).GetTensorInfo();
-            result = IsConstantSupported(compute, OverrideDataType(output, dataType), reason, reasonCapacity);
+            result = layerSupportObject->IsConstantSupported(OverrideDataType(output, dataType), reason);
             break;
         }
         case LayerType::ConvertFp16ToFp32:
         {
             const TensorInfo& input = layer.GetInputSlot(0).GetConnection()->GetTensorInfo();
             const TensorInfo& output = layer.GetOutputSlot(0).GetTensorInfo();
-            result = IsConvertFp16ToFp32Supported(compute, input, output, reason, reasonCapacity);
+            result = layerSupportObject->IsConvertFp16ToFp32Supported(input, output, reason);
             break;
         }
         case LayerType::ConvertFp32ToFp16:
         {
             const TensorInfo& input = layer.GetInputSlot(0).GetConnection()->GetTensorInfo();
             const TensorInfo& output = layer.GetOutputSlot(0).GetTensorInfo();
-            result = IsConvertFp32ToFp16Supported(compute, input, output, reason, reasonCapacity);
+            result = layerSupportObject->IsConvertFp32ToFp16Supported(input, output, reason);
             break;
         }
         case LayerType::Convolution2d:
@@ -151,23 +153,22 @@
                     OverrideDataType(cLayer->m_Bias->GetTensorInfo(), GetBiasTypeFromWeightsType(dataType));
             }
 
-            result = IsConvolution2dSupported(compute,
+            result = layerSupportObject->IsConvolution2dSupported(
                                               input,
                                               output,
                                               descriptor,
                                               OverrideDataType(cLayer->m_Weight->GetTensorInfo(), dataType),
                                               biases,
-                                              reason,
-                                              reasonCapacity);
+                                              reason);
             break;
         }
         case LayerType::MemCopy:
         {
             // MemCopy supported for CpuRef, CpuAcc and GpuAcc backends,
             // (also treat Undefined as CpuRef to avoid breaking lots of Unit tests).
-            result = compute == Compute::CpuRef || compute == Compute::Undefined
-                || compute == Compute::CpuAcc || compute == Compute::GpuAcc;
-            strcpy(reason, "Unsupported backend type");
+            result = backendId == Compute::CpuRef || backendId == Compute::Undefined
+                || backendId == Compute::CpuAcc || backendId == Compute::GpuAcc;
+            reason.value() = "Unsupported backend type";
             break;
         }
         case LayerType::DepthwiseConvolution2d:
@@ -188,30 +189,31 @@
                     OverrideDataType(cLayer->m_Bias->GetTensorInfo(), GetBiasTypeFromWeightsType(dataType));
             }
 
-            result = IsDepthwiseConvolutionSupported(compute,
+            result = layerSupportObject->IsDepthwiseConvolutionSupported(
                                                      input,
                                                      output,
                                                      descriptor,
                                                      OverrideDataType(cLayer->m_Weight->GetTensorInfo(), dataType),
                                                      biases,
-                                                     reason,
-                                                     reasonCapacity);
+                                                     reason);
             break;
         }
         case LayerType::FakeQuantization:
         {
             auto cLayer = boost::polymorphic_downcast<const FakeQuantizationLayer*>(&layer);
             const TensorInfo& input = layer.GetInputSlot(0).GetConnection()->GetTensorInfo();
-            result = IsFakeQuantizationSupported(compute, OverrideDataType(input, dataType), cLayer->GetParameters(),
-                                                 reason, reasonCapacity);
+            result = layerSupportObject->IsFakeQuantizationSupported(OverrideDataType(input, dataType),
+                                                                     cLayer->GetParameters(),
+                                                                     reason);
             break;
         }
         case LayerType::Floor:
         {
             const TensorInfo& input = layer.GetInputSlot(0).GetConnection()->GetTensorInfo();
             const TensorInfo& output = layer.GetOutputSlot(0).GetTensorInfo();
-            result = IsFloorSupported(compute, OverrideDataType(input, dataType), OverrideDataType(output, dataType),
-                                      reason, reasonCapacity);
+            result = layerSupportObject->IsFloorSupported(OverrideDataType(input, dataType),
+                                                          OverrideDataType(output, dataType),
+                                                          reason);
             break;
         }
         case LayerType::FullyConnected:
@@ -261,20 +263,19 @@
                 }
             }
 
-            result = IsFullyConnectedSupported(compute,
+            result = layerSupportObject->IsFullyConnectedSupported(
                                                OverrideDataType(input, dataType),
                                                OverrideDataType(output, dataType),
                                                OverrideDataType(cLayer->m_Weight->GetTensorInfo(), dataType),
                                                *biasInfoPtr,
                                                descriptor,
-                                               reason,
-                                               reasonCapacity);
+                                               reason);
             break;
         }
         case LayerType::Input:
         {
             const TensorInfo& input = layer.GetOutputSlot(0).GetTensorInfo();
-            result = IsInputSupported(compute, OverrideDataType(input, dataType), reason, reasonCapacity);
+            result = layerSupportObject->IsInputSupported(OverrideDataType(input, dataType), reason);
             break;
         }
         case LayerType::L2Normalization:
@@ -285,12 +286,11 @@
             const TensorInfo& input = layer.GetInputSlot(0).GetConnection()->GetTensorInfo();
             const TensorInfo& output = layer.GetOutputSlot(0).GetTensorInfo();
 
-            result = IsL2NormalizationSupported(compute,
+            result = layerSupportObject->IsL2NormalizationSupported(
                                                 OverrideDataType(input, dataType),
                                                 OverrideDataType(output, dataType),
                                                 descriptor,
-                                                reason,
-                                                reasonCapacity);
+                                                reason);
             break;
         }
         case LayerType::Lstm:
@@ -393,7 +393,7 @@
                 cellToOutputWeights = &optCellToOutputWeights;
             }
 
-            result = IsLstmSupported(compute,
+            result = layerSupportObject->IsLstmSupported(
                                      input,
                                      outputStateIn,
                                      cellStateIn,
@@ -419,8 +419,7 @@
                                      projectionBias,
                                      cellToForgetWeights,
                                      cellToOutputWeights,
-                                     reason,
-                                     reasonCapacity);
+                                     reason);
             break;
         }
         case LayerType::Merger:
@@ -444,7 +443,7 @@
             auto endPtr = boost::make_transform_iterator(inputs.end(), getTensorInfoPtr);
             std::vector<const TensorInfo*> inputPtrs(beginPtr, endPtr);
 
-            result = IsMergerSupported(compute, inputPtrs, cLayer->GetParameters(), reason, reasonCapacity);
+            result = layerSupportObject->IsMergerSupported(inputPtrs, cLayer->GetParameters(), reason);
             break;
         }
         case LayerType::Multiplication:
@@ -452,12 +451,11 @@
             const TensorInfo& input0 = layer.GetInputSlot(0).GetConnection()->GetTensorInfo();
             const TensorInfo& input1 = layer.GetInputSlot(1).GetConnection()->GetTensorInfo();
             const TensorInfo& output = layer.GetOutputSlot(0).GetTensorInfo();
-            result = IsMultiplicationSupported(compute,
+            result = layerSupportObject->IsMultiplicationSupported(
                                                OverrideDataType(input0, dataType),
                                                OverrideDataType(input1, dataType),
                                                OverrideDataType(output, dataType),
-                                               reason,
-                                               reasonCapacity);
+                                               reason);
             break;
         }
         case LayerType::Normalization:
@@ -465,15 +463,16 @@
             auto cLayer = boost::polymorphic_downcast<const NormalizationLayer*>(&layer);
             const TensorInfo& input = layer.GetInputSlot(0).GetConnection()->GetTensorInfo();
             const TensorInfo& output = layer.GetOutputSlot(0).GetTensorInfo();
-            result = IsNormalizationSupported(compute, OverrideDataType(input, dataType),
-                                              OverrideDataType(output, dataType), cLayer->GetParameters(), reason,
-                                              reasonCapacity);
+            result = layerSupportObject->IsNormalizationSupported(OverrideDataType(input, dataType),
+                                                                  OverrideDataType(output, dataType),
+                                                                  cLayer->GetParameters(),
+                                                                  reason);
             break;
         }
         case LayerType::Output:
         {
             const TensorInfo& output = layer.GetInputSlot(0).GetConnection()->GetTensorInfo();
-            result = IsOutputSupported(compute, OverrideDataType(output, dataType), reason, reasonCapacity);
+            result = layerSupportObject->IsOutputSupported(OverrideDataType(output, dataType), reason);
             break;
         }
         case LayerType::Permute:
@@ -481,8 +480,10 @@
             auto cLayer = boost::polymorphic_downcast<const PermuteLayer*>(&layer);
             const TensorInfo& input = layer.GetInputSlot(0).GetConnection()->GetTensorInfo();
             const TensorInfo& output = layer.GetOutputSlot(0).GetTensorInfo();
-            result = IsPermuteSupported(compute, OverrideDataType(input, dataType), OverrideDataType(output, dataType),
-                                        cLayer->GetParameters(), reason, reasonCapacity);
+            result = layerSupportObject->IsPermuteSupported(OverrideDataType(input, dataType),
+                                                            OverrideDataType(output, dataType),
+                                                            cLayer->GetParameters(),
+                                                            reason);
             break;
         }
         case LayerType::Pad:
@@ -490,12 +491,11 @@
             auto cLayer = boost::polymorphic_downcast<const PadLayer*>(&layer);
             const TensorInfo& input = layer.GetInputSlot(0).GetConnection()->GetTensorInfo();
             const TensorInfo& output = layer.GetOutputSlot(0).GetTensorInfo();
-            result = IsPadSupported(compute,
+            result = layerSupportObject->IsPadSupported(
                                     OverrideDataType(input, dataType),
                                     OverrideDataType(output, dataType),
                                     cLayer->GetParameters(),
-                                    reason,
-                                    reasonCapacity);
+                                    reason);
             break;
         }
         case LayerType::Pooling2d:
@@ -503,9 +503,10 @@
             auto cLayer = boost::polymorphic_downcast<const Pooling2dLayer*>(&layer);
             const TensorInfo& input = layer.GetInputSlot(0).GetConnection()->GetTensorInfo();
             const TensorInfo& output = layer.GetOutputSlot(0).GetTensorInfo();
-            result = IsPooling2dSupported(compute, OverrideDataType(input, dataType),
-                                          OverrideDataType(output, dataType), cLayer->GetParameters(), reason,
-                                          reasonCapacity);
+            result = layerSupportObject->IsPooling2dSupported(OverrideDataType(input, dataType),
+                                                              OverrideDataType(output, dataType),
+                                                              cLayer->GetParameters(),
+                                                              reason);
             break;
         }
         case LayerType::Division:
@@ -513,24 +514,23 @@
             const TensorInfo& input0 = layer.GetInputSlot(0).GetConnection()->GetTensorInfo();
             const TensorInfo& input1 = layer.GetInputSlot(1).GetConnection()->GetTensorInfo();
             const TensorInfo& output = layer.GetOutputSlot(0).GetTensorInfo();
-            result = IsDivisionSupported(compute,
+            result = layerSupportObject->IsDivisionSupported(
                                          OverrideDataType(input0, dataType),
                                          OverrideDataType(input1, dataType),
                                          OverrideDataType(output, dataType),
-                                         reason,
-                                         reasonCapacity);
+                                         reason);
             break;
         }
         case LayerType::Reshape:
         {
             const TensorInfo& input = layer.GetInputSlot(0).GetConnection()->GetTensorInfo();
-            result = IsReshapeSupported(compute, OverrideDataType(input, dataType), reason, reasonCapacity);
+            result = layerSupportObject->IsReshapeSupported(OverrideDataType(input, dataType), reason);
             break;
         }
         case LayerType::ResizeBilinear:
         {
             const TensorInfo& input = layer.GetInputSlot(0).GetConnection()->GetTensorInfo();
-            result = IsResizeBilinearSupported(compute, OverrideDataType(input, dataType), reason, reasonCapacity);
+            result = layerSupportObject->IsResizeBilinearSupported(OverrideDataType(input, dataType), reason);
             break;
         }
         case LayerType::Softmax:
@@ -538,16 +538,19 @@
             auto cLayer = boost::polymorphic_downcast<const SoftmaxLayer*>(&layer);
             const TensorInfo& input = layer.GetInputSlot(0).GetConnection()->GetTensorInfo();
             const TensorInfo& output = layer.GetOutputSlot(0).GetTensorInfo();
-            result = IsSoftmaxSupported(compute, OverrideDataType(input, dataType), OverrideDataType(output, dataType),
-                                        cLayer->GetParameters(), reason, reasonCapacity);
+            result = layerSupportObject->IsSoftmaxSupported(OverrideDataType(input, dataType),
+                                                            OverrideDataType(output, dataType),
+                                                            cLayer->GetParameters(),
+                                                            reason);
             break;
         }
         case LayerType::Splitter:
         {
             auto cLayer = boost::polymorphic_downcast<const SplitterLayer*>(&layer);
             const TensorInfo& input = layer.GetInputSlot(0).GetConnection()->GetTensorInfo();
-            result = IsSplitterSupported(compute, OverrideDataType(input, dataType), cLayer->GetParameters(), reason,
-                                         reasonCapacity);
+            result = layerSupportObject->IsSplitterSupported(OverrideDataType(input, dataType),
+                                                             cLayer->GetParameters(),
+                                                             reason);
             break;
         }
         case LayerType::Subtraction:
@@ -555,12 +558,11 @@
             const TensorInfo& input0 = layer.GetInputSlot(0).GetConnection()->GetTensorInfo();
             const TensorInfo& input1 = layer.GetInputSlot(1).GetConnection()->GetTensorInfo();
             const TensorInfo& output = layer.GetOutputSlot(0).GetTensorInfo();
-            result = IsSubtractionSupported(compute,
+            result = layerSupportObject->IsSubtractionSupported(
                                             OverrideDataType(input0, dataType),
                                             OverrideDataType(input1, dataType),
                                             OverrideDataType(output, dataType),
-                                            reason,
-                                            reasonCapacity);
+                                            reason);
             break;
         }
         case LayerType::Mean:
@@ -568,23 +570,21 @@
             auto cLayer = boost::polymorphic_downcast<const MeanLayer*>(&layer);
             const TensorInfo& input = layer.GetInputSlot(0).GetConnection()->GetTensorInfo();
             const TensorInfo& output = layer.GetOutputSlot(0).GetTensorInfo();
-            result = IsMeanSupported(compute,
+            result = layerSupportObject->IsMeanSupported(
                                      OverrideDataType(input, dataType),
                                      OverrideDataType(output, dataType),
                                      cLayer->GetParameters(),
-                                     reason,
-                                     reasonCapacity);
+                                     reason);
             break;
         }
         default:
         {
             BOOST_ASSERT_MSG(false, "WorkloadFactory did not recognise type of layer.");
-            strcpy(reason, "Unrecognised layer type");
+            reason.value() = "Unrecognised layer type";
             result = false;
             break;
         }
     }
-    outReasonIfUnsupported = reason;
     return result;
 }
 
@@ -593,7 +593,7 @@
                                         std::string& outReasonIfUnsupported)
 {
     auto layer = boost::polymorphic_downcast<const Layer*>(&connectableLayer);
-    return IsLayerSupported(layer->GetComputeDevice(), connectableLayer, dataType, outReasonIfUnsupported);
+    return IsLayerSupported(layer->GetBackendId(), connectableLayer, dataType, outReasonIfUnsupported);
 }
 
 }
diff --git a/src/backends/WorkloadFactory.hpp b/src/backends/WorkloadFactory.hpp
index 38448ca..41d6741 100644
--- a/src/backends/WorkloadFactory.hpp
+++ b/src/backends/WorkloadFactory.hpp
@@ -32,7 +32,7 @@
     /// Inform the memory manager to acquire memory
     virtual void Acquire() { }
 
-    static bool IsLayerSupported(Compute compute,
+    static bool IsLayerSupported(const BackendId& backendId,
                                  const IConnectableLayer& layer,
                                  boost::optional<DataType> dataType,
                                  std::string& outReasonIfUnsupported);