/// <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); }