Skip to content

Commit e3d2184

Browse files
authored
[SYCL][HIP] Implemented supported make_* interop functions. (intel#10526)
This PR adds missing functions in the hip backend to allow for interoperability in programs that create sycl objects from native hip objects. The new function implementations are: - `make_device` - `make_queue` - `make_event` Note that it would really make sense for intel#10491 to be merged first because this PR makes the same code change in pi2ur, for a fix that is attributed to intel#10491. --------- Signed-off-by: Jack Kirk <jack.kirk@codeplay.com>
1 parent e0c87a5 commit e3d2184

File tree

4 files changed

+83
-23
lines changed

4 files changed

+83
-23
lines changed

event.cpp

Lines changed: 26 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,10 @@ ur_event_handle_t_::ur_event_handle_t_(ur_command_t Type,
1515
ur_context_handle_t Context,
1616
ur_queue_handle_t Queue,
1717
hipStream_t Stream, uint32_t StreamToken)
18-
: CommandType{Type}, RefCount{1}, HasBeenWaitedOn{false}, IsRecorded{false},
19-
IsStarted{false}, StreamToken{StreamToken}, EvEnd{nullptr},
20-
EvStart{nullptr}, EvQueued{nullptr}, Queue{Queue}, Stream{Stream},
21-
Context{Context} {
18+
: CommandType{Type}, RefCount{1}, HasOwnership{true},
19+
HasBeenWaitedOn{false}, IsRecorded{false}, IsStarted{false},
20+
StreamToken{StreamToken}, EvEnd{nullptr}, EvStart{nullptr},
21+
EvQueued{nullptr}, Queue{Queue}, Stream{Stream}, Context{Context} {
2222

2323
bool ProfilingEnabled = Queue->URFlags & UR_QUEUE_FLAG_PROFILING_ENABLE;
2424

@@ -36,6 +36,15 @@ ur_event_handle_t_::ur_event_handle_t_(ur_command_t Type,
3636
urContextRetain(Context);
3737
}
3838

39+
ur_event_handle_t_::ur_event_handle_t_(ur_context_handle_t Context,
40+
hipEvent_t EventNative)
41+
: CommandType{UR_COMMAND_EVENTS_WAIT}, RefCount{1}, HasOwnership{false},
42+
HasBeenWaitedOn{false}, IsRecorded{false}, IsStarted{false},
43+
StreamToken{std::numeric_limits<uint32_t>::max()}, EvEnd{EventNative},
44+
EvStart{nullptr}, EvQueued{nullptr}, Queue{nullptr}, Context{Context} {
45+
urContextRetain(Context);
46+
}
47+
3948
ur_event_handle_t_::~ur_event_handle_t_() {
4049
if (Queue != nullptr) {
4150
urQueueRelease(Queue);
@@ -160,6 +169,9 @@ ur_result_t ur_event_handle_t_::wait() {
160169
}
161170

162171
ur_result_t ur_event_handle_t_::release() {
172+
if (!backendHasOwnership())
173+
return UR_RESULT_SUCCESS;
174+
163175
assert(Queue != nullptr);
164176
UR_CHECK_ERROR(hipEventDestroy(EvEnd));
165177

@@ -302,15 +314,18 @@ UR_APIEXPORT ur_result_t UR_APICALL urEventGetNativeHandle(
302314
}
303315

304316
/// Created a UR event object from a HIP event handle.
305-
/// TODO: Implement this.
306-
/// NOTE: The created UR object takes ownership of the native handle.
317+
/// NOTE: The created UR object doesn't take ownership of the native handle.
307318
///
308319
/// \param[in] hNativeEvent The native handle to create UR event object from.
309320
/// \param[out] phEvent Set to the UR event object created from native handle.
310-
///
311-
/// \return UR_RESULT_ERROR_UNSUPPORTED_FEATURE
312321
UR_APIEXPORT ur_result_t UR_APICALL urEventCreateWithNativeHandle(
313-
ur_native_handle_t, ur_context_handle_t,
314-
const ur_event_native_properties_t *, ur_event_handle_t *) {
315-
return UR_RESULT_ERROR_UNSUPPORTED_FEATURE;
322+
ur_native_handle_t hNativeEvent, ur_context_handle_t hContext,
323+
const ur_event_native_properties_t *pProperties,
324+
ur_event_handle_t *phEvent) {
325+
std::ignore = pProperties;
326+
327+
*phEvent = ur_event_handle_t_::makeWithNative(
328+
hContext, reinterpret_cast<hipEvent_t>(hNativeEvent));
329+
330+
return UR_RESULT_SUCCESS;
316331
}

event.hpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,8 @@ struct ur_event_handle_t_ {
6060

6161
uint32_t getEventId() const noexcept { return EventId; }
6262

63+
bool backendHasOwnership() const noexcept { return HasOwnership; }
64+
6365
// Returns the counter time when the associated command(s) were enqueued
6466
uint64_t getQueuedTime() const;
6567

@@ -77,6 +79,11 @@ struct ur_event_handle_t_ {
7779
StreamToken);
7880
}
7981

82+
static ur_event_handle_t makeWithNative(ur_context_handle_t context,
83+
hipEvent_t eventNative) {
84+
return new ur_event_handle_t_(context, eventNative);
85+
}
86+
8087
ur_result_t release();
8188

8289
~ur_event_handle_t_();
@@ -88,10 +95,16 @@ struct ur_event_handle_t_ {
8895
ur_queue_handle_t Queue, hipStream_t Stream,
8996
uint32_t StreamToken);
9097

98+
// This constructor is private to force programmers to use the
99+
// makeWithNative for event interop
100+
ur_event_handle_t_(ur_context_handle_t Context, hipEvent_t EventNative);
101+
91102
ur_command_t CommandType; // The type of command associated with event.
92103

93104
std::atomic_uint32_t RefCount; // Event reference count.
94105

106+
bool HasOwnership; // Signifies if event owns the native type.
107+
95108
bool HasBeenWaitedOn; // Signifies whether the event has been waited
96109
// on through a call to wait(), which implies
97110
// that it has completed.

queue.cpp

Lines changed: 38 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,9 @@ UR_APIEXPORT ur_result_t UR_APICALL urQueueRelease(ur_queue_handle_t hQueue) {
193193
try {
194194
std::unique_ptr<ur_queue_handle_t_> QueueImpl(hQueue);
195195

196+
if (!hQueue->backendHasOwnership())
197+
return UR_RESULT_SUCCESS;
198+
196199
ScopedContext Active(hQueue->getContext()->getDevice());
197200

198201
hQueue->forEachStream([](hipStream_t S) {
@@ -252,19 +255,44 @@ urQueueGetNativeHandle(ur_queue_handle_t hQueue, ur_queue_native_desc_t *,
252255
}
253256

254257
/// Created a UR queue object from a HIP queue handle.
255-
/// TODO: Implement this.
256-
/// NOTE: The created UR object takes ownership of the native handle.
258+
/// NOTE: The created UR object doesn't takes ownership of the native handle.
257259
///
258260
/// \param[in] hNativeQueue The native handle to create UR queue object from.
259261
/// \param[in] hContext is the UR context of the queue.
260262
/// \param[out] phQueue Set to the UR queue object created from native handle.
261-
/// \param pProperties->isNativeHandleOwned tells if SYCL RT should assume the
262-
/// ownership of
263-
/// the native handle, if it can.
264-
///
265-
/// \return UR_RESULT_ERROR_UNSUPPORTED_FEATURE
266263
UR_APIEXPORT ur_result_t UR_APICALL urQueueCreateWithNativeHandle(
267-
ur_native_handle_t, ur_context_handle_t, ur_device_handle_t,
268-
const ur_queue_native_properties_t *, ur_queue_handle_t *) {
269-
return UR_RESULT_ERROR_UNSUPPORTED_FEATURE;
264+
ur_native_handle_t hNativeQueue, ur_context_handle_t hContext,
265+
ur_device_handle_t hDevice, const ur_queue_native_properties_t *pProperties,
266+
ur_queue_handle_t *phQueue) {
267+
(void)hDevice;
268+
269+
unsigned int HIPFlags;
270+
hipStream_t HIPStream = reinterpret_cast<hipStream_t>(hNativeQueue);
271+
272+
auto Return = UR_CHECK_ERROR(hipStreamGetFlags(HIPStream, &HIPFlags));
273+
274+
ur_queue_flags_t Flags = 0;
275+
if (HIPFlags == hipStreamDefault)
276+
Flags = UR_QUEUE_FLAG_USE_DEFAULT_STREAM;
277+
else if (HIPFlags == hipStreamNonBlocking)
278+
Flags = UR_QUEUE_FLAG_SYNC_WITH_DEFAULT_STREAM;
279+
else
280+
detail::ur::die("Unknown hip stream");
281+
282+
std::vector<hipStream_t> ComputeHIPStreams(1, HIPStream);
283+
std::vector<hipStream_t> TransferHIPStreams(0);
284+
285+
// Create queue and set num_compute_streams to 1, as computeHIPStreams has
286+
// valid stream
287+
*phQueue =
288+
new ur_queue_handle_t_{std::move(ComputeHIPStreams),
289+
std::move(TransferHIPStreams),
290+
hContext,
291+
hContext->getDevice(),
292+
HIPFlags,
293+
Flags,
294+
/*backend_owns*/ pProperties->isNativeHandleOwned};
295+
(*phQueue)->NumComputeStreams = 1;
296+
297+
return Return;
270298
}

queue.hpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,11 +49,13 @@ struct ur_queue_handle_t_ {
4949
std::mutex ComputeStreamMutex;
5050
std::mutex TransferStreamMutex;
5151
std::mutex BarrierMutex;
52+
bool HasOwnership;
5253

5354
ur_queue_handle_t_(std::vector<native_type> &&ComputeStreams,
5455
std::vector<native_type> &&TransferStreams,
5556
ur_context_handle_t Context, ur_device_handle_t Device,
56-
unsigned int Flags, ur_queue_flags_t URFlags)
57+
unsigned int Flags, ur_queue_flags_t URFlags,
58+
bool BackendOwns = true)
5759
: ComputeStreams{std::move(ComputeStreams)},
5860
TransferStreams{std::move(TransferStreams)},
5961
DelayCompute(this->ComputeStreams.size(), false),
@@ -62,7 +64,7 @@ struct ur_queue_handle_t_ {
6264
Device{Device}, RefCount{1}, EventCount{0}, ComputeStreamIdx{0},
6365
TransferStreamIdx{0}, NumComputeStreams{0}, NumTransferStreams{0},
6466
LastSyncComputeStreams{0}, LastSyncTransferStreams{0}, Flags(Flags),
65-
URFlags(URFlags) {
67+
URFlags(URFlags), HasOwnership{BackendOwns} {
6668
urContextRetain(Context);
6769
urDeviceRetain(Device);
6870
}
@@ -235,4 +237,6 @@ struct ur_queue_handle_t_ {
235237
uint32_t getReferenceCount() const noexcept { return RefCount; }
236238

237239
uint32_t getNextEventId() noexcept { return ++EventCount; }
240+
241+
bool backendHasOwnership() const noexcept { return HasOwnership; }
238242
};

0 commit comments

Comments
 (0)