在 imageStore() 之后为 3D 纹理生成 MipMap 级别
Generating the MipMap levels for a 3D texture after imageStore()
我想创建一个 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()
处生成分段错误。
我是不是在内存屏障中遗漏了一点,还是在创建纹理时没有分配足够的内存?我做错了什么?
您使用 glMemoryBarrier
的方式有误。你应该给这个函数的位域是你想要使用结果的方式。对于mipmap生成,不需要使用内存屏障。
您正在使用 glGenerateTextureMipmap
,但您没有使用 glCreateTextures
。为什么您有时只想使用 DSA。在任何地方使用 DSA 或不使用它(对于 glTextureParameteri、glTextureStorage3D... 也会发生同样的情况)。
您正在使用 glTexImage3D
,请改用 glTextureStorage3D
。它将节省您 "useless" 向量
的构造
您正在使用非 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
时,您明确要求层,因此当驱动程序进行分配时,它将分配所有内容,而不仅仅是一个
我想创建一个 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()
处生成分段错误。
我是不是在内存屏障中遗漏了一点,还是在创建纹理时没有分配足够的内存?我做错了什么?
您使用 glMemoryBarrier
的方式有误。你应该给这个函数的位域是你想要使用结果的方式。对于mipmap生成,不需要使用内存屏障。
您正在使用 glGenerateTextureMipmap
,但您没有使用 glCreateTextures
。为什么您有时只想使用 DSA。在任何地方使用 DSA 或不使用它(对于 glTextureParameteri、glTextureStorage3D... 也会发生同样的情况)。
您正在使用 glTexImage3D
,请改用 glTextureStorage3D
。它将节省您 "useless" 向量
您正在使用非 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
时,您明确要求层,因此当驱动程序进行分配时,它将分配所有内容,而不仅仅是一个