//---------------------------------------------------------------------------// // Copyright (c) 2013-2014 Kyle Lutz // // Distributed under the Boost Software License, Version 1.0 // See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt // // See http://boostorg.github.com/compute for more information. //---------------------------------------------------------------------------// #ifndef BOOST_COMPUTE_DETAIL_GET_OBJECT_INFO_HPP #define BOOST_COMPUTE_DETAIL_GET_OBJECT_INFO_HPP #include #include #include #include #include #include #include namespace boost { namespace compute { namespace detail { template struct bound_info_function { bound_info_function(Function function, Object object, AuxInfo aux_info) : m_function(function), m_object(object), m_aux_info(aux_info) { } template cl_int operator()(Info info, size_t input_size, const void *input, size_t size, void *value, size_t *size_ret) const { return m_function( m_object, m_aux_info, info, input_size, input, size, value, size_ret ); } template cl_int operator()(Info info, size_t size, void *value, size_t *size_ret) const { return m_function(m_object, m_aux_info, info, size, value, size_ret); } Function m_function; Object m_object; AuxInfo m_aux_info; }; template struct bound_info_function { bound_info_function(Function function, Object object) : m_function(function), m_object(object) { } template cl_int operator()(Info info, size_t size, void *value, size_t *size_ret) const { return m_function(m_object, info, size, value, size_ret); } Function m_function; Object m_object; }; template inline bound_info_function bind_info_function(Function f, Object o) { return bound_info_function(f, o); } template inline bound_info_function bind_info_function(Function f, Object o, AuxInfo j) { return bound_info_function(f, o, j); } // default implementation template struct get_object_info_impl { template T operator()(Function function, Info info) const { T value; cl_int ret = function(info, sizeof(T), &value, 0); if(ret != CL_SUCCESS){ BOOST_THROW_EXCEPTION(opencl_error(ret)); } return value; } template T operator()(Function function, Info info, const size_t input_size, const void* input) const { T value; cl_int ret = function(info, input_size, input, sizeof(T), &value, 0); if(ret != CL_SUCCESS){ BOOST_THROW_EXCEPTION(opencl_error(ret)); } return value; } }; // specialization for bool template<> struct get_object_info_impl { template bool operator()(Function function, Info info) const { cl_bool value; cl_int ret = function(info, sizeof(cl_bool), &value, 0); if(ret != CL_SUCCESS){ BOOST_THROW_EXCEPTION(opencl_error(ret)); } return value == CL_TRUE; } }; // specialization for std::string template<> struct get_object_info_impl { template std::string operator()(Function function, Info info) const { size_t size = 0; cl_int ret = function(info, 0, 0, &size); if(ret != CL_SUCCESS){ BOOST_THROW_EXCEPTION(opencl_error(ret)); } if(size == 0){ return std::string(); } std::string value(size - 1, 0); ret = function(info, size, &value[0], 0); if(ret != CL_SUCCESS){ BOOST_THROW_EXCEPTION(opencl_error(ret)); } return value; } }; // specialization for std::vector template struct get_object_info_impl > { template std::vector operator()(Function function, Info info) const { size_t size = 0; cl_int ret = function(info, 0, 0, &size); if(ret != CL_SUCCESS){ BOOST_THROW_EXCEPTION(opencl_error(ret)); } if(size == 0) return std::vector(); std::vector vector(size / sizeof(T)); ret = function(info, size, &vector[0], 0); if(ret != CL_SUCCESS){ BOOST_THROW_EXCEPTION(opencl_error(ret)); } return vector; } template std::vector operator()(Function function, Info info, const size_t input_size, const void* input) const { #ifdef BOOST_COMPUTE_CL_VERSION_2_1 // For CL_KERNEL_LOCAL_SIZE_FOR_SUB_GROUP_COUNT in clGetKernelSubGroupInfo // we can't get param_value_size using param_value_size_ret if(info == CL_KERNEL_LOCAL_SIZE_FOR_SUB_GROUP_COUNT) { std::vector vector(3); cl_int ret = function( info, input_size, input, sizeof(T) * vector.size(), &vector[0], 0 ); if(ret != CL_SUCCESS){ BOOST_THROW_EXCEPTION(opencl_error(ret)); } return vector; } #endif size_t size = 0; cl_int ret = function(info, input_size, input, 0, 0, &size); if(ret != CL_SUCCESS){ BOOST_THROW_EXCEPTION(opencl_error(ret)); } std::vector vector(size / sizeof(T)); ret = function(info, input_size, input, size, &vector[0], 0); if(ret != CL_SUCCESS){ BOOST_THROW_EXCEPTION(opencl_error(ret)); } return vector; } }; // returns the value (of type T) from the given clGet*Info() function call. template inline T get_object_info(Function f, Object o, Info i) { return get_object_info_impl()(bind_info_function(f, o), i); } template inline T get_object_info(Function f, Object o, Info i, AuxInfo j) { return get_object_info_impl()(bind_info_function(f, o, j), i); } template inline T get_object_info(Function f, Object o, Info i, AuxInfo j, const size_t k, const void * l) { return get_object_info_impl()(bind_info_function(f, o, j), i, k, l); } // returns the value type for the clGet*Info() call on Object with Enum. template struct get_object_info_type; // defines the object::get_info() specialization #define BOOST_COMPUTE_DETAIL_DEFINE_GET_INFO_SPECIALIZATION(object_type, result_type, value) \ namespace detail { \ template<> struct get_object_info_type { typedef result_type type; }; \ } \ template<> inline result_type object_type::get_info() const \ { \ return get_info(value); \ } // used by BOOST_COMPUTE_DETAIL_DEFINE_GET_INFO_SPECIALIZATIONS() #define BOOST_COMPUTE_DETAIL_DEFINE_GET_INFO_IMPL(r, data, elem) \ BOOST_COMPUTE_DETAIL_DEFINE_GET_INFO_SPECIALIZATION( \ data, BOOST_PP_TUPLE_ELEM(2, 0, elem), BOOST_PP_TUPLE_ELEM(2, 1, elem) \ ) // defines the object::get_info() specialization for each // (result_type, value) tuple in seq for object_type. #define BOOST_COMPUTE_DETAIL_DEFINE_GET_INFO_SPECIALIZATIONS(object_type, seq) \ BOOST_PP_SEQ_FOR_EACH( \ BOOST_COMPUTE_DETAIL_DEFINE_GET_INFO_IMPL, object_type, seq \ ) } // end detail namespace } // end compute namespace } // end boost namespace #endif // BOOST_COMPUTE_DETAIL_GET_OBJECT_INFO_HPP