OpenCL: Implement clSetContextDestructorCallback Adding support for clSetContextDestructorCallback. This will register a destructor callback function with a context. When context destructor called, it will run the callbacks functions. Bug: angleproject:491161377 Tests-Passing: ocl_cts.test_api.context_destructor_callback Change-Id: I33605f12450e23fc86043eb257d54ec6369d098e Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/7657410 Commit-Queue: Austin Annestrand <a.annestrand@samsung.com> Reviewed-by: Geoff Lang <geofflang@chromium.org> Reviewed-by: Shahbaz Youssefi <syoussefi@chromium.org>
diff --git a/include/angle_cl.h b/include/angle_cl.h index 06c1f69..50302d8 100644 --- a/include/angle_cl.h +++ b/include/angle_cl.h
@@ -30,6 +30,7 @@ size_t cb, void *user_data); +using ContextCB = void(CL_CALLBACK *)(cl_context context, void *user_data); using MemoryCB = void(CL_CALLBACK *)(cl_mem memobj, void *user_data); using ProgramCB = void(CL_CALLBACK *)(cl_program program, void *user_data); using EventCB = void(CL_CALLBACK *)(cl_event event, cl_int event_command_status, void *user_data);
diff --git a/src/libANGLE/CLContext.cpp b/src/libANGLE/CLContext.cpp index 3b3900c..08c9683 100644 --- a/src/libANGLE/CLContext.cpp +++ b/src/libANGLE/CLContext.cpp
@@ -85,6 +85,12 @@ return angle::Result::Continue; } +angle::Result Context::setDestructorCallback(ContextCB pfnNotify, void *userData) +{ + mDestructorCallbacks->emplace(pfnNotify, userData); + return angle::Result::Continue; +} + cl_command_queue Context::createCommandQueueWithProperties(cl_device_id device, const cl_queue_properties *properties) { @@ -365,7 +371,20 @@ return mImpl->waitForEvents(Event::Cast(numEvents, eventList)); } -Context::~Context() = default; +Context::~Context() +{ + // TODO(aannestrand): make dtor callback handling a "helper" util and reuse for CLMemory dtor + // http://anglebug.com/496408119 + std::stack<CallbackData> callbacks; + mDestructorCallbacks->swap(callbacks); + while (!callbacks.empty()) + { + const ContextCB callback = callbacks.top().first; + void *const userData = callbacks.top().second; + callbacks.pop(); + callback(this, userData); + } +} void Context::ErrorCallback(const char *errinfo, const void *privateInfo, size_t cb, void *userData) {
diff --git a/src/libANGLE/CLContext.h b/src/libANGLE/CLContext.h index 2d7cbf4..ca4e1ba 100644 --- a/src/libANGLE/CLContext.h +++ b/src/libANGLE/CLContext.h
@@ -14,6 +14,8 @@ #include "libANGLE/CLPlatform.h" #include "libANGLE/renderer/CLContextImpl.h" +#include <stack> + namespace cl { @@ -29,6 +31,8 @@ void *value, size_t *valueSizeRet) const; + angle::Result setDestructorCallback(ContextCB pfnNotify, void *userData); + cl_command_queue createCommandQueueWithProperties(cl_device_id device, const cl_queue_properties *properties); @@ -125,6 +129,8 @@ const void *handle); private: + using CallbackData = std::pair<ContextCB, void *>; + Context(Platform &platform, PropArray &&properties, DevicePtrs &&devices, @@ -146,6 +152,8 @@ rx::CLContextImpl::Ptr mImpl; DevicePtrs mDevices; + angle::SynchronizedValue<std::stack<CallbackData>> mDestructorCallbacks; + friend class Object; };
diff --git a/src/libGLESv2/cl_stubs.cpp b/src/libGLESv2/cl_stubs.cpp index d5754ab..be666c0 100644 --- a/src/libGLESv2/cl_stubs.cpp +++ b/src/libGLESv2/cl_stubs.cpp
@@ -233,8 +233,7 @@ void *user_data), void *user_data) { - WARN_NOT_SUPPORTED(SetContextDestructorCallback); - return CL_INVALID_OPERATION; + CL_RETURN_ERROR(context->cast<Context>().setDestructorCallback(pfn_notify, user_data)); } cl_command_queue CreateCommandQueueWithProperties(cl_context context,