Skip to content

Commit 7f7474d

Browse files
committed
Change the image-sampler mapping to track the UR sampler object and free the memory accordingly
1 parent 4551c42 commit 7f7474d

File tree

4 files changed

+50
-25
lines changed

4 files changed

+50
-25
lines changed

unified-runtime/source/adapters/level_zero/device.hpp

+3-3
Original file line numberDiff line numberDiff line change
@@ -237,9 +237,9 @@ struct ur_device_handle_t_ : ur_object {
237237
std::unordered_map<ur_exp_image_native_handle_t, ze_image_handle_t>
238238
ZeOffsetToImageHandleMap;
239239

240-
// Map (sampled) bindless image handle to its corresponding sampler.
241-
std::unordered_map<ur_exp_image_native_handle_t, ze_sampler_handle_t>
242-
ZeImageToSamplerMap;
240+
// Map (sampled) bindless image handle to its corresponding sampler handle.
241+
std::unordered_map<ur_exp_image_native_handle_t, ur_sampler_handle_t>
242+
UrImageToSamplerMap;
243243

244244
// unique ephemeral identifer of the device in the adapter
245245
std::optional<DeviceId> Id;

unified-runtime/source/adapters/level_zero/image_common.cpp

+11-6
Original file line numberDiff line numberDiff line change
@@ -349,6 +349,8 @@ ur_result_t bindlessImagesCreateImpl(ur_context_handle_t hContext,
349349
(zeCtx, hDevice->ZeDevice, &ZeImageDesc, &ZeImage));
350350
ZE2UR_CALL(zeContextMakeImageResident, (zeCtx, hDevice->ZeDevice, ZeImage));
351351
} else {
352+
// Release sampler handle memory to avoid memory leak.
353+
UR_CALL(releaseSamplerHandle(hSampler));
352354
return UR_RESULT_ERROR_INVALID_VALUE;
353355
}
354356

@@ -363,8 +365,11 @@ ur_result_t bindlessImagesCreateImpl(ur_context_handle_t hContext,
363365
"zeImageGetDeviceOffsetExpv failed, err = {}",
364366
Result);
365367
});
366-
if (!zeImageGetDeviceOffsetExpFunctionPtr)
368+
if (!zeImageGetDeviceOffsetExpFunctionPtr) {
369+
// Release sampler handle memory to avoid memory leak.
370+
UR_CALL(releaseSamplerHandle(hSampler));
367371
return UR_RESULT_ERROR_INVALID_OPERATION;
372+
}
368373
uint64_t DeviceOffset{};
369374
ze_image_handle_t ZeImageTranslated;
370375
ZE2UR_CALL(zelLoaderTranslateHandle,
@@ -380,7 +385,7 @@ ur_result_t bindlessImagesCreateImpl(ur_context_handle_t hContext,
380385
std::scoped_lock LockAll(Lock, SLock);
381386
// Associate the bindless image with host object handle and sampler handle.
382387
hDevice->ZeOffsetToImageHandleMap[*phImage] = ZeImage;
383-
hDevice->ZeImageToSamplerMap[*phImage] = hSampler->ZeSampler;
388+
hDevice->UrImageToSamplerMap[*phImage] = hSampler;
384389
} else {
385390
Lock.lock();
386391
hDevice->ZeOffsetToImageHandleMap[*phImage] = ZeImage;
@@ -1022,11 +1027,11 @@ ur_result_t urBindlessImagesSampledImageHandleDestroyExp(
10221027
hContext, hDevice, hImage));
10231028

10241029
std::shared_lock<ur_shared_mutex> Lock(hDevice->Mutex);
1025-
auto Item = hDevice->ZeImageToSamplerMap.find(hImage);
1026-
if (Item != hDevice->ZeImageToSamplerMap.end()) {
1027-
hDevice->ZeImageToSamplerMap.erase(Item);
1030+
auto Item = hDevice->UrImageToSamplerMap.find(hImage);
1031+
if (Item != hDevice->UrImageToSamplerMap.end()) {
1032+
hDevice->UrImageToSamplerMap.erase(Item);
10281033
Lock.release();
1029-
ZE2UR_CALL(zeSamplerDestroy, (Item->second));
1034+
UR_CALL(releaseSamplerHandle(Item->second));
10301035
} else {
10311036
Lock.release();
10321037
return UR_RESULT_ERROR_INVALID_NULL_HANDLE;

unified-runtime/source/adapters/level_zero/sampler.cpp

+32-16
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,37 @@
1717
#include "context.hpp"
1818
#endif
1919

20+
ur_result_t releaseSamplerHandle(
21+
/// [in] handle of the sampler object to release
22+
ur_sampler_handle_t Sampler) {
23+
if (!Sampler->RefCount.decrementAndTest())
24+
return UR_RESULT_SUCCESS;
25+
26+
if (checkL0LoaderTeardown()) {
27+
#ifndef NDEBUG
28+
// Verify that the ZeSampler memory has not been destroyed already,
29+
// otherwise this will return ZE_RESULT_ERROR_INVALID_NULL_HANDLE. This is
30+
// logically impossible due to the way we have managed the lifetime of the
31+
// sampler handle, but it may still be a good sanity check in debug.
32+
std::shared_lock<ur_shared_mutex> Lock(Sampler->Mutex);
33+
assert(Sampler->ZeSampler &&
34+
"Invalid ZeSampler handle in releaseSamplerHandle");
35+
Lock.release();
36+
#endif
37+
auto ZeResult = ZE_CALL_NOCHECK(zeSamplerDestroy, (Sampler->ZeSampler));
38+
// Gracefully handle the case that L0 was already unloaded.
39+
if (ZeResult && (ZeResult != ZE_RESULT_ERROR_UNINITIALIZED &&
40+
ZeResult != ZE_RESULT_ERROR_UNKNOWN))
41+
return ze2urResult(ZeResult);
42+
if (ZeResult == ZE_RESULT_ERROR_UNKNOWN) {
43+
ZeResult = ZE_RESULT_ERROR_UNINITIALIZED;
44+
}
45+
}
46+
delete Sampler;
47+
48+
return UR_RESULT_SUCCESS;
49+
}
50+
2051
namespace ur::level_zero {
2152

2253
ur_result_t urSamplerCreate(
@@ -126,22 +157,7 @@ ur_result_t urSamplerRetain(
126157
ur_result_t urSamplerRelease(
127158
/// [in] handle of the sampler object to release
128159
ur_sampler_handle_t Sampler) {
129-
if (!Sampler->RefCount.decrementAndTest())
130-
return UR_RESULT_SUCCESS;
131-
132-
if (checkL0LoaderTeardown()) {
133-
auto ZeResult = ZE_CALL_NOCHECK(zeSamplerDestroy, (Sampler->ZeSampler));
134-
// Gracefully handle the case that L0 was already unloaded.
135-
if (ZeResult && (ZeResult != ZE_RESULT_ERROR_UNINITIALIZED &&
136-
ZeResult != ZE_RESULT_ERROR_UNKNOWN))
137-
return ze2urResult(ZeResult);
138-
if (ZeResult == ZE_RESULT_ERROR_UNKNOWN) {
139-
ZeResult = ZE_RESULT_ERROR_UNINITIALIZED;
140-
}
141-
}
142-
delete Sampler;
143-
144-
return UR_RESULT_SUCCESS;
160+
return releaseSamplerHandle(Sampler);
145161
}
146162

147163
ur_result_t urSamplerGetInfo(

unified-runtime/source/adapters/level_zero/sampler.hpp

+4
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,7 @@ struct ur_sampler_handle_t_ : ur_object {
1919

2020
ZeStruct<ze_sampler_desc_t> ZeSamplerDesc;
2121
};
22+
23+
ur_result_t releaseSamplerHandle(
24+
/// [in] handle of the sampler object to release
25+
ur_sampler_handle_t Sampler);

0 commit comments

Comments
 (0)