Vectors Specification Kernel

// Copyright (c) 2024 The Foundry Visionmongers Ltd.  All Rights Reserved.
kernel SpecificationVectorsKernel: ImageComputationKernel<ePixelWise>
{
  Image<eWrite, eAccessPoint> output;

param:
  float3 param1;
  int4 param2;

  void define()
  {
    /// Vectors can be defined and passed through as params.
    defineParam(param1, "param1", float3(1.0f, 2.0f, 3.0f));
    defineParam(param2, "param2", int4(1, 2, 3, 4));
  }

local:
  float3 local1;
  int4 local2;

  void init()
  {
    /// Vectors can be declared as locals and initialised in init().
    local1 = float3(1.0f, 2.0f, 3.0f) * 3.0f;
    local2 = int4(1, 2, 3, 4) + int4(2, 7, 3, 9);
  }

  void VectorOperationsExample()
  {
    /// Vectors can be either int or float types with 1-4 components in Blink i.e. int1, float3 etc.
    /// They can be constructed in intuitive ways as supported in C++:
    // C++ style constructor. Makes an int2 vector (5, 10).
    int2 i2(5, 10);
    // Initializer list construction. Makes a float3 vector (2.1f, 2.2f, 2.3f).
    float3 f3{2.1f, 2.2f, 2.3f};
    // Assignment constructor. Makes a float4 vector (1.0f, 2.0f, 3.0f, 4.0f).
    float4 f4 = float4(1.0f, 2.0f, 3.0f, 4.0f);
    // Singleton constructor. A constructor for a vector with multiple components
    // can be constructed with a single argument to produce a vector with a single
    // value for all elements. Makes an int4 vector (-10, -10, -10, -10).
    int4 i4 = int4(-10);

    /// Operators applied on vectors are applied element-wise unless specified otherwise.
    // Vector addition: int2(4, 8) + int2(2, 4) -> int2(6, 12)
    int2 addVar = int2(4, 8) + int2(2, 4);
    // Vector subtraction: int2(4, 8) - int2(2, 4) -> int2(2, 4)
    int2 subVar = int2(4, 8) - int2(2, 4);
    // Vector multiplication: int2(4, 8) * int2(2, 4) -> int2(8, 32)
    int2 mulVar = int2(4, 8) * int2(2, 4);
    // Vector division: int2(4, 8) / int2(2, 4) -> int2(2, 2)
    int2 divVar = int2(4, 8) / int2(2, 4);
    // Unary minus: -int2(4, 8) -> int2(-4, -8);
    int2 unaryMinVar = -int2(4, 8);

    /// 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.
    // int2(4, 8) + 7 -> int2(11, 15)
    int2 typePromotion1 = int2(4, 8) + 7;
    // float2(0.1f, 0.2f) + 1 -> float2(1.1f, 1.2f)
    float2 typePromotion2 = float2(0.1f, 0.2f) + 1;
    // 0.1f + int2(1) -> float2(1.1f, 1.1f)
    float2 typePromotion3 = 0.1f + int2(1);

    {
      /// Individual elements of a vector can be accessed with a swizzle operator.
      float4 vec4 = float4(1.1f, 1.2f, 1.3f, 1.4f);
      // Reading from each component.
      float comp0 = vec4.x;
      float comp1 = vec4.y;
      float comp2 = vec4.z;
      float comp3 = vec4.w;
      // Assigning to a specific component.
      // New value of vec4 is now float4(1.1f, 1.2f, 23.0f, 1.4f)
      vec4.z = 23.0f;
    }
    {
      /// Individual elements of a vector can be accessed with a subscript operator.
      float4 vec4 = float4(1.1f, 1.2f, 1.3f, 1.4f);
      // Reading from each component.
      float comp0 = vec4[0];
      float comp1 = vec4[1];
      float comp2 = vec4[2];
      float comp3 = vec4[3];
      // Assigning to a specific component.
      // New value of vec4 is now float4(1.1f, 1.2f, 23.0f, 1.4f)
      vec4[2] = 23.0f;
      // Iterate through and set first 3 components of the vector.
      // New value of vec4 is now float4(0.5f, 0.5f, 0.5f, 1.4f)
      for (int c = 0; c < 3; c++) {
        vec4[c] = 0.5f;
      }
    }

    // Writing out a vector to an image.
    output() = f4;
  }

  void process(int2 pos)
  {
    VectorOperationsExample();
  }
};