是否可以用自定义 HLSL 结构替换内置打包变量(如 float4 或 int4)而不更改数据功能?例如,不要使用
uint4
(x,y,z,w),而是使用类似以下结构:
struct customData
{
uint Rough;
uint Metal;
uint AO;
uint Spec;
};
将其从
uint4
更改的唯一目的是提高可读性,并保持数据的正确性(记住 z
是 AO
)。如果我尝试将其隐藏到我的顶点输入中,例如:
struct vertexData
{
float4 Position : ATTRIB0;
float4 Normal : ATTRIB1;
customData Custom : ATTRIB2;
float4 TexCoord : ATTRIB3;
};
..当我尝试执行此操作时,dxc 编译器会抛出有关属性重叠的错误。从一些有限的测试来看,编译器似乎会自动按如下顺序应用语义:
struct customData
{
uint Rough : ATTRIB2; // ATTRIB2+0
uint Metal : ATTRIB3; // ATTRIB2+1 (overlap with TexCoord)
uint AO : ATTRIB4; // ATTRIB2+2
uint Spec : ATTRIB5; // ATTRIB2+3
};
有可能防止这种情况发生吗?或者有什么方法可以将这些数据放入命名变量中而不改变事物的结构或顺序?此外,我对 HLSL 不太熟悉,所以我不完全确定具有唯一语义的 4 个 uint 变量和仅具有一种语义的单个 uint4 之间的最终运行时差异是什么?有什么区别吗
我感谢任何见解或建议!
为了便于阅读,您可以将这些数字保留在
uint4
中,并使用内联函数在自定义结构之间进行转换。很确定编译器会发出与直接处理 uint4
值的可读性较差的版本相同的代码。
具有唯一语义的 4 个 uint 变量与仅具有一种语义的单个 uint4 变量之间最终的运行时差异是什么?有什么区别吗
我不知道,但我认为运行时差异(如果有的话)是特定于 GPU 型号甚至驱动程序版本的。 GPU 驱动程序还包括另一个着色器编译器,即即时编译器,它将 Microsoft 制造的
fxc.exe
生成的 DXBC 字节代码或较新的 dxc.exe
生成的其他一些字节代码转换为您的特定的实际硬件指令。 GPU 模型。
另外,请注意,这些语义的数量有一个硬性限制,该限制是 32,这是一个相当小的数字。对于 D3D11,请参阅该表
上的
D3D11_VS_INPUT_REGISTER_COUNT
、
D3D11_VS_OUTPUT_REGISTER_COUNT
、
D3D11_GS_OUTPUT_REGISTER_COUNT
数字。同样的限制也适用于 D3D12,请参阅 D3D12_DS_OUTPUT_REGISTER_COUNT
、D3D12_VS_OUTPUT_REGISTER_COUNT
等,在该表上。