【问题标题】:INVALID_OPERATION on glTexSubImage3D() [duplicate]glTexSubImage3D() 上的 INVALID_OPERATION [重复]
【发布时间】:2019-11-27 02:06:03
【问题描述】:

我想使用 3D_TEXTURE 作为一个大的自定义缓冲区,因为 TEXTURE_BUFFER 在大多数 GPU 上被限制为 128MB,但 3D_TEXTURES 没有限制。不幸的是,我也不能使用 GL_SHADER_STORAGE_BUFFER,因为它仅限于 glsl 数据类型(float、uint、int)并且我需要按字节访问。

我调试了代码,发现当我尝试使用 glTexSubImage3D() 填充纹理中的数据时,它会抛出错误代码 1282 => GL_INVALID_OPERATION。但我无法解释错误代码。我检查了the reference中的所有案例, 但据我所知,我认为 GL_INVALID_OPERATION 的任何命名原因都不应该是这种情况。

  // main code:
  genSuperTex(1024);
  fillSuperTex();

void genSuperTex(int inputSize) {
  superBufferSize = inputSize; // saving the z size of the buffer...

  GLuint gerror;
  glGenTextures(1, &superBufferID);
  glBindTexture(GL_TEXTURE_3D, superBufferID);
  gerror = glGetError();
  if (gerror) std::cout << "genSuperTex(): Texture generation error = " << gerror << std::endl; // no error here

  // Setting texture parameters:
  glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
  glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
  glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
  gerror = glGetError();
  if (gerror) std::cout << "genSuperTex(): Texture param error = " << gerror << std::endl; // no error here
    
  // Generating the storage for the texture:
  // SUPERTEX_DIM = 128 for testing purposes
  glTexStorage3D(GL_TEXTURE_3D, 1, GL_R8UI, SUPERTEX_DIM, SUPERTEX_DIM, inputSize);
  gerror = glGetError();
  if (gerror) std::cout << "genSuperTex(): glTexStorage3D = " << gerror << std::endl; // no error here
}

void fillSuperTex() {
  glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); // Just out of paranoia
  glBindTexture(GL_TEXTURE_3D, superBufferID); // It is still bound, but out of paranoia.
  unsigned int index = 0;

  // I have tree of data, which all want to insert their data into the super texture
  root->insertToGLSuperBuffer(superBufferID, superBufferSize, index);
}

void TSDFMesh_SVT::insertToGLSuperBuffer(const GLuint aTexID, const unsigned int size, unsigned int & index) {
  GLuint error;

  error = glGetError();
  if (error) std::cout << "TSDFMesh_SVT::insertToGLSuperBuffer(): prev Error = " << error << std::endl; // no error here, to ensure the error is not from a previous operation

  // How many z-slices are needed for the data:
  GLsizei local_size = meSegmentCount(svtMap->getSize(), SUPERTEX_SEG_SIZE); // = 2, during debugging

  glTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, index, SUPERTEX_DIM, SUPERTEX_DIM, local_size, GL_RED, GL_UNSIGNED_BYTE, svtMap->getData()->DataPointer());
  // SUPERTEX_DIM = 128
  
  error = glGetError(); // <------------------------- Here I get: GL_INVALID_OPERATION
  if (error) std::cout << "TSDFMesh_SVT::insertToGLSuperBuffer(): gl Error = " << error << std::endl;
}

我也尝试使用 glTextureSubImage() 代替 glTexSubImage() 并将 aTexID 作为第一个参数,但没有用。

来自 opengl 参考中列出的错误:

如果纹理不是现有纹理对象的名称,则由 glTextureSubImage3D 生成 GL_INVALID_OPERATION。

不可能,因为我使用的是 glTexSubImage3D 而不是 glTextureSubImage3D。此外,我在 fillSuperTex() 的开头绑定纹理,并且在树的遍历期间没有完成 glBindTexture() 操作。

如果纹理数组尚未由先前的 glTexImage3D 或 glTexStorage3D 操作定义,则会生成 GL_INVALID_OPERATION。

在我看来,这似乎是最有可能出现的错误。但在我看来,我在创建缓冲区方面做的一切都是正确的。至少在调用它时我没有收到任何错误。并且我使用了一个断点来检查函数 genSuperTex() 是否真的被调用了。

如果类型是 GL_UNSIGNED_BYTE_3_3_2、GL_UNSIGNED_BYTE_2_3_3_REV、GL_UNSIGNED_SHORT_5_6_5 或 GL_UNSIGNED_SHORT_5_6_5_REV 之一且格式不是 GL_RGB,则会生成 GL_INVALID_OPERATION。

GL_INVALID_OPERATION is generated if type is one of GL_UNSIGNED_SHORT_4_4_4_4, GL_UNSIGNED_SHORT_4_4_4_4_REV, GL_UNSIGNED_SHORT_5_5_5_1, GL_UNSIGNED_SHORT_1_5_5_5_REV, GL_UNSIGNED_INT_8_8_8_8, GL_UNSIGNED_INT_8_8_8_8_REV, GL_UNSIGNED_INT_10_10_10_2, or GL_UNSIGNED_INT_2_10_10_10_REV and format is neither GL_RGBA nor GL_BGRA.

如果格式为 GL_STENCIL_INDEX 且基本内部格式不是 GL_STENCIL_INDEX,则生成 GL_INVALID_OPERATION。

如果非零缓冲区对象名称绑定到 GL_PIXEL_UNPACK_BUFFER 目标并且缓冲区对象的数据存储当前已映射,则会生成 GL_INVALID_OPERATION。

如果非零缓冲区对象名称绑定到 GL_PIXEL_UNPACK_BUFFER 目标,并且数据将从缓冲区对象中解包,从而导致所需的内存读取超过数据存储大小,则会生成 GL_INVALID_OPERATION。

如果非零缓冲区对象名称绑定到 GL_PIXEL_UNPACK_BUFFER 目标,并且像素不能均分到内存中存储类型指示的数据所需的字节数,则会生成 GL_INVALID_OPERATION。

在所有这些情况下,指定的条件都不适用。

如果有人知道这里的错误是什么,请告诉我。

【问题讨论】:

  • "3D_TEXTURES 没有限制" 他们肯定有:GL_MAX_3D_TEXTURE_SIZE
  • 啊,是的,没错。几周前我检查了限制,我的显卡上是 16384^3。我忘了它,因为它已经足够大了。 (实际上纹理大小超过了可用的 VRAM,如果你会使用 1 Byte per voxel。)
  • 考虑到您正在处理的数据量,最好只使用 SSBO 而不是纹理。特别是因为您显然不需要过滤。

标签: c++ opengl


【解决方案1】:

我发现了问题: 我尝试在其他地方测试创建纹理:

glGenTextures(1, &testtex);
glBindTexture(GL_TEXTURE_3D, testtex);
glTexImage3D(GL_TEXTURE_3D, 0, GL_R8UI, 64, 64, 64, 0, GL_RED, GL_UNSIGNED_BYTE, NULL);

我发现每当 internalformat 是 R8UI 时,我都会收到错误消息。对于 GL_R8 或 GL_RED 一切正常,但如果我更改为整数格式(R8I 或 R8UI),我会收到错误,尽管这些内部格式被列为有效条目。

(https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glTexImage3D.xhtml)

这是我的显卡 (NVIDIA) 的问题还是其他人得到了这个错误?

【讨论】:

  • 这并不能真正回答问题;它只是指出问题所在(或至少是 a 问题)。
猜你喜欢
  • 2023-02-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-12-02
  • 1970-01-01
  • 2023-03-19
  • 1970-01-01
  • 2017-12-17
相关资源
最近更新 更多