从 uint64_t 图像句柄创建 image2D

Posted

技术标签:

【中文标题】从 uint64_t 图像句柄创建 image2D【英文标题】:Create an image2D from a uint64_t image handle 【发布时间】:2015-11-27 17:47:45 【问题描述】:

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

The extension description says:

采样器使用 64 位整数句柄表示,并且可以是 使用构造函数在 64 位整数之间转换。

图像使用 64 位整数句柄表示,并且可能是 使用构造函数在 64 位整数之间转换。

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

#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。如果有人能说明这是否适用于任何其他驱动程序/供应商的卡,我会很高兴。

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

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

【问题讨论】:

图像可以由计算着色器写入,而纹理是只读的。 扩展规范没有提到您正在使用的任何samperType(uint64_t)imageType(uint64_t) 构造函数。该扩展提供如下构造函数:any image type(uvec2) // Converts a pair of 32-bit unsigned integers to an image type。它根本没有提到uint64_t,它不是一种 GLSL 核心,也根本没有在这个扩展中定义。 你是对的,uint64_t 是在特定于供应商的扩展 GL_NV_gpu_shader5 中定义的。但是,这并不能改变问题。甚至写 image2D(uvec2(0));产生异常“从“uint64_t”隐式转换为“int””。 【参考方案1】:

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

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

需要多次指定格式。我不知道为什么,甚至根本不需要指定格式。规范对此非常模糊。

【讨论】:

这确实解决了问题。非常感谢!太糟糕了,编译器无法提供有用的错误消息。 我希望我能给你一个拥抱。你刚刚结束了长达数小时的斗争。奉耶稣的名,赐给你恩典与平安。

以上是关于从 uint64_t 图像句柄创建 image2D的主要内容,如果未能解决你的问题,请参考以下文章

如何将字节从 uint64_t 转换为 double?

从 uint8_t* 到 uint32_t 的无效转换 - 从 32 位架构迁移到 64 位架构时?

NSDecimalNumber 返回错误的 uint64_t 值

防止将 uint64_t 转换为 uint16_t

为啥 uint32_t 与 uint64_t 速度不同?

uint8_t / uint16_t / uint32_t /uint64_t数据类型详解