From de7cb8ac871300aa6691acb96b1144b653e20f3a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nagy-Egri=20M=C3=A1t=C3=A9=20Ferenc?= Date: Thu, 16 Nov 2023 23:35:09 +0100 Subject: [PATCH] Executable folder utilities (#77) * Add BUILD_UTILITY_LIBRARIES option * Add whereami dependence * Add exe relative utilities * Update samples to use exe relative utilities * Improve diagnostic on missing file * Add missing default argument for error param * Add docs on file utilities * Add EOL * Fix typo Co-authored-by: Ronan Keryell * Simplify byte size calculation Co-authored-by: Ronan Keryell * Fix typo Co-authored-by: Ben Ashbaugh * Fix formatting * Remove implicit narrowing conversions * No unnamed type on libSDK surface * warning: enumeration value x not handled in switch --------- Co-authored-by: Ronan Keryell Co-authored-by: Ben Ashbaugh --- CMakeLists.txt | 8 +- cmake/Dependencies.cmake | 7 ++ cmake/Dependencies/whereami/whereami.cmake | 15 ++++ lib/CMakeLists.txt | 2 + lib/Utils.md | 95 ++++++++++++++++++++++ lib/include/CL/SDK/InteropWindow.hpp | 7 +- lib/include/CL/Utils/File.h | 13 +++ lib/include/CL/Utils/File.hpp | 16 ++-- lib/src/SDK/Image.c | 2 +- lib/src/SDK/InteropWindow.cpp | 6 +- lib/src/Utils/File.c | 76 +++++++++++++++++ lib/src/Utils/File.cpp | 54 +++++++++++- samples/core/binaries/main.c | 5 +- samples/core/binaries/main.cpp | 2 +- samples/core/blur/main.c | 5 +- samples/core/reduce/main.c | 7 +- samples/core/reduce/main.cpp | 17 ++-- samples/core/saxpy/main.c | 9 +- samples/core/saxpy/main.cpp | 15 +--- samples/extensions/khr/conway/main.cpp | 23 ++---- samples/extensions/khr/histogram/main.cpp | 15 +--- samples/extensions/khr/nbody/main.cpp | 23 ++---- 22 files changed, 324 insertions(+), 98 deletions(-) create mode 100644 cmake/Dependencies/whereami/whereami.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index ce86b9b1..44848667 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -23,7 +23,8 @@ project(OpenCL-SDK ) include(CMakeDependentOption) -option(OPENCL_SDK_BUILD_SAMPLES "Build sample code" ON) +option(OPENCL_SDK_BUILD_UTILITY_LIBRARIES "Build utility libraries" ON) +cmake_dependent_option(OPENCL_SDK_BUILD_SAMPLES "Build sample code" ON OPENCL_SDK_BUILD_UTILITY_LIBRARIES OFF) cmake_dependent_option(OPENCL_SDK_BUILD_OPENGL_SAMPLES "Build OpenCL-OpenGL interop sample code" ON OPENCL_SDK_BUILD_SAMPLES OFF) cmake_dependent_option(OPENCL_SDK_TEST_SAMPLES "Add CTest to samples (where applicable)" ON OPENCL_SDK_BUILD_SAMPLES OFF) @@ -47,8 +48,9 @@ list(APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake/Modules ) include(Dependencies) - -add_subdirectory(lib) +if(OPENCL_SDK_BUILD_UTILITY_LIBRARIES) + add_subdirectory(lib) +endif() if(OPENCL_SDK_BUILD_SAMPLES) add_subdirectory(samples) endif() diff --git a/cmake/Dependencies.cmake b/cmake/Dependencies.cmake index 25a97036..f9176312 100644 --- a/cmake/Dependencies.cmake +++ b/cmake/Dependencies.cmake @@ -1,3 +1,10 @@ +if(OPENCL_SDK_BUILD_UTILITY_LIBRARIES) + foreach(DEP IN ITEMS whereami) + list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/Dependencies/${DEP}") + include(${DEP}) + endforeach() +endif() + if(OPENCL_SDK_BUILD_SAMPLES) foreach(DEP IN ITEMS cargs TCLAP Stb) list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/Dependencies/${DEP}") diff --git a/cmake/Dependencies/whereami/whereami.cmake b/cmake/Dependencies/whereami/whereami.cmake new file mode 100644 index 00000000..7fcfaee4 --- /dev/null +++ b/cmake/Dependencies/whereami/whereami.cmake @@ -0,0 +1,15 @@ +cmake_minimum_required(VERSION 3.11) +include(FetchContent) +FetchContent_Declare( + whereami-external + GIT_REPOSITORY https://github.com/gpakosz/whereami.git + GIT_TAG ba364cd54fd431c76c045393b6522b4bff547f50 # master @ 2023.04.20. +) +FetchContent_MakeAvailable(whereami-external) +add_library(whereami IMPORTED INTERFACE) +target_include_directories(whereami + INTERFACE "${CMAKE_CURRENT_BINARY_DIR}/_deps/whereami-external-src/src" +) +target_sources(whereami + INTERFACE "${CMAKE_CURRENT_BINARY_DIR}/_deps/whereami-external-src/src/whereami.c" +) diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index ef7d528d..e605c8ff 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -36,6 +36,8 @@ foreach(UTIL_LIB_NAME IN ITEMS Utils UtilsCpp) $ ) target_link_libraries(${UTIL_LIB_TARGET} + PRIVATE + whereami PUBLIC ${UTIL_LIB_DEPS} OpenCL::OpenCL diff --git a/lib/Utils.md b/lib/Utils.md index 61ec0138..cd3522f3 100644 --- a/lib/Utils.md +++ b/lib/Utils.md @@ -9,6 +9,7 @@ The OpenCL Utility Library provides both C and C++ bindings with near feature pa - [Context](#context-utilities) - [Event](#event-utilities) - [Error](#error-handling-utilities) +- [File](#file-utilities) ### Platform utilities @@ -119,3 +120,97 @@ public: }; ``` This type is used as the exception type thrown by utilities when an error occurs and the compiling code defines `CL_HPP_ENABLE_EXCEPTIONS` + +### File utilities + +```c +char* cl_util_read_text_file( + const char* const filename, + size_t* const length, + cl_int* const error); +``` + +```c++ +std::string cl::util::read_text_file( + const char* const filename, + cl_int* const error = nullptr); +``` + +These functions read a text file into memory, where `filename` is evaluated relative to the current working directory. The C-version contains a terminating null and takes an optional pointer to `length` by which the length my be returned, potentially saving a subsequent call to `strlen`. The function hands ownership of the allocated storage to the caller. + +```c +unsigned char* cl_util_read_binary_file( + const char* const filename, + size_t* const length, + cl_int* const error); +``` + +```c++ +std::vector read_binary_file( + const char* const filename, + cl_int* const error = nullptr); +``` + +These functions read a binary file into memory, where `filename` is evaluated relative to the current working directory. The C-version takes an optional pointer to `length` by which the length my be returned. Because it's binary data, it is _not_ null-terminated, therefore highly recommended to take it's size. The returned types align with OpenCL APIs taking binaries as input. The function hands ownership of the allocated storage to the caller. + +```c +cl_program cl_util_read_binaries( + const cl_context context, + const cl_device_id* const devices, + const cl_uint num_devices, + const char* const program_file_name, + cl_int* const error +); +``` + +```c++ +Program::Binaries read_binary_files( + const std::vector& devices, + const char* const program_file_name, + cl_int* const error = nullptr); +``` + +These functions read a set of binary files into memory. `program_file_name` is a pattern that will be completed for every input device using the `"(program_file_name)_(name of device).bin"` pattern. If any of the files are not found, the function fails. + +```c +cl_int cl_util_write_binaries( + const cl_program program, + const char* const program_file_name); +``` + +```c++ +write_binaries( + const cl::Program::Binaries& binaries, + const std::vector& devices, + const char* const program_file_name); +``` + +These functions will write all device binaries of a program to persistent storage. `program_file_name` is a pattern that will be completed for every input device using the `"(program_file_name)_(name of device).bin"` pattern. + +```c +cl_int cl_util_executable_folder( + char* filename, + size_t* const length); +``` + +```c++ +std::string executable_folder( + cl_int* const error = nullptr); +``` + +These functions return the path to the folder containing the currently running executable. It is typically useful to find assets which are stored uniformly in a program's build and install tree. The C-version contains a terminating null and takes an optional pointer to `length` by which the length my be returned, potentially saving a subsequent call to `strlen`. + +```c +char* cl_util_read_exe_relative_text_file( + const char* const rel_path, + size_t* const length, + cl_int* const error); +``` + +```c++ +std::string read_exe_relative_text_file( + const char* const filename, + cl_int* const error = nullptr); +``` + +These functions read a text file into memory, where `filename` is evaluated relative to the executable currently running. The C-version contains a terminating null and takes an optional pointer to `length` by which the length will be returned, potentially saving a subsequent call to `strlen`. The function hands ownership of the allocated storage to the caller. diff --git a/lib/include/CL/SDK/InteropWindow.hpp b/lib/include/CL/SDK/InteropWindow.hpp index 98ba44f7..d22879ab 100644 --- a/lib/include/CL/SDK/InteropWindow.hpp +++ b/lib/include/CL/SDK/InteropWindow.hpp @@ -13,13 +13,18 @@ #include #include +// STL includes +#include + namespace cl { namespace sdk { class SDKCPP_EXPORT InteropWindow : public sf::Window { public: + using Style = std::underlying_type_t; + explicit InteropWindow( sf::VideoMode mode, const sf::String& title, - sf::Uint32 style = sf::Style::Default, + Style style = sf::Style::Default, const sf::ContextSettings& settings = sf::ContextSettings{}, cl_uint platform_id = 0, cl_uint device_id = 0, cl_bitfield device_type = CL_DEVICE_TYPE_DEFAULT); diff --git a/lib/include/CL/Utils/File.h b/lib/include/CL/Utils/File.h index 62c8e95a..7e4fd221 100644 --- a/lib/include/CL/Utils/File.h +++ b/lib/include/CL/Utils/File.h @@ -40,3 +40,16 @@ cl_program cl_util_read_binaries(const cl_context context, const cl_uint num_devices, const char* const program_file_name, cl_int* const error); + +// returns the folder containing the running executable +UTILS_EXPORT +cl_int cl_util_executable_folder(char* filename, size_t* const length); + +// read all the text file contents securely in ANSI C89 +// return pointer to C-string with file contents +// interprets filename relative to the folder containing +// the running executable +UTILS_EXPORT +char* cl_util_read_exe_relative_text_file(const char* const rel_path, + size_t* const length, + cl_int* const error); diff --git a/lib/include/CL/Utils/File.hpp b/lib/include/CL/Utils/File.hpp index 1e6f444b..b34b0bb7 100644 --- a/lib/include/CL/Utils/File.hpp +++ b/lib/include/CL/Utils/File.hpp @@ -13,18 +13,24 @@ namespace cl { namespace util { std::string UTILSCPP_EXPORT read_text_file(const char* const filename, - cl_int* const error); + cl_int* const error = nullptr); std::vector UTILSCPP_EXPORT - read_binary_file(const char* const filename, cl_int* const error); + read_binary_file(const char* const filename, cl_int* const error = nullptr); - Program::Binaries UTILSCPP_EXPORT - read_binary_files(const std::vector& devices, - const char* const program_file_name, cl_int* const error); + Program::Binaries UTILSCPP_EXPORT read_binary_files( + const std::vector& devices, + const char* const program_file_name, cl_int* const error = nullptr); cl_int UTILSCPP_EXPORT write_binaries(const cl::Program::Binaries& binaries, const std::vector& devices, const char* const program_file_name); + + std::string UTILSCPP_EXPORT + executable_folder(cl_int* const error = nullptr); + + std::string UTILSCPP_EXPORT read_exe_relative_text_file( + const char* const filename, cl_int* const error = nullptr); } } diff --git a/lib/src/SDK/Image.c b/lib/src/SDK/Image.c index cc5459ff..3807325f 100644 --- a/lib/src/SDK/Image.c +++ b/lib/src/SDK/Image.c @@ -40,7 +40,7 @@ cl_sdk_image cl_sdk_read_image(const char* const file_name, cl_int* const error) static char* to_lowercase(const char* const s, char* const d, const size_t n) { - for (size_t i = 0; i < n; ++i) d[i] = tolower(s[i]); + for (size_t i = 0; i < n; ++i) d[i] = (char)tolower(s[i]); return d; } diff --git a/lib/src/SDK/InteropWindow.cpp b/lib/src/SDK/InteropWindow.cpp index 97325ec2..46cc4829 100644 --- a/lib/src/SDK/InteropWindow.cpp +++ b/lib/src/SDK/InteropWindow.cpp @@ -3,12 +3,12 @@ #include cl::sdk::InteropWindow::InteropWindow(sf::VideoMode mode, - const sf::String& title, sf::Uint32 style, + const sf::String& title, Style style, const sf::ContextSettings& settings, cl_uint platform_id, cl_uint device_id, cl_bitfield device_type) - : sf::Window{ mode, title, style, settings }, plat_id{ platform_id }, - dev_id{ device_id }, dev_type{ device_type } + : sf::Window{ mode, title, static_cast(style), settings }, + plat_id{ platform_id }, dev_id{ device_id }, dev_type{ device_type } {} void cl::sdk::InteropWindow::run() diff --git a/lib/src/Utils/File.c b/lib/src/Utils/File.c index 73e7fec4..5cf80d1f 100644 --- a/lib/src/Utils/File.c +++ b/lib/src/Utils/File.c @@ -6,6 +6,9 @@ #include // fopen, ferror, fread, fclose #include // memset +// whereami includes +#include + // read all the text file contents securely in ANSI C89 // return pointer to C-string with file contents // can handle streams with no known size and no support for fseek @@ -337,3 +340,76 @@ cl_program cl_util_read_binaries(const cl_context context, if (error != NULL) *error = err; return program; } + +UTILS_EXPORT +cl_int cl_util_executable_folder(char *const filename, size_t *const length) +{ + cl_int err = CL_SUCCESS; + int wai_length, wai_dirname_length = 0; + char *wai_filename = NULL; + +#define IF_ERR(func, error_type, label) \ + do \ + { \ + if (func) \ + { \ + err = error_type; \ + goto label; \ + } \ + } while (0) + + wai_length = wai_getExecutablePath(NULL, 0, NULL); + IF_ERR(wai_length == -1, CL_UTIL_FILE_OPERATION_ERROR, end); + MEM_CHECK(wai_filename = (char *)malloc(wai_length), err, end); + IF_ERR(wai_getExecutablePath(wai_filename, wai_length, &wai_dirname_length) + == -1, + CL_UTIL_FILE_OPERATION_ERROR, end); + + if (length != NULL) + { + *length = (int)wai_dirname_length + 1; + } + + if (filename != NULL) + { + memmove(filename, wai_filename, wai_dirname_length); + filename[wai_dirname_length] = '\0'; + } + +end: + free(wai_filename); + + return err; +} + +// read all the text file contents securely in ANSI C89 +// return pointer to C-string with file contents +// interprets filename relative to the folder containing +// the running executable +UTILS_EXPORT +char *cl_util_read_exe_relative_text_file(const char *const rel_path, + size_t *const length, + cl_int *const error) +{ + char *result = NULL; + size_t result_size = 0; + char *abs_path = NULL; + cl_int err = CL_SUCCESS; + size_t exe_folder_length; + OCLERROR_RET(cl_util_executable_folder(NULL, &exe_folder_length), err, end); + MEM_CHECK(abs_path = + (char *)malloc(exe_folder_length + strlen(rel_path) + 1), + err, end); + OCLERROR_RET(cl_util_executable_folder(abs_path, NULL), err, end); + strcat(strcat(abs_path, "/"), rel_path); + OCLERROR_PAR(result = cl_util_read_text_file(abs_path, &result_size, &err), + err, end); + + if (length != NULL) *length = result_size; + + if (error != NULL) *error = err; +end: + free(abs_path); + + return result; +} diff --git a/lib/src/Utils/File.cpp b/lib/src/Utils/File.cpp index 4ff44f23..77c00c9f 100644 --- a/lib/src/Utils/File.cpp +++ b/lib/src/Utils/File.cpp @@ -7,6 +7,9 @@ #include #include +// whereami includes +#include + std::string cl::util::read_text_file(const char* const filename, cl_int* const error) { @@ -29,7 +32,8 @@ std::string cl::util::read_text_file(const char* const filename, } else { - detail::errHandler(CL_UTIL_FILE_OPERATION_ERROR, error, "No file!"); + detail::errHandler(CL_UTIL_FILE_OPERATION_ERROR, error, + (std::string("Unable to read ") + filename).c_str()); return std::string(); } } @@ -54,7 +58,8 @@ cl::util::read_binary_file(const char* const filename, cl_int* const error) } else { - detail::errHandler(CL_UTIL_FILE_OPERATION_ERROR, error, "No file!"); + detail::errHandler(CL_UTIL_FILE_OPERATION_ERROR, error, + (std::string("Unable to read ") + filename).c_str()); return std::vector(); } } @@ -120,3 +125,48 @@ cl_int cl::util::write_binaries(const cl::Program::Binaries& binaries, return error; } } + +std::string cl::util::executable_folder(cl_int* const error) +{ + int wai_length = wai_getExecutablePath(NULL, 0, NULL); + if (wai_length == -1) + { + detail::errHandler(CL_UTIL_FILE_OPERATION_ERROR, error, + "Unable to query executable path length!"); + return ""; + } + std::string wai_filename(wai_length, '\0'); + int wai_dirname_length = -1; + wai_length = wai_getExecutablePath(&wai_filename.front(), wai_length, + &wai_dirname_length); + if (wai_length == -1 || wai_dirname_length == -1) + { + detail::errHandler(CL_UTIL_FILE_OPERATION_ERROR, error, + "Unable to query executable path or folder length!"); + return ""; + } + + return wai_filename.substr(0, wai_dirname_length); +} + +std::string cl::util::read_exe_relative_text_file(const char* const filename, + cl_int* const error) +{ + cl_int err = CL_SUCCESS; + std::string exe_folder = executable_folder(&err); + if (err != CL_SUCCESS) + { + detail::errHandler(CL_UTIL_FILE_OPERATION_ERROR, error, + "Failed to query exe folder!"); + return ""; + } + std::string result = + read_text_file((exe_folder + "/" + filename).c_str(), &err); + if (err != CL_SUCCESS) + { + detail::errHandler(CL_UTIL_FILE_OPERATION_ERROR, error, + "Unable to read file!"); + return ""; + } + return result; +} diff --git a/samples/core/binaries/main.c b/samples/core/binaries/main.c index 4a13d922..b9d5f5bb 100644 --- a/samples/core/binaries/main.c +++ b/samples/core/binaries/main.c @@ -191,13 +191,12 @@ int main(int argc, char *argv[]) if (error != CL_SUCCESS) { // if binary not present, compile and save - const char *kernel_location = "./Collatz.cl"; char *kernel = NULL; size_t program_size = 0; char *options = NULL; - OCLERROR_PAR(kernel = cl_util_read_text_file(kernel_location, - &program_size, &error), + OCLERROR_PAR(kernel = cl_util_read_exe_relative_text_file( + "Collatz.cl", &program_size, &error), error, cont); printf("OpenCL file red... "); diff --git a/samples/core/binaries/main.cpp b/samples/core/binaries/main.cpp index e8d8b1ac..035cfab9 100644 --- a/samples/core/binaries/main.cpp +++ b/samples/core/binaries/main.cpp @@ -100,7 +100,7 @@ int main(int argc, char* argv[]) std::cout << e.what() << "\n"; std::string program_cl = - cl::util::read_text_file("./Collatz.cl", &error); + cl::util::read_exe_relative_text_file("Collatz.cl", &error); cl::Program program{ context, program_cl }; program.build(devices.at(0)); diff --git a/samples/core/blur/main.c b/samples/core/blur/main.c index f6df0eaa..d29a3a41 100644 --- a/samples/core/blur/main.c +++ b/samples/core/blur/main.c @@ -1078,14 +1078,13 @@ int main(int argc, char *argv[]) error, tmpbuf); /// Create OpenCL program - const char *kernel_location = "./blur.cl"; s.kernel = NULL; s.program_size = 0; char kernel_op[1024] = ""; // here we put some dynamic definitions s.options = kernel_op; - OCLERROR_PAR(s.kernel = cl_util_read_text_file(kernel_location, - &s.program_size, &error), + OCLERROR_PAR(s.kernel = cl_util_read_exe_relative_text_file( + "blur.cl", &s.program_size, &error), error, tmpbuf); OCLERROR_PAR(s.program = clCreateProgramWithSource(s.context, 1, diff --git a/samples/core/reduce/main.c b/samples/core/reduce/main.c index 802b2526..a9c8b1fa 100644 --- a/samples/core/reduce/main.c +++ b/samples/core/reduce/main.c @@ -336,14 +336,13 @@ int main(int argc, char *argv[]) cl_int zero_elem = !strcmp(reduce_opts.op, "min") ? CL_INT_MAX : 0; // Compile kernel - const char *kernel_location = "./reduce.cl"; char *kernel = NULL, *tmp = NULL; size_t program_size = 0; cl_program program = NULL; - OCLERROR_PAR( - kernel = cl_util_read_text_file(kernel_location, &program_size, &error), - error, que); + OCLERROR_PAR(kernel = cl_util_read_exe_relative_text_file( + "reduce.cl", &program_size, &error), + error, que); // Note append of definitions program_size += 1 + strlen(kernel_op); MEM_CHECK(tmp = (char *)realloc(kernel, program_size), error, ker); diff --git a/samples/core/reduce/main.cpp b/samples/core/reduce/main.cpp index cfa5361a..053a2286 100644 --- a/samples/core/reduce/main.cpp +++ b/samples/core/reduce/main.cpp @@ -155,18 +155,11 @@ int main(int argc, char* argv[]) : static_cast(0); // Compile kernel - const char* kernel_location = "./reduce.cl"; - std::ifstream kernel_stream{ kernel_location }; - if (!kernel_stream.is_open()) - throw std::runtime_error{ - std::string{ "Cannot open kernel source: " } + kernel_location - }; - - cl::Program program{ context, - std::string{ std::istreambuf_iterator{ - kernel_stream }, - std::istreambuf_iterator{} } - .append(kernel_op) }; // Note append + cl::Program program{ + context, + cl::util::read_exe_relative_text_file("reduce.cl") + .append(kernel_op) // Note append + }; cl::string compiler_options = cl::string{ may_use_work_group_reduce ? "-D USE_WORK_GROUP_REDUCE " : "" } diff --git a/samples/core/saxpy/main.c b/samples/core/saxpy/main.c index 13804439..92c6d0ee 100644 --- a/samples/core/saxpy/main.c +++ b/samples/core/saxpy/main.c @@ -120,7 +120,6 @@ int main(int argc, char *argv[]) cl_context context; cl_command_queue queue; - const char *kernel_location = "./saxpy.cl"; char *kernel = NULL; size_t program_size = 0; cl_program program = NULL; @@ -165,10 +164,9 @@ int main(int argc, char *argv[]) } // Compile kernel - OCLERROR_PAR( - kernel = cl_util_read_text_file(kernel_location, &program_size, &error), - error, que); - + OCLERROR_PAR(kernel = cl_util_read_exe_relative_text_file( + "saxpy.cl", &program_size, &error), + error, que); OCLERROR_PAR(program = clCreateProgramWithSource( context, 1, (const char **)&kernel, &program_size, &error), error, ker); @@ -176,7 +174,6 @@ int main(int argc, char *argv[]) cl_kernel saxpy; OCLERROR_PAR(saxpy = clCreateKernel(program, "saxpy", &error), error, prg); - // Initialize host-side storage const size_t length = saxpy_opts.length; diff --git a/samples/core/saxpy/main.cpp b/samples/core/saxpy/main.cpp index 3b87e293..c9f9b188 100644 --- a/samples/core/saxpy/main.cpp +++ b/samples/core/saxpy/main.cpp @@ -16,6 +16,7 @@ // OpenCL SDK includes #include +#include #include #include #include @@ -97,17 +98,9 @@ int main(int argc, char* argv[]) } // Compile kernel - const char* kernel_location = "./saxpy.cl"; - std::ifstream kernel_stream{ kernel_location }; - if (!kernel_stream.is_open()) - throw std::runtime_error{ - std::string{ "Cannot open kernel source: " } + kernel_location - }; - - cl::Program program{ context, - std::string{ std::istreambuf_iterator{ - kernel_stream }, - std::istreambuf_iterator{} } }; + cl::Program program{ + context, cl::util::read_exe_relative_text_file("saxpy.cl") + }; program.build(device); auto saxpy = cl::KernelFunctor( diff --git a/samples/extensions/khr/conway/main.cpp b/samples/extensions/khr/conway/main.cpp index 540e14f7..8a3f3c96 100644 --- a/samples/extensions/khr/conway/main.cpp +++ b/samples/extensions/khr/conway/main.cpp @@ -122,10 +122,8 @@ void Conway::initializeGL() if (glewInit() != GLEW_OK) std::exit(EXIT_FAILURE); auto create_shader = [](std::string file_path, cl_GLenum shader_stage) { - std::ifstream shader_stream(file_path); - std::string shader_string{ std::istreambuf_iterator{ - shader_stream }, - std::istreambuf_iterator{} }; + std::string shader_string = + cl::util::read_exe_relative_text_file(file_path.c_str()); auto pshader_string = shader_string.c_str(); GLuint shader = glCreateShader(shader_stage); glShaderSource(shader, 1, &pshader_string, NULL); @@ -183,8 +181,8 @@ void Conway::initializeGL() return program; }; - vertex_shader = create_shader("./conway.vert.glsl", GL_VERTEX_SHADER); - fragment_shader = create_shader("./conway.frag.glsl", GL_FRAGMENT_SHADER); + vertex_shader = create_shader("conway.vert.glsl", GL_VERTEX_SHADER); + fragment_shader = create_shader("conway.frag.glsl", GL_FRAGMENT_SHADER); gl_program = create_program({ vertex_shader, fragment_shader }); std::vector quad = @@ -277,16 +275,9 @@ void Conway::initializeCL() queue = cl::CommandQueue{ opencl_context, device }; // Compile kernel - const char* kernel_location = "./conway.cl"; - std::ifstream kernel_stream{ kernel_location }; - if (!kernel_stream.is_open()) - throw std::runtime_error{ std::string{ "Cannot open kernel source: " } - + kernel_location }; - - cl_program = cl::Program{ opencl_context, - std::string{ std::istreambuf_iterator{ - kernel_stream }, - std::istreambuf_iterator{} } }; + cl_program = + cl::Program{ opencl_context, + cl::util::read_exe_relative_text_file("conway.cl") }; cl_program.build(device); kernel = cl::Kernel{ cl_program, "conway" }; diff --git a/samples/extensions/khr/histogram/main.cpp b/samples/extensions/khr/histogram/main.cpp index 338f066a..a4f33ec5 100644 --- a/samples/extensions/khr/histogram/main.cpp +++ b/samples/extensions/khr/histogram/main.cpp @@ -16,6 +16,7 @@ // OpenCL SDK includes #include +#include #include #include #include @@ -89,17 +90,9 @@ int main(int argc, char* argv[]) } // Compile kernel - const char* kernel_location = "./histogram.cl"; - std::ifstream kernel_stream{ kernel_location }; - if (!kernel_stream.is_open()) - throw std::runtime_error{ - std::string{ "Cannot open kernel source: " } + kernel_location - }; - - cl::Program program{ context, - std::string{ std::istreambuf_iterator{ - kernel_stream }, - std::istreambuf_iterator{} } }; + cl::Program program{ + context, cl::util::read_exe_relative_text_file("histogram.cl") + }; program.build(device); auto histogram_shared = diff --git a/samples/extensions/khr/nbody/main.cpp b/samples/extensions/khr/nbody/main.cpp index e10601e6..c0af5d27 100644 --- a/samples/extensions/khr/nbody/main.cpp +++ b/samples/extensions/khr/nbody/main.cpp @@ -155,10 +155,8 @@ void NBody::initializeGL() if (glewInit() != GLEW_OK) std::exit(EXIT_FAILURE); auto create_shader = [](std::string file_path, cl_GLenum shader_stage) { - std::ifstream shader_stream(file_path); - std::string shader_string{ std::istreambuf_iterator{ - shader_stream }, - std::istreambuf_iterator{} }; + std::string shader_string = + cl::util::read_exe_relative_text_file(file_path.c_str()); auto pshader_string = shader_string.c_str(); GLuint shader = glCreateShader(shader_stage); glShaderSource(shader, 1, &pshader_string, NULL); @@ -216,8 +214,8 @@ void NBody::initializeGL() return program; }; - vertex_shader = create_shader("./nbody.vert.glsl", GL_VERTEX_SHADER); - fragment_shader = create_shader("./nbody.frag.glsl", GL_FRAGMENT_SHADER); + vertex_shader = create_shader("nbody.vert.glsl", GL_VERTEX_SHADER); + fragment_shader = create_shader("nbody.frag.glsl", GL_FRAGMENT_SHADER); gl_program = create_program({ vertex_shader, fragment_shader }); using uni = std::uniform_real_distribution; @@ -288,16 +286,9 @@ void NBody::initializeCL() queue = cl::CommandQueue{ opencl_context, device }; // Compile kernel - const char* kernel_location = "./nbody.cl"; - std::ifstream kernel_stream{ kernel_location }; - if (!kernel_stream.is_open()) - throw std::runtime_error{ std::string{ "Cannot open kernel source: " } - + kernel_location }; - - cl_program = cl::Program{ opencl_context, - std::string{ std::istreambuf_iterator{ - kernel_stream }, - std::istreambuf_iterator{} } }; + cl_program = + cl::Program{ opencl_context, + cl::util::read_exe_relative_text_file("nbody.cl") }; cl_program.build(device); kernel = cl::Kernel{ cl_program, "nbody" };