Skip to content
Logo LogoGuide to using Blink
⌘ K
Logo LogoGuide to using Blink

Table of Contents

  • Introduction
  • Quick Start
  • Examples
  • Blink Kernel Reference
    • Kernels
    • Images
    • Maths Functions
    • Variable Types
    • Blink Language Features
      • Blink Types
      • Kernel definition
        • Image input and output definitions
        • Kernel parameters and locals
        • Special Kernel functions
        • User-defined functions
      • Flow Control
        • Conditional statements and expressions
        • Loop statements
        • Jump statements
      • Expressions and operators
        • Mixing vector and scalar types
        • Arithmetic and bitwise operators
        • Comparison operators
        • Short-circuiting logical operators
        • Assignment operators
        • Other operators
      • Preprocessor directives
      • Restricted C++ Features
  • Resources

Previous topic

Variable Types

Next topic

Resources

Guide to using Blink
>
Blink Kernel Reference
>
Blink Language Features

Blink Language Features¶

The Blink language is based on C++ with specialisations to support optimized image-processing on both CPU and GPUs.

Blink Types¶

Blink supports:

  • Scalar types: int, float, etc.

  • Vector types: float4, int3, etc.

  • Matrix types: float3x3, float4x4.

  • Fixed-size arrays: float4 arr[16];.

Kernel definition¶

Blink kernels are described with a kernel definition.

kernel *kernel-name* : ImageComputationKernel<*granularity*> {
  *image-specifications*
  *optional-parameter-block*
  *optional-local-block*
  *optional-user-functions*
  *process-function*
};

The granularity specifies whether the kernel’s process() function will be ran for each pixel or for each component. See Kernel Granularity for details.

The sections in the kernel block are listed in their traditional order. It is recommended to follow this order but not strictly necessary.

Image input and output definitions¶

Image specifications describe the kernels input and output images as well as information about they will be accessed from the process() function.

Each image specification has the following parts:

Image<*read-spec* [, *access-pattern* [, *edge-method*]]> *image-name*;

See Image Specification.

Ranged-access images should to have their ranges set in the init() special function. See The init() Function.

Note

Blink kernels run in Nuke’s BlinkScript node can only have exactly one output image.

Kernel parameters and locals¶

Kernel parameters can be specified in the optional-parameter-block. Parameters are set before launching the kernel and can be used to alter the behaviour of the kernel without recompilation.

param:
  *type* *name*;
  ...

  void define() {
    defineParam(*name*, "User-friendly name", *default-value* [, *options*]);
    ...
  }

The special function define() can be used to set user-friendly names, default values and other information for kernel parameters by calling defineParam(). See The define() Function.

Local variables can be specified in the optional-local-block. The init() function should be written so that it initialises each local variable. init() will be called once, before any calls to process(). See The init() Function.

local:
  *type* *name*;
  ...

  void init() {
    *name* = *initialiser*;
    ...
  }

Locals should only be assigned to in the init() function. Locals can be read from process() and user-functions but cannot be assigned to.

Parameters and locals can be scalar, vector or matrix types and arrays of those types. See Data Types.

Special Kernel functions¶

The define(), init() and process() functions are special kernel functions. These names are reserved and can’t be used for other things (e.g. image names, local or param variables, function-scope variables, etc).

User-defined functions¶

User functions can be defined inside the Blink kernel specification and can be called from the init() and process() functions.

User functions can access params, locals and Image properties (e.g. bounds). Image accessors can be used in user functions, but only if they are called from the process() function.

kernel UserFunctionExample : ImageComputationKernel<ePixelWise>
{
  Image<eWrite, eAccessPoint> dst;

  param:
    int borderWidth;

    void define() {
        defineParam(borderWidth, "Border width", 5, eParamProxyScale);
    }

  local:
    int2 middle;     // Position of the middle pixel.
    int4 innerBox;   // Area inside the border.

  int2 calcDstMiddle() {
    int midx = dst.bounds.x1 + dst.bounds.x2;
    int midy = dst.bounds.y1 + dst.bounds.y2;
    return int2(midx, midy) / 2;
  }

  int4 calcInnerBox() {
    return int4(dst.bounds.x1 + borderWidth,
                dst.bounds.y1 + borderWidth,
                dst.bounds.x2 - borderWidth,
                dst.bounds.y2 - borderWidth);
  }

  void init() {
    middle = calcDstMiddle();
    innerBox = calcInnerBox();
  }

  void process(int2 pos) {
    if (pos.x <= innerBox.x || pos.y <= innerBox.y ||
        pos.x >= innerBox.z || pos.y >= innerBox.w) {
      dst() = float4(1,1,1,0);
    }
    else if (pos.x < middle.x && pos.y < middle.y) {
      dst() = float4(1,0,0,0);
    }
    else if (pos.x >= middle.x && pos.y < middle.y) {
      dst() = float4(0,1,0,0);
    }
    else if (pos.x < middle.x && pos.y >= middle.y) {
      dst() = float4(0,0,1,0);
    }
    else if (pos.x >= middle.x && pos.y >= middle.y) {
      dst() = float4(1,0,1,0);
    }
  }
};

Functions can take array arguments. See arrays.

There are some restrictions on calling user functions from the Blink kernel special functions:

  • The define() function cannot call any user-defined functions.

  • The init() function can call user-defined functions, as long as they do not include accessing Images.

  • The process() function can call user-defined functions, including those that access Images.

Note

Recursive functions are not supported. User-defined functions cannot call themselves, or have a ‘cycle’ of calls through other functions.

Flow Control¶

Conditional statements and expressions¶

Blink has if and if else statements, and the ternary-operator ?: in expressions.

kernel FlowControlIfElseExample : ImageComputationKernel<eComponentWise>
{
  Image<eWrite, eAccessPoint> dst;

  void process(int2 pos) {
    bool leftedge = pos.x == 0 ? 1 : 0;
    bool topedge = pos.y == 0 ? 1 : 0;

    if (leftedge) {
      dst() = 1.0f;
    } else if (topedge) {
      dst() = 0.5f;
    } else {
      dst() = 0.0f;
    }
  }
};

Note

switch statements are not supported.

Loop statements¶

Blink has for, while loops.

kernel FlowControlLoopExample : ImageComputationKernel<ePixelWise>
{
  Image<eRead, eAccessPoint> src;
  Image<eWrite, eAccessPoint> dst;

  void process(int2 pos) {
    float sum = 0.0f;
    for (int i = 0; i < src.kComps; i++) {
      sum += src(i);
    }

    while(sum > 0.0f) {
      sum -= 1.0f;
    }

    dst(0) = sum;
  }
};

Note

do-while loops are not supported.

Jump statements¶

Loops and functions can be exited early with jump-statements, return break and continue.

kernel FlowControlLoopJumpsExample : ImageComputationKernel<ePixelWise>
{
  Image<eRead, eAccessPoint> src;
  Image<eWrite, eAccessPoint> dst;

  void process(int2 pos) {
    if (pos.x == 0 && pos.y == 0) {
      return;
    }

    float sum = 0.0f;
    for (int i = 0; i < src.kComps; i++) {
      if (src(i) == 0.0f) {
        continue;
      }
      if (sum > 1.0f) {
        break;
      }

      sum += src(i);
    }

    dst(0) = sum;
  }
};

Note

Labels and goto statements are not supported.

Expressions and operators¶

Mixing vector and scalar types¶

Expressions can include operators that use a mix of types. The type of the result is whichever type has the highest rank.

float has a higher rank than int and other scalar types, and vector-types have higher rank than scalar types.

int a = 1 + 1;      // int + int -> int
float b = 1.0f + 1; // float + int -> float

int2 c = int2(0, 1) + 42;            // int2 + int -> int2
float2 d = float2(0.1f, 0.2f) + 42;  // float2 + int -> float2
float2 e = 0.1f + int2(0);           // float + int2 -> float2

Arithmetic and bitwise operators¶

Name

Operator

Types

Addition

a + b

scalars and vectors

Subtraction

a - b

scalars and vectors

Multiplication

a * b

scalars and vectors

Division

a / b

scalars and vectors

Unary minus

-a

scalars and vectors

Modulo

a ^ b

integer scalars

Pre-increment

++a

scalars

Post-increment

a++

scalars

Pre-decrement

--a

scalars

Post-decrement

a--

scalars

Bitwise NOT

~a

bool and integer scalars

Bitwise AND

a & b

bool and integer scalars

Bitwise OR

a | b

bool and integer scalars

Bitwise XOR

a ^ b

bool and integer scalars

Bitwise left-shift

a << b

bool and integer scalars

Bitwise right-shift

a >> b

bool and integer scalars

Comparison operators¶

Name

Operator

Types

Equals

a == b

scalars

Not equals

a != b

scalars

Greater than

a > b

scalars

Less than

a < b

scalars

Greater or equal

a >= b

scalars

Less or equal

a <= b

scalars

Short-circuiting logical operators¶

Blinks logical operators are short circuiting like C and C++. In a && b expressions, a is evaluated first and only if true is b evaluated. In a || b expressions, a is evaluated first and only if false is b evaluated.

Name

Operator

Types

Logical NOT

!a

scalars

Logical AND

a && b

scalars

Logical OR

a || b

scalars

Assignment operators¶

Name

Operator

Types

Assignment

a = b

scalars and vectors

Add-assign

a += b

scalars and vectors

Sub-assign

a -= b

scalars and vectors

Multiply-assign

a *= b

scalars and vectors

Divide-assign

a /= b

scalars and vectors

Assignments between of different scalar types and vectors of the same length are generally allowed and will do a suitable conversion.

Assignments to vectors of different lengths is not allowed.

int x = 2;
int3 i3 = int3(0, 1, 2);
float f = 3.0f;
float2 f2 = float2(0.3f, 1.7f);

x = 0.1f;  // converts to int
f = 1;     // converts to float

f2 = 42;   // converts to float2, with 42.0f in both elements
i3 = float3(1.1f, 2.2f, 3.3f);  // converts to int3

// f2 = i3; // not allowed: vectors are of different lengths

Other operators¶

Name

Operator

Types

Subscript

a[i]

vectors, matrices, arrays

Function calls

f(a,b)

Ternary conditional

a ? b : c

Swizzling

a.x

vectors

Preprocessor directives¶

Some C preprocessor features are available in Blink to support macro-replacement and conditional compilation.

  • Macro replacement directives: #define, #undef.

  • Conditional compilation directives: #ifdef, #else #endif, etc.

Restricted C++ Features¶

Many C++ features are not supported by Blink. These restrictions are necessary so Blink kernels can be compiled and optimized for a wide-range of CPU and GPU targets.

Blink kernels that use any of these features can cause undefined behaviour. Compiling a kernel that uses restricted features may succeed for some targets, but may produce unexpected results or crash.

The following C++ common features are not supported:

  • Pointers

    • Pointer types and pointer variables.

    • Pointer arithmetic and related operators.

  • Enums, switch-statements and do-while loops.

  • User-defined class, struct or union types.

  • The C++ standard library is not supported.

Other less common C++ features are not supported:

  • Templates.

  • Recursive functions.

  • Variable length arrays are not supported. All arrays must be fixed-length.

  • Virtual functions.

  • Lambda functions and function pointers.

  • Type qualifies (except const) like static, volatile and thread_local, etc.

  • C++ style casts static_cast<>, dynamic_cast<>, reinterpret_cast<>.

    • Cases where a C or C++ style cast would be useful can be replaced with a conversion-constructor call for the target type.

  • Exception handling.

  • goto and labels.

  • new, delete operators and other dynamic-memory allocation functions.

  • Function and variable attributes, e.g. [[nodiscard]], noexcept.

  • C++ type-size and type-id operators: sizeof, typeid.

  • typedef and using type-aliases.

  • Some Preprocessor directives are not supported:

    • File inclusion: #include, #once, etc.

    • Implementation specific pragmas: #pragma

    • File name and line reference directives are unsupported: #line, #file, etc.

On this page

  • Blink Types
  • Kernel definition
    • Image input and output definitions
    • Kernel parameters and locals
    • Special Kernel functions
    • User-defined functions
  • Flow Control
    • Conditional statements and expressions
    • Loop statements
    • Jump statements
  • Expressions and operators
    • Mixing vector and scalar types
    • Arithmetic and bitwise operators
    • Comparison operators
    • Short-circuiting logical operators
    • Assignment operators
    • Other operators
  • Preprocessor directives
  • Restricted C++ Features

© 2025, The Foundry