Hi,
I wrote a similar code in C++ (see code below this email).
I compile it on Mac this way:
g++ clgl_interop.cpp -o clgl_interop -framework OpenCL -framework OpenGL -lGLEW -lglfw
and on Linux this way:
g++ clgl_interop.cpp -o clgl_interop -lOpenCL -lOpenGL -lGLEW -lglfw
It looks like the culprit of my problem is the way I create the context.
On Linux, if I create the context using:
clCreateContextFromType
than it works fine.
Otherwise if in Linux I use:
clCreateContext
than it crashes with segmentation fault.
I remember somewhere I read, I think in the PyOpenCL demo "gl_interop_demo.py",
a comment about that but on that time I was not able to understand it.
Could you maybe check the latter file and elaborate this point?
Thanks
_______________________
C++ code:
_______________________
#include <stdio.h>
#include <stdlib.h>
#include <GL/glew.h>
#ifdef __WINDOWS__
#define GLFW_EXPOSE_NATIVE_WIN32
#define GLFW_EXPOSE_NATIVE_WGL
#endif
#ifdef __linux__
#define GLFW_EXPOSE_NATIVE_X11
#define GLFW_EXPOSE_NATIVE_GLX
#endif
#include <GLFW/glfw3.h>
#include <GLFW/glfw3native.h>
#ifdef __APPLE__
#include <OpenGL/OpenGL.h>
#include <OpenCL/opencl.h>
#else
#include <GL/gl.h>
#include <CL/cl.h>
#include <CL/cl_gl.h>
#endif
void window_refresh_callback(GLFWwindow* window)
{
glClear(GL_COLOR_BUFFER_BIT);
glfwSwapBuffers(window);
}
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
{
if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
glfwSetWindowShouldClose(window, GL_TRUE);
}
int main()
{
GLFWwindow* window;
int i;
int j;
char* value;
size_t valueSize;
cl_uint platformCount;
cl_platform_id* platforms;
cl_uint deviceCount;
cl_device_id* devices;
cl_uint maxComputeUnits;
cl_context context;
int err;
////////////////////////////////////////////////////////////////////////////////
///////////////////////// Creating OpenGL context... ///////////////////////////
////////////////////////////////////////////////////////////////////////////////
if (glfwInit() != GLFW_TRUE)
{
printf("Unable to initialize GLFW!\n");
glfwTerminate();
exit(EXIT_FAILURE);
}
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_SAMPLES, 4);
window = glfwCreateWindow(800, 600, "Test interop CPP", NULL, NULL);
if (!window)
{
glfwTerminate();
exit(EXIT_FAILURE);
}
glfwMakeContextCurrent(window);
glfwSetWindowRefreshCallback(window, window_refresh_callback);
glfwSetKeyCallback(window, key_callback);
glewExperimental = GL_TRUE;
if (glewInit() != GLEW_OK)
{
printf("Unable to initialize GLEW!\n");
exit(EXIT_FAILURE);
}
////////////////////////////////////////////////////////////////////////////////
///////////////////////// Creating OpenCL context... ///////////////////////////
////////////////////////////////////////////////////////////////////////////////
// get all platforms
clGetPlatformIDs(0, NULL, &platformCount);
platforms = (cl_platform_id*) malloc(sizeof(cl_platform_id) * platformCount);
clGetPlatformIDs(platformCount, platforms, NULL);
for (i = 0; i < platformCount; i++)
{
// print platform name
clGetPlatformInfo(platforms[i], CL_PLATFORM_NAME, 0, NULL, &valueSize);
value = (char*) malloc(valueSize);
clGetPlatformInfo(platforms[i], CL_PLATFORM_NAME, valueSize, value, NULL);
printf("\n%d Platform: %s\n", i + 1, value);
free(value);
// print platform profile
clGetPlatformInfo(platforms[i], CL_PLATFORM_PROFILE, 0, NULL, &valueSize);
value = (char*) malloc(valueSize);
clGetPlatformInfo(platforms[i], CL_PLATFORM_PROFILE, valueSize, value, NULL);
printf(" %d.%d Platform profile: %s\n", i + 1, 1, value);
free(value);
// print platform version
clGetPlatformInfo(platforms[i], CL_PLATFORM_VERSION, 0, NULL, &valueSize);
value = (char*) malloc(valueSize);
clGetPlatformInfo(platforms[i], CL_PLATFORM_VERSION, valueSize, value, NULL);
printf(" %d.%d Platform version: %s\n", i + 1, 2, value);
free(value);
// print platform vendor
clGetPlatformInfo(platforms[i], CL_PLATFORM_VENDOR, 0, NULL, &valueSize);
value = (char*) malloc(valueSize);
clGetPlatformInfo(platforms[i], CL_PLATFORM_VENDOR, valueSize, value, NULL);
printf(" %d.%d Platform vendor: %s\n", i + 1, 3, value);
free(value);
// print platform extensions
clGetPlatformInfo(platforms[i], CL_PLATFORM_EXTENSIONS, 0, NULL, &valueSize);
value = (char*) malloc(valueSize);
clGetPlatformInfo(platforms[i], CL_PLATFORM_EXTENSIONS, valueSize, value, NULL);
printf(" %d.%d Platform extensions: %s\n", i + 1, 4, value);
free(value);
// get all devices
clGetDeviceIDs(platforms[i], CL_DEVICE_TYPE_ALL, 0, NULL, &deviceCount);
devices = (cl_device_id*) malloc(sizeof(cl_device_id) * deviceCount);
clGetDeviceIDs(platforms[i], CL_DEVICE_TYPE_ALL, deviceCount, devices, NULL);
// for each device print critical attributes
for (j = 0; j < deviceCount; j++)
{
// print device name
clGetDeviceInfo(devices[j], CL_DEVICE_NAME, 0, NULL, &valueSize);
value = (char*) malloc(valueSize);
clGetDeviceInfo(devices[j], CL_DEVICE_NAME, valueSize, value, NULL);
printf("\n%d.%d Device: %s\n", i + 1, j + 1, value);
free(value);
// print hardware device version
clGetDeviceInfo(devices[j], CL_DEVICE_VERSION, 0, NULL, &valueSize);
value = (char*) malloc(valueSize);
clGetDeviceInfo(devices[j], CL_DEVICE_VERSION, valueSize, value, NULL);
printf(" %d.%d.%d Hardware version: %s\n", i + 1, j + 1, 1, value);
free(value);
// print software driver version
clGetDeviceInfo(devices[j], CL_DRIVER_VERSION, 0, NULL, &valueSize);
value = (char*) malloc(valueSize);
clGetDeviceInfo(devices[j], CL_DRIVER_VERSION, valueSize, value, NULL);
printf(" %d.%d.%d Software version: %s\n", i + 1, j + 1, 2, value);
free(value);
// print c version supported by compiler for device
clGetDeviceInfo(devices[j], CL_DEVICE_OPENCL_C_VERSION, 0, NULL, &valueSize);
value = (char*) malloc(valueSize);
clGetDeviceInfo(devices[j], CL_DEVICE_OPENCL_C_VERSION, valueSize, value, NULL);
printf(" %d.%d.%d OpenCL C version: %s\n", i + 1, j + 1, 3, value);
free(value);
// print parallel compute units
clGetDeviceInfo(devices[j], CL_DEVICE_MAX_COMPUTE_UNITS,
sizeof(maxComputeUnits), &maxComputeUnits, NULL);
printf(" %d.%d.%d Parallel compute units: %d\n", i + 1, j + 1, 4,
maxComputeUnits);
}
}
#ifdef __APPLE__
CGLContextObj kCGLContext = CGLGetCurrentContext();
CGLShareGroupObj kCGLShareGroup = CGLGetShareGroup(kCGLContext);
cl_context_properties properties[] =
{
CL_CONTEXT_PROPERTY_USE_CGL_SHAREGROUP_APPLE,
(cl_context_properties) kCGLShareGroup,
0
};
#endif
#ifdef __linux__
cl_context_properties properties[] =
{
CL_GL_CONTEXT_KHR, (cl_context_properties)glfwGetGLXContext(window),
CL_GLX_DISPLAY_KHR, (cl_context_properties)glfwGetX11Display(),
CL_CONTEXT_PLATFORM, (cl_context_properties)platforms[0],
0
};
#endif
#ifdef __WINDOWS__
cl_context_properties properties[] =
{
CL_GL_CONTEXT_KHR, (cl_context_properties)glfwGetWGLContext(window),
CL_WGL_HDC_KHR, (cl_context_properties)GetDC(glfwGetWin32Window(window)),
CL_CONTEXT_PLATFORM, (cl_context_properties)platforms[0],
0
};
#endif
////////////////////////////////////////////////////////////////////////////////
//////////////////////////// HERE IS THE PROBLEM: //////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// On my Linux machine, this works:
context = clCreateContextFromType(properties, CL_DEVICE_TYPE_GPU, NULL, NULL,
&err);
// On my Mac machine, this works but if I use it in Linux than it crashes with
segmentation fault:
//context = clCreateContext(properties, 1, &devices[1], NULL, NULL, &err);
////////////////////////////////////////////////////////////////////////////////
///////////////////////////// END OF THE PROBLEM: //////////////////////////////
////////////////////////////////////////////////////////////////////////////////
if (!(context))
{
printf("\nError: Failed creating OpenCL-GL shared context!\n");
exit(err);
}
else
{
printf("\nCreated OpenCL-GL shared context!\n");
}
while (!glfwWindowShouldClose(window)) // Looping here until the
window is closed...
{
glClear(GL_COLOR_BUFFER_BIT);
glfwSwapBuffers(window);
glfwPollEvents();
}
glfwDestroyWindow(window);
glfwTerminate();
free(devices);
free(platforms);
return 0;
}
Erik Zorzin
address: Viale Miramare 235, 34136 Trieste - ITALY
phone: (+39) 3291555703
webpage:
http://www.zorzin.com
(sent from my MacBook Air, Erik Zorzin - HOME)
On Thu01 Mar 2018 at 17:15:56, Andreas Kloeckner (lists(a)informa.tiker.net) wrote:
Hi Erik,
From looking at the code, it seems that the C example you point to and
PyOpenCL do equivalent things, at least up to context creation. Could
you perhaps print what the C example passes for the context properties
and compare the numerical values with the ones passed by PyOpenCL?
Andreas
Erik Zorzin - HOME <erik(a)zorzin.com> writes:
I am not a Linux expert, I don't know exactly how
to trace all differences.
I did the following test, which maybe can give you some insights.
I wrote a simple test python script (see attached python file) and made it run on both
my mac laptop (where it works fine) and my other linux computer (where I have problems).
There is one particular instruction (see comments in the Python file) that makes the
script crashing in Linux when executed:
ctx = cl.Context(properties = [(context_properties, platform)] + sharing_properties,
devices = gpus)
In case I modify this instruction this way:
ctx = cl.Context(properties = [(context_properties, platform)], devices = gpus)
then the script works fine in Linux too, but of course I don't have the CL-GL
interop.
I also made my code printing something during the execution.
This is its output when correctly executing on my mac (with the " +
sharing_properties"):
dhcp-107:PythonCLGL Erik$ python simple_test_interop.py
Have GL: True
My platform is: Apple
My GPU is: HD Graphics 5000
My context properties: 4228
My sharing properties: [(268435456, 140680091402240)]
If I run the same script (so, with the " + sharing_properties") on the linux
computer I get:
[cooper@twinpeaks examples]$ python2 simple_test_interop.py
Have GL: True
My platform is: NVIDIA CUDA
My GPU is: GeForce GT 640
My context properties: 4228
My sharing properties: [(8200, 899558088), (8202,
<OpenGL.raw.GLX._types.LP_struct__XDisplay object at 0x7f2391351290>)]
Segmentation fault (core dumped)
Sometimes I see some negative numbers in my sharing properties when on linux:
[cooper@twinpeaks examples]$ python2 simple_test_interop.py
Have GL: True
My platform is: NVIDIA CUDA
My GPU is: GeForce GT 640
My context properties: 4228
My sharing properties: [(8200, -722625272), (8202,
<OpenGL.raw.GLX._types.LP_struct__XDisplay object at 0x7f6ebf0ea290>)]
Segmentation fault (core dumped)
However, if I remove the " + sharing_properties" from my code what I get on
linux is:
[cooper@twinpeaks examples]$ python2 simple_test_interop.py
Have GL: True
My platform is: NVIDIA CUDA
My GPU is: GeForce GT 640
My context properties: 4228
My sharing properties: [(8200, 710605096), (8202,
<OpenGL.raw.GLX._types.LP_struct__XDisplay object at 0x7f920f08a290>)]
Also, under this condition, I sometimes see some negative numbers in my sharing
properties:
[cooper@twinpeaks examples]$ python2 simple_test_interop.py
Have GL: True
My platform is: NVIDIA CUDA
My GPU is: GeForce GT 640
My context properties: 4228
My sharing properties: [(8200, -173530072), (8202,
<OpenGL.raw.GLX._types.LP_struct__XDisplay object at 0x7f2fb3782290>)]
In the latter two cases, having removed the " + sharing_properties", the code
correctly opens a blank OpenGL window in linux without crashing. Of course I don't
have the CL-GL interop in this case!
As far as I can see from this simple script, the only difference I can notice is the
structure of the output of the instruction:
print "My sharing properties: ", sharing_properties
On my mac it's always something like:
My sharing properties: [(268435456, 140680091402240)]
and never see negative numbers, while on Linux is:
My sharing properties: [(8200, -173530072), (8202,
<OpenGL.raw.GLX._types.LP_struct__XDisplay object at 0x7f2fb3782290>)]
and sometimes the second number in (8200, -173530072) is positive or negative.
My guess is that the function:
get_gl_sharing_context_properties()
behaves differently in case it is executing on a Mac computer or on a Linux computer.
Would this make sense?
Best regards,
Erik
P.S: on my Linux computer python comes in both python 2.X and 3.X versions. For this,
when I installed the system it automatically created the alias python2 for python 2.X.
The linux computer have a fresh installation (basically of 1 week ago, when I assembled
that PC in order to dedicate it as a machine for numerical simulations).
Erik Zorzin
address: Viale Miramare 235, 34136 Trieste - ITALY
phone: (+39) 3291555703
webpage:
http://www.zorzin.com
(sent from my MacBook Air, Erik Zorzin - HOME)
On Thu01 Mar 2018 at 03:02:30, Andreas Kloeckner (lists(a)informa.tiker.net) wrote:
Erik Zorzin - HOME <erik(a)zorzin.com> writes:
Hi,
thank you very mush for helping me!
Please, find information obtained with coredumpctl info as txt file attached to this
email.
I was able to run the interop examples from CUDA-OpenGL, but I was also able to run this:
https://github.com/9prady9/CLGLInterop
So this looks like it's crashing in context creation (which is very
early on). That means the one likely cause is a difference in parameters
passed to clCreateContext. Could you trace through both the C example
and the Python example, find and highlight any differences and report back?
Andreas
from __future__ import absolute_import
from OpenGL.GL import *
from OpenGL.GLUT import *
import pyopencl as cl
from pyopencl.tools import get_gl_sharing_context_properties
import sys
def display():
glClear(GL_COLOR_BUFFER_BIT)
glFlush()
glutInit(sys.argv)
glutInitWindowSize(800, 200)
glutInitWindowPosition(0, 0)
glutCreateWindow('OpenCL/OpenGL simple interop test')
glutDisplayFunc(display)
print "Have GL: ", cl.have_gl()
# Getting platform...
platform = cl.get_platforms()[0]
print "My platform is: ", platform.name
# Getting gpu...
gpus = platform.get_devices(device_type = cl.device_type.GPU)
gpu = gpus[0]
print "My GPU is: ", gpu.name
# Getting properties...
context_properties = cl.context_properties.PLATFORM
print "My context properties: ", context_properties
sharing_properties = get_gl_sharing_context_properties()
print "My sharing properties: ", sharing_properties
# This crashes with segmentation fault errors!
ctx = cl.Context(properties = [(context_properties, platform)] + sharing_properties,
devices = gpus)
# This is OK!
#ctx = cl.Context(properties = [(context_properties, platform)], devices = gpus)
glutMainLoop()