0

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)

Community
  • 1
  • 1
Elouarn Laine
  • 1,665
  • 15
  • 27

1 Answers1

1

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, e.g. 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.

Reto Koradi
  • 53,228
  • 8
  • 93
  • 133
  • Thanks for the quick reply but actually, I'm trying to use `glTexImage2D()` in replacement of `glTexStorage2D()`. Indeed, when I use `glTexStorage2D()` to create my texture and then bind it, I got no errors but It seems then that write or perform atomic operations on the image has no effects. So, I thought it could be because the texture was not loaded properly. Do you think that might be the reason of my problem or Am I looking in the wrong direction ? N.B. According to the specs, using `glTexImage2D()` as I did is equivalent to `glTexStorage2D()`. Thanks by advance! – Elouarn Laine Jun 30 '16 at 15:29
  • @ElouarnLaine: There are only two ways to create a texture with immutable storage: `glTexStorage` or `glTextureView`. "*According to the specs, using glTexImage2D() as I did is equivalent to glTexStorage2D().*" According to what specs? Because the ES 3.1 spec makes it very clear that `glTexStorage2D` sets the immutable status, while `glTexImage2D` does not. – Nicol Bolas Jun 30 '16 at 17:11
  • @NicolBolas: On the [khronos documentation](https://www.khronos.org/opengles/sdk/docs/man31/) in `glTexStorage2D()` section : "_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..._". My question is : Can we bind a texture created with `glTexImage2D()` using `glBindImageTexture()` ? – Elouarn Laine Jun 30 '16 at 17:40
  • @ElouarnLaine: 1) The Khronos documentation is not the specification. 2) The documentation page says that `GL_TEXTURE_IMMUTABLE_FORMAT` is set to true by that function. So it clearly explains how it is different from `glTexImage2D`. – Nicol Bolas Jun 30 '16 at 18:19
  • @NicolBolas: Sorry for the my inaccuracies (I'm still new to Opengl). Actually, it remains unclear for me wether the following paragraph is about `glTexImage2D()` or `glTexStorage2D()`: "_Since no texture data is actually provided, the values used in the pseudo-code for [...] if it would not, in fact, alter the dimensions or format of the object._" (I assumed they were talking about `glTexImage2D()`) – Elouarn Laine Jun 30 '16 at 19:06
  • @ElouarnLaine As Nicol Bolas pointed out, `glTexStorage*()` are the only calls that produce immutable textures. I added some spec quotes to the answer. – Reto Koradi Jul 01 '16 at 07:37