OpenVX框架分析:用户内核

OpenVX框架分析:用户内核

定义用户内核,这是一种用新视觉功能扩展OpenVX的方法。
用户内核可以由OpenVX加载,并作为节点或即时函数(如果客户端提供接口)包含在图形中。用户内核通常将在与高级操作系统/CPU兼容的目标上加载和执行,而不是在远程处理器或其他加速器上。
 
图 13.用户内核安装的调用顺序
 
图 14.使用用户内核进行图形验证和释放的调用序列
 
图 15.使用用户内核执行图形的调用序列
    在第一次图形验证期间,实现将执行以下操作序列:
1)初始化本地数据节点属性
①如果VX_KERNEL_LOCAL_DATA_SIZE==0,则将VX_NODE_LOCAL_ATA_SIZE设置为0,并将VX_NODE_LOCAL_DATA\uPTR设置为NULL。
②如果VX_KERNEL_LOCAL_DATA_SIZE!=0,将VX_NODE_LOCAL_DATA_SIZE设置为VX_KERNEL_LOCAL_DATA\uSIZE,并将VX_NODE_LOCAL_DATA _PTR设置为VX_ KERNEL-LOCAL_DATA_ IZE字节的缓冲区的地址。
2)调用vx_kernel_validate_f回调。
3)调用vx_kernel_initialize_f回调(如果不是NULL):
①如果VX_KERNEL_LOCAL_DATA_SIZE==0,则允许回调设置VX_NODE_LOCAL_ATA_SIZE和VX_NODE-LOCAL_DATA_PTR。
②如果VX_KERNEL_LOCAL_DATA_SIZE!=0,则回调设置VX_NODE_LOCAL_DATA_SIZE或VX_NODE-LOCAL_DATA_PTR属性的任何尝试都将生成错误。
4)提供应用程序请求的缓冲区(可选)
如果VX_KERNEL_LOCAL_DATA_SIZE==0且VX_NODE_LOCAL_DATA _SIZE!=0,并且VX_NODE_LOCAL_DATA_PTR==NULL,则该实现将VX_NODE-LOCAL_DATA-PTR设置为VX_NODE_NOCAL_DATA_SIZE字节的缓冲区的地址。
在节点销毁时,实现将执行以下操作序列:
1)调用vx_kernel_deinitialize_f回调(如果不是NULL):如果vx_NODE_LOCAL_DATA_PTR是由实现较早设置的,则回调设置vx_NODE-LOCAL_DATA-PTR属性的任何尝试都将生成错误。
2)如果VX_NODE_LOCAL_DATA_PTR是由实现提前设置的,则在VX_kernel_deinitialize_f回调完成后,应用程序不得再使用指向内存。
如果在最后一次节点验证后发生以下任何更改,则用户节点需要重新验证:
1)VX_NODE_BORDER节点属性已修改。
2)至少有一个节点参数被具有不同元数据的数据对象替换,或者被可选参数的0引用替换,或者由于可选而被设置为以前未设置的数据对象。
节点重新验证可以由应用程序,通过调用将执行完整图形验证的vxVerifyGraph明确触发。否则,它将在下一次图形执行时自动触发。
在用户节点重新验证期间,将发生以下操作序列:
1)调用vx_kernel_deinitialize_f回调(如果不是NULL):如果vx_NODE_LOCAL_DATA_PTR是由OpenVX实现较早设置的,则回调设置vx_NODE-LOCAL_DATA-PTR属性的任何尝试都将产生错误。
2)如果需要,重新初始化本地数据节点属性如果VX_KERNEL_local_data_SIZE==0:
①将VX_NODE_LOCAL_DATA_PTR设置为NULL。
②将VX_NODE_LOCAL_DATA_SIZE设置为0。
3)调用vx_kernel_validate_f回调。
4)调用vx_kernel_initialize_f回调(如果不是NULL):
①如果VX_KERNEL_LOCAL_DATA_SIZE==0,则允许回调设置VX_NODE_LOCAL_ATA_SIZE和VX_NODE-LOCAL_DATA_PTR。
②如果VX_KERNEL_LOCAL_DATA_SIZE为!=0,则回调设置VX_NODE_LOCAL_DATA_SIZE或VX_NODE-LOCAL_DATA_PTR属性的任何尝试都将生成错误。
5)提供应用程序请求的缓冲区(可选)
如果VX_KERNEL_LOCAL_DATA_SIZE==0且VX_NODE_LOCAL_DATA _SIZE!=0,并且VX_NODE_LOCAL_DATA_PTR==NULL,则OpenVX实现将VX_NODE-LOCAL_DATA-PTR设置为VX_NODE_NOCAL_DATA_SIZE字节的缓冲区的地址。
当OpenVX实现设置VX_NODE_LOCAL_DATA_PTR时,缓冲区内的数据在内核执行之间不会持久存在。
类型定义
枚举
功能

7.6.1. 类型定义

vx_kernel_deinitialize_f

指向内核去初始化程序的指针。如果主机代码要求在节点垃圾收集期间调用,以取消初始化数据,则在不为NULL时调用此函数。
typedef vx_status (*vx_kernel_deinitialize_f)(
            vx_node node,
            const vx_reference *parameters,
            vx_uint32 num);
参数
[in] node - 包含此内核的节点的句柄。
[in] parameters - 参数引用的数组。
[in] num - 参数的数量。

vx_kernel_f

指向主机端内核的指针。
typedef vx_status (*vx_kernel_f)(
            vx_node node,
            const vx_reference *parameters,
            vx_uint32 num);
参数
[in] node - 包含此内核的节点的句柄。
[in] parameters - 参数引用的数组。
[in] num - 参数的数量。

vx_kernel_image_valid_rectangle_f

用户定义的回调函数,用于设置输出图像的有效矩形。
typedef vx_status (*vx_kernel_image_valid_rectangle_f)(
            vx_node node,
            vx_uint32 index,
            const vx_rectangle_t* const input_valid[],
            vx_rectangle_t* const output_valid[]);
VX_meta_format对象中的VX_VALID_RECT_CALLBACK属性,应在用户节点的输出验证器期间设置为所需的回调。回调不得调用vxGetValidRegionImage或 vxSetImageValidRectangle。相反,所有输入图像的有效矩形的阵列被提供给回调,以计算输出有效矩形。用户节点的输出可以是金字塔,或者仅仅是图像。如果它只是一个图像,则与该输出相关联的输出数组,只有一个元素。如果输出是金字塔,则阵列大小等于金字塔级别的数量。传递给回调的数组内存分配由框架管理,应用程序不得分配或解除分配这些指针。
如果以下情况之一为真,则回调函数vx_kernel_image_valid_rectangle_f的行为是实现定义的:
用户节点的输入自变量之一是金字塔或图像阵列。
用户节点的输入或输出参数都是金字塔数组。
参数
[inout] node - 正在验证的节点的句柄。
[in] index - 应为其设置有效区域的输出参数的索引。
[in] input_valid - 指向输入图像或包含在图像容器(例如金字塔)中,图像的有效区域阵列的指针。提供顺序与内核声明的参数列表相同。
[out] output_valid - 应在图形处理后为输出图像或图像容器(例如金字塔)设置的有效区域阵列。阵列的长度应等于图像容器的大小(例如,金字塔中的级别数)。对于简单的输出图像,阵列大小总是1。每个矩形提供一个图像的有效区域。阵列存储器分配由框架管理。
返回:描述参数验证状态的错误代码。

vx_kernel_initialize_f

指向内核初始值设定项的指针。如果主机代码要求在所有参数都经过验证后调用以初始化数据,则在不为NULL时调用此函数。
typedef vx_status (*vx_kernel_initialize_f)(
            vx_node node,
            const vx_reference *parameters,
            vx_uint32 num);
参数
[in] node - 包含此内核的节点的句柄。
[in] parameters - 参数引用的数组。
[in] num - 参数的数量。

vx_kernel_validate_f

用户自定义内核节点参数验证函数。该函数只需要填写元数据结构。
typedef vx_status (*vx_kernel_validate_f)(
            vx_node node,
            const vx_reference parameters[],
            vx_uint32 num,
            vx_meta_format metas[]);
注意
对于整组参数,此函数调用一次。
参数
[in] node - 正在验证的节点的句柄。
[in] parameters - 要验证的参数数组。
[in] num - 要验证的参数数。
[in] metas - 指向系统保存的结构引用的预分配数组的指针。系统仅为输出参数预分配多个vx_meta_format结构,这些结构由与参数相同的索引索引。验证函数填写正确的类型、格式和维度,供系统用于创建内存或对照现有内存进行检查。
返回:描述参数验证状态的错误代码。

vx_meta_format

输出验证函数使用此对象,来指定预期输出数据对象的元数据。
typedef struct _vx_meta_format *vx_meta_format;

注意

当用户节点的实际输出对象是虚拟时,通过vx_meta_format对象提供的信息,允许OpenVX框架在对象创建时,应用程序未指定元数据时,自动创建数据对象。

vx_publish_kernels_f

由vxLoadKernels加载和由vxUnloadKernels卸载的模块,vxPublishKernels输入功能的类型。
typedef vx_status (*vx_publish_kernels_f)(vx_context context);
参数
[in] context - 必须添加对上下文内核的引用。

vx_unpublish_kernels_f

由vxLoadKernels加载和由vxUnloadKernels卸载的,vxUnpublishKernels条目功能的类型。
typedef vx_status (*vx_unpublish_kernels_f)(vx_context context);
参数
[in] context - 添加了对上下文内核的引用。

7.6.2. 枚举

vx_meta_valid_rect_attribute_e

元有效矩形属性。
enum vx_meta_valid_rect_attribute_e {
    VX_VALID_RECT_CALLBACK = VX_ATTRIBUTE_BASE(VX_ID_KHRONOS, VX_TYPE_META_FORMAT) + 0x1,
};
枚举 数
VX_VALID_RECT_CALLBACK- 输出参数验证期间的有效矩形回调。 .

7.6.3. 函数

vxAddParameterToKernel

允许用户设置自定义内核的签名。
vx_status vxAddParameterToKernel(
    vx_kernel                                   kernel,
    vx_uint32                                   index,
    vx_enum                                     dir,
    vx_enum                                     data_type,
    vx_enum                                     state);
参数
[in] kernel - 对添加vxAddUserKernel的内核的引用。
[in] index - 要添加的参数的索引。
[in] dir - 参数的方向。这必须是VX_INPUT或VX_OUTPUT。
[in] data_type - 参数的类型。这必须是vx_type_e中的一个值。
[in] state - 参数的状态(必需或不需要)。这必须是vx_parameter_state_e中的值。
返回:一个vx_status_e枚举值。
返回值
VX_SUCCESS- 参数在内核上设置成功,任何其他值表示失败。
VX_ERROR_INVALID_REFERENCE- 内核不是有效的vx_kernel引用。
VX_ERROR_INVALID_PARAMETERS- 如果该参数由于任何原因无效。
前提: vxAddUserKernel

vxAddUser内核

允许用户在运行时,将自定义内核添加到上下文中。
vx_kernel vxAddUserKernel(
    vx_context                                  context,
    const vx_char                               name[VX_MAX_KERNEL_NAME],
    vx_enum                                     enumeration,
    vx_kernel_f                                 func_ptr,
    vx_uint32                                   numParams,
    vx_kernel_validate_f                        validate,
    vx_kernel_initialize_f                      init,
    vx_kernel_deinitialize_f                    deinit);
参数
[in] context - 必须添加内核的上下文引用。
[in] name - 用于匹配内核的字符串。
[in] enumeration - 客户端要使用的内核的枚举值。
[in] func_ptr - 要调用的进程本地函数指针。
[in] numParams - 此内核的参数数。
[in] validate - 指向vx_kernel_validate_f的指针,用于验证此内核的参数。
[in] init - 内核初始化函数。
[in] deinit - 内核取消初始化函数。
返回:vx_kernel引用。应使用vxGetStatus检查,阻止成功创建的任何可能错误。

vxAllocateUserKernelId

将用户定义的内核枚举分配并注册到上下文中。分配的枚举来自为0的动态分配保留的4096个枚举的可用池。
vx_status vxAllocateUserKernelId(
    vx_context                                  context,
    vx_enum*                                    pKernelEnumId);
参数
[in] context - 对实现上下文的引用。
[out] pKernelEnumId - 返回用户定义内核的vx_enum的指针。
返回值
VX_SUCCESS- 没有错误,任何其他值都表示失败。
VX_ERROR_INVALID_REFERENCE- 如果上下文不是有效的VX_context引用。
VX_ERROR_NO_RESOURCES- 枚举已用尽。

vxAllocateUserKernelLibraryId

将用户定义的内核库ID分配并注册到上下文。
vx_status vxAllocateUserKernelLibraryId(
    vx_context          context,
    vx_enum*           pLibraryId);
分配的库ID来自为动态分配保留的可用库ID池(1..255)。用户内核库开发人员可以使用返回的libraryId,在头文件中指定单个内核枚举ID,如下所示:
#define MY_KERNEL_ID1(libraryId) (VX_KERNEL_BASE(VX_ID_USER,libraryId) + 0);
#define MY_KERNEL_ID2(libraryId) (VX_KERNEL_BASE(VX_ID_USER,libraryId) + 1);
#define MY_KERNEL_ID3(libraryId) (VX_KERNEL_BASE(VX_ID_USER,libraryId) + 2);
参数
[in] context - 对实现上下文的引用。
[out] pLibraryId - 指向用户内核库Id的vx_enum的指针。
返回值
VX_SUCCESS- 没有错误,任何其他值都表示失败。
VX_ERROR_NO_RESOURCES- 枚举已用尽。

vxFinalize内核

在将所有参数添加到内核中,并且内核准备好使用后调用此API。注意,在调用vxFinalizeKernel之后,对vxAddUserKernel创建的内核的引用仍然有效。如果出现错误,则OpenVX的客户端无法使用内核。通常,这是由于请求的参数数量与给定的参数数量不匹配造成的。
vx_status vxFinalizeKernel(
    vx_kernel     kernel);
参数
[in] kernel - 对vxAddUserKernel中加载的内核的引用。
返回:vx_status_e枚举。
返回值
VX_SUCCESS- 没有错误,任何其他值都表示失败。
VX_ERROR_INVALID_REFERENCE- 内核不是有效的VX_kernel引用。
前提条件:vxAddUserKernel和vxAddParameterToKernel

vxLoad内核

将一个称为模块的内核库加载到上下文中。
vx_status vxLoadKernels(
    vx_context             context,
    const vx_char*       module);
模块必须是一个动态库,按照惯例,具有两个导出的函数,分别命名为vxPublishKernels和vxUnpublishKernels。
vxPublishKernels的类型必须为vx_publish_kernels_f,并且必须通过为每个新内核调用vxAddUserKernel将内核添加到上下文中。vxPublishKernels由vxLoadKernels调用。
vxUnpublishKernels的类型必须为vx_unpublish_kernels_f,并且必须通过为vxPublishKernels添加的每个内核调用vxRemoveKernel来从上下文中删除内核。vxUnpublishKernels由vxUnloadKernels调用。
注意
当对加载的内核的所有引用都被释放时,模块可以被自动卸载。
参数
[in] context - context-内核必须添加到上下文引用。
[in] module - 要加载的模块的简称。在有特定模块命名约定的系统上,传递的名称应忽略这些约定。例如:libxyz.so应该作为xyz传递,并且实现将执行平台所需的正确操作。
注意
此 API 使用系统预定义的模块路径。
返回:vx_status_e枚举。
返回值
VX_SUCCESS- 没有错误,任何其他值都表示失败。
VX_ERROR_INVALID_REFERENCE- 上下文不是有效的VX_context引用。
VX_ERROR_INVALID_PARAMETERS- 如果任何其他参数不正确。
参考:vxRegisterKernelLibrary、vxGetKernelByName

vxRemove内核

从其上下文中删除自定义内核并释放它。
vx_status vxRemoveKernel(
    vx_kernel      kernel);
参数
[in] kernel - 对要删除的内核的引用。从vxAddUserKernel返回。
注意
不能删除基础标准中列举的任何内核;只能删除通过vxAddUserKernel添加的内核。
返回:vx_status_e枚举。该函数将对内核创建时提供的内存资源的完全控制权,返回给应用程序。
返回值
VX_SUCCESS- 没有错误,任何其他值都表示失败。
VX_ERROR_INVALID_REFERENCE- 内核不是有效的VX_kernel引用。
VX_ERROR_INVALID_PARAMETERS- 如果传入了基本内核。
VX_FAILURE- 如果应用程序尚未释放对内核对象的所有引用,或者如果应用程序未释放对使用此内核的节点的所有引用,或者如果应用软件未释放对具有使用此内核节点的图的所有引用。

vxSetKernelAttribute

设置内核属性。
vx_status vxSetKernelAttribute(
    vx_kernel           kernel,
    vx_enum            attribute,
    const void*        ptr,
    vx_size              size);
参数
[in] kernel - 对内核的引用。
[in] attribute - 属性的枚举。参考vx_kernel_attribute_e
[in] ptr - 向读取属性的位置的指针。
[in] size - ptr指示的数据区域的大小(以字节为单位)。
注意
将内核传递给vxFinalizeKernel后,不能更改任何属性。
返回:vx_status_e枚举。
返回值
VX_SUCCESS- 没有错误,任何其他值都表示失败。
VX_ERROR_INVALID_REFERENCE- 内核不是有效的VX_kernel引用。
VX_ERROR_NOT_SUPPORTED- 如果属性不可设置。

vxSetMetaFormat属性

此功能允许用户在内核输出验证器中,设置vx_meta_format对象的属性。
vx_status vxSetMetaFormatAttribute(
    vx_meta_format      meta,
    vx_enum             attribute,
    const void*         ptr,
    vx_size             size);
vx_meta_format对象包含两种类型的信息:数据对象元数据和定义图像的有效区域,如何更改的一些特定信息。
可以设置的元数据属性,列在vxQueryMetaFormatAttribute中。
参数
[in] meta - 对要设置vx_meta_format结构的引用。
[in] attribute - 使用定义此对象元数据的数据对象属性子集,或vx_meta_format中的属性。
[in] ptr - 要在元格式对象上设置的值的输入指针。
[in] size - ptr指向的对象的大小(以字节为单位)。
返回:vx_status_e枚举。
返回值
VX_SUCCESS- 设置了属性,任何其他值都表示失败。
VX_ERROR_INVALID_REFERENCE- meta不是有效的VX_meta_format引用。
VX_ERROR_INVALID_PARAMETERS- 所需类型的大小不正确。
VX_ERROR_NOT_SUPPORTED- 元格式对象不支持对象属性。
VX_ERROR_INVALID_TYPE- 属性类型与已知的元格式类型不匹配。

vxQueryMetaFormatAttribute

此函数允许用户在内核参数中,查询vx_meta_format对象的属性。
vx_status vxQueryMetaFormatAttribute(
    vx_meta_format     meta,
    vx_enum                attribute,
    void*                     ptr,
    vx_size                  size);
vx_meta_format对象包含两种类型的信息:数据对象元数据和定义图像的有效区域,如何更改的一些特定信息。
可以查询的元数据属性由该列表标识:
注意
对于vx_image,可以使用特定属性来指定有效的区域演变。此信息不是元数据。
参数
[in] meta - 要查询vx_meta_format结构的引用。
[in] attribute - 使用定义此对象元数据的数据,对象属性子集或vx_meta_format中的属性。
[out] ptr - 要在元格式对象上查询的值的输出指针。
[in] size - ptr指向的对象的大小(以字节为单位)。
返回:vx_status_e枚举。
返回值
VX_SUCCESS- 属性已返回,任何其他值都表示失败。
VX_ERROR_INVALID_REFERENCE- meta不是有效的VX_meta_format引用。
VX_ERROR_INVALID_PARAMETERS- 所需类型的大小不正确。
VX_ERROR_NOT_SUPPORTED- 元格式对象不支持对象属性。
VX_ERROR_INVALID_TYPE- 属性类型与已知的元格式类型不匹配。

vxSetMetaFormatFromReference

从示例数据对象引用中设置元格式对象。
vx_status vxSetMetaFormatFromReference(
    vx_meta_format    meta,
    vx_reference      exemplar);
此函数根据示例的元数据设置vx_meta_format对象。
参数
[in] meta - 要设置的 meta 格式对象。
[in] exemplar - 示例数据对象。
返回:vx_status_e枚举。
返回值
VX_SUCCESS- 元格式设置正确,任何其他值表示失败。
VX_ERROR_INVALID_REFERENCE- VX_ERROR_INVALID_REFERENCE-meta不是有效的VX_meta_format引用,或者范例不是有效的VX_REFERENCE引用。

vxUnloadKernels

使用vxLoadKernels函数,从模块加载的OpenVX上下文中卸载所有内核。
vx_status vxUnloadKernels(
    vx_context         context,
    const vx_char*     module);
内核卸载是通过调用模块的vxUnpublishKernels导出函数来执行的。
注意
vxUnpublishKernels在vxLoadKernels的描述中进行了定义。
参数
[in] context - 必须删除内核对上下文的引用。
[in] module - 要卸载的模块的简称。在有特定模块命名约定的系统上,传递的名称应忽略这些约定。例如:libxyz.so应该作为xyz传递,并且实现将执行平台所需的正确操作。
注意
此 API使用系统预定义的模块路径。
返回:vx_status_e枚举。
返回值
VX_SUCCESS- 没有错误,任何其他值都表示失败。
VX_ERROR_INVALID_REFERENCE- 上下文不是有效的VX_context引用。
VX_ERROR_INVALID_PARAMETERS- 如果任何其他参数不正确。
参阅: vxLoadKernels

vxRegisterKernelLibrary

在上下文中向内核注册模块。
vx_status vxRegisterKernelLibrary(
    vx_context               context,
    const vx_char*           module,
    vx_publish_kernels_f     publish,
    vx_unpublish_kernels_f   unpublish);
如果模块不是动态库,则此函数使用模块名称,注册适当的发布和取消发布函数,因此可以调用vxLoadKernels和vxUnloadKernels。
参数
[in] context - 对上下文的引用。
[in] module - 要注册的模块的简称。
[in] publish - 用于从vxLoadKernels加载的模块的入口功能。
[in] unpublish - 从vxUnloadKernels卸载模块的入口功能。
返回:vx_status_e枚举。
返回值
VX_SUCCESS- 无错误;任何其他值表示故障。
VX_ERROR_INVALID_REFERENCE- 上下文不是有效的VX_context引用。
VX_ERROR_INVALID_PARAMETERS- 如果任何其他参数不正确。
参见:vxLoadKernels,vxUnloadKernels
 
参考文献链接
https://registry.khronos.org/OpenVX/specs/1.3.1/html/OpenVX_Specification_1_3_1.html
posted @ 2024-07-06 07:13  吴建明wujianming  阅读(6)  评论(0编辑  收藏  举报