如何使用具有非标准化纹理坐标的 vulkan 采样器? (不触发 VUID-vkCmdDrawIndexed-None-02703)
How to use a vulkan sampler with unnormalized texture-coordinates? (without triggering VUID-vkCmdDrawIndexed-None-02703)
所以我一直在我的纹理采样器中使用非标准化坐标,因为我发现在将纹理用作精灵图集时更容易处理纹理的某些部分。今天我修补了我的工作站并重新编译了所有东西,验证层开始报告这个错误:
Validation Error: [ VUID-vkCmdDrawIndexed-None-02703 ] Object 0:
handle = 0x210000000021, type = VK_OBJECT_TYPE_DESCRIPTOR_SET; Object
1: handle = 0x1c000000001c, type = VK_OBJECT_TYPE_IMAGE_VIEW; Object
2: handle = 0x1f000000001f, type = VK_OBJECT_TYPE_SAMPLER; | MessageID
= 0x30c87f64 | VkDescriptorSet 0x210000000021[] encountered the following validation error at vkCmdDrawIndexed() time: VkImageView
0x1c000000001c[] in Descriptor in binding #0 index 0 is used by
VkSampler 0x1f000000001f[] that uses invalid operator. The Vulkan spec
states: If the VkPipeline object bound to the pipeline bind point used
by this command accesses a VkSampler object that uses unnormalized
coordinates, that sampler must not be used with any of the SPIR-V
OpImageSample* or OpImageSparseSample* instructions with ImplicitLod,
Dref or Proj in their name, in any shader stage
(https://www.khronos.org/registry/vulkan/specs/1.2-extensions/html/vkspec.html#VUID-vkCmdDrawIndexed-None-02703)
我知道在使用非标准化纹理坐标时有各种限制,例如没有 mipmaps 或各向异性。这是规范中的(我认为)相关部分:
https://www.khronos.org/registry/vulkan/specs/1.2-extensions/man/html/VkSamplerCreateInfo.html
unnormalizedCoordinates controls whether to use unnormalized or
normalized texel coordinates to address texels of the image. When set
to VK_TRUE, the range of the image coordinates used to lookup the
texel is in the range of zero to the image dimensions for x, y and z.
When set to VK_FALSE the range of image coordinates is zero to one.
When unnormalizedCoordinates is VK_TRUE, images the sampler is used
with in the shader have the following requirements:
The viewType must be either VK_IMAGE_VIEW_TYPE_1D or VK_IMAGE_VIEW_TYPE_2D.
The image view must have a single layer and a single mip level.
When unnormalizedCoordinates is VK_TRUE, image built-in functions in
the shader that use the sampler have the following requirements:
The functions must not use projection.
The functions must not use offsets.
我满足所有这些要求,除非“投影”和“偏移”是指“渲染纹理期间发生的事情”。
如果是这种情况并且在渲染部分纹理时不能使用未归一化的纹理坐标,那么:
我不明白这个功能是干什么用的。 在哪里以及为什么要使用非标准化的纹理坐标?此外,许多教程会像这里一样“误导”:
https://vulkan-tutorial.com/en/Texture_mapping/Image_view_and_sampler
The unnormalizedCoordinates field specifies which coordinate system
you want to use to address texels in an image. If this field is
VK_TRUE, then you can simply use coordinates within the [0, texWidth)
and [0, texHeight) range. If it is VK_FALSE, then the texels are
addressed using the [0, 1) range on all axes. Real-world applications
almost always use normalized coordinates, because then it's possible
to use textures of varying resolutions with the exact same
coordinates.
这(仅作为示例)听起来像是个人喜好而不是“方法 a 有效,方法 b 只能用于特殊情况,很可能不是你想要的”。确实 --> 当我更改示例以使用非标准化纹理坐标时,会报告相同的验证错误。那么有人可以解释这里发生了什么吗?
谢谢!
In the shader the texture is accessed with texture (sampler2D, uv)
那是你的问题。 GLSL 是针对 OpenGL 而不是 Vulkan 编写的。因此,它不知道 Vulkan 允许的某些 OpenGL 通常不允许的事情。在 OpenGL 中,texture
函数总是使用规范化的纹理坐标。唯一不会出现的情况是您使用 rectangle textures,这是与 2D 纹理不同的纹理类型。它们是没有 Vulkan 模拟的 OpenGL 功能,因为在 Vulkan 中,您可以将任何纹理视为“矩形纹理”(“矩形纹理”的唯一真正特征是您可以使用它们的非标准化纹理坐标)。
我在 GL_KHR_vulkan_glsl extension 中没有看到允许 texture
函数使用非标准化纹理坐标的机制。所以你必须找到另一种方法来生成你的 SPIR-V,或者你需要直接编写 SPIR-V。
这是 Khrono 论坛上 post 的重复,unnormalized texture coords here 上有一个未解决的问题。
任何形式的调用:
vec4 val = texture( unormSampler, pixelCoord );
其中 unormSampler 包含非规范化采样器导致 SPIR-V 操作码 87,这是指令 OpImageSampleImplicitLod。 vulkan 规范(如您所述)明确排除了任何未规范化纹理读取的此指令。
但是:
SPIR-V 操作码 88 是未规范化王国的秘钥。 OpCode 88 指令是 OpImageSampleExplicitLod。在 Vulkan 规范的任何地方都没有列出(据我所知)这是使用非规范化采样器的非法操作。
映射到操作码 88 的秘密 GLSL 指令是 textureLod。这是使用它的代码示例。
// Set this up just like usual, except use a unnormalized sampler
layout(binding = 23) uniform sampler2D unormSampler;
void main()
{
vec4 val = textureLod( unormSampler, pixelCoord, 0); // 0 is the mipmap level to sample from
}
我没有尝试其他的 mipmap 级别(我依稀记得 Vulkan 规范说了一些关于不使用非标准化坐标的 mipmap。)。
我确实为示例尝试了 VK_FILTER_LINEAR 和 VK_FILTER_NEAREST,它们都按预期工作。 (我的测试有使用 VK_FILTER_NEAREST 时出现的伪影)
以下是不适用于 GLSL、Vulkan 和非规范化采样器的列表:
- 使用 sampler2Drect – 在加载 SPIR-V 模块时产生错误
使用任何版本的纹理(blablabla); – 导致操作码 87,根据 Vulkan 规范
使用 samplerBuffer 的——规范再次拒绝使用非规范化采样器
所以我一直在我的纹理采样器中使用非标准化坐标,因为我发现在将纹理用作精灵图集时更容易处理纹理的某些部分。今天我修补了我的工作站并重新编译了所有东西,验证层开始报告这个错误:
Validation Error: [ VUID-vkCmdDrawIndexed-None-02703 ] Object 0: handle = 0x210000000021, type = VK_OBJECT_TYPE_DESCRIPTOR_SET; Object 1: handle = 0x1c000000001c, type = VK_OBJECT_TYPE_IMAGE_VIEW; Object 2: handle = 0x1f000000001f, type = VK_OBJECT_TYPE_SAMPLER; | MessageID = 0x30c87f64 | VkDescriptorSet 0x210000000021[] encountered the following validation error at vkCmdDrawIndexed() time: VkImageView 0x1c000000001c[] in Descriptor in binding #0 index 0 is used by VkSampler 0x1f000000001f[] that uses invalid operator. The Vulkan spec states: If the VkPipeline object bound to the pipeline bind point used by this command accesses a VkSampler object that uses unnormalized coordinates, that sampler must not be used with any of the SPIR-V OpImageSample* or OpImageSparseSample* instructions with ImplicitLod, Dref or Proj in their name, in any shader stage (https://www.khronos.org/registry/vulkan/specs/1.2-extensions/html/vkspec.html#VUID-vkCmdDrawIndexed-None-02703)
我知道在使用非标准化纹理坐标时有各种限制,例如没有 mipmaps 或各向异性。这是规范中的(我认为)相关部分: https://www.khronos.org/registry/vulkan/specs/1.2-extensions/man/html/VkSamplerCreateInfo.html
unnormalizedCoordinates controls whether to use unnormalized or normalized texel coordinates to address texels of the image. When set to VK_TRUE, the range of the image coordinates used to lookup the texel is in the range of zero to the image dimensions for x, y and z. When set to VK_FALSE the range of image coordinates is zero to one.
When unnormalizedCoordinates is VK_TRUE, images the sampler is used with in the shader have the following requirements:
The viewType must be either VK_IMAGE_VIEW_TYPE_1D or VK_IMAGE_VIEW_TYPE_2D. The image view must have a single layer and a single mip level.
When unnormalizedCoordinates is VK_TRUE, image built-in functions in the shader that use the sampler have the following requirements:
The functions must not use projection. The functions must not use offsets.
我满足所有这些要求,除非“投影”和“偏移”是指“渲染纹理期间发生的事情”。
如果是这种情况并且在渲染部分纹理时不能使用未归一化的纹理坐标,那么: 我不明白这个功能是干什么用的。 在哪里以及为什么要使用非标准化的纹理坐标?此外,许多教程会像这里一样“误导”: https://vulkan-tutorial.com/en/Texture_mapping/Image_view_and_sampler
The unnormalizedCoordinates field specifies which coordinate system you want to use to address texels in an image. If this field is VK_TRUE, then you can simply use coordinates within the [0, texWidth) and [0, texHeight) range. If it is VK_FALSE, then the texels are addressed using the [0, 1) range on all axes. Real-world applications almost always use normalized coordinates, because then it's possible to use textures of varying resolutions with the exact same coordinates.
这(仅作为示例)听起来像是个人喜好而不是“方法 a 有效,方法 b 只能用于特殊情况,很可能不是你想要的”。确实 --> 当我更改示例以使用非标准化纹理坐标时,会报告相同的验证错误。那么有人可以解释这里发生了什么吗?
谢谢!
In the shader the texture is accessed with texture (sampler2D, uv)
那是你的问题。 GLSL 是针对 OpenGL 而不是 Vulkan 编写的。因此,它不知道 Vulkan 允许的某些 OpenGL 通常不允许的事情。在 OpenGL 中,texture
函数总是使用规范化的纹理坐标。唯一不会出现的情况是您使用 rectangle textures,这是与 2D 纹理不同的纹理类型。它们是没有 Vulkan 模拟的 OpenGL 功能,因为在 Vulkan 中,您可以将任何纹理视为“矩形纹理”(“矩形纹理”的唯一真正特征是您可以使用它们的非标准化纹理坐标)。
我在 GL_KHR_vulkan_glsl extension 中没有看到允许 texture
函数使用非标准化纹理坐标的机制。所以你必须找到另一种方法来生成你的 SPIR-V,或者你需要直接编写 SPIR-V。
这是 Khrono 论坛上 post 的重复,unnormalized texture coords here 上有一个未解决的问题。
任何形式的调用:
vec4 val = texture( unormSampler, pixelCoord );
其中 unormSampler 包含非规范化采样器导致 SPIR-V 操作码 87,这是指令 OpImageSampleImplicitLod。 vulkan 规范(如您所述)明确排除了任何未规范化纹理读取的此指令。
但是:
SPIR-V 操作码 88 是未规范化王国的秘钥。 OpCode 88 指令是 OpImageSampleExplicitLod。在 Vulkan 规范的任何地方都没有列出(据我所知)这是使用非规范化采样器的非法操作。
映射到操作码 88 的秘密 GLSL 指令是 textureLod。这是使用它的代码示例。
// Set this up just like usual, except use a unnormalized sampler
layout(binding = 23) uniform sampler2D unormSampler;
void main()
{
vec4 val = textureLod( unormSampler, pixelCoord, 0); // 0 is the mipmap level to sample from
}
我没有尝试其他的 mipmap 级别(我依稀记得 Vulkan 规范说了一些关于不使用非标准化坐标的 mipmap。)。
我确实为示例尝试了 VK_FILTER_LINEAR 和 VK_FILTER_NEAREST,它们都按预期工作。 (我的测试有使用 VK_FILTER_NEAREST 时出现的伪影)
以下是不适用于 GLSL、Vulkan 和非规范化采样器的列表:
- 使用 sampler2Drect – 在加载 SPIR-V 模块时产生错误
使用任何版本的纹理(blablabla); – 导致操作码 87,根据 Vulkan 规范
使用 samplerBuffer 的——规范再次拒绝使用非规范化采样器