从 uint64_t 图像句柄创建 image2D

Create an image2D from a uint64_t image handle

要在 OpenGL 中使用无绑定图像,您需要使用 glGetImageHandleARB 创建一个 GLuint64 句柄。然后,您可以将此句柄设置为统一的 image2D 变量,并像使用旧方法一样使用图像。没问题。使用 textures/samplers,还可以将(纹理)句柄设置为不是 sampler2D,而是普通的统一 uint64_t 变量。然后可以使用此句柄在运行时使用构造函数 sampler2D(handle).

“构造”采样器对象

The extension description says:

Samplers are represented using 64-bit integer handles, and may be converted to and from 64-bit integers using constructors.

Images are represented using 64-bit integer handles, and may be converted to and from 64-bit integers using constructors.

所以我假设图像的构建方式与采样器的构建方式相同,但事实并非如此。示例代码:

#version 450
#extension GL_ARB_bindless_texture : enable
#extension GL_NV_gpu_shader5 : enable

layout(bindless_image, rgba8) uniform image2D myBindlessImage;

uniform uint64_t textureHandle;
uniform uint64_t imageHandle;

void main()
{
    sampler2D mySampler = sampler2D(textureHandle); // works like a charm
    ... = texture(mySampler, texCoord);

    ... = imageLoad(myBindlessImage, texCoordI); // works like a charm

    layout(rgba8) image2D myImage = image2D(imageHandle); // error C7011: implicit cast from "uint64_t" to "int"
    ... = imageLoad(myImage, texCoordI);
}

显然,编译器不知道扩展描述中提到的 image2D(uint64_t) 构造函数和 image2D(uvec2) 构造函数。我在这里遗漏了什么,或者这只是现在没有实施,虽然它应该是?我现在用的显卡驱动是Nvidia的355.82。如果有人能说明这是否适用于任何其他 driver/vendor 的卡,我将很高兴。

顺便说一下,我为什么需要这个功能:与纹理句柄相比,图像句柄不识别整个底层数据,而只识别一个纹理级别。如果您想在着色器中执行任何 mipmap 或其他分层工作并且需要绑定 several/all 纹理级别,您可以在缓冲区中提供所有级别的句柄,然后根据需要在着色器运行时构建它们。现在,您必须为您的 n 个纹理级别定义 n 个不同的统一 image2D,这相当繁琐,尤其是在图像大小发生变化的情况下。

附录:重现编译错误的最快方法是将 image2D(0lu); 放在着色器代码中的某处。

您使用的语法有误。将 uint64_t 转换为图像的正确语法是:

layout(rgba8) image2D myImage = layout(rgba8) image2D(imageHandle);

需要多次指定格式。我不知道为什么,也不知道为什么它甚至需要指定格式。规范对此含糊不清。