【发布时间】: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 而不是纹理。特别是因为您显然不需要过滤。