在 Manjaro 下在 Intel 上使用 OpenGL 上下文时出现 OpenCL 内核 -44 编译错误

OpenCL kernel -44 compilation error while using OpenGL context on Intel under Manjaro

提问人:Stimmer02 提问时间:10/21/2023 最后编辑:Stimmer02 更新时间:10/21/2023 访问量:53

问:

最近我一直在尝试使用 OpenCL-OpenGL 互操作。经过一些反复试验,我发现我需要初始化 OpenCL 上下文,为其提供正确的属性。我在安装了 NVIDIA GPU、NVIDIA 驱动程序和 CUDA 的 Manjaro 下让它工作,但我在 Intel 设备上遇到了一些问题。

(问题仅在 Manjaro 和 Intel 下,我无法在 Windows 下在同一设备上测试它,因为没有我的)

问题是:要使用 OpenCL-OpenGL 互操作,我需要使用属性创建 OpenCL 上下文:

cl_context_properties properties[] = { //for Linux
    CL_GL_CONTEXT_KHR, (cl_context_properties) glXGetCurrentContext(),
    CL_GLX_DISPLAY_KHR, (cl_context_properties) glXGetCurrentDisplay(),
    CL_CONTEXT_PLATFORM, (cl_context_properties) platform,
    0
};

但是,如果我将其提供给上下文,那么在编译任何内核后,“buildCode”等于 -44 并返回 0 个字符串。 从 OpenCL 文档中,我知道“如果程序不是有效的程序对象”会返回 -44,但是在互联网上搜索了更多信息后,我发现了这一点,所以我的问题可能是开发人员未映射的任何内容。cl::Context context(default_device, properties);int buildCode = program.build();program.getBuildInfo<CL_PROGRAM_BUILD_LOG>(default_device)

我发现我扔到内核代码中的内容真的无关紧要。它可能是这样的:

std::string kernel_code =
        "not a valid kernel";

我会得到相同的 -44 构建代码。 在大多数这些设备上,在创建没有属性的 OpenCL 上下文后编译任何内核都没有问题。

我试过了:

  1. Manjaro 1st 与 NVIDIA GPU (GTX1070)- 工作
  2. 配备 AMD GPU (r9 380x) 的 Windows - 工作
  3. 配备 AMD GPU (radeon pro 450) 的 MacO - 工作;和英特尔 CPU (i7-6700HQ) - 工作
  4. 带有 Intel CPU 的 Manjaro 2nd (i5-3320M) - 错误 -44(无法创建没有属性的 OpenCL 上下文)
  5. 配备 Intel GPU (UHD Graphics 620) 的 Manjaro 3rd - 错误 -44
  6. Manjaro 4th with Intel GPU (UHD Graphics 620) - 错误 -44

编辑:

除了(带有 Intel CPU 的 Manjaro)之外,我测试过的每个设备都被正确识别并通过命令列出。 这是来自带有 Intel CPU 的 Manjaro:clinfoclinfo

Number of platforms                               1
  Platform Name                                   Intel(R) OpenCL
  Platform Vendor                                 Intel(R) Corporation
  Platform Version                                OpenCL 1.2 
  Platform Profile                                FULL_PROFILE
  Platform Extensions                             cl_khr_icd 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_byte_addressable_store cl_khr_depth_images cl_khr_3d_image_writes cl_intel_exec_by_local_thread cl_khr_spir cl_khr_fp64
  Platform Extensions function suffix             INTEL

  Platform Name                                   Intel(R) OpenCL
Number of devices                                 1
  Device Name                                            Intel(R) Core(TM) i5-3320M CPU @ 2.60GHz
  Device Vendor                                   Intel(R) Corporation
  Device Vendor ID                                0x8086
  Device Version                                  OpenCL 1.2 (Build 475)
  Driver Version                                  1.2.0.475
  Device OpenCL C Version                         OpenCL C 1.2 
  Device Type                                     CPU
  Device Profile                                  FULL_PROFILE
  Device Available                                Yes
  Compiler Available                              Yes
  Linker Available                                Yes
  Max compute units                               4
  Max clock frequency                             2600MHz
  Device Partition                                (core)
    Max number of sub-devices                     4
    Supported partition types                     by counts, equally, by names (Intel)
    Supported affinity domains                    (n/a)
  Max work item dimensions                        3
  Max work item sizes                             8192x8192x8192
  Max work group size                             8192
zsh: segmentation fault (core dumped)  clinfo

编辑结束

这是最简化的代码,具有正确的初始化,将重现此错误:

#define CL_HPP_TARGET_OPENCL_VERSION 200

#include <CL/opencl.hpp>
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <GL/glx.h>

#include <vector>
#include <cstdio>



GLFWwindow* initializeGLFW(uint width, uint height);
char initializeGLEW();
cl::Device getDefaultClDevice();
cl::Program compileTestKernel(cl::Context context, cl::Device default_device);


int main(){

    int width = 1024, height = 1024;
    GLFWwindow* window = initializeGLFW(width, height);
    if (window == nullptr){
        return 1;
    }

    if (initializeGLEW()){
        return 1;
    }

    cl::Device default_device = getDefaultClDevice();
    if (!default_device()){
        return 1;
    }


    cl_platform_id platform;
    clGetPlatformIDs(1, &platform, NULL);

    cl_context_properties properties[] = {
        CL_GL_CONTEXT_KHR, (cl_context_properties) glXGetCurrentContext(),
        CL_GLX_DISPLAY_KHR, (cl_context_properties) glXGetCurrentDisplay(),
        //if I comment any of properties above I get segmentatnion fault if trying to acces OpenGL memory on NVIDIA;
        //if I comment both of those I get segmentatnion fault on Intel creating context;
        //if I comment one or none I get -44 from program.build();
        //only on Intel CPU I need this to create context;

        CL_CONTEXT_PLATFORM, (cl_context_properties) platform,//this didn't influence resaults of my tests but everyone uses this in example so I guess it is important in some way;
        0
    };
    cl::Context context(default_device, properties);
    cl::Program program = compileTestKernel(context, default_device);

    cl::CommandQueue queue(context, default_device);

    cl::Kernel test(program, "test");
    queue.enqueueNDRangeKernel(test, cl::NullRange, cl::NullRange, cl::NullRange);
    queue.finish();

    int error = glGetError();
    if (error != GL_NO_ERROR) {
        std::fprintf(stderr, "OpenGL error: %d\n", error);
    }

    glfwDestroyWindow(window);

    return 0;
}




void glfwErrorCallback(int error, const char* description){
    std::fprintf(stderr, "Error: %s\n", description);
}


GLFWwindow* initializeGLFW(uint width, uint height){
    if (!glfwInit()){
        std::fprintf(stderr, "Failed to initialize GLFW!\n");
        return nullptr;
    }
    glfwSetErrorCallback(glfwErrorCallback);


    GLFWwindow* window = glfwCreateWindow(width, height, "test", NULL, NULL);
    if (!window){
        std::fprintf(stderr, "Failed to create GLFW window!\n");
        glfwTerminate();
        return nullptr;
    }

    glfwMakeContextCurrent(window);
    glViewport(0,0, width, height);
    glfwSwapInterval(1);

    return window;
}


char initializeGLEW(){
    glewExperimental = GL_TRUE;
    if (glewInit() != GLEW_OK) {
        std::fprintf(stderr, "Failed to initialize GLEW!\n");
        glfwTerminate();
        return -1;
    }

    GLenum error = glGetError();
    if (error != GL_NO_ERROR) {
        std::fprintf(stderr, "OpenGL error: %d\n", error);
    }


    const GLubyte* glVersion = glGetString(GL_VERSION);
    const GLubyte* glVendor = glGetString(GL_VENDOR);
    const GLubyte* glRenderer = glGetString(GL_RENDERER);

    std::printf("GL version:\t%s\n", glVersion);
    std::printf("GL vendor:\t%s\n", glVendor);
    std::printf("GL renderer:\t%s\n\n", glRenderer);

    return 0;
}


cl::Device getDefaultClDevice(){
    std::vector<cl::Platform> all_platforms;
    cl::Platform::get(&all_platforms);

    if (all_platforms.empty()){
        std::fprintf(stderr, "No platforms found. Check OpenCL installation!\n");
        return cl::Device();
    }

    int selection=0;

    cl::Platform default_platform = all_platforms[0];
    std::printf("Using platform:\t%s\n", default_platform.getInfo<CL_PLATFORM_NAME>().c_str());

    std::vector<cl::Device> all_devices;
    default_platform.getDevices(CL_DEVICE_TYPE_ALL, &all_devices);


    if (all_devices.size() == 0){
        std::fprintf(stderr, "No devices found. Check OpenCL installation!\n");
        return cl::Device();
    }

    cl::Device default_device = all_devices[0];
    std::printf("Using device:\t%s\n", default_device.getInfo<CL_DEVICE_NAME>().c_str());

    return default_device;
}


cl::Program compileTestKernel(cl::Context context, cl::Device default_device){
    cl::Program::Sources sources;
    std::string kernel_code =
        "   void kernel create_gradient(){}";

    sources.push_back({kernel_code.c_str(), kernel_code.length()});
    cl::Program program(context, sources);

    int buildCode = program.build();

    int error = glGetError();
    if (error != GL_NO_ERROR) {
        std::fprintf(stderr, "OpenGL error: %d\n", error);
    }

    if (buildCode != CL_SUCCESS) {
        std::fprintf(stderr, "Error building (%d): %s\n", buildCode, program.getBuildInfo<CL_PROGRAM_BUILD_LOG>(default_device).c_str());
        exit(1);
    }
    return program;
}

这些是我从我的设备收到的消息:

GL version:     4.6.0 NVIDIA 535.113.01
GL vendor:      NVIDIA Corporation
GL renderer:    NVIDIA GeForce GTX 1070/PCIe/SSE2

Using platform: NVIDIA CUDA
Using device:   NVIDIA GeForce GTX 1070

GL version:     3.0 Mesa 21.3.9 Amber
GL vendor:      Intel Open Source Technology Center
GL renderer:    Mesa DRI Intel(R) HD Graphics 4000 (IVB GT2)

Using platform: Intel(R) OpenCL
Using device:   Intel(R) Core(TM) i5-3320M CPU @ 2.60GHz
Error building (-44):

我是 OpenCL 或 OpenGL 的新手,所以可能我的问题可以很容易地由有更多经验的人来解释。如果您知道问题可能是什么,我将不胜感激地与我分享。 还请告诉我是否可以提供任何其他有用的信息,因为我一直在许多设备上进行测试。我不想用不相关的文本流淹没这个页面,而且我还必须让我的朋友为我做这件事(只有带有 NVIDIA 的 Manjaro 和带有 Intel CPU 的 Manjaro 是我的)。

C++ OpenGL OpenCL 英特尔 Manjaro

评论

0赞 Simon Goater 10/22/2023
事实上,我不知道你为什么会收到这个错误,但我的一个想法是,可能是英特尔 OpenCL 驱动程序可能不喜欢你定义的空内核。也许试着在里面放一些东西,比如一个简单的printf。
0赞 Stimmer02 10/22/2023
@SimonGoater我试过把各种内核放在那里。无论它们是在其他设备上工作正常还是产生编译错误,在英特尔上我总是得到 -44。

答: 暂无答案