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