TIOVX User Guide
vx_tutorial_graph_pipeline_two_nodes.c File Reference
#include <stdio.h>
#include <VX/vx_khr_pipelining.h>
#include <TI/tivx.h>

Go to the source code of this file.

Functions

void vx_tutorial_graph_pipeline_two_nodes ()
 Tutorial Entry Point. More...
 

Detailed Description

Pipeline a graph with two nodes

In this tutorial we learn the below concepts,

  • How to create OpenVX graph with two nodes and pipeline across two different target CPUs

To include OpenVX graph pipeline include below files

#include <TI/tivx.h>

Follow the comments in the function vx_tutorial_graph_pipeline_two_nodes() to understand this tutorial

Definition in file vx_tutorial_graph_pipeline_two_nodes.c.

Function Documentation

◆ vx_tutorial_graph_pipeline_two_nodes()

void vx_tutorial_graph_pipeline_two_nodes ( )

Tutorial Entry Point.












- Define objects that we wish to create in the OpenVX application.

  • in_img[] are the input images that we will pass to the graph
  • out_img[] are the output images we will get back from the graph
  • tmp is the intermediate image, we will not access this within the application
  • n0 and n1 are the two NOT nodes running on two different target CPUs
  • graph_parameters_queue_params_list[] are the graph parameters info that we will pipeline and associate with the graph
/
vx_context context;
vx_image in_img[MAX_NUM_BUF], tmp, out_img[MAX_NUM_BUF];
vx_node n0, n1;
vx_graph_parameter_queue_params_t graph_parameters_queue_params_list[2];
vx_graph graph;
uint32_t width, height, num_buf, pipeline_depth, buf_id, loop_id, loop_cnt, exe_time;





















- Create OpenVX context.

This MUST be done first before any OpenVX API call. The context that is returned is used as input for subsequent OpenVX APIs

/
context = vxCreateContext();



















- Allocate Input and Output images, multiple refs created to allow pipelining of graph.









- Construct the graph and set node targets such that each runs on a different CPU target

/
n0 = vxNotNode(graph, in_img[0], tmp);
n1 = vxNotNode(graph, tmp, out_img[0]);
#if defined(SOC_AM62A)
#else
#endif















- The position where input and output images are made as graph parameters. This is because for pipelining, one can only enqueue/dequeue into a graph parameter

/
/* input @ n0 index 0, becomes graph parameter 0 */
add_graph_parameter_by_node_index(graph, n0, 0);
/* output @ n1 index 1, becomes graph parameter 1 */
add_graph_parameter_by_node_index(graph, n1, 1);













- Set graph scehdule policy to make it pipelined.

  • This is done by providing a list of graph parameters that user wants to enqueue or dequeue. This is the input and output graph parameters in this case.
  • The number of buffers that can be enqueued before its internal queue becomes full is also specified via graph_parameters_queue_params_list[0].refs_list_size.
  • The list of buffers that could be every enqueued is specified via, graph_parameters_queue_params_list[0].refs_list
    /
    /* set graph schedule config such that graph parameter @ index 0 and 1 are enqueuable */
    graph_parameters_queue_params_list[0].graph_parameter_index = 0;
    graph_parameters_queue_params_list[0].refs_list_size = num_buf;
    graph_parameters_queue_params_list[0].refs_list = (vx_reference*)&in_img[0];
    graph_parameters_queue_params_list[1].graph_parameter_index = 1;
    graph_parameters_queue_params_list[1].refs_list_size = num_buf;
    graph_parameters_queue_params_list[1].refs_list = (vx_reference*)&out_img[0];
    /* Schedule mode auto is used, here we dont need to call vxScheduleGraph
    * Graph gets scheduled automatically as refs are enqueued to it
    */
    2,
    graph_parameters_queue_params_list
    );










- Set graph pipeline depth. This has to be done explicitly. Default is 1.

  • Set number of intermediate buffers. This has to be done explicitly. Default is 1.
    /
    /* explicitly set graph pipeline depth */
    tivxSetGraphPipelineDepth(graph, pipeline_depth);
    /* make the 'tmp' reference which is output of n0 @ index 1 a "multi-buffer" */








- Verify the graph

  • Optionally export the graph as graphviz dot graph to visualize the graph and its pipelined structure
  • Optionally enable real-time logging to get a waveform like trace of graph execution
    /
    #if 0
    tivxExportGraphToDot(graph, ".", "vx_tutorial_graph_pipeline_two_nodes");
    #endif






- Enqueue input and output references,



- Wait for graph instances to complete,

  • Compare output and recycle data buffers, schedule again
    /
    for(loop_id=0; loop_id<(loop_cnt+num_buf); loop_id++)
    {
    vx_image cur_out_img, cur_in_img;
    uint32_t num_refs;
    /* Get output reference, waits until a reference is available */
    vxGraphParameterDequeueDoneRef(graph, 1, (vx_reference*)&cur_out_img, 1, &num_refs);
    /* Get consumed input reference, waits until a reference is available
    */
    vxGraphParameterDequeueDoneRef(graph, 0, (vx_reference*)&cur_in_img, 1, &num_refs);
    /* A graph execution completed, since we dequeued both input and output refs */
    /* use output */
    buf_id = (buf_id+1)%num_buf;
    /* recycles dequeued input and output refs 'loop_cnt' times */
    if(loop_id<loop_cnt)
    {
    /* input and output can be enqueued in any order */
    vxGraphParameterEnqueueReadyRef(graph, 1, (vx_reference*)&cur_out_img, 1);
    vxGraphParameterEnqueueReadyRef(graph, 0, (vx_reference*)&cur_in_img, 1);
    }
    }
    /* ensure all graph processing is complete */
    vxWaitGraph(graph);


- Release all perviously allocated resources

/
for(buf_id=0; buf_id<num_buf; buf_id++)
{
vxReleaseImage(&in_img[buf_id]);
vxReleaseImage(&out_img[buf_id]);
}
vxReleaseContext(&context);

Definition at line 135 of file vx_tutorial_graph_pipeline_two_nodes.c.