summaryrefslogtreecommitdiff
path: root/libavutil/opencl.c
diff options
context:
space:
mode:
authorLenny Wang <lenny@multicorewareinc.com>2013-11-03 21:58:09 -0600
committerMichael Niedermayer <michaelni@gmx.at>2013-11-05 14:29:55 +0100
commit668255479085728bdf875a1b01c76201e2562a47 (patch)
tree98f8fb5b7faaa6e609c018ea6a167df1e3fe424b /libavutil/opencl.c
parente3f384b428351b62c83a19a8b77d93ffd415a124 (diff)
avutil/opencl: compile kernels separately
Reviewed-by: Wei Gao <highgod0401@gmail.com> Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
Diffstat (limited to 'libavutil/opencl.c')
-rw-r--r--libavutil/opencl.c193
1 files changed, 72 insertions, 121 deletions
diff --git a/libavutil/opencl.c b/libavutil/opencl.c
index e0b28c309c..ae4c476396 100644
--- a/libavutil/opencl.c
+++ b/libavutil/opencl.c
@@ -1,7 +1,8 @@
/*
- * Copyright (C) 2012 Peng Gao <peng@multicorewareinc.com>
- * Copyright (C) 2012 Li Cao <li@multicorewareinc.com>
- * Copyright (C) 2012 Wei Gao <weigao@multicorewareinc.com>
+ * Copyright (C) 2012 Peng Gao <peng@multicorewareinc.com>
+ * Copyright (C) 2012 Li Cao <li@multicorewareinc.com>
+ * Copyright (C) 2012 Wei Gao <weigao@multicorewareinc.com>
+ * Copyright (C) 2013 Lenny Wang <lwanghpc@gmail.com>
*
* This file is part of FFmpeg.
*
@@ -39,8 +40,6 @@ static pthread_mutex_t atomic_opencl_lock = PTHREAD_MUTEX_INITIALIZER;
#define UNLOCK_OPENCL
#endif
-
-#define MAX_KERNEL_NUM 500
#define MAX_KERNEL_CODE_NUM 200
typedef struct {
@@ -61,17 +60,19 @@ typedef struct {
int is_user_created;
int platform_idx;
int device_idx;
- char *build_options;
cl_platform_id platform_id;
cl_device_type device_type;
cl_context context;
cl_device_id device_id;
cl_command_queue command_queue;
+#if FF_API_OLD_OPENCL
+ char *build_options;
int program_count;
cl_program programs[MAX_KERNEL_CODE_NUM];
+ int kernel_count;
+#endif
int kernel_code_count;
KernelCode kernel_code[MAX_KERNEL_CODE_NUM];
- int kernel_count;
AVOpenCLDeviceList device_list;
} OpenclContext;
@@ -80,7 +81,9 @@ typedef struct {
static const AVOption opencl_options[] = {
{ "platform_idx", "set platform index value", OFFSET(platform_idx), AV_OPT_TYPE_INT, {.i64=-1}, -1, INT_MAX},
{ "device_idx", "set device index value", OFFSET(device_idx), AV_OPT_TYPE_INT, {.i64=-1}, -1, INT_MAX},
+#if FF_API_OLD_OPENCL
{ "build_options", "build options of opencl", OFFSET(build_options), AV_OPT_TYPE_STRING, {.str="-I."}, CHAR_MIN, CHAR_MAX},
+#endif
{ NULL }
};
@@ -194,7 +197,7 @@ static void free_device_list(AVOpenCLDeviceList *device_list)
static int get_device_list(AVOpenCLDeviceList *device_list)
{
cl_int status;
- int i, j, k, device_num, total_devices_num,ret = 0;
+ int i, j, k, device_num, total_devices_num, ret = 0;
int *devices_num;
cl_platform_id *platform_ids = NULL;
cl_device_id *device_ids = NULL;
@@ -388,66 +391,72 @@ end:
return ret;
}
-int av_opencl_create_kernel(AVOpenCLKernelEnv *env, const char *kernel_name)
+cl_program av_opencl_compile(const char *program_name, const char *build_opts)
{
+ int i;
cl_int status;
- int i, ret = 0;
+ int kernel_code_idx = 0;
+ const char *kernel_source;
+ size_t kernel_code_len;
+ char* ptr = NULL;
+ cl_program program = NULL;
+
LOCK_OPENCL;
- if (strlen(kernel_name) + 1 > AV_OPENCL_MAX_KERNEL_NAME_SIZE) {
- av_log(&opencl_ctx, AV_LOG_ERROR, "Created kernel name %s is too long\n", kernel_name);
- ret = AVERROR(EINVAL);
+ for (i = 0; i < opencl_ctx.kernel_code_count; i++) {
+ // identify a program using a unique name within the kernel source
+ ptr = av_stristr(opencl_ctx.kernel_code[i].kernel_string, program_name);
+ if (ptr && !opencl_ctx.kernel_code[i].is_compiled) {
+ kernel_source = opencl_ctx.kernel_code[i].kernel_string;
+ kernel_code_len = strlen(opencl_ctx.kernel_code[i].kernel_string);
+ kernel_code_idx = i;
+ break;
+ }
+ }
+ if (!kernel_source) {
+ av_log(&opencl_ctx, AV_LOG_ERROR,
+ "Unable to find OpenCL kernel source '%s'\n", program_name);
goto end;
}
- if (!env->kernel) {
- if (opencl_ctx.kernel_count >= MAX_KERNEL_NUM) {
- av_log(&opencl_ctx, AV_LOG_ERROR,
- "Could not create kernel with name '%s', maximum number of kernels %d already reached\n",
- kernel_name, MAX_KERNEL_NUM);
- ret = AVERROR(EINVAL);
- goto end;
- }
- if (opencl_ctx.program_count == 0) {
- av_log(&opencl_ctx, AV_LOG_ERROR, "Program count of OpenCL is 0, can not create kernel\n");
- ret = AVERROR(EINVAL);
- goto end;
- }
- for (i = 0; i < opencl_ctx.program_count; i++) {
- env->kernel = clCreateKernel(opencl_ctx.programs[i], kernel_name, &status);
- if (status == CL_SUCCESS)
- break;
- }
- if (status != CL_SUCCESS) {
- av_log(&opencl_ctx, AV_LOG_ERROR, "Could not create OpenCL kernel: %s\n", av_opencl_errstr(status));
- ret = AVERROR_EXTERNAL;
- goto end;
- }
- opencl_ctx.kernel_count++;
- env->command_queue = opencl_ctx.command_queue;
- av_strlcpy(env->kernel_name, kernel_name, sizeof(env->kernel_name));
+
+ /* create a CL program from kernel source */
+ program = clCreateProgramWithSource(opencl_ctx.context, 1, &kernel_source, &kernel_code_len, &status);
+ if(status != CL_SUCCESS) {
+ av_log(&opencl_ctx, AV_LOG_ERROR,
+ "Unable to create OpenCL program '%s': %s\n", program_name, av_opencl_errstr(status));
+ program = NULL;
+ goto end;
}
+ status = clBuildProgram(program, 1, &(opencl_ctx.device_id), build_opts, NULL, NULL);
+ if (status != CL_SUCCESS) {
+ av_log(&opencl_ctx, AV_LOG_ERROR,
+ "Compilation failed with OpenCL program: %s\n", program_name);
+ program = NULL;
+ goto end;
+ }
+
+ opencl_ctx.kernel_code[kernel_code_idx].is_compiled = 1;
end:
UNLOCK_OPENCL;
- return ret;
+ return program;
+}
+
+cl_command_queue av_opencl_get_command_queue(void)
+{
+ return opencl_ctx.command_queue;
+}
+
+#if FF_API_OLD_OPENCL
+int av_opencl_create_kernel(AVOpenCLKernelEnv *env, const char *kernel_name)
+{
+ av_log(&opencl_ctx, AV_LOG_ERROR, "Could not create OpenCL kernel %s, please update libavfilter.\n", kernel_name);
+ return AVERROR(EINVAL);
}
void av_opencl_release_kernel(AVOpenCLKernelEnv *env)
{
- cl_int status;
- LOCK_OPENCL;
- if (!env->kernel)
- goto end;
- status = clReleaseKernel(env->kernel);
- if (status != CL_SUCCESS) {
- av_log(&opencl_ctx, AV_LOG_ERROR, "Could not release kernel: %s\n",
- av_opencl_errstr(status));
- }
- env->kernel = NULL;
- env->command_queue = NULL;
- env->kernel_name[0] = 0;
- opencl_ctx.kernel_count--;
-end:
- UNLOCK_OPENCL;
+ av_log(&opencl_ctx, AV_LOG_ERROR, "Could not release OpenCL kernel, please update libavfilter.\n");
}
+#endif
static int init_opencl_env(OpenclContext *opencl_ctx, AVOpenCLExternalEnv *ext_opencl_env)
{
@@ -542,49 +551,6 @@ static int init_opencl_env(OpenclContext *opencl_ctx, AVOpenCLExternalEnv *ext_o
return ret;
}
-static int compile_kernel_file(OpenclContext *opencl_ctx)
-{
- cl_int status;
- int i, kernel_code_count = 0;
- const char *kernel_code[MAX_KERNEL_CODE_NUM] = {NULL};
- size_t kernel_code_len[MAX_KERNEL_CODE_NUM] = {0};
-
- for (i = 0; i < opencl_ctx->kernel_code_count; i++) {
- if (!opencl_ctx->kernel_code[i].is_compiled) {
- kernel_code[kernel_code_count] = opencl_ctx->kernel_code[i].kernel_string;
- kernel_code_len[kernel_code_count] = strlen(opencl_ctx->kernel_code[i].kernel_string);
- opencl_ctx->kernel_code[i].is_compiled = 1;
- kernel_code_count++;
- }
- }
- if (!kernel_code_count)
- return 0;
- /* create a CL program using the kernel source */
- opencl_ctx->programs[opencl_ctx->program_count] = clCreateProgramWithSource(opencl_ctx->context,
- kernel_code_count,
- kernel_code,
- kernel_code_len,
- &status);
- if(status != CL_SUCCESS) {
- av_log(opencl_ctx, AV_LOG_ERROR,
- "Could not create OpenCL program with source code: %s\n", av_opencl_errstr(status));
- return AVERROR_EXTERNAL;
- }
- if (!opencl_ctx->programs[opencl_ctx->program_count]) {
- av_log(opencl_ctx, AV_LOG_ERROR, "Created program is NULL\n");
- return AVERROR_EXTERNAL;
- }
- status = clBuildProgram(opencl_ctx->programs[opencl_ctx->program_count], 1, &(opencl_ctx->device_id),
- opencl_ctx->build_options, NULL, NULL);
- if (status != CL_SUCCESS) {
- av_log(opencl_ctx, AV_LOG_ERROR,
- "Could not compile OpenCL kernel: %s\n", av_opencl_errstr(status));
- return AVERROR_EXTERNAL;
- }
- opencl_ctx->program_count++;
- return 0;
-}
-
int av_opencl_init(AVOpenCLExternalEnv *ext_opencl_env)
{
int ret = 0;
@@ -597,18 +563,14 @@ int av_opencl_init(AVOpenCLExternalEnv *ext_opencl_env)
ret = init_opencl_env(&opencl_ctx, ext_opencl_env);
if (ret < 0)
goto end;
- }
- ret = compile_kernel_file(&opencl_ctx);
- if (ret < 0)
- goto end;
- if (opencl_ctx.kernel_code_count <= 0) {
- av_log(&opencl_ctx, AV_LOG_ERROR,
- "No kernel code is registered, compile kernel file failed\n");
- ret = AVERROR(EINVAL);
- goto end;
+ if (opencl_ctx.kernel_code_count <= 0) {
+ av_log(&opencl_ctx, AV_LOG_ERROR,
+ "No kernel code is registered, compile kernel file failed\n");
+ ret = AVERROR(EINVAL);
+ goto end;
+ }
}
opencl_ctx.init_count++;
-
end:
UNLOCK_OPENCL;
return ret;
@@ -617,23 +579,12 @@ end:
void av_opencl_uninit(void)
{
cl_int status;
- int i;
LOCK_OPENCL;
opencl_ctx.init_count--;
if (opencl_ctx.is_user_created)
goto end;
- if (opencl_ctx.init_count > 0 || opencl_ctx.kernel_count > 0)
+ if (opencl_ctx.init_count > 0)
goto end;
- for (i = 0; i < opencl_ctx.program_count; i++) {
- if (opencl_ctx.programs[i]) {
- status = clReleaseProgram(opencl_ctx.programs[i]);
- if (status != CL_SUCCESS) {
- av_log(&opencl_ctx, AV_LOG_ERROR,
- "Could not release OpenCL program: %s\n", av_opencl_errstr(status));
- }
- opencl_ctx.programs[i] = NULL;
- }
- }
if (opencl_ctx.command_queue) {
status = clReleaseCommandQueue(opencl_ctx.command_queue);
if (status != CL_SUCCESS) {
@@ -652,7 +603,7 @@ void av_opencl_uninit(void)
}
free_device_list(&opencl_ctx.device_list);
end:
- if ((opencl_ctx.init_count <= 0) && (opencl_ctx.kernel_count <= 0))
+ if (opencl_ctx.init_count <= 0)
av_opt_free(&opencl_ctx); //FIXME: free openclutils context
UNLOCK_OPENCL;
}