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
122 Event::~Event() = default;
123
callback(cl_int commandStatus)124 void Event::callback(cl_int commandStatus)
125 {
126 ASSERT(commandStatus >= 0 && commandStatus < 3);
127 const Callbacks callbacks = std::move(mCallbacks->at(commandStatus));
128 for (const CallbackData &data : callbacks)
129 {
130 data.first(this, commandStatus, data.second);
131 }
132 // This event can be released after the callback was called.
133 if (release())
134 {
135 delete this;
136 }
137 }
138
Cast(cl_uint numEvents,const cl_event * eventList)139 EventPtrs Event::Cast(cl_uint numEvents, const cl_event *eventList)
140 {
141 EventPtrs events;
142 events.reserve(numEvents);
143 while (numEvents-- != 0u)
144 {
145 events.emplace_back(&(*eventList++)->cast<Event>());
146 }
147 return events;
148 }
149
Event(Context & context)150 Event::Event(Context &context) : mContext(&context), mCommandType(CL_COMMAND_USER), mImpl(nullptr)
151 {
152 ANGLE_CL_IMPL_TRY(context.getImpl().createUserEvent(*this, &mImpl));
153 }
154
Event(CommandQueue & queue,cl_command_type commandType,const rx::CLEventImpl::CreateFunc & createFunc)155 Event::Event(CommandQueue &queue,
156 cl_command_type commandType,
157 const rx::CLEventImpl::CreateFunc &createFunc)
158 : mContext(&queue.getContext()),
159 mCommandQueue(&queue),
160 mCommandType(commandType),
161 mImpl(createFunc(*this))
162 {}
163
164 } // namespace cl
165