// TODO merge that with NHWC : flank by transpose shape and call InferOutputShapeNHWC
        public static void UpdateKnownTensorShapesNCHW(Model model, ref IDictionary <string, int?> ranksByName, ref IDictionary <string, TensorShape?> shapesByName)
        {
            foreach (var l in model.layers)
            {
                TensorShape?[] layerInputShapes     = new TensorShape?[l.inputs.Length];
                int?[]         layerInputShapeRanks = new int?[l.inputs.Length];

                for (int i = 0; i < l.inputs.Length; i++)
                {
                    shapesByName.TryGetValue(l.inputs[i], out TensorShape? ishape);
                    ranksByName.TryGetValue(l.inputs[i], out int?irank);

                    layerInputShapes[i]     = ishape;
                    layerInputShapeRanks[i] = irank;
                }

                // knowing rank might imply knowing shape:
                // + compute rank first
                // + compute shape
                // knowing shape might imply knowing rank:
                // + compute rank
                int?outputRank = RankInference.InferOutputRank(l, layerInputShapeRanks, layerInputShapes);
                ranksByName[l.name] = outputRank;
                TensorShape?outputShape = InferOutputShapeNCHW(l, layerInputShapeRanks, layerInputShapes);
                outputRank           = RankInference.InferOutputRank(l, layerInputShapeRanks, layerInputShapes);
                ranksByName[l.name]  = outputRank;
                shapesByName[l.name] = outputShape;
            }
        }
        public static TensorShape?[] ListTemporaryTensorShapesNCHW(Model model, IDictionary <string, TensorShape> inputShapes, ref IDictionary <string, int?> ranksByName,
                                                                   out IDictionary <string, TensorShape?> shapesByName)
        {
            Profiler.BeginSample("Barracuda.ListTemporaryTensorShapesNCHW");
            var shapes = new List <TensorShape?>();

            shapesByName = new Dictionary <string, TensorShape?>();
            foreach (var i in inputShapes)
            {
                shapesByName.Add(i.Key, i.Value);
            }

            foreach (var l in model.layers)
            {
                TensorShape?[] layerInputShapes     = new TensorShape?[l.inputs.Length];
                int?[]         layerInputShapeRanks = new int?[l.inputs.Length];

                for (int i = 0; i < l.inputs.Length; i++)
                {
                    shapesByName.TryGetValue(l.inputs[i], out TensorShape? ishape);
                    ranksByName.TryGetValue(l.inputs[i], out int?irank);

                    layerInputShapes[i]     = ishape;
                    layerInputShapeRanks[i] = irank;
                }


                int?outputRank = RankInference.InferOutputRank(l, layerInputShapeRanks, layerInputShapes);
                ranksByName[l.name] = outputRank;
                TensorShape?outputShape = InferOutputShapeNCHW(l, layerInputShapeRanks, layerInputShapes);
                outputRank          = RankInference.InferOutputRank(l, layerInputShapeRanks, layerInputShapes);
                ranksByName[l.name] = outputRank;

                shapes.Add(outputShape);
                shapesByName.Add(l.name, outputShape);
            }

            Profiler.EndSample();
            return(shapes.ToArray());
        }