From 2cacc799f7ef1dff006c97360298e4f6e847d1e9 Mon Sep 17 00:00:00 2001 From: Junyan He Date: Tue, 18 Jun 2013 16:44:49 +0800 Subject: [PATCH] add the support of clGetProgramBuildInfo and clGetProgramInfo For clGetProgramBuildInfo, CL_BUILD_IN_PROGRESS not support now and CL_PROGRAM_BUILD_LOG need do add the info collection logic in backend and not support too, just return null string now. clGetProgramInfo all are fully supported. Signed-off-by: Junyan He Reviewed-by: Ruiling Song --- src/cl_api.c | 95 +++++++++++++++++++++++++++++++++++++++++++++++++++++--- src/cl_program.c | 32 +++++++++++++++++++ src/cl_program.h | 1 + 3 files changed, 124 insertions(+), 4 deletions(-) diff --git a/src/cl_api.c b/src/cl_api.c index d8787cd..223ba9b 100644 --- a/src/cl_api.c +++ b/src/cl_api.c @@ -725,6 +725,19 @@ clUnloadCompiler(void) return 0; } +#define FILL_AND_RET(TYPE, ELT, VAL, RET) \ + do { \ + if (param_value && param_value_size < sizeof(TYPE)*ELT) \ + return CL_INVALID_VALUE; \ + if (param_value) { \ + memcpy(param_value, (VAL), sizeof(TYPE)*ELT); \ + } \ + \ + if (param_value_size_ret) \ + *param_value_size_ret = sizeof(TYPE)*ELT; \ + return RET; \ + } while(0) + cl_int clGetProgramInfo(cl_program program, cl_program_info param_name, @@ -732,8 +745,50 @@ clGetProgramInfo(cl_program program, void * param_value, size_t * param_value_size_ret) { - NOT_IMPLEMENTED; - return 0; + cl_int err = CL_SUCCESS; + char * ret_str = ""; + + CHECK_PROGRAM (program); + + if (param_name == CL_PROGRAM_REFERENCE_COUNT) { + cl_uint ref = program->ref_n; + FILL_AND_RET (cl_uint, 1, (&ref), CL_SUCCESS); + } else if (param_name == CL_PROGRAM_CONTEXT) { + cl_context context = program->ctx; + FILL_AND_RET (cl_context, 1, &context, CL_SUCCESS); + } else if (param_name == CL_PROGRAM_NUM_DEVICES) { + cl_uint num_dev = 1; // Just 1 dev now. + FILL_AND_RET (cl_uint, 1, &num_dev, CL_SUCCESS); + } else if (param_name == CL_PROGRAM_DEVICES) { + cl_device_id dev_id = program->ctx->device; + FILL_AND_RET (cl_device_id, 1, &dev_id, CL_SUCCESS); + } else if (param_name == CL_PROGRAM_SOURCE) { + + if (!program->source) + FILL_AND_RET (char, 1, &ret_str, CL_SUCCESS); + FILL_AND_RET (char, (strlen(program->source) + 1), + program->source, CL_SUCCESS); + } else if (param_name == CL_PROGRAM_BINARY_SIZES) { + FILL_AND_RET (size_t, 1, (&program->bin_sz), CL_SUCCESS); + } else if (param_name == CL_PROGRAM_BINARIES) { + if (!param_value) + return CL_SUCCESS; + + /* param_value points to an array of n + pointers allocated by the caller */ + if (program->bin_sz > 0) { + memcpy(*((void **)param_value), program->bin, program->bin_sz); + } else { + memcpy(*((void **)param_value), ret_str, 1); + } + + return CL_SUCCESS; + } else { + return CL_INVALID_VALUE; + } + +error: + return err; } cl_int @@ -744,10 +799,42 @@ clGetProgramBuildInfo(cl_program program, void * param_value, size_t * param_value_size_ret) { - NOT_IMPLEMENTED; - return 0; + cl_int err = CL_SUCCESS; + char * ret_str = ""; + + CHECK_PROGRAM (program); + INVALID_DEVICE_IF (device != program->ctx->device); + + if (param_name == CL_PROGRAM_BUILD_STATUS) { + cl_build_status status; + + if (!program->is_built) + status = CL_BUILD_NONE; + else if (program->ker_n > 0) + status = CL_BUILD_SUCCESS; + else + status = CL_BUILD_ERROR; + // TODO: Support CL_BUILD_IN_PROGRESS ? + + FILL_AND_RET (cl_build_status, 1, &status, CL_SUCCESS); + } else if (param_name == CL_PROGRAM_BUILD_OPTIONS) { + if (program->is_built && program->build_opts) + ret_str = program->build_opts; + + FILL_AND_RET (char, (strlen(ret_str)+1), ret_str, CL_SUCCESS); + } else if (param_name == CL_PROGRAM_BUILD_LOG) { + // TODO: need to add logs in backend when compiling. + FILL_AND_RET (char, (strlen(ret_str)+1), ret_str, CL_SUCCESS); + } else { + return CL_INVALID_VALUE; + } + +error: + return err; } +#undef FILL_AND_RET + cl_kernel clCreateKernel(cl_program program, const char * kernel_name, diff --git a/src/cl_program.c b/src/cl_program.c index 1b49b84..7870514 100644 --- a/src/cl_program.c +++ b/src/cl_program.c @@ -56,6 +56,12 @@ cl_program_delete(cl_program p) /* Destroy the sources if still allocated */ cl_program_release_sources(p); + /* Release the build options. */ + if (p->build_opts) { + cl_free(p->build_opts); + p->build_opts = NULL; + } + /* Remove it from the list */ assert(p->ctx); pthread_mutex_lock(&p->ctx->program_lock); @@ -274,6 +280,18 @@ LOCAL cl_int cl_program_build(cl_program p, const char *options) { cl_int err = CL_SUCCESS; + int i = 0; + int copyed = 0; + + if (options) { + if(p->build_opts) { + cl_free(p->build_opts); + p->build_opts = NULL; + } + + TRY_ALLOC (p->build_opts, cl_calloc(strlen(options) + 1, sizeof(char))); + memcpy(p->build_opts, options, strlen(options)); + } if (p->source_type == FROM_SOURCE) { p->opaque = gbe_program_new_from_source(p->source, 0, options, NULL, NULL); @@ -287,6 +305,20 @@ cl_program_build(cl_program p, const char *options) p->source_type = FROM_LLVM; } + for (i = 0; i < p->ker_n; i ++) { + const gbe_kernel opaque = gbe_program_get_kernel(p->opaque, i); + p->bin_sz += gbe_kernel_get_code_size(opaque); + } + + TRY_ALLOC (p->bin, cl_calloc(p->bin_sz, sizeof(char))); + for (i = 0; i < p->ker_n; i ++) { + const gbe_kernel opaque = gbe_program_get_kernel(p->opaque, i); + size_t sz = gbe_kernel_get_code_size(opaque); + + memcpy(p->bin + copyed, gbe_kernel_get_code(opaque), sz); + copyed += sz; + } + p->is_built = 1; error: return err; diff --git a/src/cl_program.h b/src/cl_program.h index 3e3edab..996a496 100644 --- a/src/cl_program.h +++ b/src/cl_program.h @@ -51,6 +51,7 @@ struct _cl_program { uint32_t ker_n; /* Number of declared kernels */ uint32_t source_type:2; /* Built from binary, source or LLVM */ uint32_t is_built:1; /* Did we call clBuildProgram on it? */ + char *build_opts; /* The build options for this program */ }; /* Create a empty program */ -- 2.7.4