如何在 glsl 着色器中读取具有 R8_UINT 格式和 SAMPLED_IMAGE 描述符类型的 3D 图像?

How can I read a 3D image with R8_UINT format and SAMPLED_IMAGE descriptor type in a glsl shader?

我正在使用 vulkan 创建 3D 图像 (VK_IMAGE_TYPE_3D),每个纹素格式 (VK_FORMAT_R8_UINT) 有一个无符号 8 位整数。此图像附加到一个描述符集,该描述符集的类型为 VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,该描述符集提供给 glsl 着色器。我需要这样做的原因是因为 3D 图像代表体素数据,每个纹素的 8 位代表该体素的 material 数组中的索引。

问题是我无法找到一种方法来获取与图像坐标对应的 8 位无符号整数(从图像中读取数据)。我尝试了以下方法:

附加到 uimage3D

layout (binding = 2, r8ui) uniform uimage3D scene;imageLoad(scene, ivec3(0,0,0)).r

但这会导致验证层错误

Type mismatch on descriptor slot 0.2 (expected VK_DESCRIPTOR_TYPE_STORAGE_IMAGE) but descriptor of type VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE The Vulkan spec states: layout must be consistent with the layout of the compute shader specified in stage (https://www.khronos.org/registry/vulkan/specs/1.2-extensions/html/vkspec.html#VUID-VkComputePipelineCreateInfo-layout-00703)

不过我不想使用存储映像,因为我需要优化映像以实现快速只读访问。

附加到 texture3D

layout (binding = 2, r8ui) uniform texture3D scene;导致着色器编译错误:

error: 'r8ui' : only apply to images

I don't want to use a storage image though because I need the image to be optimized for fast read-only access.

这不是使用采样图像的作用。

如果你想使用一个图像作为采样图像,那就意味着你想使用capabilities of samplers。你想通过归一化坐标访问像素,或者你想进行过滤、纹理坐标环绕、自动 mipmap 选择,或类似的东西。

您没有使用采样图像,因为您希望只读访问速度更快。这就是存储映像具有 readonly layout 限定符的原因。

如果您只想只读访问图像的单个 mipmap 级别,使用整数纹素坐标而不进行过滤或环绕,那么您需要的是存储图像。

但是,如果您确实想要使用采样图像,那么您必须遵循采样图像的规则。特别是,您没有在着色器中指定它们的格式。您指定格式的一般类别(浮点数、有符号整数和无符号整数),但这是由变量类型指定的(sampler3D vs. isampler3D vs. usampler3D, 分别).

您还需要一个采样器,通过描述符中指定的组合 sampler/image 对(映射到 GLSL samplerX 类型)或通过两个单独的变量:一个 texture类型和 sampler 类型,着色器将自行组合。