• 04/03/2020
  • Public Content

Putting it all Together: Example Code

This section summarizes the code snippets required to implement callback functions for an advanced tiling user node. The example node implements image transpose operation.
First, any user node requires input parameter validation function per spec (error handling is omitted):
static vx_status TranspValidator (vx_node node, const vx_reference parameters[], vx_uint32 num, vx_meta_format metas[]) { if (num!=2) //the node accepts single input (image) and single ouput only return VX_ERROR_INVALID_PARAMETERS; vx_status status = VX_FAILURE; vx_df_image format; vxQueryImage((vx_image)parameters[0],VX_IMAGE_FORMAT,&format, sizeof(format)); //input image format if (format != VX_DF_IMAGE_U8)//the node supports only U8 images { return VX_INVALID_FORMAT; } vx_uint32 in_width = 0, in_height = 0; const size_t sz = sizeof(vx_uint32); //Query the width & height of the input image vxQueryImage((vx_image)parameters[0],VX_IMAGE_WIDTH, &in_width, sz); vxQueryImage((vx_image)parameters[0],VX_IMAGE_HEIGHT,&in_height,sz); //Swap the width & height as required by transpose, accordingly vx_uint32 out_width = in_height; vx_uint32 out_height = in_width; vx_df_image format = VX_DF_IMAGE_U8; status = vxSetMetaFormatAttribute(meta[1], VX_IMAGE_WIDTH, &out_width, sz); status |= vxSetMetaFormatAttribute(meta[1], VX_IMAGE_HEIGHT, &out_height, sz); status |= vxSetMetaFormatAttribute(meta[1], VX_IMAGE_FORMAT, &format, sizeof(format)); return status; }
This function verifies that the (single) input image is of the correct format.  It also validates the the output parameter plus sets the “meta format attributes” defining the output image. In the case of transpose, the output width equals the input height, and the output height equals the input width. The validator also specifies that the output image is of the same format as input (VX_DF_IMAGE_U8).
The tile mapping function is first callback that is specific to the Advanced tiling:
static vx_status TranspTileMapping(vx_node node, vx_reference params[], const vx_tile_t_attributes_intel_t* dstRectIn, vx_tile_t_attributes_intel_t* srcRectOut, vx_uint32 param_num) { //Given the output tile attributes (dstRectIn), //set the input tile attributes which are required (srcRectOut) srcRectOut->x = dstRectIn->y; srcRectOut->y = dstRectIn->x; srcRectOut->tile_block.width = dstRectIn->tile_block.height; srcRectOut->tile_block.height = dstRectIn->tile_block.width; return VX_SUCCESS; }
This function sets the input tile which is required to produce a given output tile. In the case of transpose, the mapping is trivial (swap).
The last function that is required is the kernel function, which actually performs the computation of the transpose:
static vx_status TranspAdvancedTilingKernel(vx_node node, void * parameters[], vx_uint32 num, void * tile_memory, vx_size tile_memory_size) { vx_tile_t *pInTileIn = (vx_tile_intel_t *)parameters[0]; vx_tile_t *pInTileOut = (vx_tile_intel_t *)parameters[1]; const vx_uint8 *pSrc = pInTileIn->base[0]; vx_uint8 *pDst = pInTileOut->base[0]; const int srcStride = pInTileIn->addr[0].stride_y; const int dstStride = pInTileOut->addr[0].stride_y; const int output_tile_width = pInTileOut->addr[0].dim_x; const int output_tile_height = pInTileOut->addr[0].dim_y; vx_uint8 *pDstRow = pDst; //for each output line for(int y = 0; y < output_tile_height; y++) { vx_uint8 *pSrcColumn = pSrc + y*sizeof(vx_uint8); //for each output pixel for this line for(int int x = 0; x < output_tile_width; x++) { pDstRow[x] = *pSrcColumn; pSrcColumn += srcStride; } pDstRow += dstStride; } return VX_SUCCESS; }
The runtime passes the pointer for the output tile to be processed, along with the pointer for the input tile that was requested through the tile-mapping function. Note the correct usage of the stride_y for the source and destination buffers. The tiling kernel should make no assumptions about the way in which the buffers are laid out in system memory and respect the striding.
//create a kernel via the vxAddAdvancedTilingKernelIntel interface vx_kernel kernel = vxAddAdvancedTilingKernelIntel (context, (vx_char *)"AdvancedTilingTranspose",//name TRANSPOSE_ID, //enumeration TranspAdvancedTilingKernel, //kernel_func_ptr TranspTileMapping, //mapping_func_ptr 2, //num_params TranspValidator, //input/output validate NULL, //initialize NULL, //deinitialize NULL, //preprocess NULL, //postprocess NULL, //settiledimensions NULL); //tiledimensionsinit //add the parameters for this kernel vxAddParameterToKernel(kernel, 0, VX_INPUT, VX_TYPE_IMAGE, VX_PARAMETER_STATE_REQUIRED); vxAddParameterToKernel(kernel, 1, VX_OUTPUT, VX_TYPE_IMAGE, VX_PARAMETER_STATE_REQUIRED); //done with publishing the kernel vxFinalizeKernel(kernel);

Product and Performance Information


Intel's compilers may or may not optimize to the same degree for non-Intel microprocessors for optimizations that are not unique to Intel microprocessors. These optimizations include SSE2, SSE3, and SSSE3 instruction sets and other optimizations. Intel does not guarantee the availability, functionality, or effectiveness of any optimization on microprocessors not manufactured by Intel. Microprocessor-dependent optimizations in this product are intended for use with Intel microprocessors. Certain optimizations not specific to Intel microarchitecture are reserved for Intel microprocessors. Please refer to the applicable product User and Reference Guides for more information regarding the specific instruction sets covered by this notice.

Notice revision #20110804