microo8
microo8

Reputation: 3784

opencl - using image multiple times

So I want to make a app that shows some images and when the window resizes, it scales also all images to fit on the screen. My strategy is this:

  1. call clCreateImage for every original image and store the cl_mem pointers in a global map (something like: filename -> cl_mem)
  2. call scale(cl_mem img, int width, int height), that calls a kernel and reads the output image data. Then show the scaled images.
  3. when the a window resize event occures: drop all scaled images and call scale(...) another time, with the cl_mem pointers stored in the map

I tried it on a small scale where I just create one image, and call scale two times. The first is OK and scaled, but the second is corrupted. I don't know why, the src image is CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, the out image is created in scale function.

original: https://ibb.co/pQDwScW

first time scaled (to fit in 300x300): https://ibb.co/nnN9kTY

second try (to fit in 500x500): https://ibb.co/561SkSn

But also when I try just 300x300 and then also 300x300 it is corrupted. Is there a rule, that images can't be used in a kernel multiple times? Or im just missing something?

EDIT:

C code is here: https://pastebin.com/NpSaxRyT

It is used from golang with cgo, so the createImage returns the cl_mem as void*, so that the Go part doesn't need to include cl.h.

init() function is called on startup of the Go program. createImage function is called from Go with pixel data.

So the image pointers (cl_mem pointers) are in Go and then the resize (scale) function is called. It takes the void* pointer and buffer pointer where the pixel data will be transfered. Also the buffer is allocated by Go, but with the first image it is OK and I think that the GC doesn't kick in (also tried to disable GC entirely).

like so:

    outData := make([]byte, outWidth*outHeight*ir.pixelSize)
    ret := C.resize(
        cl_mem_img_pointer, //unsafe.Pointer (void*)
        C.int(origWidth),
        C.int(origHeight),
        C.int(outWidth),
        C.int(outHeight),
        C.int(rowPitch),
        C.uint(image_channel_order),
        C.uint(image_channel_data_type),
        unsafe.Pointer(&outData[0]),
    )

Upvotes: 1

Views: 197

Answers (1)

huseyin tugrul buyukisik
huseyin tugrul buyukisik

Reputation: 11920

You are releasing right after the first resize operation

if err := ir.Release(); err != nil {
    t.Fatal(err)
}

img2, err := ir.Resize(200, 200)
if err != nil {
    t.Fatal(err)
}

and the 200x200 resize failes as it can not find the img component that was released.

All of OpenCL objects are re-usable until you exit the program. Before exiting, just don't forget to release the resources in the reverse-order they were allocated.

If you are using only same kernel for all tasks, you can use just one global kernel object to be used for all resize calls. It only needs re-setting kernel arguments which are changed between calls. For example, changing sizes of output image, image buffer itself, etc.

Upvotes: 1

Related Questions