Commit 2babe0a0 authored by Dominik Charousset's avatar Dominik Charousset

Use `caf::intrusive_ptr` for OpenCL pointers

parent e14237b0
...@@ -22,27 +22,31 @@ ...@@ -22,27 +22,31 @@
#include <string> #include <string>
#include "caf/config.hpp"
#include "caf/detail/limited_vector.hpp" #include "caf/detail/limited_vector.hpp"
#if defined __APPLE__ || defined(MACOSX) #ifdef CAF_MACOS
#include <OpenCL/opencl.h> # include <OpenCL/opencl.h>
#else #else
#include <CL/opencl.h> # include <CL/opencl.h>
#endif #endif
// needed for OpenCL 1.0 compatibility (works around missing clReleaseDevice)
extern "C" {
cl_int clReleaseDeviceDummy(cl_device_id);
cl_int clRetainDeviceDummy(cl_device_id);
} // extern "C"
namespace caf { namespace caf {
namespace opencl { namespace opencl {
/** /**
* @brief A vector of up to three elements used for OpenCL dimensions. * A vector of up to three elements used for OpenCL dimensions.
*/ */
using dim_vec = detail::limited_vector<size_t, 3>; using dim_vec = detail::limited_vector<size_t, 3>;
std::string get_opencl_error(cl_int err); std::string get_opencl_error(cl_int err);
cl_int clReleaseDeviceDummy(cl_device_id);
cl_int clRetainDeviceDummy(cl_device_id);
} // namespace opencl } // namespace opencl
} // namespace caf } // namespace caf
......
...@@ -24,104 +24,33 @@ ...@@ -24,104 +24,33 @@
#include <algorithm> #include <algorithm>
#include <type_traits> #include <type_traits>
namespace caf { #include "caf/intrusive_ptr.hpp"
namespace opencl {
template <class T, cl_int (*ref)(T), cl_int (*deref)(T)> #include "caf/opencl/global.hpp"
class smart_ptr {
public:
using element_type = typename std::remove_pointer<T>::type;
using pointer = element_type*;
using reference = element_type&;
using const_pointer = const element_type*;
using const_reference = const element_type&;
smart_ptr(pointer ptr = nullptr, bool inc_ref_count = true) : m_ptr(nullptr) { #define CAF_OPENCL_PTR_ALIAS(aliasname, cltype, claddref, clrelease) \
reset(ptr, inc_ref_count); inline void intrusive_ptr_add_ref(cltype ptr) { claddref(ptr); } \
} inline void intrusive_ptr_release(cltype ptr) { clrelease(ptr); } \
namespace caf { \
namespace opencl { \
using aliasname = intrusive_ptr<std::remove_pointer<cltype>::type>; \
} /* namespace opencl */ \
} // namespace caf
~smart_ptr() { CAF_OPENCL_PTR_ALIAS(mem_ptr, cl_mem, clRetainMemObject, clReleaseMemObject)
reset();
}
smart_ptr(smart_ptr&& other) : m_ptr(nullptr) { CAF_OPENCL_PTR_ALIAS(event_ptr, cl_event, clRetainEvent, clReleaseEvent)
swap(other);
}
smart_ptr(const smart_ptr& other) : m_ptr(nullptr) { CAF_OPENCL_PTR_ALIAS(kernel_ptr, cl_kernel, clRetainKernel, clReleaseKernel)
reset(other.m_ptr);
}
smart_ptr& operator=(pointer ptr) { CAF_OPENCL_PTR_ALIAS(context_ptr, cl_context, clRetainContext, clReleaseContext)
reset(ptr);
return *this;
}
smart_ptr& operator=(smart_ptr&& other) { CAF_OPENCL_PTR_ALIAS(program_ptr, cl_program, clRetainProgram, clReleaseProgram)
swap(other);
return *this;
}
smart_ptr& operator=(const smart_ptr& other) { CAF_OPENCL_PTR_ALIAS(device_ptr, cl_device_id,
smart_ptr tmp{other}; clRetainDeviceDummy, clReleaseDeviceDummy)
swap(tmp);
return *this;
}
void swap(smart_ptr& other) { CAF_OPENCL_PTR_ALIAS(command_queue_ptr, cl_command_queue,
std::swap(m_ptr, other.m_ptr); clRetainCommandQueue, clReleaseCommandQueue)
}
void reset(pointer ptr = nullptr, bool inc_ref_count = true) {
if (m_ptr) {
deref(m_ptr);
}
m_ptr = ptr;
if (ptr && inc_ref_count) {
ref(ptr);
}
}
// does not modify reference count of ptr
void adopt(pointer ptr) {
reset(ptr, false);
}
pointer get() const {
return m_ptr;
}
pointer operator->() const {
return m_ptr;
}
reference operator*() const {
return *m_ptr;
}
bool operator!() const {
return m_ptr == nullptr;
}
explicit operator bool() const {
return m_ptr != nullptr;
}
private:
pointer m_ptr;
};
using mem_ptr = smart_ptr<cl_mem, clRetainMemObject, clReleaseMemObject>;
using event_ptr = smart_ptr<cl_event, clRetainEvent, clReleaseEvent>;
using kernel_ptr = smart_ptr<cl_kernel, clRetainKernel, clReleaseKernel>;
using context_ptr = smart_ptr<cl_context, clRetainContext, clReleaseContext>;
using program_ptr = smart_ptr<cl_program, clRetainProgram, clReleaseProgram>;
using device_ptr =
smart_ptr<cl_device_id, clRetainDeviceDummy, clReleaseDeviceDummy>;
using command_queue_ptr =
smart_ptr<cl_command_queue, clRetainCommandQueue, clReleaseCommandQueue>;
} // namespace opencl
} // namespace caf
#endif // CAF_OPENCL_SMART_PTR_HPP #endif // CAF_OPENCL_SMART_PTR_HPP
...@@ -19,6 +19,14 @@ ...@@ -19,6 +19,14 @@
#include "caf/opencl/global.hpp" #include "caf/opencl/global.hpp"
cl_int clReleaseDeviceDummy(cl_device_id) {
return 0;
}
cl_int clRetainDeviceDummy(cl_device_id) {
return 0;
}
namespace caf { namespace caf {
namespace opencl { namespace opencl {
...@@ -123,8 +131,5 @@ std::string get_opencl_error(cl_int err) { ...@@ -123,8 +131,5 @@ std::string get_opencl_error(cl_int err) {
} }
} }
cl_int clReleaseDeviceDummy(cl_device_id) { return 0; }
cl_int clRetainDeviceDummy(cl_device_id) { return 0; }
} // namespace opencl } // namespace opencl
} // namespace caf } // namespace caf
...@@ -65,15 +65,17 @@ void opencl_metainfo::initialize() { ...@@ -65,15 +65,17 @@ void opencl_metainfo::initialize() {
auto lift = [](cl_device_id ptr) { return device_ptr{ptr, false}; }; auto lift = [](cl_device_id ptr) { return device_ptr{ptr, false}; };
std::transform(ds.begin(), ds.end(), devices.begin(), lift); std::transform(ds.begin(), ds.end(), devices.begin(), lift);
// create a context // create a context
m_context.adopt(v2get(CAF_CLF(clCreateContext), nullptr, num_devs, ds.data(), m_context.reset(v2get(CAF_CLF(clCreateContext), nullptr, num_devs, ds.data(),
pfn_notify, nullptr)); pfn_notify, nullptr),
false);
for (auto& device : devices) { for (auto& device : devices) {
CAF_LOG_DEBUG("creating command queue for device(s)"); CAF_LOG_DEBUG("creating command queue for device(s)");
command_queue_ptr cmd_queue; command_queue_ptr cmd_queue;
try { try {
cmd_queue.adopt(v2get(CAF_CLF(clCreateCommandQueue), cmd_queue.reset(v2get(CAF_CLF(clCreateCommandQueue),
m_context.get(), device.get(), m_context.get(), device.get(),
unsigned{CL_QUEUE_PROFILING_ENABLE})); unsigned{CL_QUEUE_PROFILING_ENABLE}),
false);
} }
catch (std::runtime_error&) { catch (std::runtime_error&) {
CAF_LOG_DEBUG("unable to create command queue for device"); CAF_LOG_DEBUG("unable to create command queue for device");
......
...@@ -44,7 +44,6 @@ program program::create(const char* kernel_source, const char* options, ...@@ -44,7 +44,6 @@ program program::create(const char* kernel_source, const char* options,
auto metainfo = opencl_metainfo::instance(); auto metainfo = opencl_metainfo::instance();
auto devices = metainfo->get_devices(); auto devices = metainfo->get_devices();
auto context = metainfo->m_context; auto context = metainfo->m_context;
if (devices.size() <= device_id) { if (devices.size() <= device_id) {
ostringstream oss; ostringstream oss;
oss << "Device id " << device_id oss << "Device id " << device_id
...@@ -53,13 +52,12 @@ program program::create(const char* kernel_source, const char* options, ...@@ -53,13 +52,12 @@ program program::create(const char* kernel_source, const char* options,
CAF_LOGM_ERROR("caf::opencl::program", oss.str()); CAF_LOGM_ERROR("caf::opencl::program", oss.str());
throw runtime_error(oss.str()); throw runtime_error(oss.str());
} }
// create program object from kernel source // create program object from kernel source
size_t kernel_source_length = strlen(kernel_source); size_t kernel_source_length = strlen(kernel_source);
program_ptr pptr; program_ptr pptr;
pptr.adopt(v2get(CAF_CLF(clCreateProgramWithSource),context.get(), cl_uint{1}, auto rawptr = v2get(CAF_CLF(clCreateProgramWithSource),context.get(),
&kernel_source, &kernel_source_length)); cl_uint{1}, &kernel_source, &kernel_source_length);
pptr.reset(rawptr, false);
// build programm from program object // build programm from program object
auto dev_tmp = devices[device_id].m_device.get(); auto dev_tmp = devices[device_id].m_device.get();
cl_int err = clBuildProgram(pptr.get(), 1, &dev_tmp, cl_int err = clBuildProgram(pptr.get(), 1, &dev_tmp,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment