Reputation: 3784
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:
cl_mem
pointers in a global map (something like: filename -> cl_mem
)scale(cl_mem img, int width, int height)
, that calls a kernel and reads the output image data. Then show the scaled images.scale(...)
another time, with the cl_mem
pointers stored in the mapI 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
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