~hedgepigdaniel/dewobble

2b6b10c79ed8622dc5f809289dac7ecd1479c7be — Daniel Playfair Cal 2 years ago 5fabd56
refactor: simplify OpenCL context initialisation
1 files changed, 19 insertions(+), 67 deletions(-)

M src/filter/filter_sync.cpp
M src/filter/filter_sync.cpp => src/filter/filter_sync.cpp +19 -67
@@ 35,78 35,30 @@ ocl::Program read_opencl_program_from_string(string source, string program_opts)

void init_opencl_context(cl_context context, cl_device_id device)
{
    int err;
    vector<cl_context_properties> props;
    cl_platform_id platform = NULL;
    vector<char> platform_name;
    size_t param_value_size = 0;

    err = clGetContextInfo(
        context, CL_CONTEXT_PROPERTIES, 0, NULL, &param_value_size);
    if (err != CL_SUCCESS) {
        std::cerr << "clGetContextInfo failed to get props size\n";
        throw err;
    }
    if (param_value_size == 0) {
        std::cerr << "clGetContextInfo returned size 0\n";
        throw 1;
    }
    props.resize(param_value_size);
    err = clGetContextInfo(
        context, CL_CONTEXT_PROPERTIES, param_value_size, props.data(), NULL);
    if (err != CL_SUCCESS) {
        std::cerr << "clGetContextInfo failed\n";
        throw err;
    }
    for (int i = 0; props[i] != 0; i = i + 2) {
        if (props[i] == CL_CONTEXT_PLATFORM) {
            platform = (cl_platform_id)props[i + 1];
        }
    }
    if (platform == NULL) {
        std::cerr << "Failed to find platform in cl context props\n";
        throw 1;
    }

    err = clGetPlatformInfo(
        platform, CL_PLATFORM_NAME, 0, NULL, &param_value_size);
    ocl::Context opencv_context = ocl::Context::fromHandle(context);

    if (err != CL_SUCCESS) {
        std::cerr << "clGetPlatformInfo failed to get platform name size\n";
        throw err;
    }
    if (param_value_size == 0) {
        std::cerr << "clGetPlatformInfo returned 0 size for name\n";
        throw 1;
    /**
     * Due to https://github.com/opencv/opencv/issues/20537, We must find the
     * device from the context wrapper, not create it independently.
     */
    ocl::Device opencv_device;
    bool device_found = false;
    for (size_t i = 0; i < opencv_context.ndevices(); i++) {
        ocl::Device opencv_context_device = opencv_context.device(i);
        if (opencv_context_device.ptr() == device) {
            opencv_device = opencv_context_device;
            device_found = true;
            break;
        }
    }
    platform_name.resize(param_value_size);
    err = clGetPlatformInfo(
        platform,
        CL_PLATFORM_NAME,
        param_value_size,
        platform_name.data(),
        NULL);
    if (err != CL_SUCCESS) {
        std::cerr << "clGetPlatformInfo failed\n";
        throw err;
    if (!device_found) {
        throw;
    }

    std::cerr << "Initialising OpenCV OpenCL context with platform \""
              << string(platform_name.begin(), platform_name.end()) << "\"\n";

    /**
     * OpenCV's `ocl::OpenCLExecutionContext::create` takes ownership of the
     * device and context, in the sense that when the thread exits it calls
     * clReleaseDevice and clReleaseContext on them. So, counteract this
     * behaviour by incrementing the refcount.
     */
    clRetainContext(context);
    clRetainDevice(device);
    ocl::OpenCLExecutionContext opencv_execution_context =
        ocl::OpenCLExecutionContext::create(opencv_context, opencv_device);

    ocl::OpenCLExecutionContext opencv_context =
        ocl::OpenCLExecutionContext::create(
            platform_name.data(), platform, context, device);
    opencv_context.bind();
    opencv_execution_context.bind();
}

void FilterSync::cvtColorBgrToNv12(UMat input, UMat output)