0
votes

My android app passes in an OpenGL texture2D to my OpenCL kernel, however when I use clCreateFromGLTexture2D() with mipmap level 1, I get CL_INVALID_MIPLEVEL.

I am creating my OpenGL texture and generating mipmaps like this:

    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);

The texture is then rendered to by binding it with a 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);

I then create a cl memory object like so:

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

The memory object is created successfully when the miplevel is set to 0 and all the kernels work fine. It's only when the miplevel is set to that the above function call gives me CL_INVALID_MIPLEVEL error.

OpenCL specification docs (http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/clCreateFromGLTexture2D.html) say that a possible reason could be that the OpenGL implementation does not support creating from non-zero mipmap levels. However I don't know if this is definitely the case and am not sure how to find out.

EDIT: After Andon's reply I changed my OpenGL texture generation to following:

    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);

and after drawing into the FBO which is bound with the texture, this is how I generate mipmaps:

    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();

I still get the same error when trying to create a CL memory object from GL texture with mipmap level not equal to 0.

1

1 Answers

1
votes

There is something very unusual about the dimensions of your second-level mipmap in this code. The dimensions of mipmap LOD N+1 should be LOD N{w,h}/2. You can have LODs with the same resolution in GL, but those LODs will not be mipmaps. To make your 2D texture mipmap complete, you need log2 (max (width,height))-1 LODs in addition to the base image 0, and each should be 1/4 the resolution (1/2 each dimension) of the last. I have to agree with CL on this one, LOD 1 is not really a mipmap.

Moreover, you are calling glGenerateMipmap (...) on a newly created texture that has no data store. That is a meaningless thing to do, glGenerateMipmap (...) will build your mip-chain for you starting with the base LOD image; at the time you called this, there was no base LOD.

Your call to GLES20.glGenerateMipmap(GLES20.GL_TEXTURE_2D); really ought to be moved to a point after you draw into your FBO. Done properly, you do not have to manually allocate storage for lower detail mipmap LODs. This function will take care of that for you. Thus, you should actually remove the code that allocates LOD 1 in the first place.