以下 OpenGL/GLFW/GLAD 代码(MCVE 版本)使进程崩溃,并在 nvoglv64.dll 中出现以下访问冲突异常:
0x00007FFC731F586F (nvoglv64.dll) in ConsoleApplication2.exe: 0xC0000005: Zugriffsverletzung beim Lesen an Position 0x0000000000024AA8.
在glfwDestroyWindow(window)
下面代码列表末尾的调用中,我不知道为什么。glTexPageCommitmentARB
当不调用或使用commit
of调用它时,此调用不会崩溃GL_FALSE/0
。
我现在已经阅读了三遍 ARB_sparse_texture的规范,检查了(x、y、z、宽度、高度、内部格式的页面大小的深度倍数)的每个参数的条件glTexPageCommitmentARB
,我有点确定我已经遵循有关如何正确使用该功能的所有说明。我之前也用调试上下文和调试消息回调检查了任何 OpenGL 错误,没有输出。
更多信息:
- 操作系统:Windows 10 x64 (20H2)
- 驱动程序:Nvidia 461.09 (DCH)
- GLAD 配置:OpenGL 4.3 核心 + ARB_sparse_texture + ARB_sparse_texture2
- GLFW:来自 Git 提交0b9e48fa3df9c18的全新本地 MSVC x64 发布版本
下面代码中调用之前的 fprintfglTexPageCommitmentARB
在程序结束时在崩溃之前打印以下输出:
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, "%s\n", "gladLoadGLLoader failed");
exit(2);
}
if (!GLAD_GL_ARB_sparse_texture || !GLAD_GL_ARB_sparse_texture2) {
fprintf(stderr, "%s\n", "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, height, 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_R16UI, GL_VIRTUAL_PAGE_SIZE_Y_ARB, 1, &height);
glGetInternalformativ(GL_TEXTURE_2D, GL_R16UI, GL_VIRTUAL_PAGE_SIZE_Z_ARB, 1, &depth);
glGetIntegerv(GL_MAX_SPARSE_TEXTURE_SIZE_ARB, &maxSparseTexSize);
fprintf(stderr, "%d %d %d %d\n", width, height, depth, maxSparseTexSize);
glTexStorage2D(
/*target*/GL_TEXTURE_2D,
/*levels*/1,
/*internalFormat*/GL_R16UI,
/*width*/maxSparseTexSize,
/*height*/maxSparseTexSize);
// commit one page at (0, 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();
}
我在这里遗漏了什么还是只是驱动程序或 GLFW 错误?
wglDeleteContext(...)
编辑:更多信息:在主线程调用GL 上下文之后,崩溃发生在驱动程序线程 (nvoglv64.dll)中。当 Visual Studio 2019 调试器因异常停止时,我可以看到存在三个驱动程序线程(全部来自 nvoglv64.dll)(其中一个发出访问冲突异常),而主线程在wglDeleteContext(...)
.
EDIT2:对此进行更多实验,当纹理未被取消引用(参考计数为 0)并在销毁 GL 上下文之前由驱动程序处理时,总是发生崩溃。例如,在上面的代码中,当我 glDeleteTextures(1, &tex);
之前调用时glDestroyWindow(window)
,不会发生崩溃(可重现)。在实际应用程序中,我从中提取了上述 MCVE,纹理也作为颜色附件附加在 FBO 中。当我没有删除FBO 而只是减少了纹理的引用计数时(通过调用glDeleteTextures(...)
,崩溃仍然会发生。只有当我也取消引用 FBOglDeleteFramebuffers(...)
和纹理连同它时,才会不再发生崩溃。