为什么GL.EnableVertexArrayAttrib 在一台机器上崩溃,但在另一台机器上没有崩溃?



我正在使用OpenTK,一个用于C#的OpenGL库。我在我的主PC(Nvidia视频卡(上开始了一个项目,一切都很好。然后我在我的笔记本电脑(AMD视频卡(上继续它,在呼叫GL时出现异常。EnableVertexArrayAttrib.

最少的复制代码:

创建具有"test"属性的着色器 int vertexShaderID = GL.CreateShader(ShaderType.VertexShader(; GL.ShaderSource(vertexShaderID, "in vec3 test; void main(( { gl_Position = vec4(0, 0, 0, 0(; }"); GL.编译着色器(顶点着色器ID(; int fragmentShaderID = GL。CreateShader(ShaderType.FragmentShader(; GL.ShaderSource(fragmentShaderID, "void main(( { gl_FragColor = vec4(0, 0, 0, 0(; }"); GL.编译着色器(fragmentShaderID(; int programID = GL。创建程序((; GL.使用程序(程序ID(; GL.AttachShader(programID, vertexShaderID(; GL.AttachShader(programID, fragmentShaderID(; GL.链接程序(程序ID(; 创建一个 VAO,获取"测试"属性位置并启用它 int vao = GL。GenVertexArray((; int attrib = GL。GetAttribLocation(programID, "test"(; GL.EnableVertexArrayAttrib(vao, attrib(;在 AMD 上抛出 AccessViolationException,但不在 NVIDIA 上抛出

我在 Windows 8.1 AMD 笔记本电脑上拥有最新的 GPU 驱动程序和最新的 OpenTK。

您将 4.5 个直接状态访问 (DSA( 调用与 3.3 个调用混合在一起,不要这样做,它只会导致像这样的错误。

问题在于 3.3glGen*和 4.5glCreate*函数之间的行为存在细微差异。glGen*版本仅为对象保留一个位置,但将其创建推迟到第一次使用glBind*绑定对象时。我不确定为什么会这样决定。无论如何,这通常无关紧要,因为必须先绑定对象才能对它执行任何操作。至少在DSA成为现实之前是这样。因此,您的VAO永远不会受到约束,因此永远不会创建,也没有什么可以启用的。

有两种方法可以修复程序:

  1. 承诺使用 OpenGL 4.5 函数。它们使用起来更舒适,不需要glBind*调用就可以只调用下一个函数,它更像方法。此外,还有一些新功能可以为您提供更精细的控制 - 显式统一位置(4.3+(也很好。这并不是什么新鲜事,所有现代 GPU 都支持它。不确定较旧的控制台或手机,我也知道 VirtualBox VM 仅限于 3.3 .

    在这种情况下,您需要做的就是使用CreateVertexArrayCreateVertexArrays函数创建 VAO。

    int vao;
    GL.CreateVertexArrays(1,out vao);
    int attrib = GL.GetAttribLocation(programID, "test");
    GL.EnableVertexArrayAttrib(vao, attrib);
    

    你也可以至少给glBind*打电话一次,但不要依赖它,这对未来的读者来说并不明显。

  2. 保持使用 3.3 并使用EnableVertexAttribArray而不是EnableVertexArrayAttrib.是的,这是一个非常可怕的命名决定,代码完成很有可能背叛了你,然后你刚刚填写了适当的参数。此函数更改当前绑定的 VAO 的状态。

    int vao = GL.GenVertexArray();
    int attrib = GL.GetAttribLocation(programID, "test");
    GL.BindVertexArray(vao); //Only here is the actual VAO with 'vao' handle created.
    GL.EnableVertexAttribArray(attrib); // Changes currently the bound VAO's state.
    

关于它在 NVIDIA 上工作的原因?OpenGL驱动程序是一团糟。他们试图预测常见错误并修复它们 - 例如,在核心中没有绑定VAO的绘制,缺少索引缓冲区,越界绘制调用,合理的默认位置,采样器或着色器中的一些细微错误。严重依赖隐藏的全球上下文状态根本无济于事。我个人的经验是,英伟达往往是最宽容的,AMD是50-50,英特尔是最严格的。如果可以的话,我建议同时在集成卡和专用卡上进行真正开发。在一张卡上出现黑屏,而在另一张卡上工作,并想知道过去 X 小时内的哪些更改可能是原因,这并不令人愉快。

相关内容

最新更新