vulkanvalidation-layers

How to use a vulkan sampler with unnormalized texture-coordinates? (without triggering VUID-vkCmdDrawIndexed-None-02703)


So I have been using unnormalized coordinates in my texture-sampler since I find it easier to address certain parts of a texture when using it as a sprite atlas. Today I patched my workstation and recompiled everything and this error started to get reported by the validation layers:

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)

I know there are various restrictions when using unnormalized texture coordinates like no mipmaps or anisotropy. Here is the (i think) relevant part from the spec: 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.

I meet all these requirements unless "projection" and "offsets" means "stuff that happens during rendering the texture".

If that is the case and unnormalized texture-coordinates cannot be used while rendering parts of the texture then: I don't understand what this feature is for. Where and why would one use unnormalized texture coordinates? Furthermore many tutorials would be "missleading" like here: 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.

This (just as an example) sounds like personal preference and not "method a works and method b can only be used in special circumstances and is most likely not what you want". Indeed --> when I change the sample to use unnormalized texture-coordinates the same validation-error gets reported. So can someone explain what is going on here?

Thank you!


Solution

  • In the shader the texture is accessed with texture (sampler2D, uv)

    Well there's your problem. GLSL was written against OpenGL, not Vulkan. As such, it doesn't know about some of the things Vulkan allows that OpenGL normally doesn't. In OpenGL, the texture function always uses normalized texture coordinates. The only time it doesn't is if you're using rectangle textures, which are a different texture type from 2D textures. They are an OpenGL feature that has no Vulkan analog, because in Vulkan, you can treat any texture as a "rectangle texture" (the only real feature of "rectangle textures" is that you can use non-normalized texture coordinates with them).

    I don't see a mechanism in the GL_KHR_vulkan_glsl extension that would allow the texture function to use non-normalized texture coordinates. So you'd have to find an alternative way to generate your SPIR-V, or you'll need to write the SPIR-V directly.