So, searching the forum for Vulkan and Bindless lead to this question from 2+ years ago. That being said, it’s worth revisiting to clarify matters.
Vulkan doesn’t need bindless textures in the same way that OpenGL does. That doesn’t make the idea of bindless worthless in Vulkan. It’s just that in OpenGL, one of the main reasons to use it is to avoid the cost of changing texture bindings, which is a fundamentally costly operation.
Modifying descriptor sets is a costly operation in Vulkan, but not nearly so much as changing bindings in OpenGL. The main issue in Vulkan is that you have to do the synchronization yourself, unless you have otherwise ensured that the descriptor set you are modifying is not being used by a rendering command that has not completed execution. Generally speaking, you would be swapping descriptor sets in the middle of a scene, not modifying them.
While that might be cheaper than OpenGL texture binding, it’s not as cheap as possible. It still represents a state change, so it costs something. And probably more of a “something” than a push constant change.
You can still get most of the effects of “bindless” textures by using a sampler array. And I don’t mean an array texture; I mean a sampler2D[Count] array. In OpenGL, such an array would consume Count individual texture units. But in Vulkan, that entire array is a single descriptor location; it is an arrayed descriptor.
In Vulkan, the limits on number of sampled images, storage images, and samplers per stage and total are governed by several individual limitations. On modern desktop hardware, you’ll find that the limits on sampled images and storage images are… large. Intel supports between 768 and 1200 sampled images, with NVIDIA and AMD supporting thousands, if not MAX_UINT.
The point being that the number of such images isn’t a particular problem (the “minimum guaranteed” is low, but real implementation limits are not). But there is one potential problem.
If the implementation does not offer the feature shaderSampledImageArrayDynamicIndexing (or you don’t turn it on), then you cannot sample from an array of sampled images/textures with an index which is not a compile-time constant. And not every implementation offers that feature, though all desktop implementations do.
Now, I could point out that doing this limits you to only using dynamically uniform indices. But that limitation also exists for ARB_bindless_texture; it’s only NVIDIA’s NV_gpu_shader5 that removes that limitation.
With all of that in hand, you can effectively build the equivalent of bindless texturing. Making an image resident and getting its “handle” is equivalent to just putting the texture in the descriptor array. Converting the “handle” into a texture means fetching the texture from the sampler array. The mapping is pretty close to 1:1.
VK_EXT_descriptor_indexing provides features that make descriptor arrays like this even more flexible with regard to implementing “bindless” of this form.
NVIDIA is currently exploring VK_NVX_image_view_handle, which is the API side of bindless texturing. But there is no SPIR-V extension to consume this handle, so the extension by itself isn’t worth much.