opencl – using image multiple times

huangapple go评论93阅读模式
英文:

opencl - using image multiple times

问题

所以,我想制作一个应用程序,显示一些图像,并且当窗口调整大小时,将所有图像按比例缩放以适应屏幕。
我的策略如下:

  1. 对于每个原始图像,调用clCreateImage并将cl_mem指针存储在全局映射中(类似于:文件名->cl_mem)。
  2. 调用scale(cl_mem img, int width, int height),该函数调用一个内核并读取输出图像数据。然后显示缩放后的图像。
  3. 当窗口调整大小事件发生时:删除所有缩放后的图像,并再次调用scale(...),使用映射中存储的cl_mem指针。

我在小规模上尝试了一下,只创建了一个图像,并调用了两次scale。第一次是正常的,并且进行了缩放,但第二次却损坏了。我不知道为什么,源图像是CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR,输出图像是在scale函数中创建的。

原始图像:https://ibb.co/pQDwScW

第一次缩放(适应300x300):https://ibb.co/nnN9kTY

第二次尝试(适应500x500):https://ibb.co/561SkSn

但是,即使我只尝试300x300,然后再尝试300x300,它也会损坏。
是否有一个规则,即图像不能在内核中多次使用?还是我漏掉了什么?

编辑:

C代码在这里:https://pastebin.com/NpSaxRyT

它是从使用cgo的golang中使用的,因此createImagecl_mem作为void*返回,以便Go部分不需要包含cl.h

init()函数在Go程序启动时调用。createImage函数从Go中使用像素数据调用。

因此,图像指针(cl_mem指针)在Go中,然后调用resizescale)函数。它接受void*指针和缓冲区指针,用于传输像素数据。
缓冲区也是由Go分配的,但是对于第一个图像,它是正常的,我认为垃圾回收没有启动(还尝试禁用了整个垃圾回收)。

示例代码如下:

    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]),
    )
英文:

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]),
    )

答案1

得分: 1

在第一次调整大小操作之后,你正在释放资源。

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

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

200x200 的调整大小操作失败,因为它找不到已释放的 img 组件。

在退出程序之前,所有的 OpenCL 对象都是可重用的。在退出之前,只需按照它们分配的相反顺序释放资源。

如果你在所有任务中只使用相同的内核,你可以只使用一个全局内核对象来处理所有的调整大小调用。只需要重新设置在调用之间发生变化的内核参数,例如输出图像的大小、图像缓冲本身等。

英文:

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.

huangapple
  • 本文由 发表于 2022年2月8日 16:06:26
  • 转载请务必保留本文链接:https://go.coder-hub.com/71030389.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定