【问题标题】:Generating the MipMap levels for a 3D texture after imageStore()在 imageStore() 之后为 3D 纹理生成 MipMap 级别
【发布时间】:2019-01-03 22:55:17
【问题描述】:

我想创建一个 3D 纹理,将最低(0 级)mipmap 级别设置为在着色器中生成的一些数据,然后自动填充其余的 mipmap 级别。

我按如下方式创建纹理:

//Initialize texture dimensions
width = w;
height = h;
depth = d;
//set the texture rendering target, always GL_TEXTURE3D for 3D images
target = GL_TEXTURE_3D;
//Create the texture
glGenTextures(1, &textureID);
glBindTexture(target, textureID);
glObjectLabel(GL_TEXTURE, textureID, -1, "\"3D Texture\"");
//Set the texture sampling parameters
glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
glTexParameteri(target, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_BORDER);
glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
//Allocate VRAM storage for the texture
vector<GLbyte> empty = vector<GLbyte>(width*height*depth*(32));
glTexImage3D(target, 0, GL_RGBA8, width, height, depth, 0,
    GL_RGBA, GL_FLOAT, empty.data());

然后,我使用 imageStore 在着色器中写入它(按 LOD 0 的预期工作)。

然后我尝试像这样生成 mipmap 级别:

glDrawArrays(GL_TRIANGLE_STRIP,0,4);
glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
glGenerateTextureMipmap(textureID);

但是,这会导致在 glGenerateTextureMipmap() 处生成分段错误。

我是在内存屏障中遗漏了一点,还是在创建纹理时没有分配足够的内存?我做错了什么?

【问题讨论】:

  • sizeof(GLfloat) 在您的 vector 构造函数中是怎么回事?如果你想要字节不应该是vector&lt;unsigned char&gt;
  • 你是对的,那是我的错,我已经更改它并验证它适用于当前版本。它应该是 8*4(每个组件 8 个字节的组件数量)我搞砸了,谢谢你的注意。然而,分段错误本身并没有消失
  • 你确定你 glGenerateTextureMipmap()吗?那是4.5的功能。检查该函数指针是否实际上不为 NULL。
  • @derhass 我正在运行 OpenGL 4.6(至少 glGetString() 报告是这样)。此外,我在另一部分调用了该函数,但它没有出现段错误。所以至少它不是空指针。
  • 对于内存屏障本身,请参阅Which memory barrier does glGenerateMipmap require?。对于崩溃,我不知道是什么原因造成的。

标签: c++ opengl segmentation-fault textures mipmaps


【解决方案1】:

您以错误的方式使用glMemoryBarrier。你应该给这个函数的位域是你想要使用结果的方式。对于 mipmap 的生成,不需要使用内存屏障。

您正在使用glGenerateTextureMipmap,但您没有使用glCreateTextures。为什么您有时只想使用 DSA。在任何地方都使用 DSA 或不使用它(glTextureParameteri、glTextureStorage3D...也是如此)。

您正在使用glTexImage3D,请改用glTextureStorage3D。它将为您节省“无用”向量的构建

您使用的是非 mipmap 过滤,所以请使用类似GL_NEAREST_MIPMAP_NEAREST 的 mipmap 过滤。我不知道这是否是导致崩溃的原因,但这是第一个想法。

告诉我们当您更正代码时会发生什么;)。 如果 ARB_DEBUG_OUTPUT 的输出告诉你什么,也许你可以给我们。


关于崩溃,似乎使用glTexStorage3D 可以解决问题。我没有证据,我可能是错的,但我怀疑这种工作: glTexImage3D 不分配内存,而是使用纹理进行分配。 (这就是为什么我更喜欢 Vulkan,因为它是明确的)。

所以,当您在没有 glGenerateMipmap3D 的情况下执行 glTexImage3D 时,会发生以下情况:

使用glTexImage3D:假设我们需要这个尺寸的图像。使用纹理:驱动程序看到不需要 mipmapping,因此尽管有 GL_TEXTURE_MAX_LEVEL,它只分配一个驱动程序。调用 generateMipmap : 崩溃,因为驱动程序试图到达尚未分配的其他层

第二种方式,使用前先使用generateMipmap:

glTexImage3D + generateMipmap :我需要一张带有 mipmap 的图片。当您使用它时,驱动程序会看到您确实需要所有层,因此它将分配所需的层。

当您使用glTextureStorage3D 时,您明确要求层,因此当驱动程序进行分配时,它将分配所有内容而不仅仅是一个

【讨论】:

  • 我可以告诉你一些事情。将 glGenTextureMipmap 放在开头,在渲染循环之前,然后再次调用它解决了分段错误。而且那个“无用”的向量也不是没用的。在 NVIDIA 卡上,驱动程序会清除分配的内存,但在 AMD 卡上不会。我的算法要求将纹理初始化为 0。所以在 AMD 卡上它会中断。 “空”向量基本上保证了与 AMD 卡的兼容性。
  • 如果我通过 glGenTextures 手动初始化所​​有内容,我也不需要调用 glCreateTextures。
  • 我认为你的 CPU 根本不关心纹理的“初始化”。请使用 glClearTexImage 或等效的以更有效的方式清除您的纹理:)
  • 引用 OpenGL 参考 glClearTexImage :If data is NULL, then the pointer is ignored and the sub-range of the texture image is filled with zeros. 我认为这是您想要的,无需构建矢量。
  • 很抱歉这是一个错字。 (Je m'excuse, c'etait pas intentnel)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-09-16
相关资源
最近更新 更多