opencl - 多次使用图像
opencl - using image multiple times
所以我想制作一个显示一些图像的应用程序,当 window 调整大小时,它也会缩放所有图像以适合屏幕。
我的策略是:
- 为每个原始图像调用 clCreateImage 并将
cl_mem
指针存储在全局地图中(类似于:filename -> cl_mem
)
- 调用
scale(cl_mem img, int width, int height)
,调用内核并读取输出图像数据。然后显示缩放后的图像。
- 当 window 调整大小事件发生时:删除所有缩放的图像并再次调用
scale(...)
,cl_mem
指针存储在地图中
我在小规模上尝试过,我只创建了一张图片,然后调用了两次 scale
。第一个是好的并且缩放了,但是第二个是损坏的。不知道为什么,src图片是CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR
,out图片是在scale
函数中创建的
第一次缩放(以适应 300x300):https://ibb.co/nnN9kTY
第二次尝试(适合 500x500):https://ibb.co/561SkSn
但是当我只尝试 300x300 然后又尝试 300x300 时它也被损坏了。
有没有规定,图像不能在内核中多次使用?或者我只是遗漏了什么?
编辑:
C 代码在这里:https://pastebin.com/NpSaxRyT
它是从golang和cgo一起使用的,所以createImage
returns cl_mem
as void*
,所以Go部分不需要包含cl.h
.
init()
函数在 Go 程序启动时被调用。 createImage
使用像素数据从 Go 调用函数。
因此图像指针(cl_mem
指针)在 Go 中,然后调用 resize
(scale
) 函数。它采用将传输像素数据的 void*
指针和缓冲区指针。
缓冲区也是由 Go 分配的,但是第一张图片没问题,我认为 GC 没有启动(也尝试完全禁用 GC)。
像这样:
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]),
)
您在第一次调整大小操作后立即释放
if err := ir.Release(); err != nil {
t.Fatal(err)
}
img2, err := ir.Resize(200, 200)
if err != nil {
t.Fatal(err)
}
并且 200x200 调整大小失败,因为它找不到已发布的 img 组件。
在您退出程序之前,所有 OpenCL 对象都是 re-usable。退出前,别忘了释放 reverse-order 分配的资源。
如果您只对所有任务使用同一个内核,则可以只使用一个全局内核对象来用于所有调整大小调用。它只需要 re-setting 个在调用之间更改的内核参数。例如,更改输出图像的大小、图像缓冲区本身等
所以我想制作一个显示一些图像的应用程序,当 window 调整大小时,它也会缩放所有图像以适合屏幕。 我的策略是:
- 为每个原始图像调用 clCreateImage 并将
cl_mem
指针存储在全局地图中(类似于:filename -> cl_mem
) - 调用
scale(cl_mem img, int width, int height)
,调用内核并读取输出图像数据。然后显示缩放后的图像。 - 当 window 调整大小事件发生时:删除所有缩放的图像并再次调用
scale(...)
,cl_mem
指针存储在地图中
我在小规模上尝试过,我只创建了一张图片,然后调用了两次 scale
。第一个是好的并且缩放了,但是第二个是损坏的。不知道为什么,src图片是CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR
,out图片是在scale
函数中创建的
第一次缩放(以适应 300x300):https://ibb.co/nnN9kTY
第二次尝试(适合 500x500):https://ibb.co/561SkSn
但是当我只尝试 300x300 然后又尝试 300x300 时它也被损坏了。 有没有规定,图像不能在内核中多次使用?或者我只是遗漏了什么?
编辑:
C 代码在这里:https://pastebin.com/NpSaxRyT
它是从golang和cgo一起使用的,所以createImage
returns cl_mem
as void*
,所以Go部分不需要包含cl.h
.
init()
函数在 Go 程序启动时被调用。 createImage
使用像素数据从 Go 调用函数。
因此图像指针(cl_mem
指针)在 Go 中,然后调用 resize
(scale
) 函数。它采用将传输像素数据的 void*
指针和缓冲区指针。
缓冲区也是由 Go 分配的,但是第一张图片没问题,我认为 GC 没有启动(也尝试完全禁用 GC)。
像这样:
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]),
)
您在第一次调整大小操作后立即释放
if err := ir.Release(); err != nil {
t.Fatal(err)
}
img2, err := ir.Resize(200, 200)
if err != nil {
t.Fatal(err)
}
并且 200x200 调整大小失败,因为它找不到已发布的 img 组件。
在您退出程序之前,所有 OpenCL 对象都是 re-usable。退出前,别忘了释放 reverse-order 分配的资源。
如果您只对所有任务使用同一个内核,则可以只使用一个全局内核对象来用于所有调整大小调用。它只需要 re-setting 个在调用之间更改的内核参数。例如,更改输出图像的大小、图像缓冲区本身等