OpenCL.jl
OpenCL.jl copied to clipboard
Image support
Thanks for the great OpenCL package, for me it works out of the box on Windows 8.1 (using CUDA) and Ubuntu 14.04 (using Intel OpenCL and the AMD APP SDK).
I have used PyOpenCL before for GPU image processing and a typical code to create a RGBA image buffer on the device using PyOpenCL is this
iform = cl.ImageFormat(cl.channel_order.RGBA, cl.channel_type.UNSIGNED_INT8)
im_buffer = im.tostring()
cl_img = cl.Image(context, cl.mem_flags.READ_ONLY |
cl.mem_flags.COPY_HOST_PTR, iform, self.im.size, None, im_buffer)
I have not had success in trying to load an image onto the device using OpenCL.jl. I can create the image format object using
using Images
import OpenCL
const cl = OpenCL
function load_image(image_pathname)
img = imread(image_pathname)
img = convert(Array, img)
img
end
img = load_image("test.jpg")
device = first(cl.devices())
iform = cl.CL_image_format(cl.CL_RGBA, cl.CL_UNSIGNED_INT8)
But I cannot find an image class as in PyOpenCL.
If it is already supported, can you create a simple example that loads an image onto the device, please?
@nowozin thanks for trying out OpenCL.jl and for the helpful feedback! Image support is coming soon. I actually have a branch with partial image support that you can checkout, although it is unfinished. I stopped working on this after a discussion with @SimonDanisch who is working on OpenGL support for Julia. We agreed that it would be best to try and work out a common OpenCL image / OpenGL buffer datatype that could be shared between the two libraries to avoid needless duplication. This would also help with OpenGL support in OpenCL.jl which is not yet implemented.
@SimonDanisch I know you are busy with other parts of your GSOC project, but do you have some spare cycles to work on this in the near future?
@SimonDanisch let me know if you need some help.
Thanks Valentin, would be cool if we can work all together on this! =) This is part of GSOC for me, as I want to build my 3D visualizations on a solid foundation ;) I must admit, I don't really have a strategy to get all of this done in a nice way. If I look at your code, it seems that you're a lot further than me, so I wonder if you already have some ideas for fusing the types? One thing that I'd begin with is to completely seperate the low level interface to OpenCL/OpenGL and then have some abstraction packages on top of that. This ways it becomes easyer to build up a higher level abstraction layer, which includes our shared types for example.
Hi, @vchuravy These are the calls to create an OpenGL texture:
#Find the correct type of the data
imgType = eltype(data)
if imgType == Uint8
glImgType = GL_UNSIGNED_BYTE
elseif imgType == Float32
glImgType = GL_FLOAT
elseif imgType == Int8
glImgType = GL_BYTE
else
error("Type: $(imgType) not supported")
end
id = glGenTextures()
#Texture type can be GL_TEXTURE_1D, 2D, 3D
glBindTexture(textureType, id)
#setting texture parameters for example:
glTexParameteri(textureType, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE)
#Selecting the right OpenGL function
if textureType == GL_TEXTURE_1D
texImageFunc = glTexImage1D
elseif textureType == GL_TEXTURE_2D
texImageFunc = glTexImage2D
elseif textureType == GL_TEXTURE_3D
texImageFunc = glTexImage3D
else
error("wrong target texture type. valid are: GL_Texture_1D, GL_Texture_2D, GL_Texture_3D")
end
#pixelDataFormat Format can be RGB, GL_RGBA, GL_LUMINANCE, and some more
#Must be provided, or can be inferred from the Image properties
#Same goes for dims, which are: x,[y,[z]], and the number of dims depends on
texImageFunc(textureType, 0, pixelDataFormat, dims..., 0, pixelDataFormat, glImgType, data)
Thanks @SimonDanisch this is helpful. I don't have a computer right now with the necessary OpenCL support to work on this at the moment :-\
I think it would be great to have a motavating example for OpenGL / OpenGL integration. There are cool raytraced 3D Julia set demos that use OpenCL for the computational kernels and OpenGL for the rendering. It would be a nice way to test out the generality of the OpenGL library support you are working on.
@jakebolewski that is a fantastic idea. I started to port the Apple example https://github.com/darcyliu/CocoaSampleCode/tree/master/OpenCL_RayTraced_Quaternion_Julia-Set_Example to Juli. So that I don't have to write the OpenCL code myself.
@SimonDanisch and I are studying at the same university and we are planning to look into this together.
Cool! Can't wait to see what you guys come up with.
Nice! I always wanted to make a raytraced julia-set visualisation with OpenGL =) Tell me when you're ready, or when you need help!
@SimonDanisch https://github.com/vchuravy/qjulia_gpu here you go. The OpenCL code loads and computes.
@jakebolewski Do I see it correctly that we currently don't have clEnqueueReleaseGLObjects and clEnqueueAcquireGLObjects exposed? Also why need a shape of an Image to account for the dimensions of the encoding?
cl.Image{cl.RGBA, Float32}(ctx, :w, shape = (width, height, 1, 1, 1, 1))
I also learned to highly appreciate the ease of OpenCL.jl in comparison to the C code. It took me a while to notice that I could throw most of the original code out since we handle those parts in the library :) :+1:
@vchuravy wow that was fast! Great to see that it requires so little code. You should check out Color.jl to see if any of the color types could work for this example
It does not look like I wrote the OpenCL api stubs. Should not be too hard to add them. It would be great if you could keep Image and OpenGL related changes separate by creating a new OpenGL branch and pulling in related Image changes as you need them.
The shape information is redundant. I think I left it in there for the time being because I was looking at Images.jl and the memory layout was different than what I was expecting so keeping it this way for experimentation allows for more flexiblity. Once we settle on some common datatypes we can get rid of this. Looking at this again, Image should also have a dimension type parameter like array (so Image{RGBA, Float32, 2}). You could then use typealiases to make things a bit shorter (Image2D{RGBA, Float32}, Image3D, etc...).
@jakebolewski Thanks for the input. I am currently stuck on OCL context creation from properties. Especially how the properties list should look like. The code I am working with looks like this
import OpenCL
const cl = OpenCL
//OpenGL Context initialization happens
device = first(cl.devices(:gpu))
platform = cl.info(device, :platform)
currentContext = ccall(("glXGetCurrentContext", "libGL"), Ptr{Void}, ())
currentDisplay = ccall(("glXGetCurrentDisplay", "libGL"), Ptr{Void}, ())
props = [(cl.CL_GL_CONTEXT_KHR, currentContext),
(cl.CL_GLX_DISPLAY_KHR, currentDisplay),
(cl.CL_CONTEXT_PLATFORM, platform)]
const ctx = cl.Context(device, properties = props)
During context creation I get the following error:
ERROR: key not found: -1000
in CLError at /home/wallnuss/.julia/v0.3/OpenCL/src/error.jl:159
in Context at /home/wallnuss/.julia/v0.3/OpenCL/src/context.jl:75
in Context at /home/wallnuss/.julia/v0.3/OpenCL/src/context.jl:81
in include_from_node1 at ./loading.jl:128
while loading /home/wallnuss/src/experiments_in_julia/qjulia_gpu/qjulia.jl, in expression starting
on line 42
When I remove CL_GL_CONTEXT_KHR and CL_GLX_DISPLAY the error goes away. So I am wondering it cl._parse_properties is doing the right thing for those properties.
println(props) = (Uint32,Any)[(0x00002008,Ptr{Void} @0x0000000005b1e510),(0x0000200a,Ptr{Void} @0x000000000a805130),(0x00001084,OpenCL.Platform('NVIDIA CUDA' @0x000000000129ee30))]
println(cl._parse_properties(props)) = Uint64[8200,95544592,8202,176181552,4228,19525168,0]
Any Ideas?
One potential issue that CL_context_properties is define in the specificatiosn as intptr_t but we define it as Csize_t. As far as I know inptr should be a platform debended Integer and Csize_t is a platform depended UInteger
Update: first version is working for windows!
@SimonDanisch :clap:
@vchuravy were you able to figure out the original problem? I pushed the changes you mentioned and cleaned up a the context properties in a branch https://github.com/JuliaGPU/OpenCL.jl/tree/jcb/fixglctx.
@jakebolewski Great work with jcb/fixglctx context creation works as expected. :) But when I wan the properties back from the context with cl.properties(ctx) I get nothing useful. props``` in the properties methods contains[0,9870096,9870096,9870096,0,4294967296,0,0]instead of[0,8200,171244208,8202,168761248,4228,178407648,0]````
Below is the smallest test I could come up with.
using OpenCL; const cl = OpenCL
device = first(cl.devices())
props = [(cl.CL_CONTEXT_PLATFORM, cl.info(device, :platform))]
ctx = cl.Context(device, properties = props)
println(props)
println(cl._parse_properties(props))
println(cl.properties(ctx))
@SimonDanisch I currently get a SIGSEV on cl.api.clCreateFromGLTexture2D but Texture creation works.
Well, as long as things are not set up correctly, a SIGSEV doesn't surprise me;)
It doesn't really make sense to investigate it, before the rest works.
But there's also a chance, that you need to create the function pointer for clCreateFromGLTexture2D with clGetExtensionFunctionAddressForPlatform.
I've already written that code, but didn't use it, as it worked fine for me without it:
const clCreateFromGLTexture_PTR = cl.api.clGetExtensionFunctionAddressForPlatform(platform.id, "clCreateFromGLTexture")
function clCreateFromGLTexture(context, flags, texture_target, miplevel, texture, errcode_ret)
ccall(clCreateFromGLTexture_PTR, cl.CL_mem, (cl.CL_context, cl.CL_mem_flags, Cuint, Cint, Cuint, Ptr{cl.CL_int}), context, flags, texture_target, miplevel, texture, errcode_ret)
end
@SimonDanisch I will look into that @jakebolewski Please take a look at https://github.com/JuliaGPU/OpenCL.jl/tree/vc/fixglctx I think I found the problem with properties parsing
I finally found what error: -1000 means CL_INVALID_GL_SHAREGROUP_REFERENCE_KHR :)
So probably the problem is not the way we currently do things but me using a NVIDIA Optimus chipset as OpenCL target and the Intel Chipset as OpenGl target... So I would need someone with a sane Linux laptop to test it for me :)
@vchuravy looks good to me. Could you make a pull request? I just have some minor comments to make, but that is easier to do inline. You should have full commit access now if you accepted membership to JuliaGPU so you should push these changes to a branch in the main repo.
Can you use Intel's OpenCL implementation with your chipset?
@jakebolewski Thanks for that :) PRs are in with #32 and #33
Intel OpenCL CPU implementation doesn't support the necessary extensions and I only have a HD3000 as integrated chipset so no luck for me there.
Hi all,
just curious, as GSOC has ended, is there working image support now in OpenCL.jl?
Thanks, Sebastian
Sadly, that wasn't in the scope of GSOC. But we're working on it!
Hi,
thanks for all your work so far. Since some time has passed, is an Image type still on the radar? (This is most useful for fast hardware-assisted linear interpolation as doing so manually without using the GPU texture units is significantly slower.)
Thanks for considering, Sebastian
@nowozin I have not been doing a lot of work in OpenCL recently (and I believe Jake is in a similar situation), so development of OpenCL.jl has been stagnant. I am planning to make sure that it works under Julia v0.4 (as soon as development for that has settled down), but otherwise I have no plans on working on big features in the foreseeable future.
If you are willing you are willing to offer help that would be most welcome.
I'm also interested in hardware interpolation of images (as seen here in PyOpenCL), but I'm not sure where to start. Has anyone taken a crack at this yet?
Not that I know of, but now that GPU support in Julia seems to be spectacular (and still getting better), I'm excited about this. But I'm not qualified to advise you how to start. Maybe https://github.com/JuliaGPU/GPUShowcases.jl would offer some useful clues? My impression is that this doesn't need to be OpenCL-specific, that the Julia infrastructure can support multiple backends.
@SimonDanisch last worked on supporting the OpenCL definition of images, but I don't think any of the attempts ever got to a point. I would be excited to see if we can make Images.jl and OpenCL.jl play nicely with each other.
This issue dates back to 2014 and it seems that the discussion got mixed between OpenCL and OpenGL efforts. I will close the issue as part of house cleaning and an attempt to maintain a lightweight OpenCL.jl package for a recent version of the language.