glGetActiveUniformName 是一个函数,可用于根据 documentation 查询 GLSL 制服的名称长度。这可以通过将 uniformName 设置为 NULL (0) 并提供 GLsizei 指针作为长度的 out 变量来完成。执行此操作时,将期望在 length 参数中返回制服名称的长度,但在调用上述函数后该变量不变。给出的错误是 GL_INVALID_VALUE,根据文档,它可能意味着以下三件事之一:
GL_INVALID_VALUE is generated if uniformIndex is greater than or equal to the value of GL_ACTIVE_UNIFORMS.
GL_INVALID_VALUE is generated if bufSize is negative.
GL_INVALID_VALUE is generated if program is not the name of a program object for which glLinkProgram has been issued.
在我的情况下,uniformIndex 为 0,GL_ACTIVE_UNIFORMS 报告为 5。 bufSize 故意设置为 0,因此不能为负。在使用的程序上使用 GL_LINK_STATUS 调用 glGetProgram 返回 GL_TRUE (1)。这排除了此错误的所有 3 个已知原因。在调用 glGetActiveUniformName 并使用有效的 bufSize 和 uniformName 调用之前,根据 glGetError 没有先前的错误,两者都成功而没有错误,并按预期写入了uniformName 中的缓冲区;正确书写制服名称。
除了不报制服名称的长度和错误之外,还有其他令人不安的迹象;如果 bufSize 设置为大于零的正值,并且uniformName 保留为NULL (0),则函数无论如何都会写入uniformName,这可能会导致严重的内存损坏。这种行为也不符合规范,规范规定uniformName 应为NULL (0),则不应向其写入任何内容。
将上述所有信息放在一起,我想我可以安全地得出结论,我的代码中没有错误,而是我自己的代码之外的某个地方存在错误,这就是我在这里发布的原因。当如上所述使用时,有没有人可以验证此函数的行为?
我认为这很可能是驱动程序问题,这意味着只有运行 nVidia 驱动程序/硬件的人才会看到该问题,但现在排除任何用户组还为时过早。
P.S.:上述情况发生在安装了 nVidia GeForce 660 GTX 且运行最新驱动程序(专门更新以验证上述声明)的机器上。该机器是运行 64 位 Windows 7 Professional SP1 的 Dell XPS 8500。该程序是使用 Visual Studio 2012 Professional 构建的,已完全更新。这篇文章也发布到了 nVidia 开发者论坛和 DevMaster,发布在这里是为了更好地曝光并希望更快地解决问题。
更新 1:有问题的代码在另一台具有不同 GPU(nVidia GeForce 9600M GT)的机器上进行了测试,再次使用最新的驱动程序并提供了相同的结果。这台机器运行的是 64 位 Windows 7 Ultimate SP1。同样,二进制文件是用 VS2012 构建的。
最佳答案
这里的文档似乎是错误的。 OpenGL 规范在这里非常明确:length
是用于实际写入缓冲区的字符数。此外,规范不要求对 uniformName
参数进行任何 NULL 检查。
或者,换句话说,您不能使用 glGetActiveUniformName
来获取制服名称的长度。你必须用 glGetActiveUniform
做到这一点。
我已经更正了 documentation on the wiki 。
关于c++ - glGetActiveUniformName 的意外行为,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/14968677/