【问题标题】:Creating OpenCL memory object from OpenGL ES mipmaps从 OpenGL ES mipmaps 创建 OpenCL 内存对象
【发布时间】:2014-05-12 15:35:38
【问题描述】:

我的 android 应用程序将 OpenGL texture2D 传递给我的 OpenCL 内核,但是当我将 clCreateFromGLTexture2D() 与 mipmap 级别 1 一起使用时,我得到 CL_INVALID_MIPLEVEL。

我正在创建我的 OpenGL 纹理并像这样生成 mipmap:

    GLES20.glGenTextures ( 2, targetTex, 0 );
    GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, targetTex[0]);
    GLES20.glGenerateMipmap(GLES20.GL_TEXTURE_2D);
    GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D,GLES20.GL_TEXTURE_MIN_FILTER,GLES20.GL_LINEAR);
    GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D,GLES20.GL_TEXTURE_MAG_FILTER,GLES20.GL_LINEAR);
    GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGBA, image_width, image_height, 0, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, null);
    GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 1, GLES20.GL_RGBA, image_width, image_height, 0, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, null);
    GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, 0);

然后通过将纹理与 FBO 绑定来渲染纹理:

    targetFramebuffer = IntBuffer.allocate(1);
    GLES20.glGenFramebuffers(1, targetFramebuffer);
    GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, targetFramebuffer.get(0));
    GLES20.glFramebufferTexture2D(GLES20.GL_FRAMEBUFFER, GLES20.GL_COLOR_ATTACHMENT0, GLES20.GL_TEXTURE_2D, targetTex[0], 0);
    GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0);

然后我像这样创建一个 cl 内存对象:

    mem_images[0] = clCreateFromGLTexture2D(m_clContext, CL_MEM_READ_ONLY, GL_TEXTURE_2D, 1, in_tex, &err);

miplevel 设置为 0 且所有内核工作正常时,内存对象创建成功。只有当 miplevel 设置为上述函数调用时才会出现 CL_INVALID_MIPLEVEL 错误。

OpenCL 规范文档 (http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/clCreateFromGLTexture2D.html) 说可能的原因是 OpenGL 实现不支持从非零 mipmap 级别创建。但是我不知道这是否确实如此,也不知道如何找出答案。

编辑: 在 Andon 的回复之后,我将 OpenGL 纹理生成更改为以下内容:

    GLES20.glGenTextures ( 2, targetTex, 0 );
    GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, targetTex[0]);
    GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D,GLES20.GL_TEXTURE_MIN_FILTER,GLES20.GL_LINEAR_MIPMAP_NEAREST);
    GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D,GLES20.GL_TEXTURE_MAG_FILTER,GLES20.GL_LINEAR);
    GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGBA, image_width, image_height, 0, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, null);
    GLES20.glGenerateMipmap(GLES20.GL_TEXTURE_2D);
    GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, 0);

在绘制到与纹理绑定的 FBO 之后,这就是我生成 mipmap 的方式:

    GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);
    GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, targetTex[0]);
    GLES20.glGenerateMipmap(GLES20.GL_TEXTURE_2D);
    GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, 0);
    GLES20.glFinish();

在尝试从 mipmap 级别不等于 0 的 GL 纹理创建 CL 内存对象时,我仍然遇到相同的错误。

【问题讨论】:

    标签: android opengl-es opengl-es-2.0 opencl mipmaps


    【解决方案1】:

    在这段代码中,您的二级 mipmap 的尺寸有一些非常不寻常的地方。 mipmap LOD N+1 的尺寸应该是 LOD N{w,h}/2。您可以在 GL 中拥有具有相同分辨率的 LOD,但这些 LOD 不会是 mipmap。为了使你的 2D 纹理 mipmap 完整,除了基础图像 0 之外,还需要 log2 (max (width,height))-1 LOD,每个 LOD 应该是分辨率的 1/4(1/2每个维度)的最后一个。我必须同意 CL 的观点,LOD 1 并不是真正的 mipmap。

    此外,您正在对没有数据存储的新创建纹理调用glGenerateMipmap (...)。这是没有意义的事情,glGenerateMipmap (...) 将从基础 LOD 图像开始为您构建您的 mip 链;在你调用它的时候,还没有基本 LOD。

    您对GLES20.glGenerateMipmap(GLES20.GL_TEXTURE_2D); 的调用确实应该移到 您进入您的FBO 之后。正确完成后,您不必手动为细节较低的 mipmap LOD 分配存储空间。此功能将为您处理。因此,您实际上应该首先删除分配 LOD 1 的代码。

    【讨论】:

    • 您好,我已经实施了更改,但仍然遇到同样的错误。但是,+1 的解释。
    • @amirhbp:在这种情况下,您必须拥有“不支持从非零 mipmap 级别创建的 OpenGL 实现”。因为假设image_widthimage_height 不为零,所以您现在应该有一个完整的mipmap 纹理。
    • 有没有办法检查这个?此外,如果 OpenGL 实现不支持这一点,OpenGL ES 不应该在调用 GLES20.glGenerateMipmap(GLES20.GL_TEXTURE_2D) 时生成错误。这是否意味着 Android 不支持 mipmap?因为我使用的是 Android 的 OpenGL ES :/
    • 不,GLES20.glGenerateMipmap(GLES20.GL_TEXTURE_2D) 从基础图像级别生成一组 mipmap,默认为 0。这与您在 CL 代码中尝试执行的操作不同。
    • @amirhbp:我不知道,我从未尝试在嵌入式平台上使用 OpenCL。但是,我可以肯定地告诉您,Android 没有 single OpenGL ES 实现。至少有 4 家主要的硬件供应商拥有自己的实现,我敢肯定还有几十家我从未听说过的小型供应商也这样做。
    猜你喜欢
    • 1970-01-01
    • 2012-02-16
    • 1970-01-01
    • 1970-01-01
    • 2011-11-03
    • 2015-01-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多