#include "CL_state.h" #include #include #include #include #ifdef HAVE_OCL namespace cl { CL_state* CL_state::instance_ = NULL; CL_state* CL_state::instance() { static Guard g; if (instance_ == NULL) { instance_ = new CL_state; } return instance_; } CL_state::CL_state() : kernels_(KERNEL_MAX, 0) { } CL_state::~CL_state() { size_t i; for (i=0; i < kernels_.size(); ++i) { if (kernels_[i]) clReleaseKernel(kernels_[i]); } for (i=0; i < programs_.size(); ++i) { clReleaseProgram(programs_[i]); } } bool CL_state::init(const char *argv_0) { if (ocl_context_.create()) { std::cout << ocl_context_.version() << std::endl; } else { std::cout << "CL_state::Constructor: [ERROR] Could not create OpenCL context!" << std::endl; return false; } return load_programs(argv_0); } const cl_kernel& CL_state::kernel(Kernel_type k) { return kernels_[k]; } bool CL_state::load_programs(const char *argv_0) { // path to shader directory std::string full_path(argv_0); #ifdef _WIN32 full_path = full_path.substr(0, full_path.find_last_of('\\')+1); full_path += "kernels\\"; #elif __APPLE__ full_path = full_path.substr(0, full_path.find_last_of('/')+1); full_path += "kernels/"; #else full_path = full_path.substr(0, full_path.find_last_of('/')+1); full_path += "kernels/"; #endif cl_program program; program = load_program(full_path+"blendshapes.cl"); if (program) { kernels_[BLENDSHAPE_KERNEL] = get_kernel(program, "blend"); programs_.push_back(program); } else { return false; } program = load_program(full_path+"correspondences.cl"); if (program) { kernels_[CORRESPONDENCES_PS2MESH_KERNEL] = get_kernel(program, "ps2mesh"); kernels_[CORRESPONDENCES_MESH2PS_KERNEL] = get_kernel(program, "mesh2ps"); kernels_[CORRESPONDENCES_PS2PS_KERNEL] = get_kernel(program, "ps2ps"); programs_.push_back(program); } else { return false; } return true; } cl_program CL_state::load_program(const std::string& filename) { cl_program program=0; cl_int err; std::string str; std::stringstream ss; size_t size; // read file to string std::ifstream ifs(filename.c_str()); if (!ifs) { std::cout << "CL_state::load_program: [ERROR] No such file\"" << filename << "\"." << std::endl; return 0; } ss << ifs.rdbuf(); str = ss.str(); const char* source = str.c_str(); size = ss.str().size(); //create cl program program = clCreateProgramWithSource(ocl_context_.context(), 1, &source, &size, &err); if (err != CL_SUCCESS) { std::cout << "CL_state::load_program: [WARNING] Could not create program for \"" << filename << "\"." << std::endl; return 0; } //compile program err = clBuildProgram(program, 1, &(ocl_context_.device_id()), NULL, NULL, NULL); if (err != CL_SUCCESS) { clGetProgramBuildInfo(program, ocl_context_.device_id(), CL_PROGRAM_BUILD_LOG, 0, NULL, &size); str.resize(size); clGetProgramBuildInfo(program, ocl_context_.device_id(), CL_PROGRAM_BUILD_LOG, size, &str[0], NULL); std::cout << "CL_state::load_program: [WARNING] Could not build program for \"" << filename << "\". Log:" << std::endl; std::cout << str << std::endl; return 0; } return program; } cl_kernel CL_state::get_kernel(cl_program program, const char *kernel_name) { cl_int err; cl_kernel kernel; kernel = clCreateKernel(program, kernel_name, &err); if (err != CL_SUCCESS) { std::cout << "CL_state::get_kernel: [WARNING] Could not create kernel with name \"" << kernel_name << "\"." << std::endl; return 0; } return kernel; } } //namespace cl #endif