@@ -1833,6 +1833,10 @@ UR_APIEXPORT ur_result_t UR_APICALL urMemBufferCreateWithNativeHandle(
1833
1833
UR_CALL (
1834
1834
Buffer->getZeHandle (ZeHandleDst, ur_mem_handle_t_::write_only, Device));
1835
1835
1836
+ // Indicate that this buffer has the device buffer mapped to a native buffer
1837
+ // and track the native pointer such that the memory is synced later at
1838
+ // memory free.
1839
+ Buffer->DeviceMappedHostNativePtr = Ptr;
1836
1840
// zeCommandListAppendMemoryCopy must not be called from simultaneous
1837
1841
// threads with the same command list handle, so we need exclusive lock.
1838
1842
std::scoped_lock<ur_mutex> Lock (Context->ImmediateCommandListMutex );
@@ -2169,6 +2173,17 @@ ur_result_t _ur_buffer::free() {
2169
2173
? Plt->ContextsMutex
2170
2174
: UrContext->Mutex );
2171
2175
2176
+ // If this memory was allocated as a proxy device buffer, then we must
2177
+ // copy the final memory contents back to the original native pointer
2178
+ // before releasing the buffer memory.
2179
+ if (DeviceMappedHostNativePtr != nullptr ) {
2180
+ // zeCommandListAppendMemoryCopy must not be called from simultaneous
2181
+ // threads with the same command list handle, so we need exclusive lock.
2182
+ std::scoped_lock<ur_mutex> Lock (UrContext->ImmediateCommandListMutex );
2183
+ ZE2UR_CALL (zeCommandListAppendMemoryCopy,
2184
+ (UrContext->ZeCommandListInit , DeviceMappedHostNativePtr,
2185
+ ZeHandle, Size, nullptr , 0 , nullptr ));
2186
+ }
2172
2187
UR_CALL (USMFreeHelper (reinterpret_cast <ur_context_handle_t >(UrContext),
2173
2188
ZeHandle));
2174
2189
break ;
0 commit comments