I have posted this also to StackOverflow because this is a programming issue, but I am posting this here because it is only related to Manjaro.
Recently I’ve been trying to use OpenCL-OpenGL interop. After some trial and error I’ve found that I need to initialize OpenCL context providing it correct properties. I got it working under Manjaro with NVIDIA GPU, NVIDIA driver and CUDA installed but I got some problems on Intel devices.
(Problem is only under Manjaro with Intel and I am not able to test it under Windows on same devices because there are not mine)
The problem is: to use OpenCL-OpenGL interop I need to create OpenCL context using properties:
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
};
but if I provide this to context cl::Context context(default_device, properties);
then after compilation of any kernel int buildCode = program.build();
‘buildCode’ is equal to -44 and program.getBuildInfo<CL_PROGRAM_BUILD_LOG>(default_device)
returns 0 character string.
From OpenCL documentation I know that -44 is returned “if program is a not a valid program object” but after searching more on the internet I have found this so my problem could be anything that was unmapped by developers.
I have found that it really des not matter what I throw into the kernel code. It could be something like this:
std::string kernel_code =
"not a valid kernel";
and I will get the same -44 build code.
On most of those devices there is no problem compiling any kernel after creating OpenCL context without properties.
I’ve tried It on:
- Manjaro 1st with NVIDIA GPU (GTX1070)- working
- Windows with AMD GPU (r9 380x) - working
- MacOs with AMD GPU (radeon pro 450) - working; and Intel CPU (i7-6700HQ) - working
- Manjaro 2nd with Intel CPU (i5-3320M)- error -44 (cannot create OpenCL context without properties)
- Manjaro 3rd with Intel GPU (UHD Graphics 620) - error -44
- Manjaro 4th with Intel GPU (UHD Graphics 620) - error -44
Every single device but (Manjaro with Intel CPU) I have tested was properly recognized and listed by clinfo
command.
This is clinfo
from Manjaro with Intel CPU:
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
This is most simplified code with proper initialization that will reproduce this error:
#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;
}
EDIT:
I compiled this code using g++ main.cpp -lglfw -lGLEW -lOpenCL -lGL -lX11 -lXrandr -lXi -ldl -lpthread
END OF EDIT
Those are messages That I got from my devices:
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
and
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):
I am new to either OpenCL or OpenGL so probably my problem could be easily explained by someone with more experience. If you have any idea of what the problem could be I would appreciate sharing it with me.
Please also tell me if there is any additional useful info that I can provide because there are many devices I’ve been testing this on. I don’t wanna flood this page with irrelevant stream of text and also I would have to ask my friends to do this for me (only Manjaro with NVIDIA and Manjaro with Intel CPU are mine).