I've been reading over the Vulkan spec and some examples from Khronos but I can't find a lot of information on Immutable Samplers in general.
What I'm trying to do is have a descriptor set full of immutable samplers (of type VK_DESCRIPTOR_TYPE_SAMPLER, not ...COMBINED_IMAGE_SAMPLER) and when I want to sample a texture, I access the sampler like this in my shader:
layout (location = 0) out vec4 out_color;
layout (set = 0, binding = 0) uniform sampler immutableSampler;
layout (set = 3, binding = 0) uniform texture2D color;
void main()
{
vec4 textureColor = texture(sampler2D(color, immutableSampler), in_uv);
out_color = textureColor;
}
With this shader the idea is:
- In the pipeline layout I have an immutable sampler at binding point 0 in set 0
- I also have a descriptor set (3) with an image described at binding point 0 which I bind as part of my command buffer
- I apply the immutable sampler to the image in the shader
- Then actually access the image as a
sampler2D
However, the way I've seen it done in the Khronos sample is:
- Describe an immutable sampler of VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER at a bind point in the pipeline layout (providing only the sampler)
- Create an image and bind it to the same binding point (without a sampler)
- Access the image as a
sampler2D
in the shader; the image you've bound is paired with the immutable sampler at that binding
In the Vulkan spec it does not say which way is "correct" only noting that:
If
descriptorType
specifies aVK_DESCRIPTOR_TYPE_SAMPLER
orVK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER
type descriptor, thenpImmutableSamplers
can be used to initialize a set of immutable samplers.
Now if my shader just worked the way I expected I wouldn't be asking this question. The problem I'm running into is that upon validation the Vulkan layers complain that my VkPipeline is using a descriptor set (set 0, binding 0 where the sampler lives) which has never been bound! Even if I bind garbage data there I'm still going to have to (at least once) update the descriptor set with garbage just to suppress another validation error. However at the same time the Vulkan spec says:
Immutable samplers are permanently bound into the set layout; later binding a sampler into an immutable sampler slot in a descriptor set is not allowed
So binding data to that bind point wouldn't even be allowed!
I'm very unsure right now whether my approach to immutable samplers is even supposed to be valid as it's sort of ambiguous. The spec says I can bind a Sampler without an image but complains when I do and the few examples I've found are binding a Combined Image Sampler. Am I just doing this wrong?
If my approach is supposed to be valid and could work I'd really like that as I'm trying to architect a system for both DirectX 12 and Vulkan. DX12 has a place in its "root layout" (pipeline layout) where ALL immutable samplers are bound without images associated with them. I'd like to emulate this behavior to keep parity between the renderers but I'm very unsure if that's really possible with Vulkan and it's very ambiguous in the spec.