Skip to content

Commit

Permalink
Add first prototype of cllayerinfo. (#175)
Browse files Browse the repository at this point in the history
* Add first prototype of cllayerinfo.

* Added scheme to silence layers during loading and exit.

* Added a first test of cllayerinfo.

* Fix lock if no layers are found.

* Improve style.

* Copy layer library name as it is transient.

* Add new required definitions.

* Remove deprecated OPENCL_ICD_LOADER_DISABLE_OPENCLON12 CMake option.

* Factor compile definitions.

* Add variable to disable cllayerinfo build.

* Refactor CMake test file.

* Remove options for now as suggested by the working group.

* Remove constants

* Include share.h for mingw

Co-authored-by: Ben Ashbaugh <ben.ashbaugh@intel.com>

* Add cllayerinfo to install and export target.

* Use CMakeDependOption.

Co-authored-by: Nagy-Egri Máté Ferenc <beiktatas+github@outlook.hu>

---------

Co-authored-by: Ben Ashbaugh <ben.ashbaugh@intel.com>
Co-authored-by: Nagy-Egri Máté Ferenc <beiktatas+github@outlook.hu>
  • Loading branch information
3 people authored Feb 2, 2023
1 parent 217a177 commit 2cde5d0
Show file tree
Hide file tree
Showing 6 changed files with 263 additions and 20 deletions.
57 changes: 55 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ endif()
# It is currently needed default while the specification is being formalized,
# and to study the performance impact.
option (ENABLE_OPENCL_LAYERS "Enable OpenCL Layers" ON)
include(CMakeDependentOption)
cmake_dependent_option(ENABLE_OPENCL_LAYERINFO "Enable building cllayerinfo tool" ON ENABLE_OPENCL_LAYERS OFF)

set (CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
include(JoinPaths)
Expand Down Expand Up @@ -150,22 +152,64 @@ else ()
target_link_libraries (OpenCL PUBLIC OpenCL::Headers)
endif ()

target_compile_definitions (OpenCL
PRIVATE
set (OPENCL_COMPILE_DEFINITIONS
CL_TARGET_OPENCL_VERSION=300
OPENCL_ICD_LOADER_VERSION_MAJOR=3
OPENCL_ICD_LOADER_VERSION_MINOR=0
OPENCL_ICD_LOADER_VERSION_REV=5
$<$<BOOL:${ENABLE_OPENCL_LAYERS}>:CL_ENABLE_LAYERS>
)

target_compile_definitions (OpenCL
PRIVATE
${OPENCL_COMPILE_DEFINITIONS}
)

target_include_directories (OpenCL
PRIVATE
${CMAKE_CURRENT_BINARY_DIR}
loader
)
target_link_libraries (OpenCL PUBLIC ${CMAKE_DL_LIBS})

if (ENABLE_OPENCL_LAYERINFO)

set (OPENCL_LAYER_INFO_SOURCES
loader/cllayerinfo.c
${OPENCL_ICD_LOADER_SOURCES}
)

add_executable(cllayerinfo ${OPENCL_LAYER_INFO_SOURCES})

add_executable(OpenCL::cllayerinfo ALIAS cllayerinfo)

target_compile_definitions (cllayerinfo
PRIVATE
CL_LAYER_INFO
${OPENCL_COMPILE_DEFINITIONS}
)

if (EXISTS ${OPENCL_ICD_LOADER_HEADERS_DIR}/CL/cl.h)
target_include_directories (cllayerinfo PUBLIC $<BUILD_INTERFACE:${OPENCL_ICD_LOADER_HEADERS_DIR}>)
else ()
target_link_libraries (cllayerinfo PUBLIC OpenCL::Headers)
endif ()

if (WIN32)
target_link_libraries (cllayerinfo PRIVATE cfgmgr32.lib runtimeobject.lib)
else ()
target_link_libraries (cllayerinfo PRIVATE ${CMAKE_THREAD_LIBS_INIT})
endif ()

target_link_libraries (cllayerinfo PUBLIC ${CMAKE_DL_LIBS})

target_include_directories (cllayerinfo
PRIVATE
${CMAKE_CURRENT_BINARY_DIR}
loader
)
endif ()

option (OPENCL_ICD_LOADER_BUILD_TESTING "Enable support for OpenCL ICD Loader testing." OFF)

if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME OR OPENCL_ICD_LOADER_BUILD_TESTING)
Expand All @@ -191,6 +235,15 @@ install(
OPTIONAL
)

if (ENABLE_OPENCL_LAYERINFO)
install(
TARGETS cllayerinfo
EXPORT OpenCLICDLoaderTargets
RUNTIME
DESTINATION ${CMAKE_INSTALL_BINDIR}
)
endif()

export(
EXPORT OpenCLICDLoaderTargets
FILE ${PROJECT_BINARY_DIR}/OpenCLICDLoader/OpenCLICDLoaderTargets.cmake
Expand Down
132 changes: 132 additions & 0 deletions loader/cllayerinfo.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
/*
* Copyright (c) 2022 The Khronos Group Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* OpenCL is a trademark of Apple Inc. used under license by Khronos.
*/

#include "icd.h"
#include <stdio.h>
#include <stdlib.h>
#include <CL/cl_layer.h>
#if defined(_WIN32)
#include <io.h>
#include <share.h>
#include <sys/stat.h>
#else
#include <unistd.h>
#endif
#include <fcntl.h>

int stdout_bak, stderr_bak;

// Temporarily deactivate stdout:
// https://stackoverflow.com/a/4832902

#if defined(_WIN32)
#define SECURE 1
#define OPEN _open
#define OPEN_FLAGS _O_WRONLY
#define CLOSE _close
#define DUP _dup
#define DUP2 _dup2
#define NULL_STREAM "nul"
#else
#define OPEN open
#define OPEN_FLAGS O_WRONLY
#define CLOSE close
#define DUP dup
#define DUP2 dup2
#define NULL_STREAM "/dev/null"
#endif

static inline int
silence_stream(FILE *file, int fd)
{
int new_fd, fd_bak;
fflush(file);
fd_bak = DUP(fd);
#if defined(_WIN32) && SECURE
_sopen_s(&new_fd, NULL_STREAM, OPEN_FLAGS, _SH_DENYNO, _S_IWRITE);
#else
new_fd = OPEN(NULL_STREAM, OPEN_FLAGS);
#endif
DUP2(new_fd, fd);
CLOSE(new_fd);
return fd_bak;
}

static void silence_layers(void)
{
stdout_bak = silence_stream(stdout, 1);
stderr_bak = silence_stream(stderr, 2);
}

static inline void
restore_stream(FILE *file, int fd, int fd_bak)
{
fflush(file);
DUP2(fd_bak, fd);
CLOSE(fd_bak);
}

static void restore_outputs(void)
{
restore_stream(stdout, 1, stdout_bak);
restore_stream(stderr, 2, stderr_bak);
}

void printLayerInfo(const struct KHRLayer *layer)
{
cl_layer_api_version api_version = 0;
pfn_clGetLayerInfo p_clGetLayerInfo = (pfn_clGetLayerInfo)(size_t)layer->p_clGetLayerInfo;
cl_int result = CL_SUCCESS;
size_t sz;

printf("%s:\n", layer->libraryName);
result = p_clGetLayerInfo(CL_LAYER_API_VERSION, sizeof(api_version), &api_version, NULL);
if (CL_SUCCESS == result)
printf("\tCL_LAYER_API_VERSION: %d\n", (int)api_version);

result = p_clGetLayerInfo(CL_LAYER_NAME, 0, NULL, &sz);
if (CL_SUCCESS == result)
{
char *name = (char *)malloc(sz);
if (name)
{
result = p_clGetLayerInfo(CL_LAYER_NAME, sz, name, NULL);
if (CL_SUCCESS == result)
printf("\tCL_LAYER_NAME: %s\n", name);
free(name);
}
}
}

int main (int argc, char *argv[])
{
(void)argc;
(void)argv;
silence_layers();
atexit(restore_outputs);
khrIcdInitialize();
restore_outputs();
atexit(silence_layers);
const struct KHRLayer *layer = khrFirstLayer;
while (layer)
{
printLayerInfo(layer);
layer = layer->next;
}
return 0;
}
14 changes: 14 additions & 0 deletions loader/icd.c
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,20 @@ void khrIcdLayerAdd(const char *libraryName)
KHR_ICD_TRACE("failed to allocate memory\n");
goto Done;
}
#ifdef CL_LAYER_INFO
{
// Not using strdup as it is not standard c
size_t sz_name = strlen(libraryName) + 1;
layer->libraryName = malloc(sz_name);
if (!layer->libraryName)
{
KHR_ICD_TRACE("failed to allocate memory\n");
goto Done;
}
memcpy(layer->libraryName, libraryName, sz_name);
layer->p_clGetLayerInfo = (void *)(size_t)p_clGetLayerInfo;
}
#endif

if (khrFirstLayer) {
targetDispatch = &(khrFirstLayer->dispatch);
Expand Down
6 changes: 6 additions & 0 deletions loader/icd.h
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,12 @@ struct KHRLayer
struct _cl_icd_dispatch dispatch;
// The next layer in the chain
struct KHRLayer *next;
#ifdef CL_LAYER_INFO
// The layer library name
char *libraryName;
// the pointer to the clGetLayerInfo funciton
void *p_clGetLayerInfo;
#endif
};

// the global layer state
Expand Down
33 changes: 23 additions & 10 deletions test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -18,17 +18,30 @@ add_test (
NAME opencl_icd_loader_test
COMMAND icd_loader_test
)
get_property(GENERATOR_IS_MULTI_CONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
if(GENERATOR_IS_MULTI_CONFIG)
set_tests_properties(opencl_icd_loader_test
PROPERTIES
ENVIRONMENT OCL_ICD_FILENAMES=$<TARGET_FILE:OpenCLDriverStub>
WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/$<CONFIG>"

if (ENABLE_OPENCL_LAYERINFO)
add_test (
NAME cllayerinfo_test
COMMAND cllayerinfo
)
else()
set_tests_properties(opencl_icd_loader_test
endif ()

get_property(GENERATOR_IS_MULTI_CONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
if (GENERATOR_IS_MULTI_CONFIG)
set (TEST_WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/$<CONFIG>")
else ()
set (TEST_WORKING_DIRECTORY "${CMAKE_BINARY_DIR}")
endif()

set_tests_properties(opencl_icd_loader_test
PROPERTIES
ENVIRONMENT OCL_ICD_FILENAMES=$<TARGET_FILE:OpenCLDriverStub>
WORKING_DIRECTORY "${TEST_WORKING_DIRECTORY}"
)
if (ENABLE_OPENCL_LAYERINFO)
set_tests_properties(cllayerinfo_test
PROPERTIES
ENVIRONMENT OCL_ICD_FILENAMES=$<TARGET_FILE:OpenCLDriverStub>
WORKING_DIRECTORY "${CMAKE_BINARY_DIR}"
ENVIRONMENT OPENCL_LAYERS=$<TARGET_FILE:PrintLayer>
WORKING_DIRECTORY "${TEST_WORKING_DIRECTORY}"
)
endif()
41 changes: 33 additions & 8 deletions test/layer/icd_print_layer.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,34 +17,58 @@
*/

#include "icd_print_layer.h"
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>

struct _cl_icd_dispatch dispatch;

const struct _cl_icd_dispatch *tdispatch;

static cl_layer_api_version api_version = CL_LAYER_API_VERSION_100;
static const char name[] = "print_layer";

static inline cl_int
set_param_value(
size_t param_value_size,
void *param_value,
size_t *param_value_size_ret,
size_t src_size,
const void *src) {
if (param_value && param_value_size < src_size)
return CL_INVALID_VALUE;
if (param_value)
memcpy(param_value, src, src_size);
if (param_value_size_ret)
*param_value_size_ret = src_size;
return CL_SUCCESS;
}

CL_API_ENTRY cl_int CL_API_CALL
clGetLayerInfo(
cl_layer_info param_name,
size_t param_value_size,
void *param_value,
size_t *param_value_size_ret) {
size_t sz = 0;
const void *src = NULL;
if (param_value_size && !param_value)
return CL_INVALID_VALUE;
if (!param_value && !param_value_size_ret)
return CL_INVALID_VALUE;
switch (param_name) {
case CL_LAYER_API_VERSION:
if (param_value_size < sizeof(cl_layer_api_version))
return CL_INVALID_VALUE;
if (param_value)
*((cl_layer_api_version *)param_value) = CL_LAYER_API_VERSION_100;
if (param_value_size_ret)
*param_value_size_ret = sizeof(cl_layer_api_version);
sz = sizeof(api_version);
src = &api_version;
break;
case CL_LAYER_NAME:
sz = sizeof(name);
src = name;
break;
default:
return CL_INVALID_VALUE;
}
return CL_SUCCESS;
return set_param_value(param_value_size, param_value, param_value_size_ret, sz, src);
}

CL_API_ENTRY cl_int CL_API_CALL
Expand All @@ -53,14 +77,15 @@ clInitLayer(
const struct _cl_icd_dispatch *target_dispatch,
cl_uint *num_entries_out,
const struct _cl_icd_dispatch **layer_dispatch_ret) {
if (!target_dispatch || !layer_dispatch_ret ||!num_entries_out || num_entries < sizeof(dispatch)/sizeof(dispatch.clGetPlatformIDs))
if (!target_dispatch || !layer_dispatch_ret || !num_entries_out || num_entries < sizeof(dispatch)/sizeof(dispatch.clGetPlatformIDs))
return CL_INVALID_VALUE;

_init_dispatch();

tdispatch = target_dispatch;
*layer_dispatch_ret = &dispatch;
*num_entries_out = sizeof(dispatch)/sizeof(dispatch.clGetPlatformIDs);

return CL_SUCCESS;
}

Expand Down

0 comments on commit 2cde5d0

Please sign in to comment.