c - OpenCL / OpenGL Interop using GtkGLArea -


i know looks visit when need have question.

building on previous question, ran basic opengl program. i'm adding opencl interop trivial cl script shrinks triangle small amount each time renders.

all i'm getting blank screen. commenting out section acquires , releases gl objects allows rendering work before. fails integrate opencl compnent.

opencl.h header helper functions use register cl objects , free them single function call in end.

edit: 12th june 2015 uncommented /*fprintf(stderr, "error: " x " failed %d\n", cl_stat);*/ line reveals more info:

error: set cl kernel arg failed -38 error: acquiring gl objects failed -5 

the opencl error code -38 means it's invalid memory object according this list followed out of resources error when trying re-acquire gl objects.

here's main.c

#include <stdlib.h> #include <stdio.h> #include <string.h>  #include <glib.h>  #include <gdk/gdkx.h> #include <epoxy/glx.h> #include <epoxy/gl.h> #include <gtk/gtk.h>  #include <cl/opencl.h> #include "cl_utils.h"  #define ignore_var(type, identifier) \ { \   type ignored_variable_abcd = identifier; \   identifier = ignored_variable_abcd; \ }  #define cl_assert(x) \   /*if(print_info) \     printf(x "...\n"); */\   if(cl_stat != cl_success) \   { \     /*fprintf(stderr, "error: " x " failed %d\n", cl_stat);*/ \     goto exception; \   }  const glchar *vert_src = "\n" \ "#version 330                                  \n" \ "#extension gl_arb_explicit_attrib_location: enable  \n" \ "                                              \n" \ "layout(location = 0) in vec2 in_position;     \n" \ "                                              \n" \ "void main()                                   \n" \ "{                                             \n" \ "  gl_position = vec4(in_position, 0.0, 1.0);  \n" \ "}                                             \n";  const glchar *frag_src = "\n" \ "void main (void)                              \n" \ "{                                             \n" \ "  gl_fragcolor = vec4(1.0, 1.0, 1.0, 1.0);    \n" \ "}                                             \n";  const char *cl_src = "\n" \ "typedef struct point{                         \n" \ "  float x;                                    \n" \ "  float y;                                    \n" \ "} point;                                      \n" \ "                                              \n" \ "__kernel void cl_func(__global point* point)  \n" \ "{                                             \n" \ "  const int = get_global_id(0);             \n" \ "  const float d = 0.99;                       \n" \ "                                              \n" \ "  if(i>=3)                                    \n" \ "    return;                                   \n" \ "                                              \n" \ "  point[i].x = point[i].x * d;                \n" \ "  point[i].y = point[i].y * d;                \n" \ "}                                             \n";  struct cl {   clu_object_stack* stack;    cl_platform_id* platform;   cl_uint num_platforms;    cl_device_id* device;   cl_uint num_devices;    cl_context context;   cl_context_properties properties[7];    cl_command_queue queue;    cl_program program;   cl_kernel kernel;    cl_mem buffer; } cl;  struct cl cl;  gluint gl_vao, gl_buffer, gl_program;  cl_int init_cl(gtkglarea *area) {   cl_int cl_stat;    cl.stack = clucreateobjectstack(44);    cl_stat = clgetplatformids(0, null, &cl.num_platforms);   cl_assert("got number of platforms");    cl.platform = malloc((size_t)cl.num_platforms * sizeof(cl_platform_id));   cl_stat = clgetplatformids(cl.num_platforms, cl.platform, null);   cl_assert("got platforms");    cl_stat = clgetdeviceids(cl.platform[0], cl_device_type_gpu, 0, null, &cl.num_devices);   cl_assert("got number of devices");   printf("number of gpu devices: %d\n", cl.num_devices);    if(cl.num_devices == 0)   {     fprintf(stderr, "num devices cannot 0\n");     goto exception;   }    cl.device = malloc((size_t)cl.num_devices * sizeof(cl_device_id));   cl_stat = clgetdeviceids(cl.platform[0], cl_device_type_gpu, cl.num_devices, cl.device, null);   cl_assert("got devices");    if(cl.device == null)   {     fprintf(stderr, "devices list null\n");     goto exception;   }    gtk_gl_area_make_current (area);   cl.properties[0] = cl_gl_context_khr;   cl.properties[1] = (cl_context_properties) glxgetcurrentcontext();   cl.properties[2] = cl_glx_display_khr;   cl.properties[3] = (cl_context_properties) glxgetcurrentdisplay();   cl.properties[4] = cl_context_platform;   cl.properties[5] = (cl_context_properties) cl.platform[0];   cl.properties[6] = 0;    cl.context = clucreatecontext(cl.stack, cl.properties, cl.num_devices, cl.device, null, null, &cl_stat);   cl_assert("created cl context");    cl.queue = clucreatecommandqueue(cl.stack, cl.context, cl.device[0], 0, &cl_stat);   cl_assert("created command queue");    cl.buffer = clucreatefromglbuffer(cl.stack, cl.context, cl_mem_write_only, gl_buffer, null);   cl_assert("created cl memory object gl buffer");    cl.program = clucreateprogramwithsource(cl.stack, cl.context, 1, (const char **)&cl_src, null, &cl_stat);   cl_assert("created cl program object");    cl_stat = clbuildprogram(cl.program, cl.num_devices, cl.device, null, null, null);   if(cl_stat != cl_success)   {     size_t ret_size;     clgetprogrambuildinfo(cl.program, cl.device[0], cl_program_build_log, 0, null, &ret_size);     char e_str[ret_size];     clgetprogrambuildinfo(cl.program, cl.device[0], cl_program_build_log, ret_size, e_str, &ret_size);     printf("%s\n", e_str);   }   cl_assert("built cl program object");    cl.kernel = clucreatekernel(cl.stack, cl.program, "cl_func", &cl_stat);   cl_assert("created cl kernel object");    return 0; exception:   return 1; }  static gboolean realise(gtkglarea *area, gdkglcontext *context); static gboolean render(gtkglarea *area, gdkglcontext *context);  int main(int argc, char** argv) {   gtk_init(&argc, &argv);    gtkwidget *window  = gtk_window_new(gtk_window_toplevel),             *gl_area = gtk_gl_area_new();    g_signal_connect(window,  "delete-event", g_callback(gtk_main_quit), null);   g_signal_connect(gl_area, "realize",      g_callback(realise),       null);   g_signal_connect(gl_area, "render",       g_callback(render),        null);    gtk_container_add(gtk_container(window), gl_area);    gtk_widget_show_all(window);    gtk_main();    clufreeobjectstack(cl.stack);   free(cl.platform);   free(cl.device);    return 0; }  static gboolean realise(gtkglarea *area, gdkglcontext *context) {   ignore_var(gdkglcontext*, context);    gtk_gl_area_make_current(gtk_gl_area(area));   if (gtk_gl_area_get_error (gtk_gl_area(area)) != null)   {     printf("failed initialiize buffers\n");     return false;   }    glfloat verts[] =    {     +0.0f, +1.0f,     -1.0f, -1.0f,     +1.0f, -1.0f,   };    gluint frag_shader, vert_shader;   frag_shader = glcreateshader(gl_fragment_shader);   vert_shader = glcreateshader(gl_vertex_shader);    glshadersource(frag_shader, 1, &frag_src, null);   glshadersource(vert_shader, 1, &vert_src, null);    glcompileshader(frag_shader);   glcompileshader(vert_shader);    gl_program = glcreateprogram();   glattachshader(gl_program, frag_shader);   glattachshader(gl_program, vert_shader);   gllinkprogram(gl_program);    glgenbuffers(1, &gl_buffer);   glbindbuffer(gl_array_buffer, gl_buffer);   glbufferdata(gl_array_buffer, sizeof(verts), verts, gl_dynamic_draw);    glgenvertexarrays(1, &gl_vao);   glbindvertexarray(gl_vao);    glenablevertexattribarray(0);   glvertexattribpointer(0, 2, gl_float, gl_false, 0, (void*)0);   glbindvertexarray(0);    //gldeletebuffers(1, &gl_buffer);   if(init_cl(area))     return false;    return true; }  static gboolean render(gtkglarea *area, gdkglcontext *context) {   ignore_var(gdkglcontext*, context);   ignore_var(gtkglarea*, area);   cl_int cl_stat;    glclear(gl_color_buffer_bit | gl_depth_buffer_bit);   glclearcolor(0.0, 0.0, 0.0, 1.0);    gluseprogram(gl_program);   glbindvertexarray(gl_vao);   gldrawarrays(gl_triangles, 0, 3);    glbindvertexarray (0);   gluseprogram (0);    glfinish();    cl_stat = clenqueueacquireglobjects(cl.queue, 1, &cl.buffer, 0, null, null);   cl_assert("acquiring gl objects");    cl_stat = clsetkernelarg(cl.kernel, 0, sizeof(cl_mem), (const void*)cl.buffer);   cl_assert("set cl kernel arg");    //size_t g_sz[1] = { 32 };   //cl_stat = clenqueuendrangekernel(cl.queue, cl.kernel, 1, null, g_sz, null, 0, null, null);   cl_stat = clenqueuetask(cl.queue, cl.kernel, 0, null, null);   cl_assert("executing cl kernel");   cl_stat = clenqueuereleaseglobjects(cl.queue, 1, &cl.buffer, 0, null, null);   cl_assert("releasing gl buffer");   clfinish(cl.queue);    return true;  exception:   return false; } 

the sconstruct

import os  cflags = '--std=c11 -g -wall' env = {'path':os.environ['path']}  env = environment(cflags=cflags, env=env)  if os.name 'posix':   env['env']['term'] = os.environ['term']   env.parseconfig('pkg-config --cflags --libs gtk+-3.0')   env.append(libs = ['epoxy', 'gl', 'opencl'])   env.program(target='gl', source=['main.c', 'cl_utils.c'])  # vim: set filetype=python: 

cl_utils.c

#include <stdlib.h> #include <stdio.h>  #include "cl_utils.h"  #define func __func__  #define cl_assert(object, label) \   if(!object) \   { \     fprintf(stderr, "cl_error: failed create cl %s object: %d\n", #object, *cl_stat); \     goto label; \   } \   else \   { \     printf("cl_info: created cl_%s object\n", #object); \   }  #define platform_info(_) \     _(profile) \     _(version) \     _(name) \     _(vendor) \     _(extensions)  const char* space = " ";  #define to_string(type, enum, ...) [enum] = #type, const char* clu_type_string[] = { clu_table(to_string) }; #undef to_string  #define to_string(x) [cl_platform_##x] = #x,  const char* platform_info_string[] = { platform_info(to_string) }; #undef to_string  const char* clgetplatforminfostring(cl_platform_info platform_info) {     return platform_info_string[platform_info]; }  cl_int infoplatforms(cl_platform_id* platforms, cl_int num_platforms, cl_platform_info* params, cl_int num_params) {     cl_int cl_stat;     size_t buffer_size = 10, buffer_ret_size = 0;     char* buffer = (char*)malloc(buffer_size);      for(cl_int = 0; < num_platforms; i++)     {         for(cl_int j = 0; j < num_params; j++)         {             cl_stat = clgetplatforminfo(platforms[i], params[j], 0, null, &buffer_ret_size);              if(cl_stat != cl_success)             {                 fprintf(stderr, "error: clgetplatforminfo failed\n");                 goto end;             }              if(buffer_ret_size > buffer_size)             {                 void* tmp = null;                 buffer_size = buffer_ret_size;                 tmp = realloc(buffer, buffer_size);                 if(tmp == null)                 {                     fprintf(stderr, "error: not realloc memory\n");                     perror("error: ");                     goto end;                 }                 else                     buffer = (char*)tmp;             }              cl_stat = clgetplatforminfo(platforms[i], params[j], buffer_size, buffer, &buffer_ret_size);              if(cl_stat != cl_success)             {                 fprintf(stderr, "error: clgetplatforminfo failed\n");                 goto end;             }              printf("%s: %s\n", clgetplatforminfostring(params[j]), buffer);         }         printf("\n");     }  end:     if(cl_stat != cl_success)     {         printf("sent error handler!\n");         printf("cl_error: %d\n", cl_stat);     }      free(buffer);      if(cl_stat != cl_success)         return 1;          return 0; }  clu_object_stack* clucreateobjectstack(int init_len) {   clu_object_stack* stack = (clu_object_stack*)malloc(sizeof(clu_object_stack));   stack->length = init_len;   stack->num_objects = 0;   stack->list = (clu_object*)malloc(sizeof(clu_object) * init_len);    return stack; }  void clufreeobjectstack(clu_object_stack* stack) {   cl_int ret = cl_success;    printf("freeing stack: %p\n", stack);   int i;   for(i=stack->num_objects-1; i>=0; i--)   {     switch(stack->list[i].type)     {       #define to_free(cl_type, enum, element, clurelease) \       case enum: \         ret = clurelease(stack->list[i].element); \         /*printf("releasing " #cl_type "\n");*/ \         break;        clu_table(to_free)       #undef to_free        default:         printf("error: invalid or unsupported object type\n");         break;     }      if(ret != cl_success)     {       printf("failed release %s\n", clu_type_string[stack->list[i].type]);     }   }   free(stack->list);   free(stack); }  int cluassigntoobjectgroup(struct clu_object_stack* stack, void* obj, cl_type type) {   if(stack->num_objects >= stack->length)   {     printf("stack error\n");     return -1;   }    stack->list[stack->num_objects].type = type;    switch(type)   {     #define to_assign(cl_type, enum, element, ...) \       case enum: \         stack->list[stack->num_objects].element=*(cl_type*)obj; \         /*printf("assigning " #cl_type "\n");*/ \         break;      clu_table(to_assign)     #undef to_assign      default:       printf("cluassigntoobjectgroup failed\n");       break;   }    stack->num_objects++;    return 0; }  cl_context clucreatecontext(     clu_object_stack *stack,     cl_context_properties *properties,     cl_uint num_devices,     const cl_device_id *devices,     pfn_notify func,     void *user_data,     cl_int* cl_stat) {    cl_context context= clcreatecontext(properties, num_devices, devices, func, user_data, cl_stat);    if(context == 0)     printf("created 0 value cl context\n");   cl_assert(context, error_ret);   cluassigntoobjectgroup(stack, &context, clu_context);  error_ret:   if(devices == null)     fprintf(stderr, "%2sdevices cannot null\n", space);   if(num_devices == 0)     fprintf(stderr, "%2snum_devices cannot zero\n", space);   if((func == null) && (user_data != null))     fprintf(stderr, "%2spfn_notify cannot null when user_data not null\n", space);    return context; }  cl_command_queue clucreatecommandqueue(     clu_object_stack *stack,     cl_context context,     cl_device_id device,     cl_command_queue_properties properties,     cl_int *cl_stat) {   cl_command_queue queue = clcreatecommandqueue(context, device, properties, cl_stat);    cl_assert(queue, error_ret);   cluassigntoobjectgroup(stack, &queue, clu_command_queue);  error_ret:   return queue; }  cl_mem clucreatebuffer(     clu_object_stack* stack,     cl_context context,     cl_mem_flags flags,     size_t size,     void *host_ptr,     cl_int *cl_stat) {   cl_mem buffer = clcreatebuffer(context, flags, size, host_ptr, cl_stat);    cl_assert(buffer, error_ret);   cluassigntoobjectgroup(stack, &buffer, clu_mem_object);  error_ret:   return buffer; }  cl_program clucreateprogramwithsource(     clu_object_stack* stack,      cl_context context,     cl_uint count,     const char **strings,     const size_t *lengths,     cl_int *cl_stat) {   cl_program program = clcreateprogramwithsource(context, count, strings, lengths, cl_stat);    cl_assert(program, error_ret);   cluassigntoobjectgroup(stack, &program, clu_program);  error_ret:   return program; }  cl_kernel clucreatekernel(     clu_object_stack* stack,     cl_program  program,     const char *kernel_name,     cl_int *cl_stat) {   cl_kernel kernel = clcreatekernel(program, kernel_name, cl_stat);    cl_assert(kernel, error_ret);   cluassigntoobjectgroup(stack, &kernel, clu_kernel);  error_ret:   return kernel; }  cl_mem clucreatefromglbuffer(     clu_object_stack* stack,     cl_context context,     cl_mem_flags flags,     gluint bufobj,     cl_int* cl_stat) {   cl_mem gl_buffer = clcreatefromglbuffer(context, flags, bufobj, cl_stat);    cl_assert(gl_buffer, error_ret);   cluassigntoobjectgroup(stack, &gl_buffer, clu_mem_object);  error_ret:   return gl_buffer; } 

cl_utils.h

#ifndef __cl_utils_h__ #define __cl_utils_h__  #ifdef __cplusplus extern "c" { #endif /* c++ */  #include <stdarg.h>  #if defined(__apple__) || defined(macosx) #include <opencl/opencl.h> #else #include <cl/opencl.h> #endif  #include <epoxy/gl.h>  #define clu_table(_) \   _(cl_context, clu_context, context, clreleasecontext) \   _(cl_command_queue, clu_command_queue, queue, clreleasecommandqueue) \   _(cl_mem,clu_mem_object, mem_object, clreleasememobject) \   _(cl_program, clu_program, program, clreleaseprogram) \   _(cl_kernel, clu_kernel, kernel, clreleasekernel)  #define to_enum(cl_type, enum, ...) enum, typedef enum cl_type{   clu_table(to_enum) } cl_type; #undef to_enum  typedef void (*pfn_notify)(const char *errinfo, const void *private_info, size_t cb, void *user_data);  //extern const char* clu_type_string[];  typedef struct clu_object clu_object;  struct clu_object{   cl_type type;   union{     cl_context context;     cl_command_queue queue;     cl_mem mem_object;     cl_program program;     cl_kernel kernel;   }; };  typedef struct clu_object_stack{   struct clu_object* list;   int num_objects;   int length; } clu_object_stack;  const char* clgetplatforminfostring(cl_platform_info platform_info); int infoplatforms(cl_platform_id* platforms, cl_int num_platforms, cl_platform_info* params, cl_int num_params);  clu_object_stack* clucreateobjectstack(int init_len); void clufreeobjectstack(clu_object_stack* stack);  int cluassigntoobjectgroup(struct clu_object_stack* stack, void* obj, cl_type type);  cl_context clucreatecontext(     clu_object_stack *stack,     cl_context_properties *properties,     cl_uint num_devices,     const cl_device_id *devices,     pfn_notify func,     void *user_data,     cl_int* cl_stat);  cl_command_queue clucreatecommandqueue(     clu_object_stack* stack,     cl_context context,     cl_device_id device,     cl_command_queue_properties properties,     cl_int *cl_stat);  cl_mem clucreatebuffer(     clu_object_stack* stack,     cl_context context,     cl_mem_flags flags,     size_t size,     void *host_ptr,     cl_int * cl_stat);  cl_program clucreateprogramwithsource(     clu_object_stack* stack,      cl_context context,     cl_uint count,     const char **strings,     const size_t *lengths,     cl_int *cl_stat);  cl_kernel clucreatekernel(     clu_object_stack* stack,     cl_program  program,     const char *kernel_name,     cl_int *cl_stat);  cl_mem clucreatefromglbuffer(     clu_object_stack* stack,     cl_context context,     cl_mem_flags flags,     gluint bufobj,     cl_int* cl_stat);  #ifdef __cplusplus } #endif /* c++ */  #endif /* __cl_utils_h__ */ 

to enable cl-gl interoperability, things have set in specific order:

 1. create opengl context  2. create opencl context  3. create opengl buffers  4. start opengl rendering 

one possible issue create opengl buffers before opencl context (before call init_cl).


Comments

Popular posts from this blog

python - TypeError: start must be a integer -

c# - DevExpress RepositoryItemComboBox BackColor property ignored -

django - Creating multiple model instances in DRF3 -