Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Clarify spec around isNativeHandleOwned. #2193

Merged
merged 5 commits into from
Jan 22, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 27 additions & 27 deletions include/ur_api.h
Original file line number Diff line number Diff line change
Expand Up @@ -1615,9 +1615,9 @@ typedef struct ur_platform_native_properties_t {
ur_structure_type_t stype;
/// [in,out][optional] pointer to extension-specific structure
void *pNext;
/// [in] Indicates UR owns the native handle or if it came from an
/// interoperability operation in the application that asked to not
/// transfer the ownership to the unified-runtime.
/// [in] If true then ownership of the native handle is transferred to
/// the resultant object. This means the object will be responsible for
/// releasing the native resources at the end of its lifetime.
bool isNativeHandleOwned;

} ur_platform_native_properties_t;
Expand Down Expand Up @@ -2696,9 +2696,9 @@ typedef struct ur_device_native_properties_t {
ur_structure_type_t stype;
/// [in,out][optional] pointer to extension-specific structure
void *pNext;
/// [in] Indicates UR owns the native handle or if it came from an
/// interoperability operation in the application that asked to not
/// transfer the ownership to the unified-runtime.
/// [in] If true then ownership of the native handle is transferred to
/// the resultant object. This means the object will be responsible for
/// releasing the native resources at the end of its lifetime.
bool isNativeHandleOwned;

} ur_device_native_properties_t;
Expand Down Expand Up @@ -3076,9 +3076,9 @@ typedef struct ur_context_native_properties_t {
ur_structure_type_t stype;
/// [in,out][optional] pointer to extension-specific structure
void *pNext;
/// [in] Indicates UR owns the native handle or if it came from an
/// interoperability operation in the application that asked to not transfer
/// the ownership to the unified-runtime.
/// [in] If true then ownership of the native handle is transferred to
/// the resultant object. This means the object will be responsible for
/// releasing the native resources at the end of its lifetime.
bool isNativeHandleOwned;

} ur_context_native_properties_t;
Expand Down Expand Up @@ -3697,9 +3697,9 @@ typedef struct ur_mem_native_properties_t {
ur_structure_type_t stype;
/// [in,out][optional] pointer to extension-specific structure
void *pNext;
/// [in] Indicates UR owns the native handle or if it came from an
/// interoperability operation in the application that asked to not
/// transfer the ownership to the unified-runtime.
/// [in] If true then ownership of the native handle is transferred to
/// the resultant object. This means the object will be responsible for
/// releasing the native resources at the end of its lifetime.
bool isNativeHandleOwned;

} ur_mem_native_properties_t;
Expand Down Expand Up @@ -4103,9 +4103,9 @@ typedef struct ur_sampler_native_properties_t {
ur_structure_type_t stype;
/// [in,out][optional] pointer to extension-specific structure
void *pNext;
/// [in] Indicates UR owns the native handle or if it came from an
/// interoperability operation in the application that asked to not
/// transfer the ownership to the unified-runtime.
/// [in] If true then ownership of the native handle is transferred to
/// the resultant object. This means the object will be responsible for
/// releasing the native resources at the end of its lifetime.
bool isNativeHandleOwned;

} ur_sampler_native_properties_t;
Expand Down Expand Up @@ -5811,9 +5811,9 @@ typedef struct ur_program_native_properties_t {
ur_structure_type_t stype;
/// [in,out][optional] pointer to extension-specific structure
void *pNext;
/// [in] Indicates UR owns the native handle or if it came from an
/// interoperability operation in the application that asked to not
/// transfer the ownership to the unified-runtime.
/// [in] If true then ownership of the native handle is transferred to
/// the resultant object. This means the object will be responsible for
/// releasing the native resources at the end of its lifetime.
bool isNativeHandleOwned;

} ur_program_native_properties_t;
Expand Down Expand Up @@ -6480,9 +6480,9 @@ typedef struct ur_kernel_native_properties_t {
ur_structure_type_t stype;
/// [in,out][optional] pointer to extension-specific structure
void *pNext;
/// [in] Indicates UR owns the native handle or if it came from an
/// interoperability operation in the application that asked to not transfer
/// the ownership to the unified-runtime.
/// [in] If true then ownership of the native handle is transferred to
/// the resultant object. This means the object will be responsible for
/// releasing the native resources at the end of its lifetime.
bool isNativeHandleOwned;

} ur_kernel_native_properties_t;
Expand Down Expand Up @@ -6875,9 +6875,9 @@ typedef struct ur_queue_native_properties_t {
ur_structure_type_t stype;
/// [in,out][optional] pointer to extension-specific structure
void *pNext;
/// [in] Indicates UR owns the native handle or if it came from an
/// interoperability operation in the application that asked to not transfer
/// the ownership to the unified-runtime.
/// [in] If true then ownership of the native handle is transferred to
/// the resultant object. This means the object will be responsible for
/// releasing the native resources at the end of its lifetime.
bool isNativeHandleOwned;

} ur_queue_native_properties_t;
Expand Down Expand Up @@ -7301,9 +7301,9 @@ typedef struct ur_event_native_properties_t {
ur_structure_type_t stype;
/// [in,out][optional] pointer to extension-specific structure
void *pNext;
/// [in] Indicates UR owns the native handle or if it came from an
/// interoperability operation in the application that asked to not transfer
/// the ownership to the unified-runtime.
/// [in] If true then ownership of the native handle is transferred to
/// the resultant object. This means the object will be responsible for
/// releasing the native resources at the end of its lifetime.
bool isNativeHandleOwned;

} ur_event_native_properties_t;
Expand Down
46 changes: 35 additions & 11 deletions scripts/core/PROG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -287,17 +287,6 @@ ${x}QueueRetain. An application must call ${x}QueueRelease
when a queue object is no longer needed. When a queue object's reference count becomes
zero, it is deleted by the runtime.

Native Driver Access
----------------------------------

The runtime API provides accessors for native handles.
For example, given a ${x}_program_handle_t, we can
call ${x}ProgramGetNativeHandle to retrieve a ${x}_native_handle_t.
We can then leverage a platform extension to convert the
native handle to a driver handle. For example, OpenCL platform
may expose an extension ${x}ProgramCreateWithNativeHandle to retrieve
a cl_program.

Memory
======

Expand Down Expand Up @@ -340,3 +329,38 @@ through ${x}_usm_desc_t structure. Allocations that specify different pool handl
isolated and not reside on the same page. Memory pool is subject to limits specified during pool creation.

Even if no ${x}_usm_pool_handle_t is provided to an allocation function, each adapter may still perform memory pooling.

Native Handles
==============

In addition to the regular object creation APIs, ${X} objects can be
constructed with handles obtained directly from an adapter's associated
backend. This is achieved by casting the backend handle to a
${x}_native_handle_t and passing it to the relevant ``CreateWithNativeHandle``
entry point.


.. note::
Not all backends have a 1:1 equivalent for every ${X} handle type, as such
any ``CreateWithNativeHandle`` or ``GetNativeHandle`` entry point *may* fail
with the error code ${X}_RESULT_ERROR_UNSUPPORTED_FEATURE for a given
adapter.

Native Handle Ownership
-----------------------

By default a ${X} object constructed from a native handle doesn't own the
native handle, it is guaranteed not to retain a reference to the native handle,
or cause its resources to be released. A ${X} object that doesn't own its
associated native handle **must** be destroyed before the native handle is.

Ownership of the native handle can be transferred to the ${X} object by passing
``isNativeHandleOwned = true`` in the native properties struct when calling the
``CreateWithNativeHandle`` entry point. A ${X} object that owns a native handle
will attempt to release the native resources associated with that handle on
destruction. The same native handle **must not** have its ownership transferred
to more than one ${X} object.

Ownership of a native handle obtained from a ${X} object via a
``GetNativeHandle`` entry point **must not** be transferred to a new ${X}
object.
6 changes: 3 additions & 3 deletions scripts/core/context.yml
Original file line number Diff line number Diff line change
Expand Up @@ -209,9 +209,9 @@ members:
- type: bool
name: isNativeHandleOwned
desc: |
[in] Indicates UR owns the native handle or if it came from an interoperability
operation in the application that asked to not transfer the ownership to
the unified-runtime.
[in] If true then ownership of the native handle is transferred to
the resultant object. This means the object will be responsible for
releasing the native resources at the end of its lifetime.
--- #--------------------------------------------------------------------------
type: function
desc: "Create runtime context object from native context handle."
Expand Down
8 changes: 4 additions & 4 deletions scripts/core/device.yml
Original file line number Diff line number Diff line change
Expand Up @@ -803,10 +803,10 @@ base: $x_base_properties_t
members:
- type: bool
name: isNativeHandleOwned
desc: >
[in] Indicates UR owns the native handle or if it came from an
interoperability operation in the application that asked to not
transfer the ownership to the unified-runtime.
desc: |
[in] If true then ownership of the native handle is transferred to
the resultant object. This means the object will be responsible for
releasing the native resources at the end of its lifetime.
--- #--------------------------------------------------------------------------
type: function
desc: "Create runtime device object from native device handle."
Expand Down
6 changes: 3 additions & 3 deletions scripts/core/event.yml
Original file line number Diff line number Diff line change
Expand Up @@ -289,9 +289,9 @@ members:
- type: bool
name: isNativeHandleOwned
desc: |
[in] Indicates UR owns the native handle or if it came from an interoperability
operation in the application that asked to not transfer the ownership to
the unified-runtime.
[in] If true then ownership of the native handle is transferred to
the resultant object. This means the object will be responsible for
releasing the native resources at the end of its lifetime.
--- #--------------------------------------------------------------------------
type: function
desc: "Create runtime event object from native event handle."
Expand Down
6 changes: 3 additions & 3 deletions scripts/core/kernel.yml
Original file line number Diff line number Diff line change
Expand Up @@ -513,9 +513,9 @@ members:
- type: bool
name: isNativeHandleOwned
desc: |
[in] Indicates UR owns the native handle or if it came from an interoperability
operation in the application that asked to not transfer the ownership to
the unified-runtime.
[in] If true then ownership of the native handle is transferred to
the resultant object. This means the object will be responsible for
releasing the native resources at the end of its lifetime.
--- #--------------------------------------------------------------------------
type: function
desc: "Create runtime kernel object from native kernel handle."
Expand Down
8 changes: 4 additions & 4 deletions scripts/core/memory.yml
Original file line number Diff line number Diff line change
Expand Up @@ -474,10 +474,10 @@ base: $x_base_properties_t
members:
- type: bool
name: isNativeHandleOwned
desc: >
[in] Indicates UR owns the native handle or if it came from an
interoperability operation in the application that asked to not
transfer the ownership to the unified-runtime.
desc: |
[in] If true then ownership of the native handle is transferred to
the resultant object. This means the object will be responsible for
releasing the native resources at the end of its lifetime.
--- #--------------------------------------------------------------------------
type: function
desc: "Create runtime buffer memory object from native memory handle."
Expand Down
8 changes: 4 additions & 4 deletions scripts/core/platform.yml
Original file line number Diff line number Diff line change
Expand Up @@ -202,10 +202,10 @@ base: $x_base_properties_t
members:
- type: bool
name: isNativeHandleOwned
desc: >
[in] Indicates UR owns the native handle or if it came from an
interoperability operation in the application that asked to not
transfer the ownership to the unified-runtime.
desc: |
[in] If true then ownership of the native handle is transferred to
the resultant object. This means the object will be responsible for
releasing the native resources at the end of its lifetime.
--- #--------------------------------------------------------------------------
type: function
desc: "Create runtime platform object from native platform handle."
Expand Down
8 changes: 4 additions & 4 deletions scripts/core/program.yml
Original file line number Diff line number Diff line change
Expand Up @@ -584,10 +584,10 @@ base: $x_base_properties_t
members:
- type: bool
name: isNativeHandleOwned
desc: >
[in] Indicates UR owns the native handle or if it came from an
interoperability operation in the application that asked to not
transfer the ownership to the unified-runtime.
desc: |
[in] If true then ownership of the native handle is transferred to
the resultant object. This means the object will be responsible for
releasing the native resources at the end of its lifetime.
--- #--------------------------------------------------------------------------
type: function
desc: "Create runtime program object from native program handle."
Expand Down
6 changes: 3 additions & 3 deletions scripts/core/queue.yml
Original file line number Diff line number Diff line change
Expand Up @@ -262,9 +262,9 @@ members:
- type: bool
name: isNativeHandleOwned
desc: |
[in] Indicates UR owns the native handle or if it came from an interoperability
operation in the application that asked to not transfer the ownership to
the unified-runtime.
[in] If true then ownership of the native handle is transferred to
the resultant object. This means the object will be responsible for
releasing the native resources at the end of its lifetime.
--- #--------------------------------------------------------------------------
type: function
desc: "Create runtime queue object from native queue handle."
Expand Down
8 changes: 4 additions & 4 deletions scripts/core/sampler.yml
Original file line number Diff line number Diff line change
Expand Up @@ -206,10 +206,10 @@ base: $x_base_properties_t
members:
- type: bool
name: isNativeHandleOwned
desc: >
[in] Indicates UR owns the native handle or if it came from an
interoperability operation in the application that asked to not
transfer the ownership to the unified-runtime.
desc: |
[in] If true then ownership of the native handle is transferred to
the resultant object. This means the object will be responsible for
releasing the native resources at the end of its lifetime.
--- #--------------------------------------------------------------------------
type: function
desc: "Create runtime sampler object from native sampler handle."
Expand Down
20 changes: 11 additions & 9 deletions source/adapters/cuda/queue.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -284,17 +284,19 @@ UR_APIEXPORT ur_result_t UR_APICALL urQueueCreateWithNativeHandle(
std::vector<CUstream> ComputeCuStreams(1, CuStream);
std::vector<CUstream> TransferCuStreams(0);

auto isNativeHandleOwned =
pProperties ? pProperties->isNativeHandleOwned : false;

// Create queue and set num_compute_streams to 1, as computeCuStreams has
// valid stream
*phQueue =
new ur_queue_handle_t_{std::move(ComputeCuStreams),
std::move(TransferCuStreams),
hContext,
hDevice,
CuFlags,
Flags,
/*priority*/ 0,
/*backend_owns*/ pProperties->isNativeHandleOwned};
*phQueue = new ur_queue_handle_t_{std::move(ComputeCuStreams),
std::move(TransferCuStreams),
hContext,
hDevice,
CuFlags,
Flags,
/*priority*/ 0,
/*backend_owns*/ isNativeHandleOwned};
(*phQueue)->NumComputeStreams = 1;

return UR_RESULT_SUCCESS;
Expand Down
3 changes: 3 additions & 0 deletions source/adapters/hip/memory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,9 @@ UR_APIEXPORT ur_result_t UR_APICALL
urMemGetNativeHandle(ur_mem_handle_t hMem, ur_device_handle_t Device,
ur_native_handle_t *phNativeMem) {
UR_ASSERT(Device != nullptr, UR_RESULT_ERROR_INVALID_NULL_HANDLE);
if (hMem->isImage()) {
return UR_RESULT_ERROR_UNSUPPORTED_FEATURE;
}
#if defined(__HIP_PLATFORM_NVIDIA__)
if (sizeof(BufferMem::native_type) > sizeof(ur_native_handle_t)) {
// Check that all the upper bits that cannot be represented by
Expand Down
20 changes: 11 additions & 9 deletions source/adapters/hip/queue.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -318,17 +318,19 @@ UR_APIEXPORT ur_result_t UR_APICALL urQueueCreateWithNativeHandle(
std::vector<hipStream_t> ComputeHIPStreams(1, HIPStream);
std::vector<hipStream_t> TransferHIPStreams(0);

auto isNativeHandleOwned =
pProperties ? pProperties->isNativeHandleOwned : false;

// Create queue and set num_compute_streams to 1, as computeHIPStreams has
// valid stream
*phQueue =
new ur_queue_handle_t_{std::move(ComputeHIPStreams),
std::move(TransferHIPStreams),
hContext,
hDevice,
HIPFlags,
Flags,
/*priority*/ 0,
/*backend_owns*/ pProperties->isNativeHandleOwned};
*phQueue = new ur_queue_handle_t_{std::move(ComputeHIPStreams),
std::move(TransferHIPStreams),
hContext,
hDevice,
HIPFlags,
Flags,
/*priority*/ 0,
/*backend_owns*/ isNativeHandleOwned};
(*phQueue)->NumComputeStreams = 1;

return UR_RESULT_SUCCESS;
Expand Down
2 changes: 1 addition & 1 deletion source/adapters/level_zero/context.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ ur_result_t urContextCreateWithNativeHandle(
const ur_context_native_properties_t *Properties,
/// [out] pointer to the handle of the context object created.
ur_context_handle_t *Context) {
bool OwnNativeHandle = Properties->isNativeHandleOwned;
bool OwnNativeHandle = Properties ? Properties->isNativeHandleOwned : false;
try {
ze_context_handle_t ZeContext =
reinterpret_cast<ze_context_handle_t>(NativeContext);
Expand Down
6 changes: 3 additions & 3 deletions source/adapters/level_zero/kernel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1118,9 +1118,9 @@ ur_result_t urKernelCreateWithNativeHandle(
ze_kernel_handle_t ZeKernel = ur_cast<ze_kernel_handle_t>(NativeKernel);
ur_kernel_handle_t_ *Kernel = nullptr;
try {
Kernel = new ur_kernel_handle_t_(ZeKernel, Properties->isNativeHandleOwned,
Context);
if (Properties->isNativeHandleOwned) {
auto OwnNativeHandle = Properties ? Properties->isNativeHandleOwned : false;
Kernel = new ur_kernel_handle_t_(ZeKernel, OwnNativeHandle, Context);
if (OwnNativeHandle) {
// If ownership is passed to the adapter we need to pass the kernel
// to this vector which is then used during ZeKernelRelease.
Kernel->ZeKernels.push_back(ZeKernel);
Expand Down
Loading
Loading