简体   繁体   中英

OpenGL ES 3.1 - Unable to create IMMUTABLE Textures with glTexImage2D

I'm trying to create an immutable texture with glTexImage2D() that I can then bind using glBindImageTexture()

Here's my C++ code :

GLuint id;
glGenTextures(1, &id);

glBindTexture(GL_TEXTURE_2D, id);

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);


GLint width = 2046;
GLint height = 1086;

// Not sure what to put here 1, 2, 4 or 8 ?
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);

GLint levels;
glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, &levels);

for (int i = 0; i < levels + 1; i++)
{

    glTexImage2D(GL_TEXTURE_2D, i, GL_R32UI, width, height, 0, GL_RED_INTEGER, GL_UNSIGNED_INT, NULL);
    width = glm::max(1, (width / 2));
    height = glm::max(1, (height / 2));

    // check OpenGL error
    GLenum err;
    while ((err = glGetError()) != GL_NO_ERROR) {
        ALOGE("ERROR_GL_TEXTURE_INIT: %i", err);
    }
}

GLint status;
glGetTexParameteriv(GL_TEXTURE_2D,GL_TEXTURE_IMMUTABLE_FORMAT,&status);
ALOGE("IMMUTABLE_TEXTURE: %i", status);

glBindTexture(GL_TEXTURE_2D, 0);

glBindImageTexture(0, id, 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32UI);

// check OpenGL error
GLenum err;
while ((err = glGetError()) != GL_NO_ERROR) {
    ALOGE("ERROR_GL_TEXTURE_IMG-USE: %i", err);
}

As I don't need Mipmap levels I set GL_TEXTURE_MAX_LEVEL to 0 .
Then I call glTexImage2D() to set up all texture's levels (only one here) and I have no errors raised.

Unfortunately the result of
glGetTexParameteriv(GL_TEXTURE_2D,GL_TEXTURE_IMMUTABLE_FORMAT,&status) is 0 which means that the texture is not immutable .

Now, when I try to call glBindImageTexture() , error 1282 is raised because as it is written in the khronos documentation , this opengl function needs an immutable texture.

Any ideas on what I'm doing wrong ?

Thanks in advance ;)

EDIT :

Thank you to both of you for your time and for all the information provided but There are things I don't understand.

This paragraph of the glTexStorage2D() man ( khronos documentation ) confuses me:

The behavior of glTexStorage2D depends on the target parameter. When target is GL_TEXTURE_2D, calling glTexStorage2D is equivalent, assuming no errors are generated, to executing the following pseudo-code:

for (i = 0; i < levels; i++)
{
    glTexImage2D(target, i, internalformat, width, height, 0, format, type, NULL);
    width = max(1, (width / 2));
    height = max(1, (height / 2));
}

Since no texture data is actually provided, the values used in the pseudo-code for format and type are irrelevant and may be considered to be any values that are legal for the chosen internalformat enumerant. internalformat must be one of the sized internal formats given in Table 1, or one of the compressed internal formats given in Table 2 below. Upon success, the value of GL_TEXTURE_IMMUTABLE_FORMAT becomes GL_TRUE . The value of GL_TEXTURE_IMMUTABLE_FORMAT may be discovered by calling glGetTexParameter with pname set to GL_TEXTURE_IMMUTABLE_FORMAT. No further changes to the dimensions or format of the texture object may be made. Using any command that might alter the dimensions or format of the texture object (such as glTexImage2D or another call to glTexStorage2D) will result in the generation of a GL_INVALID_OPERATION error, even if it would not, in fact, alter the dimensions or format of the object.

It remains unclear for me wether the paragraph above is about glTexImage2D() or glTexStorage2D() .

Moreover, my underlying question is: Can we bind a texture created with glTexImage2D() using glBindImageTexture() ? (I saw code samples where these two functions were actually used together, here for instance)

To allocate immutable texture storage, you use glTexStorage2D() instead of glTexImage2D() . So your call to allocate the texture memory becomes:

glTexStorage2D(GL_TEXTURE_2D, levels, GL_R32UI, width, height);

In this case, you allocate all mipmap levels with this single call, so you won't need the loop you currently have.

Also, I'm not sure what your expectations for this are:

GLint levels;
glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, &levels);

In your code, you just created the texture when you make this call. So querying the number of levels is meaningless. If you want a mipmapped texture, you'll have to calculate the number of mipmaps you need, based on the size. If you don't need mipmapping, you simply pass 1 for the second argument to glTexStorage2D() .


Since there were some follow-up questions on whether there are other ways to create an immutable texture, eg with glTexImage2D() , the answer is no. Section 8.17 titled "Immutable-Format Texture Images" of the ES 3.1 spec, starting on page 190, explains how to create immutable textures. The only calls listed in that section are glTexStorage2D() and glTexStorage3D() . It also specifically mentioned that these calls set the GL_TEXTURE_IMMUTABLE_FORMAT property to true.

The only other call mentioning that it creates a immutable texture is glTexStorage2DMultisample() from section 8.8 on page 171.

This means that glTexImage2D() creates textures that are not immutable. Confirming this is section 8.18 titled "Texture State" on page 194, where the default values for various texture properties are listed:

In the initial state, [..] The value of TEXTURE_IMMUTABLE_FORMAT is FALSE.

Since the specification of glTexImage2D() does not mention changing the value, it will remain false.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM