/// <summary>
        /// Encode a MPSCnnKernel into a command Buffer. The operation shall proceed out-of-place.
        /// We calculate the appropriate offset as per how TensorFlow calculates its padding using input image size and stride here.
        /// This [Link](https://github.com/tensorflow/tensorflow/blob/master/tensorflow/python/ops/nn.py) has an explanation in header comments how tensorFlow pads its convolution input images.
        /// </summary>
        /// <param name="commandBuffer">A valid MTLCommandBuffer to receive the encoded filter</param>
        /// <param name="sourceImage">A valid MPSImage object containing the source image.</param>
        /// <param name="destinationImage">A valid MPSImage to be overwritten by result image. destinationImage may not alias sourceImage</param>
        public override void EncodeToCommandBuffer(IMTLCommandBuffer commandBuffer, MPSImage sourceImage, MPSImage destinationImage)
        {
            // select offset according to padding being used or not
            if (padding)
            {
                var pad_along_height = ((destinationImage.Height - 1) * StrideInPixelsY + KernelHeight - sourceImage.Height);
                var pad_along_width  = ((destinationImage.Width - 1) * StrideInPixelsX + KernelWidth - sourceImage.Width);
                var pad_top          = pad_along_height / 2;
                var pad_left         = pad_along_width / 2;

                Offset = new MPSOffset {
                    X = (nint)(KernelWidth / 2 - pad_left),
                    Y = (nint)(KernelHeight / 2 - pad_top),
                    Z = 0
                };
            }
            else
            {
                Offset = new MPSOffset {
                    X = (nint)(KernelWidth / 2),
                    Y = (nint)(KernelHeight / 2),
                    Z = 0
                };
            }
            base.EncodeToCommandBuffer(commandBuffer, sourceImage, destinationImage);
        }
		/// <summary>
		/// Encode a MPSCnnKernel into a command Buffer. The operation shall proceed out-of-place.
		/// We calculate the appropriate offset as per how TensorFlow calculates its padding using input image size and stride here.
		/// This [Link](https://github.com/tensorflow/tensorflow/blob/master/tensorflow/python/ops/nn.py) has an explanation in header comments how tensorFlow pads its convolution input images.
		/// </summary>
		/// <param name="commandBuffer">A valid MTLCommandBuffer to receive the encoded filter</param>
		/// <param name="sourceImage">A valid MPSImage object containing the source image.</param>
		/// <param name="destinationImage">A valid MPSImage to be overwritten by result image. destinationImage may not alias sourceImage</param>
		public override void EncodeToCommandBuffer (IMTLCommandBuffer commandBuffer, MPSImage sourceImage, MPSImage destinationImage)
		{
			// select offset according to padding being used or not
			if (padding) {
				var pad_along_height = ((destinationImage.Height - 1) * StrideInPixelsY + KernelHeight - sourceImage.Height);
				var pad_along_width = ((destinationImage.Width - 1) * StrideInPixelsX + KernelWidth - sourceImage.Width);
				var pad_top = pad_along_height / 2;
				var pad_left = pad_along_width / 2;

				Offset = new MPSOffset {
					X = (nint)(KernelWidth / 2 - pad_left),
					Y = (nint)(KernelHeight / 2 - pad_top),
					Z = 0
				};
			} else {
				Offset = new MPSOffset {
					X = (nint)(KernelWidth / 2),
					Y = (nint)(KernelHeight / 2),
					Z = 0
				};
			}
			base.EncodeToCommandBuffer (commandBuffer, sourceImage, destinationImage);
		}