Overview
This sample shows how to build your applications in a x86_64 host, targeting Jetson devices that use aarch64 architecture. It uses several features first made available in cmake-3.5. The sample application itself creates an input image, applies a box filter to it and save the result to disk.
Instructions
JetPack's installer already set up the cross-compilation toolchain using gcc, but if some reason it isn't available, install it manually with:
apt-get install gcc-aarch64-linux-gnu g++-aarch64-linux-gnu
Now cmake can be instructed to create a cross-compiling build tree by calling it as follows in the samples directory:
cmake . -DCMAKE_TOOLCHAIN_FILE=Toolchain_aarch64_l4t.cmake
The file Toolchain_aarch64_l4t.cmake
is included in the samples directory and defines the cross-compiler that will be used, among other configurations. In particular, it also allows cross-compilation of CUDA applications, provided that the CUDA aarch64 cross-compilation libraries are correctly installed on host.
Note This sample can also be compiled targeting the host. Just omit the CMAKE_TOOLCHAIN_FILE
parameter during cmake invocation.
The usage is:
./vpi_sample_08_cross_aarch64_l4t <backend>
where
backend: either cpu , cuda or pva ; it defines the backend that will perform the processing.
Source Code
For convenience, here's the code that is also installed in the samples directory.
Language:
C++
39 #define CHECK_STATUS(STMT) \
42 VPIStatus status = (STMT); \
43 if (status != VPI_SUCCESS) \
45 char buffer[VPI_MAX_STATUS_MESSAGE_LENGTH]; \
46 vpiGetLastStatusMessage(buffer, sizeof(buffer)); \
47 std::ostringstream ss; \
48 ss << vpiStatusGetName(status) << ": " << buffer; \
49 throw std::runtime_error(ss.str()); \
53 int main(
int argc,
char *argv[])
66 throw std::runtime_error(std::string(
"Usage: " ) + argv[0] +
" <cpu|pva|cuda>" );
69 std::string strBackend = argv[1];
74 if (strBackend ==
"cpu" )
78 else if (strBackend ==
"cuda" )
82 else if (strBackend ==
"pva" )
88 throw std::runtime_error(
"Backend '" + strBackend +
89 "' not recognized, it must be either cpu, cuda or pva." );
95 char imgContents[512][512];
96 for (
int i = 0; i < 512; ++i)
98 for (
int j = 0; j < 512; ++j)
100 imgContents[i][j] = i * 512 + j + i;
108 memset(&imgData, 0,
sizeof (imgData));
136 std::ofstream fd((
"boxfiltered_" + strBackend +
".pgm" ).c_str());
138 fd <<
"P5\n512 512 255\n" ;
139 for (
int i = 0; i < 512; ++i)
150 catch (std::exception &e)
152 std::cerr << e.what() << std::endl;
Declares functions that implement the Box Filter algorithm.
Functions and structures for dealing with VPI images.
Declaration of VPI status codes handling functions.
Declares functions dealing with VPI streams.
VPIStatus vpiSubmitBoxFilter(VPIStream stream, uint32_t backend, VPIImage input, VPIImage output, int32_t kernelSizeX, int32_t kernelSizeY, VPIBorderExtension border)
Runs a 2D box filter over an image.
VPIStatus vpiImageCreateHostMemWrapper(const VPIImageData *hostData, uint32_t flags, VPIImage *img)
Create an image object by wrapping around an existing host memory block.
int32_t height
Height of this plane in pixels.
int32_t numPlanes
Number of planes.
int32_t width
Width of this plane in pixels.
void * data
Pointer to the first row of this plane.
int32_t pitchBytes
Difference in bytes of beginning of one row and the beginning of the previous.
VPIImagePlane planes[VPI_MAX_PLANE_COUNT]
Data of all image planes.
VPIImageFormat format
Image format.
VPIStatus vpiImageLock(VPIImage img, VPILockMode mode, VPIImageData *hostData)
Acquires the lock on an image object and returns a pointer to the image planes.
void vpiImageDestroy(VPIImage img)
Destroy an image instance.
struct VPIImageImpl * VPIImage
A handle to an image.
VPIStatus vpiImageCreate(int32_t width, int32_t height, VPIImageFormat fmt, uint32_t flags, VPIImage *img)
Create an empty image instance with the specified flags.
VPIStatus vpiImageUnlock(VPIImage img)
Releases the lock on an image object.
Stores information about image characteristics and content.
struct VPIStreamImpl * VPIStream
A handle to a stream.
VPIStatus vpiStreamSync(VPIStream stream)
Blocks the calling thread until all submitted commands in this stream queue are done (queue is empty)...
VPIBackend
VPI Backend types.
void vpiStreamDestroy(VPIStream stream)
Destroy a stream instance and deallocate all HW resources.
VPIStatus vpiStreamCreate(uint32_t flags, VPIStream *stream)
Create a stream instance.
@ VPI_BACKEND_CUDA
CUDA backend.
@ VPI_BACKEND_PVA
PVA backend.
@ VPI_BACKEND_CPU
CPU backend.
@ VPI_BORDER_ZERO
All pixels outside the image are considered to be zero.
@ VPI_LOCK_READ
Lock memory only for reading.
Here is the cmake toolchain file that is being used.
27 set(CMAKE_SYSTEM_NAME Linux)
28 set(CMAKE_SYSTEM_PROCESSOR aarch64)
30 set(target_arch aarch64-linux-gnu)
31 set(CMAKE_LIBRARY_ARCHITECTURE ${target_arch} CACHE STRING "" FORCE)
33 # Configure cmake to look for libraries, include directories and
34 # packages inside the target root prefix.
35 set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
36 set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
37 set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
38 set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
39 set(CMAKE_FIND_ROOT_PATH "/usr/${target_arch}")
41 # needed to avoid doing some more strict compiler checks that
42 # are failing when cross-compiling
43 set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)
45 # specify the toolchain programs
46 find_program(CMAKE_C_COMPILER ${target_arch}-gcc)
47 find_program(CMAKE_CXX_COMPILER ${target_arch}-g++)
48 if(NOT CMAKE_C_COMPILER OR NOT CMAKE_CXX_COMPILER)
49 message(FATAL_ERROR "Can't find suitable C/C++ cross compiler for ${target_arch}")
52 set(CMAKE_AR ${target_arch}-ar CACHE FILEPATH "" FORCE)
53 set(CMAKE_RANLIB ${target_arch}-ranlib)
54 set(CMAKE_LINKER ${target_arch}-ld)
56 # Not all shared libraries dependencies are instaled in host machine.
57 # Make sure linker doesn't complain.
58 set(CMAKE_EXE_LINKER_FLAGS_INIT -Wl,--allow-shlib-undefined)
60 # instruct nvcc to use our cross-compiler
61 set(CMAKE_CUDA_FLAGS "-ccbin ${CMAKE_CXX_COMPILER} -Xcompiler -fPIC" CACHE STRING "" FORCE)
63 # vim: ts=8:sw=4:sts=4:et:ai
And finally the accompanying CMakeLists.txt. Note that it is just a plain simple CMakeLists.txt. Everything related to cross-compilation is defined in the toolchain file above.
27 cmake_minimum_required(VERSION 3.5)
29 # To cross-compile for aarch64-l4t target from x86,
30 # pass -DCMAKE_TOOLCHAIN_FILE=Toolchain_aarch64_l4t.cmake
31 # to cmake when creating build tree.
33 project(vpi_sample_08_cross_aarch64_l4t)
35 find_package(vpi ${vpi_API_VERSION} REQUIRED)
37 add_executable(${PROJECT_NAME} main.cpp)
38 target_link_libraries(${PROJECT_NAME} vpi)
40 # vim: ts=8:sw=4:sts=4:et:ai