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

Use `caf::intrusive_ptr` for OpenCL pointers

parent e14237b0
......@@ -22,27 +22,31 @@
#include <string>
#include "caf/config.hpp"
#include "caf/detail/limited_vector.hpp"
#if defined __APPLE__ || defined(MACOSX)
#include <OpenCL/opencl.h>
#ifdef CAF_MACOS
# include <OpenCL/opencl.h>
#else
#include <CL/opencl.h>
# include <CL/opencl.h>
#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 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>;
std::string get_opencl_error(cl_int err);
cl_int clReleaseDeviceDummy(cl_device_id);
cl_int clRetainDeviceDummy(cl_device_id);
} // namespace opencl
} // namespace caf
......
......@@ -24,104 +24,33 @@
#include <algorithm>
#include <type_traits>
namespace caf {
namespace opencl {
#include "caf/intrusive_ptr.hpp"
template <class T, cl_int (*ref)(T), cl_int (*deref)(T)>
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&;
#include "caf/opencl/global.hpp"
smart_ptr(pointer ptr = nullptr, bool inc_ref_count = true) : m_ptr(nullptr) {
reset(ptr, inc_ref_count);
}
#define CAF_OPENCL_PTR_ALIAS(aliasname, cltype, claddref, clrelease) \
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() {
reset();
}
CAF_OPENCL_PTR_ALIAS(mem_ptr, cl_mem, clRetainMemObject, clReleaseMemObject)
smart_ptr(smart_ptr&& other) : m_ptr(nullptr) {
swap(other);
}
CAF_OPENCL_PTR_ALIAS(event_ptr, cl_event, clRetainEvent, clReleaseEvent)
smart_ptr(const smart_ptr& other) : m_ptr(nullptr) {
reset(other.m_ptr);
}
CAF_OPENCL_PTR_ALIAS(kernel_ptr, cl_kernel, clRetainKernel, clReleaseKernel)
smart_ptr& operator=(pointer ptr) {
reset(ptr);
return *this;
}
CAF_OPENCL_PTR_ALIAS(context_ptr, cl_context, clRetainContext, clReleaseContext)
smart_ptr& operator=(smart_ptr&& other) {
swap(other);
return *this;
}
CAF_OPENCL_PTR_ALIAS(program_ptr, cl_program, clRetainProgram, clReleaseProgram)
smart_ptr& operator=(const smart_ptr& other) {
smart_ptr tmp{other};
swap(tmp);
return *this;
}
CAF_OPENCL_PTR_ALIAS(device_ptr, cl_device_id,
clRetainDeviceDummy, clReleaseDeviceDummy)
void swap(smart_ptr& other) {
std::swap(m_ptr, other.m_ptr);
}
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
CAF_OPENCL_PTR_ALIAS(command_queue_ptr, cl_command_queue,
clRetainCommandQueue, clReleaseCommandQueue)
#endif // CAF_OPENCL_SMART_PTR_HPP
......@@ -19,6 +19,14 @@
#include "caf/opencl/global.hpp"
cl_int clReleaseDeviceDummy(cl_device_id) {
return 0;
}
cl_int clRetainDeviceDummy(cl_device_id) {
return 0;
}
namespace caf {
namespace opencl {
......@@ -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 caf
......@@ -65,15 +65,17 @@ void opencl_metainfo::initialize() {
auto lift = [](cl_device_id ptr) { return device_ptr{ptr, false}; };
std::transform(ds.begin(), ds.end(), devices.begin(), lift);
// create a context
m_context.adopt(v2get(CAF_CLF(clCreateContext), nullptr, num_devs, ds.data(),
pfn_notify, nullptr));
m_context.reset(v2get(CAF_CLF(clCreateContext), nullptr, num_devs, ds.data(),
pfn_notify, nullptr),
false);
for (auto& device : devices) {
CAF_LOG_DEBUG("creating command queue for device(s)");
command_queue_ptr cmd_queue;
try {
cmd_queue.adopt(v2get(CAF_CLF(clCreateCommandQueue),
cmd_queue.reset(v2get(CAF_CLF(clCreateCommandQueue),
m_context.get(), device.get(),
unsigned{CL_QUEUE_PROFILING_ENABLE}));
unsigned{CL_QUEUE_PROFILING_ENABLE}),
false);
}
catch (std::runtime_error&) {
CAF_LOG_DEBUG("unable to create command queue for device");
......
......@@ -44,7 +44,6 @@ program program::create(const char* kernel_source, const char* options,
auto metainfo = opencl_metainfo::instance();
auto devices = metainfo->get_devices();
auto context = metainfo->m_context;
if (devices.size() <= device_id) {
ostringstream oss;
oss << "Device id " << device_id
......@@ -53,13 +52,12 @@ program program::create(const char* kernel_source, const char* options,
CAF_LOGM_ERROR("caf::opencl::program", oss.str());
throw runtime_error(oss.str());
}
// create program object from kernel source
size_t kernel_source_length = strlen(kernel_source);
program_ptr pptr;
pptr.adopt(v2get(CAF_CLF(clCreateProgramWithSource),context.get(), cl_uint{1},
&kernel_source, &kernel_source_length));
auto rawptr = v2get(CAF_CLF(clCreateProgramWithSource),context.get(),
cl_uint{1}, &kernel_source, &kernel_source_length);
pptr.reset(rawptr, false);
// build programm from program object
auto dev_tmp = devices[device_id].m_device.get();
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