C++ glGetActiveUniformName的意外行为

C++ glGetActiveUniformName的意外行为,c++,opengl,opengl-3,C++,Opengl,Opengl 3,glGetActiveUniformName是一个函数,可用于根据查询GLSL制服的名称长度。这可以通过将uniformName设置为NULL(0)并将GLsizei指针作为out变量提供给length来实现。在执行此操作时,我们希望在length参数中返回统一名称的长度,但在如上所述调用函数后,此变量保持不变。给出了一个错误,即GL_无效_值,根据文档,该错误可能表示以下三种情况之一: GL_INVALID_VALUE is generated if uniformIndex is great

glGetActiveUniformName是一个函数,可用于根据查询GLSL制服的名称长度。这可以通过将uniformName设置为NULL(0)并将GLsizei指针作为out变量提供给length来实现。在执行此操作时,我们希望在length参数中返回统一名称的长度,但在如上所述调用函数后,此变量保持不变。给出了一个错误,即GL_无效_值,根据文档,该错误可能表示以下三种情况之一:

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_制服报告为5。bufSize故意设置为0,因此不能为负值。在所用程序上调用具有GL_LINK_状态的glGetProgram将返回GL_TRUE(1)。这排除了导致此错误的所有3个已知原因。根据glGetError,在调用glGetActiveUniformName并使用有效的bufSize和uniformName调用它之前,没有出现任何以前的错误。这两个操作均成功,没有错误,并按预期写入uniformName中的缓冲区;正确书写制服的名称

除了不报告制服名称的长度和错误之外,还有其他令人不安的迹象;如果bufSize设置为大于零的正值,且uniformName保留为NULL(0),则函数仍会写入uniformName,这可能会导致严重的内存损坏。此行为也不符合规范,该规范规定uniformName应为NULL(0),则不应向其写入任何内容

把上面所有的信息放在一起,我想我可以安全地得出结论,我的代码中没有错误,但是在我自己的代码之外的某个地方有一个错误,这就是我在这里发布的原因。当如上所述使用时,是否有人可以验证此函数的行为

我认为这很可能是一个驱动程序问题,这意味着只有运行nVidia驱动程序/硬件的人才会看到这个问题,但现在排除任何用户组还为时过早

注意:上述情况发生在一台安装了nVidia GeForce 660 GTX且运行最新驱动程序(专门更新以验证上述声明)的机器上。该机器是运行64位Windows 7 Professional SP1的Dell XPS 8500。该程序是使用Visual Studio 2012 Professional构建的,完全更新。这篇文章也被发布到英伟达开发者论坛和DevMaster,这里发布了更好的曝光,并希望更快地解决这个问题。
更新1:问题代码在另一台具有不同GPU(nVidia GeForce 9600M GT)的机器上进行了测试,同样使用了最新的驱动程序,并提供了相同的结果。此计算机正在运行64位Windows 7 Ultimate SP1。同样,二进制文件是用VS2012构建的。

这里的文档似乎是错误的。OpenGL规范在这里非常明确:
length
表示实际写入缓冲区的字符数。此外,规范不需要对
uniformName
参数进行任何空检查

或者,换句话说,您不能使用
glGetActiveUniformName
获取制服名称的长度。您必须使用
glGetActiveUniform
执行此操作


我已经更正了。

FYI:来自同一制造商的不同GPU通常会运行相同的代码(当然,存在实际的硬件差异)。谢谢您的回答。我已经通知了Khronos关于他们文件的这个问题。glGetActiveUniform和GL_UNIFORM_NAME_LENGTH可以很好地工作,并且可以很容易地用它替换原始调用。