OpenCL 和 OpenGL 互操作扩展不工作(clGetGLContextInfoKHR 崩溃)

OpenCL and OpenGL interop extension not working (clGetGLContextInfoKHR crash)

我正在努力让 GL+CL 协同工作。

我一直在关注 this tutorial. In my code I first call clGetPlatformIDs and retrieve the first (and only) platform. I also get my gl_context from SDL2. Then I want to query the device used by OpenGL with help of clGetGLContextInfoKHR. I successfully obtain this function with clGetExtensionFunctionAddressForPlatform(platform_id, "clGetGLContextInfoKHR") but unfortunately when I call it, I get a segmentation fault. My code is written in Rust but I use low level OpenCL binding,所以它看起来几乎像它的 C 版本。

    pub fn new(gl_context: &GLContext) -> Result<Self, ClGlError> {
        println!("Initialising OpenCL context");
        let raw = unsafe { gl_context.raw() };
        println!("Getting default opencl platform");
        let platform_id = Self::default_platform()?; // this is valid and not null
        let mut props:[cl_sys::cl_context_properties;5] = [
            //OpenCL platform
            cl_sys::CL_CONTEXT_PLATFORM as cl_sys::cl_context_properties, platform_id as cl_sys::cl_context_properties,
            //OpenGL context
            cl_sys::CL_GL_CONTEXT_KHR,   raw as cl_sys::cl_context_properties,
            0
        ];
        let mut device: cl_device_id = std::ptr::null_mut();
        let p: *mut cl_device_id = (&mut device) as *mut cl_device_id;
        let fn_name = b"clGetGLContextInfoKHR[=10=]" as *const u8 as *const i8;
        println!("Getting clGetGLContextInfoKHR");
        let clGetGLContextInfoKHR = unsafe{clGetExtensionFunctionAddressForPlatform(platform_id, fn_name ) as cl_sys::clGetGLContextInfoKHR_fn};
        if clGetGLContextInfoKHR.is_null(){
            // error handling here
        }
        println!("Getting device"); // this is the last thing I see before segfault
        unsafe{
            (*clGetGLContextInfoKHR)(props.as_mut_ptr(),cl_sys::CL_CURRENT_DEVICE_FOR_GL_CONTEXT_KHR,std::mem::size_of::<cl_device_id>(),device as *mut c_void,std::ptr::null_mut());
        }

        panic!("All good") // this is never reached
    } 

我有一张支持 cl_khr_gl_sharing 的相当新的显卡。 这是 clinfo

Number of platforms                               1
  Platform Name                                   NVIDIA CUDA
  Platform Vendor                                 NVIDIA Corporation
  Platform Version                                OpenCL 1.2 CUDA 11.2.162
  Platform Profile                                FULL_PROFILE
  Platform Extensions                             cl_khr_global_int32_base_atomics cl_khr_global_int32_extended_atomics cl_khr_local_int32_base_atomics cl_khr_local_int32_extended_atomics cl_khr_fp64 cl_khr_byte_addressable_store cl_khr_icd cl_khr_gl_sharing cl_nv_compiler_options cl_nv_device_attribute_query cl_nv_pragma_unroll cl_nv_copy_opts cl_nv_create_buffer cl_khr_int64_base_atomics cl_khr_int64_extended_atomics cl_khr_device_uuid
  Platform Extensions function suffix             NV

  Platform Name                                   NVIDIA CUDA
Number of devices                                 1
  Device Name                                     GeForce GTX 960
  Device Vendor                                   NVIDIA Corporation
  Device Vendor ID                                0x10de
  Device Version                                  OpenCL 1.2 CUDA
  Driver Version                                  460.80
  Device OpenCL C Version                         OpenCL C 1.2 
  Device Type                                     GPU
  Device Extensions                               cl_khr_global_int32_base_atomics cl_khr_global_int32_extended_atomics cl_khr_local_int32_base_atomics cl_khr_local_int32_extended_atomics cl_khr_fp64 cl_khr_byte_addressable_store cl_khr_icd cl_khr_gl_sharing cl_nv_compiler_options cl_nv_device_attribute_query cl_nv_pragma_unroll cl_nv_copy_opts cl_nv_create_buffer cl_khr_int64_base_atomics cl_khr_int64_extended_atomics cl_khr_device_uuid

也许最重要的线索可能是,每当我调用 clGetGLContextInfoKHR(包装在更安全和更高级别的 API) 它崩溃了。我认为所有这些库的代码中都存在错误的可能性很小,所以这可能是我环境中的一些问题。但是,如您所见,我的显卡显然支持所有必要的扩展。

我不确定为什么 clGetGLContextInfoKHR 会失败,但我发现调用它并不是真的必要。

相反,您可以在 Linux

上使用它
cl_context_properties properties[] = {
    CL_GL_CONTEXT_KHR, (cl_context_properties) glXGetCurrentContext(),
    CL_GLX_DISPLAY_KHR, (cl_context_properties) glXGetCurrentDisplay(),
    CL_CONTEXT_PLATFORM, (cl_context_properties) platform,
    0
};

这个在 Windows

cl_context_properties properties[] = {
    CL_GL_CONTEXT_KHR, (cl_context_properties) wglGetCurrentContext(),
    CL_WGL_HDC_KHR, (cl_context_properties) wglGetCurrentDC(),
    CL_CONTEXT_PLATFORM, (cl_context_properties) platform,
    0
};

或者这个在 OS X

CGLContextObj glContext = CGLGetCurrentContext();
CGLShareGroupObj shareGroup = CGLGetShareGroup(glContext);
cl_context_properties properties[] = {
    CL_CONTEXT_PROPERTY_USE_CGL_SHAREGROUP_APPLE,
    (cl_context_properties)shareGroup,
    0
};

更多信息可以在书中找到

OpenCL in Action: How to Accelerate Graphics and Computations