Vulkan使用location来绑定,而hlsl使用语义绑定,但SPIRV编译器通常会按输入的顺序来自动指定location,一个结构体如下:
struct InVertexAssembly { float3 Position : POSITION; float3 Normal : NORMAL; float3 Tangent : TANGENT; float4 Color : COLOR0; float2 TexCoord0 : TEXCOORD0; float2 TexCoord1 : TEXCOORD1; float2 TexCoord2 : TEXCOORD2; float2 TexCoord3 : TEXCOORD3; };
其中Position的location为隐式的0,Normal的location为隐式的1,可以通过spirv-dis工具来查看编译的字节码信息。
如果希望用户去自定义shader的输入方式,像unity中可以使用cg语言,通过语义绑定来允许用户不需要关注布局。如果使用以上方法调换变量位置则会出现数据传输的错误。要实现这种语义绑定,那让那我们可以在不修改编译器情况下来完成,定义一套自己的语义。
#ifdef PLATFORM_VULKAN #define LAYOUT_LOCATION(index) [[vk::location(index)]] #else #define LAYOUT_LOCATION(index) #endif #define EIS_POSITION LAYOUT_LOCATION(0) #define EIS_NORMAL LAYOUT_LOCATION(1) #define EIS_TANGENT LAYOUT_LOCATION(2) #define EIS_VERTCOLOR LAYOUT_LOCATION(3) #define EIS_TEXCOORD0 LAYOUT_LOCATION(4) #define EIS_TEXCOORD1 LAYOUT_LOCATION(5) #define EIS_TEXCOORD2 LAYOUT_LOCATION(6) #define EIS_TEXCOORD3 LAYOUT_LOCATION(7)
来修改一下结构体,这样就通过宏去给每个输入字段手动指定了一个location。
struct InVertexAssembly { EIS_POSITION float3 Position : POSITION; EIS_NORMAL float3 Normal : NORMAL; EIS_TANGENT float3 Tangent : TANGENT; EIS_VERTCOLOR float4 Color : COLOR0; EIS_TEXCOORD0 float2 TexCoord0 : TEXCOORD0; EIS_TEXCOORD1 float2 TexCoord1 : TEXCOORD1; EIS_TEXCOORD2 float2 TexCoord2 : TEXCOORD2; EIS_TEXCOORD3 float2 TexCoord3 : TEXCOORD3; };
比如允许用户像unity一样,通过语义绑定自定义输入结构,前面的语义对应的location允许vk和gl使用,hlsl自身的语义d3d使用。
struct a2v { EIS_NORMAL Normal : NORMAL; EIS_POSITION Pos : POSITION; }