looking for an explanation on how to bind more than 80 textures to a Vulkan pipeline on MacOS.
TLDR: MacOS/MoltenVK has a limitation of 80 unique samplers bound at once. CombinedImageSamplers count against that limit, even if only one sampler handle is shared amongst all sampled images. Lastly, it seems that SPIR-V does not support bindless texture arrays if I were to try and split out my descriptors into a single Sampler and a bindless array of sampled images. What is the solution?
Long explanation below:
I am currently working on portability and being explicit about hardware requirements for my Vulkan renderer. I used the fantastic vulkan.gpuinfo.org site to get upper bounds on descriptor counts per type so I can check against those maximums when allocating descriptor sets. (I have to program defensively and proactively because my driver is very permissive and returns a VK_SUCCESS status with no validation errors if I over allocate my descriptor pools).
When it comes to samplers, for example, I have the UpdateAfterBind bit set on my set allocation calls and my pools. According to gpuinfo.org, approximately 99% of reported Windows and Linux devices have support for 65536 samplers bound to a pipeline when the sets are created with the UPDATE_AFTER_BIND flag set. This is obviously more than sufficient.
However, MacOS can only support 80 samplers bound to a pipeline even when the sets are created with the UPDATE_AFTER_BIND flag.
https://vulkan.gpuinfo.org/displaycoreproperty.php?platform=linux&name=maxDescriptorSetUpdateAfterBindSamplers&core=1.2
I was previously using CombinedImageSamplers, but each one of those counts against the sampler count in maxDescriptorSetUpdateAfterBindSamplers
. (Example, 640 combinedImageSamplers == 640 samplers and 640 sampled images). I thought I could solve this by splitting out my descriptors into a single sampler and the array of sampled images like below:
layout (set = 1, binding = 2) uniform texture2D textures[];
layout (set = 1, binding = 3) uniform sampler textureSampler;
However - I can't do this because it seems that glslang cannot compile GLSL into SPIR-V when bindless textures are at play (it can however compile combined sampled images with no problem, see below) layout (set = 1, binding = 2) uniform sampler2D textures[];
In summary, the hardware maximums for MacOS are prohibitively low - for those that have Vulkan renderers that support MacOS - how are you getting around the 80 sampler limit for maxDescriptorSetUpdateAfterBindSamplers
?
Please let me know if you need more information.
I am able to create a descriptor set layout with 80 or fewer CombinedImageSampler descriptors, and can access it in my shader by
layout (set = 1, binding = 2) uniform sampler2D textures[];
I am unable to get my GLSL to compile to SPIR-V if I modify the GLSL to accept a single sampler and a Texture2D array like below:
layout (set = 1, binding = 2) uniform texture2D textures[];
layout (set = 1, binding = 3) uniform sampler textureSampler;
So, it seems I am stuck using combined image samplers, which would be fine except for the 80 unique sampler limitation.
Without knowing what code your shader contains: just based on your bindings, the shader should compile. Perhaps you can provide the full code, or the errors which your compiler is generating?
The following glsl code compiles without a problem using glslangvalidator and glslc.
Regarding hardware limits on Mac: you can use separate samplers and textures to provide a large number of bindless textures via two descriptors (one sampler, one texture2Darray). In my engine I use the following layout, with 2048 texture layers per array. This provides 120*2048=245760 texture layers.
If limiting yourself to Metal 3 compatible hardware, you might want to look into MoltenVK and configuring it with MVK_CONFIG_USE_METAL_ARGUMENT_BUFFERS. See https://github.com/KhronosGroup/MoltenVK
P.S.: I would have preferred to start off by commenting, but cannot due to the lack of reputation. Hopefully my answer will help you nonetheless.