Blink API

Using Blink in the NDK

Introduction

Blink integrates into NUKE's PlanarIops to allow you to do Blink-based image processing inside an NDK plug-in, and get the benefits of Blink's SIMD and GPU acceleration.

You can also run Blink kernels inside the BlinkScript node, but the advantage of writing your own Blink-based plug-ins is that images can be left on the GPU between kernel iterations. This can lead to a considerable saving in transfer time to-and-from the GPU, especially if you are running many Blink kernels on the same images.

In addition, the API gives you access to ImageRollingKernels and ImageReductionKernels, neither of which can be used inside the BlinkScript node.

Getting Data To and From Blink Images

In order to do any image processing with Blink, your data needs to be in a Blink Image. In Nuke, there are two ways to achieve this.

Using DD::Image::ImagePlanes

DD::Image::ImagePlanes can be wrapped up in Blink::Images, using the ImagePlaneAsBlinkImage function in the Blink.h header file in include/DDImage.

bool ImagePlaneAsBlinkImage(DD::Image::ImagePlane &imagePlane, Blink::Image &blinkImage)

You should check the return value from this function to make sure the call has been successful before attempting to use the Blink Image. An unsuccessful call will not make any changes to the ImagePlane passed in.

When this function returns true, "blinkImage" will be assigned to a Blink::Image which shares its underlying memory buffer with "imagePlane". This memory buffer will not be changed by Image independently of imagePlane, so can continue to be used even if the original image plane is deleted or goes out of scope.

Nuke's ImagePlanes are always on the CPU at present, so a Blink Image set up with the ImagePlaneAsBlinkImage will also be on the CPU. Use the distributeTo() or makeLike() functions on the Blink Image to transfer it to the GPU.

Copying your own data to and from Blink Images

You can also use the copyToBuffer() and copyFromBuffer() functions to copy data from a buffer on the CPU to and from a Blink Image. As well as a pointer to the data buffer, these functions take a BlinkBufferDesc that describes how data is laid out inside the buffer:

  • "pixelStepBytes" is the number of bytes required to step from one pixel to the next. For example, in a planar layout such as RRRRGGGGBBBBAAAA, this will be the size in bytes of one component of a pixel, e.g. sizeof(R). In a packed layout such as RGBARGBARGBARGBA, it will be the size in bytes of one component multiplied by the number of components, e.g. sizeof(RGBA).
  • "rowStepBytes" is the number of bytes required to step from the start of one row to the start of the next. In a planar layout this will be the width of the image multiplied by the size of a component, plus any padding that has been added to the end of each row. For a packed layout, it will be the width of the image multiplied by the size of a component multiplied by the number of components, again plus any padding that has been added to the end of each row.
  • "componentStepBytes" is the number of bytes required to step from one component within a pixel to the next component, e.g. from R to G. In a planar layout this will be the size in bytes of one component multiplied by the size of the image. In a packed layout, this will be the size in bytes of one component.

Example Plug-in

Building the Example Plug-in

Building the example plug-in is exactly like building any other NDK plug-in, but there is one extra library you need to link against. This is libRIPFramework.*, where the ".*" represents the dynamic library extension for your operating system.

 All Classes Namespaces Files Functions Variables


©2013 The Foundry Visionmongers, Ltd. All Rights Reserved.