GreyFox
GreyFox

Reputation: 45

glTexImage3D throws error 1282 (invalid operation)

I am trying to upload volumetric data as a 3D texture via OpenGL. However, when specifying the formats and data itself through glTexImage3D, an GL_INVALID_OPERATION error is thrown.

The code (including the debugging code I added to find out where the error was comming from) is the following:

void Texture3D::upload()
{
  std::cout << "TEX GL ERROR: " << glGetError() << std::endl;

  glGenTextures(1, &_textureId);
  std::cout << "TEX GL ERROR: " << glGetError() << std::endl;

  glBindTexture(GL_TEXTURE_3D, _textureId);
  std::cout << "TEX GL ERROR: " << glGetError() << std::endl;

  glTexStorage3D(GL_TEXTURE_3D, 6, GL_R8, _width, _height, _depth);
  std::cout << "TEX GL ERROR: " << glGetError() << std::endl;

  glTexImage3D(GL_TEXTURE_3D, 0, GL_R8, _width, _height, _depth, 0,  GL_RED,  GL_UNSIGNED_BYTE, _data);
  std::cout << "TEX GL ERROR: " << glGetError() << std::endl;

  glGenerateMipmap(GL_TEXTURE_3D);

  std::cout << "TEX GL ERROR: " << glGetError() << std::endl;
  }

I thought it might be an GL_INVALID_VALUE for any of the format, internal format, or pixel format I am specifying in the glTexImage3D, however I have checked with the documentation of glTexImage3D and everything seems correct.

I have created a minimal, verifiable example (using GLFW and GLEW)

#include <iostream>
#include <GL/glew.h>
#include <GLFW/glfw3.h>

GLFWwindow * _window = nullptr;
unsigned int _textureId = GL_INVALID_VALUE;

void initGLFWContext()
{
  if (!glfwInit())
    {
      std::cerr << "GLFW: Couldnt initialize" << std::endl;
      exit(-1);
    }

    glfwWindowHint(GLFW_SAMPLES, 4);

    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 5);

    glfwWindowHint(GLFW_RESIZABLE, GLFW_TRUE);

    glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); 

    _window = glfwCreateWindow(1024, 1024, "Test Window", NULL, NULL);
    if (!_window)
    {
      std::cerr << "GLFW Error: Couldnt create window" << std::endl;
      glfwTerminate();
      exit(-1);
    }

    //glfwSetKeyCallback(_window, kbCb);
    //glfwSetCursorPosCallback(_window, mmCb);
    //glfwSetMouseButtonCallback(_window, mCb);
    //glfwSetFramebufferSizeCallback(_window, resizeCb);

    glfwMakeContextCurrent(_window);

    glfwSetWindowPos(_window, 0, 0);

    glfwSwapInterval(1);

    // Initializes glew
    glewExperimental = GL_TRUE;
    GLenum err = glewInit();
    if (GLEW_OK != err)
    {
      std::cerr << "GLEW Error: " << glewGetErrorString(err) << std::endl;
      exit(-1);
    }
}

void initOpenGL()
{
  glEnable(GL_DEPTH_TEST);
  //glEnable(GL_BLEND);
  glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
  glFrontFace(GL_CCW);
  glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
  glEnable(GL_CULL_FACE);
}

void minimalVerifiableExample()
{
  initGLFWContext();
  initOpenGL();

  const unsigned int volSide = 256;
  const unsigned int volumeSize = volSide * volSide * volSide;
  unsigned char * volumeData = new unsigned char[volumeSize]();

  std::cout << "TEX GL ERROR: " << glGetError() << std::endl;

  glGenTextures(1, &_textureId);
  std::cout << "TEX GL ERROR: " << glGetError() << std::endl;

  glBindTexture(GL_TEXTURE_3D, _textureId);
  std::cout << "TEX GL ERROR: " << glGetError() << std::endl;

  glTexStorage3D(GL_TEXTURE_3D, 
                 6, 
                 GL_R8, 
                 volSide, 
                 volSide, 
                 volSide);
  std::cout << "TEX GL ERROR: " << glGetError() << std::endl;

  glTexImage3D(GL_TEXTURE_3D, 
               0, 
               GL_R8, 
               volSide, 
               volSide, 
               volSide, 
               0, 
               GL_RED, 
               GL_UNSIGNED_BYTE, 
               volumeData);
  std::cout << "TEX GL ERROR: " << glGetError() << std::endl;

  glGenerateMipmap(GL_TEXTURE_3D);
  std::cout << "TEX GL ERROR: " << glGetError() << std::endl;

  while(!glfwWindowShouldClose(_window))
  {
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glfwPollEvents();
    glfwSwapBuffers(_window);
  }

  glfwDestroyWindow(_window);
  glfwTerminate();

  delete[] volumeData;
}

int main(int argc, char ** argv)
{
  (void) argc;
  (void) argv;
  minimalVerifiableExample();
  return 0;
}

And this is the output I get:

TEX GL ERROR: 0
TEX GL ERROR: 0
TEX GL ERROR: 0
TEX GL ERROR: 0
TEX GL ERROR: 1282
TEX GL ERROR: 0

Am I doing something wrong when uploading the texture or anywhere else?

Upvotes: 4

Views: 947

Answers (1)

BDL
BDL

Reputation: 22157

1282 is a GL_INVALID_OPERATION and is caused by the combination of

glTexStorage3D
glTexImage3D

It is not allowed to recreate the storage for an immutable storage texture object. After calling glTexStorage3D, the texture uses immutable storage. glTexImage3D requests a new storage which is not allowed anymore.

If you try to upload data to the immutable storage texture object, you'll have to use glTexSubImage3D instead which will upload data but not request new storage.

Upvotes: 6

Related Questions