Skip to content

Commit 5551986

Browse files
committed
[L0 v2] implement native handle API for event
1 parent e3247c2 commit 5551986

File tree

7 files changed

+142
-63
lines changed

7 files changed

+142
-63
lines changed

source/adapters/level_zero/v2/api.cpp

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -181,21 +181,6 @@ ur_result_t urKernelGetSuggestedLocalWorkSize(ur_kernel_handle_t hKernel,
181181
return UR_RESULT_ERROR_UNSUPPORTED_FEATURE;
182182
}
183183

184-
ur_result_t urEventGetNativeHandle(ur_event_handle_t hEvent,
185-
ur_native_handle_t *phNativeEvent) {
186-
logger::error("{} function not implemented!", __FUNCTION__);
187-
return UR_RESULT_ERROR_UNSUPPORTED_FEATURE;
188-
}
189-
190-
ur_result_t
191-
urEventCreateWithNativeHandle(ur_native_handle_t hNativeEvent,
192-
ur_context_handle_t hContext,
193-
const ur_event_native_properties_t *pProperties,
194-
ur_event_handle_t *phEvent) {
195-
logger::error("{} function not implemented!", __FUNCTION__);
196-
return UR_RESULT_ERROR_UNSUPPORTED_FEATURE;
197-
}
198-
199184
ur_result_t urEventSetCallback(ur_event_handle_t hEvent,
200185
ur_execution_info_t execStatus,
201186
ur_event_callback_t pfnNotify, void *pUserData) {

source/adapters/level_zero/v2/event.cpp

Lines changed: 77 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -10,39 +10,36 @@
1010

1111
#include <ze_api.h>
1212

13+
#include "context.hpp"
1314
#include "event.hpp"
1415
#include "event_pool.hpp"
1516
#include "event_provider.hpp"
1617
#include "queue_api.hpp"
1718

1819
#include "../ur_interface_loader.hpp"
1920

20-
ur_event_handle_t_::ur_event_handle_t_(
21-
v2::raii::cache_borrowed_event eventAllocation, v2::event_pool *pool)
22-
: zeEvent(std::move(eventAllocation)), pool(pool),
21+
ur_event_handle_t_::ur_event_handle_t_(ze_event_handle_t hZeEvent,
22+
ur_device_handle_t hDevice,
23+
ur_command_t commandType,
24+
v2::event_flags_t flags)
25+
: hZeEvent(hZeEvent), hDevice(hDevice), flags(flags),
2326
adjustedEventStartTimestamp(0), recordEventEndTimestamp(0),
2427
adjustedEventEndTimestamp(0),
2528
zeTimerResolution(getDevice()->ZeDeviceProperties->timerResolution),
26-
timestampMaxValue(getDevice()->getTimestampMask()) {}
27-
28-
void ur_event_handle_t_::resetQueueAndCommand(ur_queue_handle_t hQueue,
29-
ur_command_t commandType) {
30-
this->hQueue = hQueue;
31-
this->commandType = commandType;
32-
}
29+
timestampMaxValue(getDevice()->getTimestampMask()),
30+
commandType(commandType) {}
3331

3432
void ur_event_handle_t_::reset() {
3533
// consider make an abstraction for regular/counter based
3634
// events if there's more of this type of conditions
37-
if (pool->getFlags() & v2::EVENT_FLAGS_COUNTER) {
38-
zeEventHostReset(zeEvent.get());
35+
if (flags & v2::EVENT_FLAGS_COUNTER) {
36+
zeEventHostReset(hZeEvent);
3937
}
4038
}
4139

4240
ze_event_handle_t ur_event_handle_t_::getZeEvent() const {
43-
assert(hQueue);
4441
assert(commandType != UR_COMMAND_FORCE_UINT32);
45-
return zeEvent.get();
42+
return hZeEvent;
4643
}
4744

4845
ur_result_t ur_event_handle_t_::retain() {
@@ -51,11 +48,10 @@ ur_result_t ur_event_handle_t_::retain() {
5148
}
5249

5350
ur_result_t ur_event_handle_t_::releaseDeferred() {
54-
assert(zeEventQueryStatus(zeEvent.get()) == ZE_RESULT_SUCCESS);
51+
assert(zeEventQueryStatus(hZeEvent) == ZE_RESULT_SUCCESS);
5552
assert(RefCount.load() == 0);
5653

57-
pool->free(this);
58-
return UR_RESULT_SUCCESS;
54+
return this->forceRelease();
5955
}
6056

6157
ur_result_t ur_event_handle_t_::release() {
@@ -69,14 +65,12 @@ ur_result_t ur_event_handle_t_::release() {
6965
// L0 will write end timestamp to this event some time in the future,
7066
// so we can't release it yet.
7167

72-
assert(hQueue);
68+
assert(hQueue); // hQueue must have been set in recordStartTimestamp
7369
hQueue->deferEventFree(this);
7470
return UR_RESULT_SUCCESS;
7571
}
7672

77-
pool->free(this);
78-
79-
return UR_RESULT_SUCCESS;
73+
return this->forceRelease();
8074
}
8175

8276
bool ur_event_handle_t_::isTimestamped() const {
@@ -85,12 +79,10 @@ bool ur_event_handle_t_::isTimestamped() const {
8579
}
8680

8781
bool ur_event_handle_t_::isProfilingEnabled() const {
88-
return pool->getFlags() & v2::EVENT_FLAGS_PROFILING_ENABLED;
82+
return flags & v2::EVENT_FLAGS_PROFILING_ENABLED;
8983
}
9084

91-
ur_device_handle_t ur_event_handle_t_::getDevice() const {
92-
return pool->getProvider()->device();
93-
}
85+
ur_device_handle_t ur_event_handle_t_::getDevice() const { return hDevice; }
9486

9587
uint64_t ur_event_handle_t_::getEventStartTimestmap() const {
9688
return adjustedEventStartTimestamp;
@@ -121,7 +113,7 @@ uint64_t ur_event_handle_t_::getEventEndTimestamp() {
121113
if (adjustedEventEndTimestamp)
122114
return adjustedEventEndTimestamp;
123115

124-
auto status = zeEventQueryStatus(zeEvent.get());
116+
auto status = zeEventQueryStatus(hZeEvent);
125117
if (status != ZE_RESULT_SUCCESS) {
126118
// profiling info not ready
127119
return 0;
@@ -134,7 +126,12 @@ uint64_t ur_event_handle_t_::getEventEndTimestamp() {
134126
return adjustedEventEndTimestamp;
135127
}
136128

137-
void ur_event_handle_t_::recordStartTimestamp() {
129+
void ur_event_handle_t_::recordStartTimestamp(ur_queue_handle_t hQueue) {
130+
// this->hQueue can be for events created from native handle
131+
assert(hQueue == this->hQueue || !this->hQueue);
132+
133+
this->hQueue = hQueue;
134+
138135
uint64_t deviceStartTimestamp = 0;
139136
UR_CALL_THROWS(ur::level_zero::urDeviceGetGlobalTimestamps(
140137
getDevice(), &deviceStartTimestamp, nullptr));
@@ -145,13 +142,45 @@ void ur_event_handle_t_::recordStartTimestamp() {
145142

146143
std::pair<uint64_t *, ze_event_handle_t>
147144
ur_event_handle_t_::getEventEndTimestampAndHandle() {
148-
return {&recordEventEndTimestamp, zeEvent.get()};
145+
return {&recordEventEndTimestamp, hZeEvent};
149146
}
150147

151148
ur_queue_handle_t ur_event_handle_t_::getQueue() const { return hQueue; }
152149

153150
ur_command_t ur_event_handle_t_::getCommandType() const { return commandType; }
154151

152+
ur_pooled_event_t::ur_pooled_event_t(
153+
v2::raii::cache_borrowed_event eventAllocation, v2::event_pool *pool)
154+
: ur_event_handle_t_(eventAllocation.get(), pool->getProvider()->device(),
155+
UR_COMMAND_FORCE_UINT32, pool->getFlags()),
156+
zeEvent(std::move(eventAllocation)), pool(pool) {}
157+
158+
void ur_pooled_event_t::resetQueueAndCommand(ur_queue_handle_t hQueue,
159+
ur_command_t commandType) {
160+
this->hQueue = hQueue;
161+
this->commandType = commandType;
162+
}
163+
164+
ur_result_t ur_pooled_event_t::forceRelease() {
165+
pool->free(this);
166+
return UR_RESULT_SUCCESS;
167+
}
168+
169+
ur_native_event_t::ur_native_event_t(
170+
ur_native_handle_t hNativeEvent, ur_context_handle_t hContext,
171+
const ur_event_native_properties_t *pProperties)
172+
: ur_event_handle_t_(reinterpret_cast<ze_event_handle_t>(hNativeEvent),
173+
hContext->getDevices()[0],
174+
UR_EXT_COMMAND_TYPE_USER, v2::EVENT_FLAGS_PROFILING_ENABLED /* TODO: this follows legacy adapter logic, we could check this with zeEventGetPool */),
175+
zeEvent(reinterpret_cast<ze_event_handle_t>(hNativeEvent),
176+
pProperties ? pProperties->isNativeHandleOwned : false) {}
177+
178+
ur_result_t ur_native_event_t::forceRelease() {
179+
zeEvent.release();
180+
delete this;
181+
return UR_RESULT_SUCCESS;
182+
}
183+
155184
namespace ur::level_zero {
156185
ur_result_t urEventRetain(ur_event_handle_t hEvent) { return hEvent->retain(); }
157186

@@ -288,4 +317,24 @@ ur_result_t urEventGetProfilingInfo(
288317

289318
return UR_RESULT_SUCCESS;
290319
}
320+
321+
ur_result_t urEventGetNativeHandle(ur_event_handle_t hEvent,
322+
ur_native_handle_t *phNativeEvent) try {
323+
*phNativeEvent = reinterpret_cast<ur_native_handle_t>(hEvent->getZeEvent());
324+
return UR_RESULT_SUCCESS;
325+
} catch (...) {
326+
return exceptionToResult(std::current_exception());
327+
}
328+
329+
ur_result_t
330+
urEventCreateWithNativeHandle(ur_native_handle_t hNativeEvent,
331+
ur_context_handle_t hContext,
332+
const ur_event_native_properties_t *pProperties,
333+
ur_event_handle_t *phEvent) try {
334+
*phEvent = new ur_native_event_t(hNativeEvent, hContext, pProperties);
335+
return UR_RESULT_SUCCESS;
336+
} catch (...) {
337+
return exceptionToResult(std::current_exception());
338+
}
339+
291340
} // namespace ur::level_zero

source/adapters/level_zero/v2/event.hpp

Lines changed: 47 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -24,16 +24,19 @@ class event_pool;
2424

2525
struct ur_event_handle_t_ : _ur_object {
2626
public:
27-
ur_event_handle_t_(v2::raii::cache_borrowed_event eventAllocation,
28-
v2::event_pool *pool);
27+
ur_event_handle_t_(ze_event_handle_t hZeEvent, ur_device_handle_t hDevice,
28+
ur_command_t commandType, v2::event_flags_t flags);
2929

30-
// Set the queue and command that this event is associated with
31-
void resetQueueAndCommand(ur_queue_handle_t hQueue, ur_command_t commandType);
30+
// releases event immediately
31+
virtual ur_result_t forceRelease() = 0;
32+
virtual ~ur_event_handle_t_() = default;
3233

3334
void reset();
3435
ze_event_handle_t getZeEvent() const;
3536

3637
ur_result_t retain();
38+
39+
// releases event immediately, or adds to a list for deffered deletion
3740
ur_result_t release();
3841

3942
// releases a signaled and no longer in-use event, that's on the
@@ -47,7 +50,7 @@ struct ur_event_handle_t_ : _ur_object {
4750
// Tells if this event comes from a pool that has profiling enabled.
4851
bool isProfilingEnabled() const;
4952

50-
// Device associated with this event
53+
// Get the device associated with this event
5154
ur_device_handle_t getDevice() const;
5255

5356
// Queue associated with this event
@@ -56,7 +59,9 @@ struct ur_event_handle_t_ : _ur_object {
5659
// Get the type of the command that this event is associated with
5760
ur_command_t getCommandType() const;
5861

59-
void recordStartTimestamp();
62+
// record the start timestamp of the event, to be obtained by
63+
// urEventGetProfilingInfo
64+
void recordStartTimestamp(ur_queue_handle_t);
6065

6166
// Get pointer to the end timestamp, and ze event handle.
6267
// Caller is responsible for signaling the event once the timestamp is ready.
@@ -65,16 +70,47 @@ struct ur_event_handle_t_ : _ur_object {
6570
uint64_t getEventStartTimestmap() const;
6671
uint64_t getEventEndTimestamp();
6772

68-
private:
69-
ur_queue_handle_t hQueue = nullptr;
70-
ur_command_t commandType = UR_COMMAND_FORCE_UINT32;
71-
v2::raii::cache_borrowed_event zeEvent;
72-
v2::event_pool *pool;
73+
protected:
74+
// non-owning handle to the L0 event
75+
const ze_event_handle_t hZeEvent;
76+
77+
// device associated with this event
78+
const ur_device_handle_t hDevice;
79+
80+
v2::event_flags_t flags;
7381

7482
uint64_t adjustedEventStartTimestamp;
7583
uint64_t recordEventEndTimestamp;
7684
uint64_t adjustedEventEndTimestamp;
7785

7886
const uint64_t zeTimerResolution;
7987
const uint64_t timestampMaxValue;
88+
89+
ur_queue_handle_t hQueue;
90+
ur_command_t commandType;
91+
};
92+
93+
struct ur_pooled_event_t : ur_event_handle_t_ {
94+
ur_pooled_event_t(v2::raii::cache_borrowed_event eventAllocation,
95+
v2::event_pool *pool);
96+
97+
// Set the queue and command that this event is associated with
98+
void resetQueueAndCommand(ur_queue_handle_t hQueue, ur_command_t commandType);
99+
100+
ur_result_t forceRelease() override;
101+
102+
private:
103+
v2::raii::cache_borrowed_event zeEvent;
104+
v2::event_pool *pool;
105+
};
106+
107+
struct ur_native_event_t : ur_event_handle_t_ {
108+
ur_native_event_t(ur_native_handle_t hNativeEvent,
109+
ur_context_handle_t hContext,
110+
const ur_event_native_properties_t *pProperties);
111+
112+
ur_result_t forceRelease() override;
113+
114+
private:
115+
v2::raii::ze_event_handle_t zeEvent;
80116
};

source/adapters/level_zero/v2/event_pool.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,15 @@
99
//===----------------------------------------------------------------------===//
1010
#include "event_pool.hpp"
1111
#include "common/latency_tracker.hpp"
12+
#include "event.hpp"
1213
#include "ur_api.h"
1314

1415
namespace v2 {
1516

1617
static constexpr size_t EVENTS_BURST = 64;
1718

18-
ur_event_handle_t_ *event_pool::allocate(ur_queue_handle_t hQueue,
19-
ur_command_t commandType) {
19+
ur_pooled_event_t *event_pool::allocate(ur_queue_handle_t hQueue,
20+
ur_command_t commandType) {
2021
TRACK_SCOPE_LATENCY("event_pool::allocate");
2122

2223
std::unique_lock<std::mutex> lock(*mutex);
@@ -38,7 +39,7 @@ ur_event_handle_t_ *event_pool::allocate(ur_queue_handle_t hQueue,
3839
return event;
3940
}
4041

41-
void event_pool::free(ur_event_handle_t_ *event) {
42+
void event_pool::free(ur_pooled_event_t *event) {
4243
TRACK_SCOPE_LATENCY("event_pool::free");
4344

4445
std::unique_lock<std::mutex> lock(*mutex);

source/adapters/level_zero/v2/event_pool.hpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -41,20 +41,20 @@ class event_pool {
4141
DeviceId Id() { return provider->device()->Id.value(); };
4242

4343
// Allocate an event from the pool. Thread safe.
44-
ur_event_handle_t_ *allocate(ur_queue_handle_t hQueue,
45-
ur_command_t commandType);
44+
ur_pooled_event_t *allocate(ur_queue_handle_t hQueue,
45+
ur_command_t commandType);
4646

4747
// Free an event back to the pool. Thread safe.
48-
void free(ur_event_handle_t_ *event);
48+
void free(ur_pooled_event_t *event);
4949

5050
event_provider *getProvider() const;
5151
event_flags_t getFlags() const;
5252

5353
private:
5454
std::unique_ptr<event_provider> provider;
5555

56-
std::deque<ur_event_handle_t_> events;
57-
std::vector<ur_event_handle_t_ *> freelist;
56+
std::deque<ur_pooled_event_t> events;
57+
std::vector<ur_pooled_event_t *> freelist;
5858

5959
std::unique_ptr<std::mutex> mutex;
6060
};

source/adapters/level_zero/v2/queue_immediate_in_order.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1049,7 +1049,7 @@ ur_result_t ur_queue_immediate_in_order_t::enqueueTimestampRecordingExp(
10491049
auto [pWaitEvents, numWaitEvents] =
10501050
getWaitListView(phEventWaitList, numEventsInWaitList);
10511051

1052-
signalEvent->recordStartTimestamp();
1052+
signalEvent->recordStartTimestamp(this);
10531053

10541054
auto [timestampPtr, zeSignalEvent] =
10551055
signalEvent->getEventEndTimestampAndHandle();

test/adapters/level_zero/v2/event_pool_test.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,14 @@ using namespace v2;
2626

2727
static constexpr size_t MAX_DEVICES = 10;
2828

29+
// mock necessary functions from context, we can't pull in entire context implementation due to
30+
// a lot of other dependencies
31+
std::vector<ur_device_handle_t> mockVec{nullptr};
32+
const std::vector<ur_device_handle_t> &
33+
ur_context_handle_t_::getDevices() const {
34+
return mockVec;
35+
}
36+
2937
enum ProviderType {
3038
TEST_PROVIDER_NORMAL,
3139
TEST_PROVIDER_COUNTER,

0 commit comments

Comments
 (0)