Modifying a HLSL shader to work in Vulkan, do I have to separate textures/samplers?

1.9k views Asked by At

I'm modifying a HLSL shader used in D3D12 to compile to SPIR-V because I want to use the same shader code in Vulkan. Here's the shader:

#if !VULKAN
#define layout(a)  
#else
#define register(a) blank
#endif

struct VSOutput
{
    float4 pos : SV_Position;
    float2 uv : TEXCOORD;
    float4 color : COLOR;
};

layout(binding=1) Texture2D<float4> tex : register(t0);
layout(binding=1) SamplerState sLinear : register(s0);

float4 main( VSOutput vsOut ) : SV_Target
{
    return tex.SampleLevel( sLinear, vsOut.uv, 0 ) * vsOut.color;
};

Can I use the same binding for both texture and sampler if my descriptor set at index 1 has type VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER or must I use two binding slots, one for the texture and one for the sampler? I'm asking because my pipeline creation fails with error

Vulkan warning: [ParameterValidation], code: 9: vkCreateGraphicsPipelines: returned VK_ERROR_INITIALIZATION_FAILED, indicating that initialization of an object has failed

if using this shader instead of a GLSL shader compiled into SPIR-V. My GLSL shader uses the texture like this:

layout (binding = 1) uniform sampler2D textureMap;
2

There are 2 answers

0
Nicol Bolas On BEST ANSWER

As far as SPIR-V and Vulkan are concerned, the SPIR-V equivalent ought to work. That is, you can have an image variable and a sampler variable, both bound to the same binding, and use COMBINED_IMAGE_SAMPLER on it:

VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER descriptor set entries can also be accessed via separate sampler and sampled image shader variables.

and:

It is valid for multiple shader variables to be assigned the same descriptor set and binding values, as long as all those that are statically used by the entry point being compiled are compatible with the descriptor type in the descriptor set layout binding.

Combined image/sampler descriptor types are compatible with both images and samplers.

Of course, that doesn't mean that the validation layer you're using knows that ;) Note that the last quote is from a recent clarification made to the specification, so layers may not have implemented it correctly.

I would suggest, if your code is otherwise correct, filing a bug report on it.


layout (binding = 1) uniform sampler2D textureMap;

It's always a good idea to specify set as well. KHR_vulkan_glsl defaults to set 0, but it's better to have an explicit statement.

0
Ekzuzy On

If you are using combined image image sampler, you need to use one binding. But you need to define both set number and binding number through the layout qualifier:

layout( set=S, binding=B ) ...

Here is an example of using a combined image sampler. If you want you can also use separate sampler and sampled image objects. Then you must define them in two separate bindings and use two descriptors. But the combined image sampler descriptor may have a better performance on some platforms.