2

I'm trying to load an external OpenCL kernel and the clCreateKernel returns an error code: -46 CL_INVALID_KERNEL_NAME. The file structure is the following:

.
├── CMakeLists.txt
└── src
    ├── cl.hpp
    ├── GameOfLife.cpp
    └── kernels
        └── programs.cl

This is my first CMake project, thus I'm not sure the following CMake is correct:

cmake_minimum_required(VERSION 3.5)
project(gpgpu_gameoflife)

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -lOpenCL")

set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR})
include_directories(${PROJECT_SOURCE_DIR}/src/kernels)

# source: http://igorbarbosa.com/articles/how-to-use-opengl-freeglut-and-cmake/
#########################################################
# FIND GLUT
#########################################################
find_package(GLUT REQUIRED)
include_directories(${GLUT_INCLUDE_DIRS})
link_directories(${GLUT_LIBRARY_DIRS})
add_definitions(${GLUT_DEFINITIONS})
if(NOT GLUT_FOUND)
    message(ERROR " GLUT not found!")
endif(NOT GLUT_FOUND)
#########################################################
# FIND OPENGL
#########################################################
find_package(OpenGL REQUIRED)
include_directories(${OpenGL_INCLUDE_DIRS})
link_directories(${OpenGL_LIBRARY_DIRS})
add_definitions(${OpenGL_DEFINITIONS})
if(NOT OPENGL_FOUND)
    message(ERROR " OPENGL not found!")
endif(NOT OPENGL_FOUND)


set(SOURCE_FILES
        src/GameOfLife.cpp
        src/kernels/programs.cl
        )
add_executable(gpgpu_gameoflife ${SOURCE_FILES})

target_link_libraries(gpgpu_gameoflife ${OPENGL_LIBRARIES} ${GLUT_LIBRARY})

For the following function call I get an empty string as a result, thus I think the kernel file is not available to be read (the kernel itself is not empty).

std::string sourceCode = fileToString("kernels/programs.cl");

...

std::string fileToString(const std::string &path) {
    std::ifstream file(path, std::ios::in | std::ios::binary);
    if (file) {
        std::ostringstream contents;
        contents << file.rdbuf();
        file.close();
        return (contents.str());
    }
    return "";
}

Could you please tell me how to create an OpenCL application using CMake that loads an external kernel? Or is this not a good practice?

Thank you!

Dániel Stein
  • 417
  • 3
  • 16
  • I expect this has nothing to do with OpenCL or CMake and is the usual "the working directory when I run my program isn't the directory I think it is". I have a function very similar to that in several of my small programs for testing OpenCL functionality (I work with writing the driver/runtime components for OpenCL). – Mats Petersson Jun 03 '16 at 07:30
  • Suggestion: Instead of returning an empty string, return something like `"#error Couldn't find the kernel file"` - that way, the compilation will go wrong, rather than the clCreateKernel, and the error will be more obvious. Or add an assert at the point just before your `return "";` - the principle of reporting errors as soon as possible, and make it obvious. – Mats Petersson Jun 03 '16 at 07:34
  • @MatsPetersson yes, thanks, the problem was that the file wasn't copied. A single line with `configure_file` solved it. I thought the source files would be automatically copied and perhaps available relative to the run directory, but it wasn't. – Dániel Stein Jun 03 '16 at 08:12
  • It is not a very good practice to leave the kernel outside, except in some specific cases. ie: data crunching algorithms that are open source, so everybody can change the kernel, or modify it to its needs (virtual coins mining). But if your app only works with a given kernel, then you can add it inside the code itself as a const string, and don't depend on an external file. – DarkZeros Jun 03 '16 at 10:47

2 Answers2

4

Although the following line in CMake solves my problem, I'm still waiting for other answers maybe containing a better solution.

configure_file(src/kernels/programs.cl kernels/programs.cl COPYONLY)
Dániel Stein
  • 417
  • 3
  • 16
  • I have the feeling this works only if you do in source build. A more general solution could be `configure_file(src/kernels/programs.cl ${RUNTIME_OUTPUT_DIRECTORY}/kernels/programs.cl COPYONLY)`. See https://cmake.org/cmake/help/v3.5/prop_tgt/RUNTIME_OUTPUT_DIRECTORY.html and http://stackoverflow.com/a/6595001/2436175. – Antonio Jun 03 '16 at 12:27
  • 1
    @Antonio according to the `configure_file` documentation this should be the general solution. "If is a relative path it is evaluated with respect to the current binary directory." – https://cmake.org/cmake/help/v3.0/command/configure_file.html – Dániel Stein Jun 03 '16 at 16:07
0

you should update your path depending from where you build your program

If your project looks like this:

── CMakeLists.txt
└── src
|    ├── cl.hpp
|    ├── GameOfLife.cpp
|    └── kernels
|        └── programs.cl
└── build

and you call "make" from the build directory, the string path should look like this: "../src/kernels/programs.cl". Alternatively you can set a CMake variable with "set(PATH_TO_FILE "${CMAKE_SOURCE_DIR}/src/kernels/programs.cl") and pass it to the main args