如何解决在 glfwDestroyWindow
以下 OpenGL/GLFW/GLAD 代码(MCVE 版本)使进程崩溃,并在 nvoglv64.dll 中出现以下访问冲突异常:
0x00007FFC731F586F (nvoglv64.dll) in ConsoleApplication2.exe: 0xC0000005: Zugriffsverletzung beim Lesen an Position 0x0000000000024AA8.
在下面代码清单末尾的 glfwDestroyWindow(window)
调用中,我不知道为什么。当不调用 glTexPageCommitmentARB
或使用 commit
的 GL_FALSE/0
调用它时,此调用不会崩溃。
我已经阅读了 ARB_sparse_texture 的规范三遍,检查了 glTexPageCommitmentARB
(x,y,z,width,height,depth内部格式的页面大小的倍数),我有点确定我已经遵循了有关如何正确使用该功能的所有说明。之前,我还使用调试上下文和调试消息回调检查了任何 OpenGL 错误,但没有任何输出。
更多信息:
- 操作系统:Windows 10 x64 (20H2)
- 驱动程序:Nvidia 461.09 (DCH)
- GLAD 配置:OpenGL 4.3 核心 + ARB_sparse_texture + ARB_sparse_texture2
- GLFW:来自 Git 提交的全新本地 MSVC x64 Release 构建 0b9e48fa3df9c18
下面代码中 glTexPageCommitmentARB
调用之前的 fprintf 在程序结束崩溃前打印以下输出:
256 128 1 32768
#include <stdlib.h>
#include <stdio.h>
#include <glad/glad.h>
#include <GLFW/glfw3.h>
int main(int argc,char** argv) {
glfwInit();
glfwWindowHint(GLFW_OPENGL_PROFILE,GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR,4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MInor,3);
glfwWindowHint(GLFW_VISIBLE,GLFW_FALSE);
GLFWwindow* window = glfwCreateWindow(800,600,"",NULL,NULL);
if (window == NULL) {
fprintf(stderr,"%s\n","GLFW window NULL");
exit(1);
}
glfwMakeContextCurrent(window);
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) {
fprintf(stderr,"gladLoadGLLoader Failed");
exit(2);
}
if (!GLAD_GL_ARB_sparse_texture || !GLAD_GL_ARB_sparse_texture2) {
fprintf(stderr,"GL_ARB_sparse_texture or GL_ARB_sparse_texture2 unsupported");
exit(3);
}
gluint tex;
glGenTextures(1,&tex);
glBindTexture(GL_TEXTURE_2D,tex);
// activate sparse allocation for this texture
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_SPARSE_ARB,GL_TRUE);
// use default page size index 0 (as per ARB_sparse_texture2)
glTexParameteri(GL_TEXTURE_2D,GL_VIRTUAL_PAGE_SIZE_INDEX_ARB,0);
GLint width,depth,maxSparseTexSize;
// query page size for width,height and depth
// R16UI is supported as sparse texture internal format as per
// https://www.khronos.org/registry/OpenGL/extensions/ARB/ARB_sparse_texture.txt
glGetInternalformativ(GL_TEXTURE_2D,GL_R16UI,GL_VIRTUAL_PAGE_SIZE_X_ARB,1,&width);
glGetInternalformativ(GL_TEXTURE_2D,GL_VIRTUAL_PAGE_SIZE_Y_ARB,&height);
glGetInternalformativ(GL_TEXTURE_2D,GL_VIRTUAL_PAGE_SIZE_Z_ARB,&depth);
glGetIntegerv(GL_MAX_SPARSE_TEXTURE_SIZE_ARB,&maxSparseTexSize);
fprintf(stderr,"%d %d %d %d\n",maxSparseTexSize);
glTexStorage2D(
/*target*/GL_TEXTURE_2D,/*levels*/1,/*internalFormat*/GL_R16UI,/*width*/maxSparseTexSize,/*height*/maxSparseTexSize);
// commit one page at (0,0)
glTexPageCommitmentARB(GL_TEXTURE_2D,/*level*/0,/*xoffset*/0,/*yoffset*/0,/*zoffset*/0,/*width*/width,/*height*/height,/*depth*/depth,/*commit*/GL_TRUE);
glfwDestroyWindow(window);
glfwTerminate();
}
编辑:更多信息:
崩溃发生在驱动程序线程 (nvoglv64.dll) 中,紧跟在为 GL 上下文调用 wglDeleteContext(...)
的主线程之后。当 Visual Studio 2019 调试器因异常而停止时,我可以看到存在三个驱动程序线程(全部来自 nvoglv64.dll)(其中一个发出访问冲突异常),而主线程在 wglDeleteContext(...)
之后立即停止。
EDIT2:对此进行更多实验,当纹理未取消引用(引用计数为 0)并在销毁 GL 上下文之前由驱动程序处理时,总是会发生崩溃。例如,在上面的代码中,当我在 glDeleteTextures(1,&tex);
之前调用 glDestroyWindow(window)
时,不会发生崩溃(可重现)。在我提取上述 MCVE 的实际应用程序中,纹理也作为颜色附件附加到 FBO 中。当我没有删除 FBO 而只是减少纹理的引用计数时(通过调用 glDeleteTextures(...)
,崩溃仍然会发生。只有当我还通过 {{1} 取消引用 FBO 时} 以及随之而来的纹理,是否不会再发生崩溃。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。