0

I've written an OpenCL-kernel (JOCL) which takes a few hundred megabytes of input data and produces a viewport-friendly RGB-Image as result. This image shall be presented in an SWT-GUI with a refresh rate of about at least 10 fps to allow realtime interaction (panning, zooming, gamma, etc.).

I came up with a solution that works but doesn't feel optimal:

  1. create a byte[]-array in Java as frame buffer (ABGR)
  2. wrap the byte[]-array by a CL-buffer
  3. create an ImageData to wrap the byte[]-array
  4. pass the CL-buffer to the OpenCL-kernel as argument
  5. for each frame update, repeat:
    1. call the OpenCL-kernel to populate the byte[]-array
    2. create a new Image based on the ImageData-object
    3. draw the image to some Canvas
    4. Canvas.redraw()

What I don't like about this solution is:

  • I assume the byte[]-array will be copied and converted to the target's layout in order to draw the image within the canvas. Both could be omitted if I knew the memory location and layout of the frame buffer.
  • I believe the Canvas' internal frame buffer resides in the host's memory. So after all it has to be copied back into the graphics card's memory.
  • I'd like to use ByteBuffer.allocateDirect() rather than allocating the byte[]-array within the JVM's memory, but I can't construct an ImageData-object based thereon, as a backing array is optional. (Ok, I might use a try-or-fallback-approach.)
  • ImageData accepts a maximum of 8 bits per channel (I didn't find this explicitly mentioned in the documentation, but in the source code). I'd like to produce 10 bits per channel (10:10:10) as result for machines that are capable of handling them.

How can I reduce the number of memory copies and conversions?

I'm not afraid of implementing several platform-/device-specific memory layouts within the kernel. I still have my currently working implementation as fallback for some weird cases and less common platforms.

I know there's a GLCanvas that can be used for a more direct access for implementations using OpenGL (like JOGL), but I don't like the idea of depending on and bundling OpenGL with my project, just to accelerate the framebuffer writes.

Update: I think I have to use OpenGL to glue those parts together: the garbage collector kills my byte[]-array every now and then, which results in a crash of the whole JVM. Yet another copy (direct buffer -> byte[]-array) would solve this problem, which is inacceptable.

It seems to be impossible to adapt the existing implementation of GLCanvas to communicate with OpenCL as it lacks a system to communicate with a window system. OpenGL in contrast provides such an integration.

Kai Giebeler
  • 517
  • 6
  • 12
  • You haven't really asked a specific question here. In my opinion SWT is not suited to high performance code like this at all. – greg-449 Jun 03 '16 at 12:54
  • Right, thanks. I updated the question. // High performance is possible when using OpenGL in SWT. – Kai Giebeler Jun 03 '16 at 13:49
  • 1
    If high performance is possible when using OpenGL in SWT then use OpenCL/OpenGL interop to get an OpenCL image as an OpenGL texture and then use it in SWT. – Dithermaster Jun 04 '16 at 03:22
  • A mentioned in the opening I wanted to avoid the additional complexity of OpenGL just to glue those parts together but now I think I have to go this way (see update) – Kai Giebeler Jun 05 '16 at 00:48
  • After having another look at this, one of the largest problems for the "frequent updates" seems to be that there is no possibility to update an SWT image. At all. (At least, I did not find one). Disposing each frame image and creating a new one would seem odd for me. In fact, even though it would seem like a kludge at the first glance: Using the `SWT_AWT` bridge to use an AWT (!) `Canvas` to display a `BufferedImage` (which can easily be updated in various ways) might be an option as well. Alternatively, the option of using LWJGL to just display the image should work, too. – Marco13 Jun 06 '16 at 10:12

0 Answers0