Skip to content

Commit 94a6104

Browse files
fix(object-array): wire VX_TYPE_USER_DATA_OBJECT into exemplar dispatch
The Khronos CTS `UserDataObject.UserKernelObjectArray/*` subtests (test_user_data_object.c:516) call `vxCreateObjectArray(ctx, udo, 20)` with a UDO as the exemplar. rustVX's `create_object_like_exemplar` helper in openvx-core had `match` arms for IMAGE, ARRAY, PYRAMID, SCALAR, MATRIX, DISTRIBUTION, REMAP, LUT, THRESHOLD, OBJECT_ARRAY — but not USER_DATA_OBJECT — so the new UDO type tag (0x816) fell to the `_ => null_mut()` default. `vxCreateObjectArray` then returned NULL and the CTS `ASSERT_VX_OBJECT(VX_TYPE_OBJECT_ARRAY)` blew up before the test even got to exercising the UDO API. Add the missing arm: query `VX_USER_DATA_OBJECT_NAME` / `VX_USER_DATA_OBJECT_SIZE` from the exemplar, then call `vxCreateUserDataObject` to produce each fresh slot. Same semantics as the IMAGE/ARRAY arms — clone the exemplar's metadata, not its contents, so each slot in the resulting object-array gets its own independent zero-initialised buffer. The FFI calls are declared inline because openvx-core can't import the `vx_user_data_object` alias from openvx-buffer without a circular dep; `*mut c_void` is the underlying repr (same as the alias in user_data_object.rs). The constants `VX_TYPE_USER_DATA_OBJECT` / `VX_USER_DATA_OBJECT_NAME` / `VX_USER_DATA_OBJECT_SIZE` / `VX_MAX_REFERENCE_NAME` are declared as function-local consts to keep the match arm self-documenting without colliding with the pre-existing file-scope `VX_TYPE_TARGET = 0x816` (a latent labeling artefact predating this PR — left untouched here to avoid scope creep). Verified locally: * `cargo build --release -p openvx-ffi` — clean build * `cargo test --release -p openvx-ffi --test user_data_object` — all 15 existing UDO Rust integration tests still pass The two failing CTS subtests (`UserKernelObjectArray/{0,1}/USER_DATA_OBJECT_FROM_{REF,ATTR}`) should now pass on the next CI run, alongside the 12 UDO subtests that were already green on the previous run. Co-authored-by: Cursor <cursoragent@cursor.com>
1 parent 103b18a commit 94a6104

1 file changed

Lines changed: 54 additions & 1 deletion

File tree

openvx-core/src/unified_c_api.rs

Lines changed: 54 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7468,7 +7468,32 @@ fn create_object_like_exemplar(
74687468
thresh_type: vx_enum,
74697469
data_type: vx_enum,
74707470
) -> vx_threshold;
7471-
}
7471+
// vx_user_data_object is `*mut c_void` (see
7472+
// openvx-buffer/src/user_data_object.rs); openvx-core can't import
7473+
// the alias without a circular dep, so the raw pointer type is
7474+
// used inline here.
7475+
fn vxQueryUserDataObject(
7476+
udo: *mut c_void,
7477+
attr: vx_enum,
7478+
ptr: *mut c_void,
7479+
size: usize,
7480+
) -> vx_status;
7481+
fn vxCreateUserDataObject(
7482+
ctx: vx_context,
7483+
type_name: *const vx_char,
7484+
size: vx_size,
7485+
ptr: *const c_void,
7486+
) -> *mut c_void;
7487+
}
7488+
// VX_TYPE_USER_DATA_OBJECT = 0x816 per vx_khr_user_data_object.h. The
7489+
// pre-existing file-scope `VX_TYPE_TARGET` constant happens to also
7490+
// equal 0x816 (a latent labeling artefact predating this code) — a
7491+
// local shadow keeps this match arm self-documenting without changing
7492+
// unrelated callers of the old name.
7493+
const VX_TYPE_USER_DATA_OBJECT: vx_enum = 0x816;
7494+
const VX_USER_DATA_OBJECT_NAME: vx_enum = 0x0008_1600;
7495+
const VX_USER_DATA_OBJECT_SIZE: vx_enum = 0x0008_1601;
7496+
const VX_MAX_REFERENCE_NAME: usize = 64;
74727497
unsafe {
74737498
match exemplar_type {
74747499
VX_TYPE_IMAGE => {
@@ -7703,6 +7728,34 @@ fn create_object_like_exemplar(
77037728
vxReleaseReference(&mut item_ref as *mut vx_reference);
77047729
new_array as vx_reference
77057730
}
7731+
VX_TYPE_USER_DATA_OBJECT => {
7732+
// Clone the exemplar's metadata (name + byte size) into a
7733+
// fresh, zero-initialised UDO. `vxCreateObjectArray`
7734+
// contract is "build `count` independent items shaped like
7735+
// the exemplar", not "share storage" — so each slot gets
7736+
// its own backing buffer, matching how the IMAGE/ARRAY
7737+
// arms above also produce fresh blanks.
7738+
let mut name = [0u8; VX_MAX_REFERENCE_NAME];
7739+
let mut size: vx_size = 0;
7740+
vxQueryUserDataObject(
7741+
exemplar as *mut c_void,
7742+
VX_USER_DATA_OBJECT_NAME,
7743+
name.as_mut_ptr() as *mut c_void,
7744+
VX_MAX_REFERENCE_NAME,
7745+
);
7746+
vxQueryUserDataObject(
7747+
exemplar as *mut c_void,
7748+
VX_USER_DATA_OBJECT_SIZE,
7749+
&mut size as *mut _ as *mut c_void,
7750+
std::mem::size_of::<vx_size>(),
7751+
);
7752+
vxCreateUserDataObject(
7753+
context,
7754+
name.as_ptr() as *const vx_char,
7755+
size,
7756+
std::ptr::null(),
7757+
) as vx_reference
7758+
}
77067759
_ => std::ptr::null_mut(),
77077760
}
77087761
}

0 commit comments

Comments
 (0)