Skip to content

Commit 464f953

Browse files
igchoraarongreig
andcommitted
Implement partial support for UR_QUEUE_INFO_EMPTY (#18601)
By storing last event in the queue. This only works for in-order queues and when last enqueued operation had signalEvent set. Otherwise UR_RESULT_ERROR_UNSUPPORTED_ENUMERATION is returned. --------- Co-authored-by: aarongreig <aaron.greig@codeplay.com>
1 parent 9a3dcd8 commit 464f953

3 files changed

Lines changed: 48 additions & 11 deletions

File tree

source/adapters/opencl/event.hpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,16 +69,20 @@ inline cl_event *ifUrEvent(ur_event_handle_t *ReturnedEvent, cl_event &Event) {
6969
inline ur_result_t createUREvent(cl_event Event, ur_context_handle_t Context,
7070
ur_queue_handle_t Queue,
7171
ur_event_handle_t *ReturnedEvent) {
72+
assert(Queue);
7273
if (ReturnedEvent) {
7374
try {
7475
auto UREvent =
7576
std::make_unique<ur_event_handle_t_>(Event, Context, Queue);
7677
*ReturnedEvent = UREvent.release();
78+
UR_RETURN_ON_FAILURE(Queue->storeLastEvent(*ReturnedEvent));
7779
} catch (std::bad_alloc &) {
7880
return UR_RESULT_ERROR_OUT_OF_RESOURCES;
7981
} catch (...) {
8082
return UR_RESULT_ERROR_UNKNOWN;
8183
}
84+
} else {
85+
UR_RETURN_ON_FAILURE(Queue->storeLastEvent(nullptr));
8286
}
8387
return UR_RESULT_SUCCESS;
8488
}

source/adapters/opencl/queue.cpp

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -94,8 +94,8 @@ ur_result_t ur_queue_handle_t_::makeWithNative(native_type NativeQueue,
9494
UR_RETURN_ON_FAILURE(urDeviceCreateWithNativeHandle(
9595
hNativeHandle, nullptr, nullptr, &Device));
9696
}
97-
auto URQueue =
98-
std::make_unique<ur_queue_handle_t_>(NativeQueue, Context, Device);
97+
auto URQueue = std::make_unique<ur_queue_handle_t_>(NativeQueue, Context,
98+
Device, false);
9999
Queue = URQueue.release();
100100
} catch (std::bad_alloc &) {
101101
return UR_RESULT_ERROR_OUT_OF_RESOURCES;
@@ -125,14 +125,16 @@ UR_APIEXPORT ur_result_t UR_APICALL urQueueCreate(
125125

126126
cl_int RetErr = CL_INVALID_OPERATION;
127127

128+
bool InOrder = !(CLProperties & SupportByOpenCL &
129+
CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE);
128130
if (Version < oclv::V2_0) {
129131
cl_command_queue Queue =
130132
clCreateCommandQueue(hContext->CLContext, hDevice->CLDevice,
131133
CLProperties & SupportByOpenCL, &RetErr);
132134
CL_RETURN_ON_FAILURE(RetErr);
133135
try {
134-
auto URQueue =
135-
std::make_unique<ur_queue_handle_t_>(Queue, hContext, hDevice);
136+
auto URQueue = std::make_unique<ur_queue_handle_t_>(Queue, hContext,
137+
hDevice, InOrder);
136138
*phQueue = URQueue.release();
137139
} catch (std::bad_alloc &) {
138140
return UR_RESULT_ERROR_OUT_OF_RESOURCES;
@@ -151,7 +153,7 @@ UR_APIEXPORT ur_result_t UR_APICALL urQueueCreate(
151153
CL_RETURN_ON_FAILURE(RetErr);
152154
try {
153155
auto URQueue =
154-
std::make_unique<ur_queue_handle_t_>(Queue, hContext, hDevice);
156+
std::make_unique<ur_queue_handle_t_>(Queue, hContext, hDevice, InOrder);
155157
*phQueue = URQueue.release();
156158
} catch (std::bad_alloc &) {
157159
return UR_RESULT_ERROR_OUT_OF_RESOURCES;
@@ -166,12 +168,23 @@ UR_APIEXPORT ur_result_t UR_APICALL urQueueGetInfo(ur_queue_handle_t hQueue,
166168
size_t propSize,
167169
void *pPropValue,
168170
size_t *pPropSizeRet) {
169-
if (propName == UR_QUEUE_INFO_EMPTY) {
170-
// OpenCL doesn't provide API to check the status of the queue.
171-
return UR_RESULT_ERROR_UNSUPPORTED_ENUMERATION;
172-
}
173171
cl_command_queue_info CLCommandQueueInfo = mapURQueueInfoToCL(propName);
174172
UrReturnHelper ReturnValue(propSize, pPropValue, pPropSizeRet);
173+
if (propName == UR_QUEUE_INFO_EMPTY) {
174+
if (!hQueue->LastEvent) {
175+
// OpenCL doesn't provide API to check the status of the queue.
176+
return UR_RESULT_ERROR_UNSUPPORTED_ENUMERATION;
177+
} else {
178+
ur_event_status_t Status;
179+
UR_RETURN_ON_FAILURE(urEventGetInfo(
180+
hQueue->LastEvent, UR_EVENT_INFO_COMMAND_EXECUTION_STATUS,
181+
sizeof(ur_event_status_t), (void *)&Status, nullptr));
182+
if (Status == UR_EVENT_STATUS_COMPLETE) {
183+
return ReturnValue(true);
184+
}
185+
return ReturnValue(false);
186+
}
187+
}
175188
switch (propName) {
176189
case UR_QUEUE_INFO_CONTEXT: {
177190
return ReturnValue(hQueue->Context);

source/adapters/opencl/queue.hpp

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,14 @@ struct ur_queue_handle_t_ : ur::opencl::handle_base {
2424
std::optional<ur_queue_handle_t> DeviceDefault = std::nullopt;
2525
std::atomic<uint32_t> RefCount = 0;
2626
bool IsNativeHandleOwned = true;
27+
// Used to implement UR_QUEUE_INFO_EMPTY query
28+
bool IsInOrder;
29+
ur_event_handle_t LastEvent = nullptr;
2730

2831
ur_queue_handle_t_(native_type Queue, ur_context_handle_t Ctx,
29-
ur_device_handle_t Dev)
30-
: handle_base(), CLQueue(Queue), Context(Ctx), Device(Dev) {
32+
ur_device_handle_t Dev, bool InOrder)
33+
: handle_base(), CLQueue(Queue), Context(Ctx), Device(Dev),
34+
IsInOrder(InOrder) {
3135
RefCount = 1;
3236
urDeviceRetain(Device);
3337
urContextRetain(Context);
@@ -54,4 +58,20 @@ struct ur_queue_handle_t_ : ur::opencl::handle_base {
5458
uint32_t decrementReferenceCount() noexcept { return --RefCount; }
5559

5660
uint32_t getReferenceCount() const noexcept { return RefCount; }
61+
62+
// Stores last event for in-order queues. Has no effect if queue is Out Of
63+
// Order. The last event is used to implement UR_QUEUE_INFO_EMPTY query.
64+
ur_result_t storeLastEvent(ur_event_handle_t Event) {
65+
if (!IsInOrder) {
66+
return UR_RESULT_SUCCESS;
67+
}
68+
if (LastEvent) {
69+
UR_RETURN_ON_FAILURE(urEventRelease(LastEvent));
70+
}
71+
LastEvent = Event;
72+
if (LastEvent) {
73+
UR_RETURN_ON_FAILURE(urEventRetain(LastEvent));
74+
}
75+
return UR_RESULT_SUCCESS;
76+
}
5777
};

0 commit comments

Comments
 (0)