Program Listing for File openclKernelProcessor.hpp#
↰ Return to documentation for file (librapid/include/librapid/opencl/openclKernelProcessor.hpp)
#ifndef LIBRAPID_OPENCL_KERNEL_PROCESSOR_HPP
#define LIBRAPID_OPENCL_KERNEL_PROCESSOR_HPP
#if defined(LIBRAPID_HAS_OPENCL)
namespace librapid::opencl {
template<typename Scalar, bool noCast = false, size_t... I, typename... Args>
void setKernelArgs(cl::Kernel &kernel, const std::tuple<Args...> &args,
std::index_sequence<I...>) {
constexpr auto caster = [](auto &&x) {
using T = std::decay_t<decltype(x)>;
if constexpr (noCast || std::is_same_v<T, cl::Buffer>) {
return x;
} else if constexpr (typetraits::TypeInfo<T>::type == detail::LibRapidType::Scalar) {
return static_cast<Scalar>(x);
} else {
return x;
}
};
((kernel.setArg(I, caster(std::get<I>(args)))), ...);
}
template<typename Scalar, bool noCast = false, typename... Args>
void runLinearKernel(const std::string &kernelName, int64_t numElements, Args... args) {
static_assert(sizeof(Scalar) > 2,
"Scalar type must be larger than 2 bytes. Please create an issue on GitHub "
"if you need support for smaller types.");
std::string kernelNameFull = kernelName + "_" + typetraits::TypeInfo<Scalar>::name;
cl::Kernel kernel(global::openCLProgram, kernelNameFull.c_str());
setKernelArgs<Scalar, noCast>(
kernel, std::make_tuple(args...), std::make_index_sequence<sizeof...(Args)>());
cl::NDRange range(numElements);
auto err =
global::openCLQueue.enqueueNDRangeKernel(kernel, cl::NullRange, range, cl::NullRange);
LIBRAPID_ASSERT(err == CL_SUCCESS,
"OpenCL kernel execution failed with error code {}: {}",
err,
getOpenCLErrorString(err));
}
} // namespace librapid::opencl
#endif // LIBRAPID_HAS_OPENCL
#endif // LIBRAPID_OPENCL_KERNEL_PROCESSOR_HPP