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 
13 #include <cstring>
14 
15 namespace cl
16 {
17 
setUserEventStatus(cl_int executionStatus)18 cl_int Event::setUserEventStatus(cl_int executionStatus)
19 {
20     const cl_int errorCode = mImpl->setUserEventStatus(executionStatus);
21     if (errorCode == CL_SUCCESS)
22     {
23         mStatusWasChanged = true;
24     }
25     return errorCode;
26 }
27 
getInfo(EventInfo name,size_t valueSize,void * value,size_t * valueSizeRet) const28 cl_int Event::getInfo(EventInfo name, size_t valueSize, void *value, size_t *valueSizeRet) const
29 {
30     cl_int execStatus     = 0;
31     cl_uint valUInt       = 0u;
32     void *valPointer      = nullptr;
33     const void *copyValue = nullptr;
34     size_t copySize       = 0u;
35 
36     switch (name)
37     {
38         case EventInfo::CommandQueue:
39             valPointer = CommandQueue::CastNative(mCommandQueue.get());
40             copyValue  = &valPointer;
41             copySize   = sizeof(valPointer);
42             break;
43         case EventInfo::CommandType:
44             copyValue = &mCommandType;
45             copySize  = sizeof(mCommandType);
46             break;
47         case EventInfo::ReferenceCount:
48             valUInt   = getRefCount();
49             copyValue = &valUInt;
50             copySize  = sizeof(valUInt);
51             break;
52         case EventInfo::CommandExecutionStatus:
53         {
54             const cl_int errorCode = mImpl->getCommandExecutionStatus(execStatus);
55             if (errorCode != CL_SUCCESS)
56             {
57                 return errorCode;
58             }
59             copyValue = &execStatus;
60             copySize  = sizeof(execStatus);
61             break;
62         }
63         case EventInfo::Context:
64             valPointer = mContext->getNative();
65             copyValue  = &valPointer;
66             copySize   = sizeof(valPointer);
67             break;
68         default:
69             return CL_INVALID_VALUE;
70     }
71 
72     if (value != nullptr)
73     {
74         // CL_INVALID_VALUE if size in bytes specified by param_value_size is < size of return type
75         // as described in the Event Queries table and param_value is not NULL.
76         if (valueSize < copySize)
77         {
78             return CL_INVALID_VALUE;
79         }
80         if (copyValue != nullptr)
81         {
82             std::memcpy(value, copyValue, copySize);
83         }
84     }
85     if (valueSizeRet != nullptr)
86     {
87         *valueSizeRet = copySize;
88     }
89     return CL_SUCCESS;
90 }
91 
setCallback(cl_int commandExecCallbackType,EventCB pfnNotify,void * userData)92 cl_int Event::setCallback(cl_int commandExecCallbackType, EventCB pfnNotify, void *userData)
93 {
94     auto callbacks = mCallbacks.synchronize();
95     // Only when required register a single callback with the back end for each callback type.
96     if ((*callbacks)[commandExecCallbackType].empty())
97     {
98         ANGLE_CL_TRY(mImpl->setCallback(*this, commandExecCallbackType));
99         // This event has to be retained until the callback is called.
100         retain();
101     }
102     (*callbacks)[commandExecCallbackType].emplace_back(pfnNotify, userData);
103     return CL_SUCCESS;
104 }
105 
getProfilingInfo(ProfilingInfo name,size_t valueSize,void * value,size_t * valueSizeRet)106 cl_int Event::getProfilingInfo(ProfilingInfo name,
107                                size_t valueSize,
108                                void *value,
109                                size_t *valueSizeRet)
110 {
111     return mImpl->getProfilingInfo(name, valueSize, value, valueSizeRet);
112 }
113 
114 Event::~Event() = default;
115 
callback(cl_int commandStatus)116 void Event::callback(cl_int commandStatus)
117 {
118     ASSERT(commandStatus >= 0 && commandStatus < 3);
119     const Callbacks callbacks = std::move(mCallbacks->at(commandStatus));
120     for (const CallbackData &data : callbacks)
121     {
122         data.first(this, commandStatus, data.second);
123     }
124     // This event can be released after the callback was called.
125     if (release())
126     {
127         delete this;
128     }
129 }
130 
Cast(cl_uint numEvents,const cl_event * eventList)131 EventPtrs Event::Cast(cl_uint numEvents, const cl_event *eventList)
132 {
133     EventPtrs events;
134     events.reserve(numEvents);
135     while (numEvents-- != 0u)
136     {
137         events.emplace_back(&(*eventList++)->cast<Event>());
138     }
139     return events;
140 }
141 
Event(Context & context,cl_int & errorCode)142 Event::Event(Context &context, cl_int &errorCode)
143     : mContext(&context),
144       mCommandType(CL_COMMAND_USER),
145       mImpl(context.getImpl().createUserEvent(*this, errorCode))
146 {}
147 
Event(CommandQueue & queue,cl_command_type commandType,const rx::CLEventImpl::CreateFunc & createFunc,cl_int & errorCode)148 Event::Event(CommandQueue &queue,
149              cl_command_type commandType,
150              const rx::CLEventImpl::CreateFunc &createFunc,
151              cl_int &errorCode)
152     : mContext(&queue.getContext()),
153       mCommandQueue(&queue),
154       mCommandType(commandType),
155       mImpl(createFunc(*this))
156 {}
157 
158 }  // namespace cl
159