Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implementation of cl_khr_icd 2.0.0 loader managed dispatch #33

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
94 changes: 73 additions & 21 deletions icd_generator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -542,20 +542,15 @@ def self.generate_ocl_icd_loader_header
clGetExtensionFunctionAddress_fn ext_fn_ptr;
};

struct platform_icd {
char * extension_suffix;
char * version;
struct vendor_icd *vicd;
cl_platform_id pid;
cl_uint ngpus; /* number of GPU devices */
cl_uint ncpus; /* number of CPU devices */
cl_uint ndevs; /* total number of devices, of all types */
};

extern struct _cl_icd_dispatch master_dispatch;
EOF
ocl_icd_header += "extern struct _cl_icd_dispatch master_dispatch;\n"
$cl_objects.each { |o|
ocl_icd_header += "struct _cl_#{o} { struct _cl_icd_dispatch *dispatch; };\n"
ocl_icd_header += <<EOF
struct _cl_#{o} {
struct _cl_icd_dispatch *dispatch;
struct _cl_disp_data *disp_data;
};
EOF
}
return ocl_icd_header
end
Expand Down Expand Up @@ -721,14 +716,55 @@ def self.generate_ocl_icd_loader_gen_source
#include "ocl_icd_debug.h"
#define hidden_alias(name) \\
typeof(name) name##_hid __attribute__ ((alias (#name), visibility("hidden")))

EOF
api_proc = proc { |disp, (func_name, entry)|
next if skip_funcs.include?(func_name)
cleanup = proc { |entry|
clean_entry = entry.sub(/(.*\)).*/m,'\1').gsub("/*","").gsub("*/","").gsub("\r","") + "{\n"
return_type = entry.match(/CL_API_ENTRY (.*) CL_API_CALL/)[1]
parameters = clean_entry.match(/\(.*\)/m)[0][1..-2]
parameters.gsub!(/\[.*?\]/,"")
parameters.sub!(/\(.*?\*\s*(.*?)\)\s*\(.*?\)/m,'\1')
ps = parameters.split(",")
ps = ps.collect { |p|
p = p.split
p = p[-1].gsub("*","")
}
[clean_entry, return_type, parameters, ps]
}
api_stub = proc { |(func_name, entry)|
clean_entry, return_type, parameters, ps = cleanup.call(entry)
clean_entry = clean_entry.gsub(func_name, func_name+"_unsupp").gsub("CL_API_ENTRY", "")
ocl_icd_loader_gen_source += 'static '
ocl_icd_loader_gen_source += clean_entry.gsub(/\*\[.*?\]/,"* ").gsub(/\[.+?\]/,"")
if(ps.include?("errcode_ret")) then
ocl_icd_loader_gen_source += " if( errcode_ret != NULL ) {\n";
ocl_icd_loader_gen_source += " *errcode_ret = CL_INVALID_OPERATION;\n"
ocl_icd_loader_gen_source += " }\n"
if return_type != "void" then
ocl_icd_loader_gen_source += " RETURN(NULL);\n"
else
ocl_icd_loader_gen_source += " return;\n"
end
elsif ($non_standard_error.include?(func_name)) then
if return_type != "void" then
ocl_icd_loader_gen_source += " RETURN(NULL);\n"
else
ocl_icd_loader_gen_source += " return;\n"
end
elsif func_name == "clGetExtensionFunctionAddress"
ocl_icd_loader_gen_source += " return NULL;\n"
else
if return_type != "void" then
ocl_icd_loader_gen_source += " RETURN(CL_INVALID_OPERATION);\n" if return_type != "void"
else
ocl_icd_loader_gen_source += " return;\n"
end
end
ocl_icd_loader_gen_source += "}\n\n"
}
api_proc = proc { |disp, (func_name, entry)|
next if skip_funcs.include?(func_name)
clean_entry, return_type, parameters, ps = cleanup.call(entry)
if disp
clean_entry = clean_entry.gsub(func_name, func_name+"_disp").gsub("CL_API_ENTRY", "").gsub("CL_API_CALL", "")
ocl_icd_loader_gen_source += '__attribute__((visibility("hidden"))) '
Expand All @@ -741,11 +777,6 @@ def self.generate_ocl_icd_loader_gen_source
first_parameter = first_parameter[0][0..-2]
end
fps = first_parameter.split
ps = parameters.split(",")
ps = ps.collect { |p|
p = p.split
p = p[-1].gsub("*","")
}
if !disp
ocl_icd_loader_gen_source += " debug_trace();\n"
ocl_icd_loader_gen_source += " _initClIcd_no_inline();\n" if fps[0] == "cl_platform_id"
Expand All @@ -757,7 +788,7 @@ def self.generate_ocl_icd_loader_gen_source
ocl_icd_loader_gen_source += generate_get_extension_address_for_platform if func_name == "clGetExtensionFunctionAddressForPlatform"
raise "Unsupported data_type #{fps[0]}" if ! $cl_data_type_error[fps[0]]
error_handler = lambda {
if(ps.include?("errcode_ret")) then
if(ps.include?("errcode_ret")) then
ocl_icd_loader_gen_source += " if( errcode_ret != NULL ) {\n";
ocl_icd_loader_gen_source += " *errcode_ret = #{$cl_data_type_error[fps[0]]};\n"
ocl_icd_loader_gen_source += " }\n"
Expand Down Expand Up @@ -792,11 +823,12 @@ def self.generate_ocl_icd_loader_gen_source
else
return_debug="return"
end
ocl_icd_loader_gen_source += " #{return_debug}(((struct _#{fps[0]} *)#{fps[1]})->dispatch->#{func_name}("
ocl_icd_loader_gen_source += " #{return_debug}(KHR_ICD2_DISPATCH((struct _#{fps[0]} *)#{fps[1]})->#{func_name}("
ocl_icd_loader_gen_source += ps.join(", ")
ocl_icd_loader_gen_source += "));\n"
ocl_icd_loader_gen_source += "}\n\n"
}
$api_entries.each &(api_stub)
$api_entries.each &(api_proc.curry[true])
$api_entries.each &(api_proc.curry[false])
ocl_icd_loader_gen_source += "#pragma GCC visibility push(hidden)\n\n"
Expand Down Expand Up @@ -865,6 +897,26 @@ def self.generate_ocl_icd_loader_gen_source
}
#endif

void _populate_dispatch_table(
cl_platform_id pid,
clIcdGetFunctionAddressForPlatformKHR_fn pltfn_fn_ptr,
struct _cl_icd_dispatch *dispatch) {
EOF
($api_entries.length+$buff).times { |i|
if ( e = $known_entries[i] ) then
ocl_icd_loader_gen_source << <<EOF
dispatch->#{e} = (typeof(#{e})*)pltfn_fn_ptr(pid, "#{e}");
if (!dispatch->#{e})
dispatch->#{e} = #{e}_unsupp;
EOF
else
ocl_icd_loader_gen_source << " dispatch->clUnknown#{i} = NULL;\n"
end
}

ocl_icd_loader_gen_source << <<EOF
}

#pragma GCC visibility pop

EOF
Expand Down
57 changes: 42 additions & 15 deletions ocl_icd_loader.c
Original file line number Diff line number Diff line change
Expand Up @@ -357,19 +357,19 @@ static void _count_devices(struct platform_icd *p) {
/* Ensure they are 0 in case of errors */
p->ngpus = p->ncpus = p->ndevs = 0;

error = p->pid->dispatch->clGetDeviceIDs(p->pid, CL_DEVICE_TYPE_GPU, 0, NULL, &(p->ngpus));
error = KHR_ICD2_DISPATCH(p->pid)->clGetDeviceIDs(p->pid, CL_DEVICE_TYPE_GPU, 0, NULL, &(p->ngpus));
if (error != CL_SUCCESS && error != CL_DEVICE_NOT_FOUND){
debug(D_WARN, "Error %s while counting GPU devices in platform %p",
_clerror2string(error), p->pid);
}

error = p->pid->dispatch->clGetDeviceIDs(p->pid, CL_DEVICE_TYPE_CPU, 0, NULL, &(p->ncpus));
error = KHR_ICD2_DISPATCH(p->pid)->clGetDeviceIDs(p->pid, CL_DEVICE_TYPE_CPU, 0, NULL, &(p->ncpus));
if (error != CL_SUCCESS && error != CL_DEVICE_NOT_FOUND){
debug(D_WARN, "Error %s while counting CPU devices in platform %p",
_clerror2string(error), p->pid);
}

error = p->pid->dispatch->clGetDeviceIDs(p->pid, CL_DEVICE_TYPE_ALL, 0, NULL, &(p->ndevs));
error = KHR_ICD2_DISPATCH(p->pid)->clGetDeviceIDs(p->pid, CL_DEVICE_TYPE_ALL, 0, NULL, &(p->ndevs));
if (error != CL_SUCCESS && error != CL_DEVICE_NOT_FOUND){
debug(D_WARN, "Error %s while counting ALL devices in platform %p",
_clerror2string(error), p->pid);
Expand Down Expand Up @@ -496,6 +496,11 @@ static inline void _find_and_check_platforms(cl_uint num_icds) {
debug(D_WARN, "Not enough platform allocated. Skipping ICD");
continue;
}
clIcdGetFunctionAddressForPlatformKHR_fn pltfn_fn_ptr =
_get_function_addr(dlh, picd->ext_fn_ptr, "clIcdGetFunctionAddressForPlatformKHR");
clIcdSetPlatformDispatchDataKHR_fn spltdd_fn_ptr =
_get_function_addr(dlh, picd->ext_fn_ptr, "clIcdSetPlatformDispatchDataKHR");

for(j=0; j<num_platforms; j++) {
debug(D_LOG, "Checking platform %i", j);
struct platform_icd *p=&_picds[_num_picds];
Expand All @@ -504,13 +509,35 @@ static inline void _find_and_check_platforms(cl_uint num_icds) {
p->vicd=&_icds[i];
p->pid=platforms[j];

if (KHR_ICD2_HAS_TAG(p->pid) && !pltfn_fn_ptr) {
debug(D_WARN, "Found icd 2 platform, but it is missing clIcdGetFunctionAddressForPlatformKHR, skipping it");
continue;
}

if (KHR_ICD2_HAS_TAG(p->pid) && !spltdd_fn_ptr) {
debug(D_WARN, "Found icd 2 platform, but it is missing clIcdSetPlatformDispatchDataKHR, skipping it");
continue;
}

if (KHR_ICD2_HAS_TAG(p->pid) && !(((size_t)((p->pid)->dispatch->clUnloadCompiler)) == CL_ICD2_TAG_KHR)) {
debug(D_WARN, "Found icd 2 platform, but it is missing clUnloadCompiler tag, skipping it");
continue;
}

if (KHR_ICD2_HAS_TAG(p->pid))
{
_populate_dispatch_table(p->pid, pltfn_fn_ptr, &p->disp_data.dispatch);
spltdd_fn_ptr(p->pid, &p->disp_data);
debug(D_LOG, "Found icd 2 platform, using loader managed dispatch");
}

/* If clGetPlatformInfo is not exported and we are here, it
* means that OCL_ICD_ASSUME_ICD_EXTENSION. Si we try to take it
* from the dispatch * table. If that fails too, we have to
* bail.
*/
if (plt_info_ptr == NULL) {
plt_info_ptr = p->pid->dispatch->clGetPlatformInfo;
plt_info_ptr = KHR_ICD2_DISPATCH(p->pid)->clGetPlatformInfo;
if (plt_info_ptr == NULL) {
debug(D_WARN, "Missing clGetPlatformInfo even in ICD dispatch table, skipping it");
continue;
Expand Down Expand Up @@ -1176,8 +1203,8 @@ hidden_alias(clGetPlatformIDs);
RETURN_WITH_ERRCODE(errcode_ret, CL_INVALID_PLATFORM, NULL); \
} \
} \
RETURN(((struct _cl_platform_id *) properties[i+1]) \
->dispatch->clCreateContext(properties, num_devices, devices, \
RETURN(KHR_ICD2_DISPATCH((struct _cl_platform_id *) properties[i+1]) \
->clCreateContext(properties, num_devices, devices, \
pfn_notify, user_data, errcode_ret)); \
} \
i += 2; \
Expand All @@ -1189,8 +1216,8 @@ hidden_alias(clGetPlatformIDs);
if((struct _cl_device_id *)devices[0] == NULL) { \
RETURN_WITH_ERRCODE(errcode_ret, CL_INVALID_DEVICE, NULL); \
} \
RETURN(((struct _cl_device_id *)devices[0]) \
->dispatch->clCreateContext(properties, num_devices, devices, \
RETURN(KHR_ICD2_DISPATCH((struct _cl_device_id *)devices[0]) \
->clCreateContext(properties, num_devices, devices, \
pfn_notify, user_data, errcode_ret));


Expand Down Expand Up @@ -1239,15 +1266,15 @@ hidden_alias(clCreateContext);
goto out; \
} \
} \
return ((struct _cl_platform_id *) properties[i+1]) \
->dispatch->clCreateContextFromType(properties, device_type, \
return KHR_ICD2_DISPATCH((struct _cl_platform_id *) properties[i+1]) \
->clCreateContextFromType(properties, device_type, \
pfn_notify, user_data, errcode_ret); \
} \
i += 2; \
} \
} else { \
cl_platform_id default_platform=getDefaultPlatformID(); \
RETURN(default_platform->dispatch->clCreateContextFromType \
RETURN(KHR_ICD2_DISPATCH(default_platform)->clCreateContextFromType \
(properties, device_type, pfn_notify, user_data, errcode_ret)); \
} \
out: \
Expand Down Expand Up @@ -1292,8 +1319,8 @@ hidden_alias(clCreateContextFromType);
RETURN(CL_INVALID_PLATFORM); \
} \
} \
RETURN(((struct _cl_platform_id *) properties[i+1]) \
->dispatch->clGetGLContextInfoKHR(properties, param_name, \
RETURN(KHR_ICD2_DISPATCH((struct _cl_platform_id *) properties[i+1]) \
->clGetGLContextInfoKHR(properties, param_name, \
param_value_size, param_value, param_value_size_ret)); \
} \
i += 2; \
Expand Down Expand Up @@ -1333,8 +1360,8 @@ hidden_alias(clGetGLContextInfoKHR);
RETURN(CL_INVALID_VALUE); \
if( (struct _cl_event *)event_list[0] == NULL ) \
RETURN(CL_INVALID_EVENT); \
RETURN(((struct _cl_event *)event_list[0]) \
->dispatch->clWaitForEvents(num_events, event_list));
RETURN(KHR_ICD2_DISPATCH((struct _cl_event *)event_list[0]) \
->clWaitForEvents(num_events, event_list));

__attribute__ ((visibility ("hidden"))) cl_int
clWaitForEvents_disp(cl_uint num_events,
Expand Down
55 changes: 54 additions & 1 deletion ocl_icd_loader.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#include "ocl_icd.h"
#include "ocl_icd_loader_gen.h"
#include <stdint.h>

cl_platform_id __attribute__((visibility("internal")))
getDefaultPlatformID();
Expand Down Expand Up @@ -73,6 +74,58 @@ struct layer_icd {
#endif
};

__attribute__((visibility("hidden"))) extern struct layer_icd *_first_layer;

#ifndef CL_ICD2_TAG_KHR
#define CL_ICD2_TAG_KHR ((size_t)0x4F50454E434C3331ULL)

typedef void * CL_API_CALL
clIcdGetFunctionAddressForPlatformKHR_t(
cl_platform_id platform,
const char* function_name);

typedef clIcdGetFunctionAddressForPlatformKHR_t *
clIcdGetFunctionAddressForPlatformKHR_fn;

typedef cl_int CL_API_CALL
clIcdSetPlatformDispatchDataKHR_t(
cl_platform_id platform,
void *disp_data);

typedef clIcdSetPlatformDispatchDataKHR_t *
clIcdSetPlatformDispatchDataKHR_fn;

__attribute__((visibility("hidden")))
extern void _populate_dispatch_table(
cl_platform_id platform,
clIcdGetFunctionAddressForPlatformKHR_fn pltfn_fn_ptr,
struct _cl_icd_dispatch* dispatch);
#endif

struct _cl_disp_data
{
struct _cl_icd_dispatch dispatch;
};

#define KHR_ICD2_HAS_TAG(object) \
(((size_t)((object)->dispatch->clGetPlatformIDs)) == CL_ICD2_TAG_KHR)

#define KHR_ICD2_DISPATCH(object) \
(KHR_ICD2_HAS_TAG(object) ? \
&(object)->disp_data->dispatch : \
(object)->dispatch)

struct platform_icd {
char *extension_suffix;
char *version;
struct vendor_icd *vicd;
cl_platform_id pid;
cl_uint ngpus; /* number of GPU devices */
cl_uint ncpus; /* number of CPU devices */
cl_uint ndevs; /* total number of devices, of all types */
struct _cl_disp_data disp_data;
};

__attribute__((visibility("hidden")))
extern struct layer_icd *_first_layer;

#endif
Loading