0

I need to index into array of 2 uniform sampler2D. The index is dynamic per frame.That's,I have a dynamic uniform buffer which provides that index to a fragment shader. I use Vulkan API 1.2. In device feature listing I have:

shaderSampledImageArrayDynamicIndexing = 1

I am not sure 100% but It looks like this feature is core in 1.2.Nevertheless I did try to enable it during device creation like this:

       VkPhysicalDeviceFeatures features = {}; 
       features.shaderSampledImageArrayDynamicIndexing = VK_TRUE;
     

Then plugging into device creation:

    VkDeviceCreateInfo deviceCreateInfo = {};
    deviceCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
    deviceCreateInfo.pQueueCreateInfos = queueCreateInfos;
    deviceCreateInfo.queueCreateInfoCount = 1;
    deviceCreateInfo.pEnabledFeatures = &features ;
    deviceCreateInfo.enabledExtensionCount = NUM_DEVICE_EXTENSIONS;
    deviceCreateInfo.ppEnabledExtensionNames = deviceExtensionNames;

In the shader it looks like this:

   layout(std140,set=0,binding=1)uniform Material
   {
    vec4   fparams0;
    vec4   fparams1; 
    uvec4  iparams; //.z - array texture idx
    uvec4  iparams1;
   }material;


   layout (set=1,binding = 0)uniform sampler2D u_ColorMaps[2];
   layout (location = 0)in vec2 texCoord;
   layout(location = 0) out vec4 outColor;
   void main()
   {

      outColor  =  texture(u_ColorMaps[material.iparams.z],texCoord);
     
   }
   

What I get is a combination of image pixels with some weird color. If I change to fixed indices - it works correctly. material.iparams.z param has been verified,it provides correct index number every frame (0 or 1). No idea what else is missing.Validation layers say nothing.

Mys setup: Windows, RTX3000 ,NVIDIA beta driver 443.41 (Vulkan 1.2)

Update:

I also found that dynamically indexed sampler return a value in Red channel (r) which is close to one and zeros in GB. I don't set red color anyway,also the textures I fetch don't contain red. Here are two sreenshot, the upper is correct result which I get when indexing with constant value. Second is what happens when I index with dynamic uint which comes from dynamic UBO:

Correct enter image description here

Wrong enter image description here

6
  • "nonuniformEXT" What is this supposed to do, and why are you claiming that something isn't uniform when it very definitely is? The value you're using as an index is a uniform. Commented Jul 22, 2020 at 13:25
  • @NicolBolas forget about this function,just tried it to see what happens.Will edit this part.It doesn't work without it either. Commented Jul 22, 2020 at 13:39
  • How is that? By "dynamic indexing" I mean that before rendering the frame I update material.iparams.z via uniform buffer. Of course this is dynamic indexing! Using fixed values I have no problems here. And I don't see any reason for voting this question for closing as this is actually a well defined problem. Commented Jul 22, 2020 at 13:49
  • @NicolBolas also,in Vulkan at least the dynamic indexing is of two types: 1) Indexing from a uniform 2)indexing from a varying value. Both are possible and nonuniformEXT exists for the second case when the indexing changes across the current draw call.In my case it doesn't as it comes from the uniform buffer which is updated once before running the command buffer. Commented Jul 22, 2020 at 13:52
  • Hmm, I am successfully using this approach in some shaders of mine. Have you enabled GL_EXT_nonuniform_qualifier in your shader(s)? #version 460 #extension GL_EXT_nonuniform_qualifier : require is what I am using. Furthermore: How are you creating the descriptor set for the array of samplers? Maybe you could post the code for that?! Commented Jul 23, 2020 at 14:03

1 Answer 1

5

The problem was due to usage of Y′CBCR samplers. It appears that Vulkan disallows indexing dynamically into array of such uniforms.

Here is what Vulkan specs says:

If the combined image sampler enables sampler Y′CBCR conversion or samples a subsampled image, it must be indexed only by constant integral expressions when aggregated into arrays in shader code, irrespective of the shaderSampledImageArrayDynamicIndexing feature.

So,the solution for me was to provide two separately bound samplers and use dynamic indices with if()..else condition to decide which sampler to use. Push constants would also work,but in this case I have to re-record command buffers all the time. Hopefully this info will be helpful to other people working with video formats in Vulkan API.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.