1 //
2 // Copyright 2021 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 // CLEvent.cpp: Implements the cl::Event class.
7
8 #include "libANGLE/CLEvent.h"
9
10 #include "libANGLE/CLCommandQueue.h"
11 #include "libANGLE/CLContext.h"
12 #include "libANGLE/cl_utils.h"
13
14 #include <cstring>
15
16 namespace cl
17 {
18
setUserEventStatus(cl_int executionStatus)19 angle::Result Event::setUserEventStatus(cl_int executionStatus)
20 {
21 ANGLE_TRY(mImpl->setUserEventStatus(executionStatus));
22 mStatusWasChanged = true;
23 return angle::Result::Continue;
24 }
25
getInfo(EventInfo name,size_t valueSize,void * value,size_t * valueSizeRet) const26 angle::Result Event::getInfo(EventInfo name,
27 size_t valueSize,
28 void *value,
29 size_t *valueSizeRet) const
30 {
31 cl_int execStatus = 0;
32 cl_uint valUInt = 0u;
33 void *valPointer = nullptr;
34 const void *copyValue = nullptr;
35 size_t copySize = 0u;
36
37 switch (name)
38 {
39 case EventInfo::CommandQueue:
40 valPointer = CommandQueue::CastNative(mCommandQueue.get());
41 copyValue = &valPointer;
42 copySize = sizeof(valPointer);
43 break;
44 case EventInfo::CommandType:
45 copyValue = &mCommandType;
46 copySize = sizeof(mCommandType);
47 break;
48 case EventInfo::ReferenceCount:
49 valUInt = getRefCount();
50 copyValue = &valUInt;
51 copySize = sizeof(valUInt);
52 break;
53 case EventInfo::CommandExecutionStatus:
54 {
55 ANGLE_TRY(mImpl->getCommandExecutionStatus(execStatus));
56 copyValue = &execStatus;
57 copySize = sizeof(execStatus);
58 break;
59 }
60 case EventInfo::Context:
61 valPointer = mContext->getNative();
62 copyValue = &valPointer;
63 copySize = sizeof(valPointer);
64 break;
65 default:
66 ANGLE_CL_RETURN_ERROR(CL_INVALID_VALUE);
67 }
68
69 if (value != nullptr)
70 {
71 // CL_INVALID_VALUE if size in bytes specified by param_value_size is < size of return type
72 // as described in the Event Queries table and param_value is not NULL.
73 if (valueSize < copySize)
74 {
75 ANGLE_CL_RETURN_ERROR(CL_INVALID_VALUE);
76 }
77 if (copyValue != nullptr)
78 {
79 std::memcpy(value, copyValue, copySize);
80 }
81 }
82 if (valueSizeRet != nullptr)
83 {
84 *valueSizeRet = copySize;
85 }
86 return angle::Result::Continue;
87 }
88
setCallback(cl_int commandExecCallbackType,EventCB pfnNotify,void * userData)89 angle::Result Event::setCallback(cl_int commandExecCallbackType, EventCB pfnNotify, void *userData)
90 {
91 auto callbacks = mCallbacks.synchronize();
92
93 // Spec mentions that the callback will be called when the execution status of the event is
94 // equal to past the status specified by commandExecCallbackType
95 cl_int currentStatus;
96 ANGLE_TRY(mImpl->getCommandExecutionStatus(currentStatus));
97 if (currentStatus <= commandExecCallbackType)
98 {
99 pfnNotify(this, commandExecCallbackType, userData);
100 return angle::Result::Continue;
101 }
102
103 // Only when required register a single callback with the back end for each callback type.
104 if ((*callbacks)[commandExecCallbackType].empty())
105 {
106 ANGLE_TRY(mImpl->setCallback(*this, commandExecCallbackType));
107 // This event has to be retained until the callback is called.
108 retain();
109 }
110 (*callbacks)[commandExecCallbackType].emplace_back(pfnNotify, userData);
111 return angle::Result::Continue;
112 }
113
getProfilingInfo(ProfilingInfo name,size_t valueSize,void * value,size_t * valueSizeRet)114 angle::Result Event::getProfilingInfo(ProfilingInfo name,
115 size_t valueSize,
116 void *value,
117 size_t *valueSizeRet)
118 {
119 return mImpl->getProfilingInfo(name, valueSize, value, valueSizeRet);
120 }
121
initBackend(const rx::CLEventImpl::CreateFunc & createFunc)122 angle::Result Event::initBackend(const rx::CLEventImpl::CreateFunc &createFunc)
123 {
124 if (isUserEvent())
125 {
126 return mContext->getImpl().createUserEvent(*this, &mImpl);
127 }
128 else
129 {
130 mImpl = createFunc(*this);
131 if (mImpl == nullptr)
132 {
133 ANGLE_CL_RETURN_ERROR(CL_OUT_OF_HOST_MEMORY);
134 }
135 return mImpl->onEventCreate();
136 }
137 }
138
139 Event::~Event() = default;
140
callback(cl_int commandStatus)141 void Event::callback(cl_int commandStatus)
142 {
143 ASSERT(commandStatus >= 0 && commandStatus < 3);
144 const Callbacks callbacks = std::move(mCallbacks->at(commandStatus));
145 for (const CallbackData &data : callbacks)
146 {
147 data.first(this, commandStatus, data.second);
148 }
149 // This event can be released after the callback was called.
150 if (release())
151 {
152 delete this;
153 }
154 }
155
Cast(cl_uint numEvents,const cl_event * eventList)156 EventPtrs Event::Cast(cl_uint numEvents, const cl_event *eventList)
157 {
158 EventPtrs events;
159 events.reserve(numEvents);
160 while (numEvents-- != 0u)
161 {
162 events.emplace_back(&(*eventList++)->cast<Event>());
163 }
164 return events;
165 }
166
Event(Context & context)167 Event::Event(Context &context) : mContext(&context), mCommandType(CL_COMMAND_USER), mImpl(nullptr)
168 {
169 ANGLE_CL_IMPL_TRY(context.getImpl().createUserEvent(*this, &mImpl));
170 }
171
Event(CommandQueue & queue,cl_command_type commandType)172 Event::Event(CommandQueue &queue, cl_command_type commandType)
173 : mContext(&queue.getContext()),
174 mCommandQueue(&queue),
175 mCommandType(commandType),
176 mImpl(nullptr)
177 {}
178
179 } // namespace cl
180