1

I am interested in writing a real-time ray tracing application in c++ and I heard that using OpenCL-OpenGL interoperability is a good way to do this (to make good use of the GPU), so I have started writing a c++ project using this interoperability and using GLFW for window management. I should mention that although I have some coding experience, I do not have so much in c++ and have not worked with OpenCL or OpenGL before attempting this project, so I would appreciate it if answers are given with this in mind (that is, beginner-friendly terminology is preferred).

So far I have been able to get OpenCL-OpenGL interoperability working with an example using a vertex buffer object. I have also demonstrated that I can create image data with an RGBA array (at least on the CPU), send this to an OpenGL texture with glTexImage2D() and display it using glBlitFramebuffer().

My problem is that I don't know how to create an OpenCL kernel that is able to calculate pixel data such that it can be given as the data parameter in glTexImage2D(). I understand that to use the interoperability, we must first create OpenGL objects and then create OpenCL objects from these to write the data on as these objects share memory, so I am assuming I must first create an empty OpenGL array object then create an OpenCL array object from this to apply an appropriate kernel to which would write the pixel data before using the OpenGL array object as the data parameter in glTexImage2D(), but I am not sure what kind of object to use and have not seen any examples demonstrating this. A simple example showing how OpenCL can create pixel data for an OpenGL texture image (assuming a valid OpenCL-OpenGL context) would be much appreciated. Please do not leave any line out as I might not be able to fill in the blanks!

It's also very possible that the method I described above for implementing a ray tracer is not possible or at least not recommended, so if this is the case please outline an advised alternate method for sending OpenCL kernel calculated pixel data to OpenGL and subsequently drawing this to the screen. The answer to this similar question does not go into enough detail for me and the CL/GL interop link is not working. The answer mentions that this can be achieved using a renderbuffer rather than a texture, but it says at the bottom of the Khronos OpenGL wiki for Renderbuffer Objects that the only way to send pixel data to them is via pixel transfer operations but I can not find any straightforward explanation for how to initialize data this way.

Note that I am using OpenCL c (no c++ bindings).

Joe
  • 13
  • 2
  • What about these links? [One](https://stackoverflow.com/questions/38087119/problems-with-opencl-opengl-texture-interop-windows), [two](https://stackoverflow.com/questions/13891981/opengl-opencl-interop-opencl-rendering-to-texture-trouble), [three](https://web.engr.oregonstate.edu/~mjb/cs575/Handouts/opencl.opengl.rendertexture.2pp.pdf) – Alexey S. Larionov May 24 '22 at 21:49
  • As far as I can tell these are two vaguely similar questions with large blocks of code and a powerpoint without accompanying presentation which is hard to read. As mentioned I am only a beginner for this stuff. I need something which answers my question more directly. – Joe May 24 '22 at 22:04
  • Not sure if it is of any use, but here is a raytracer written in the [fragment shader](https://stackoverflow.com/a/70131254/9238288). – jackw11111 May 25 '22 at 02:36
  • This is not exactly what I asked for but it looks like a great example. I will try doing this if I end up giving up on the OpenCL-OpenGL interop method. Thanks. – Joe May 25 '22 at 07:59

1 Answers1

0

From your second para you are creating an OpenCL context with a platform specific combination of GLX_DISPLAY / WGL_HDC and GL_CONTEXT properties to interoperate with OpenGL, and you can create a vertex buffer object that can be read/written as necessary by both OpenGL and OpenCL.

That's most of the work. In OpenGL you can copy any VBO into a texture with

glBindBuffer(GL_PIXEL_UNPACK_BUFER, myVBO);
glTexSubImage2D(GL_TEXTURE_2D, level, x, y, width, height, format, size, NULL);

with the NULL at the end meaning to copy from GPU memory (the unpack buffer) rather than CPU memory.

As with copying from regular CPU memory, you might also need to change the pixel alignment if it isn't 32 bit.

Hugh Fisher
  • 2,321
  • 13
  • 8
  • Thank you very much this looks promising. Unfortunately I only managed to get the OpenGL/OpenCL interoperability working for VBOs of float arrays and I am for some reason having some issues trying to get it working for VBOs of unsigned char arrays. When I get it working I will test your suggestion and accept the answer if it runs well. – Joe May 25 '22 at 07:58
  • This is great! Works like a charm. I should ask though -- I have read about other methods to achieve OpenCL-OpenGL interop rendering (not that I understand them yet). Would the speed/efficiency of this method be comparative to other methods? It seems that for every frame I will need to update the VBO with an OpenCL kernel, then blit this data to the screen but having to pass through a texture first. Would this have much of an impact on speed at all? If so, are there more direct methods that are faster? – Joe May 25 '22 at 08:48
  • Sorry, not at all expert on high performance OpenCL so don't know about more direct methods. I've mostly given up on OpenCL because for my needs GL compute shaders are good enough – Hugh Fisher May 26 '22 at 00:42