单HLSL生成多CSO变体:VS项目重复FxCompile项加载失败求助
HLSL着色器变体编译重复项错误解决方法
要为HLSL着色器的不同预定义宏组合生成对应的CSO文件,在vcxproj中添加多组FxCompile配置时,会触发Visual Studio报错:
错误:无法加载包含重复项目项的项目:MyShader.hlsl被作为'FxCompile'和'FxCompile'项类型包含。
原配置代码如下:
<FxCompile Include="MyShader.hlsl"> <PreprocessorDefinitions>USE_X=1</PreprocessorDefinitions> <ObjectFileOutput>MyShader_USEX.cso</ObjectFileOutput> </FxCompile> <FxCompile Include="MyShader.hlsl"> <PreprocessorDefinitions>USE_Y=1</PreprocessorDefinitions> <ObjectFileOutput>MyShader_USEY.cso</ObjectFileOutput> </FxCompile> <FxCompile Include="MyShader.hlsl"> <PreprocessorDefinitions>USE_X=1;USE_Y=1;USE_Z=1</PreprocessorDefinitions> <ObjectFileOutput>MyShader_XYZ.cso</ObjectFileOutput> </FxCompile>
错误原因
MSBuild不允许同一文件被多次添加为同一种项目项类型(这里都是FxCompile),哪怕输出路径和预定义宏不同,也会被判定为重复项。
解决方法
方法一:添加Unique标识区分变体
给每个FxCompile项添加<Unique>标签,设置唯一值让MSBuild识别为不同的构建项,修改后的配置如下:
<FxCompile Include="MyShader.hlsl"> <PreprocessorDefinitions>USE_X=1</PreprocessorDefinitions> <ObjectFileOutput>MyShader_USEX.cso</ObjectFileOutput> <Unique>Variant_USEX</Unique> </FxCompile> <FxCompile Include="MyShader.hlsl"> <PreprocessorDefinitions>USE_Y=1</PreprocessorDefinitions> <ObjectFileOutput>MyShader_USEY.cso</ObjectFileOutput> <Unique>Variant_USEY</Unique> </FxCompile> <FxCompile Include="MyShader.hlsl"> <PreprocessorDefinitions>USE_X=1;USE_Y=1;USE_Z=1</PreprocessorDefinitions> <ObjectFileOutput>MyShader_XYZ.cso</ObjectFileOutput> <Unique>Variant_XYZ</Unique> </FxCompile>
方法二:用脚本手动调用fxc编译
跳过vcxproj的FxCompile配置,写一个批处理脚本直接调用fxc.exe编译所有变体,示例脚本:
:: 替换成你的着色器入口函数名和目标 shader model fxc.exe /E main /T ps_5_0 /D USE_X=1 /Fo MyShader_USEX.cso MyShader.hlsl fxc.exe /E main /T ps_5_0 /D USE_Y=1 /Fo MyShader_USEY.cso MyShader.hlsl fxc.exe /E main /T ps_5_0 /D USE_X=1;USE_Y=1;USE_Z=1 /Fo MyShader_XYZ.cso MyShader.hlsl
将脚本添加到项目的构建事件中(项目属性→生成事件→预生成事件/生成事件),让编译时自动执行。
方法三:批量生成变体配置
利用MSBuild的ItemGroup元数据批量定义所有变体,避免重复编写FxCompile项。示例配置:
<ItemGroup> <ShaderVariant Include="USEX"> <Defines>USE_X=1</Defines> <Output>MyShader_USEX.cso</Output> </ShaderVariant> <ShaderVariant Include="USEY"> <Defines>USE_Y=1</Defines> <Output>MyShader_USEY.cso</Output> </ShaderVariant> <ShaderVariant Include="XYZ"> <Defines>USE_X=1;USE_Y=1;USE_Z=1</Defines> <Output>MyShader_XYZ.cso</Output> </ShaderVariant> </ItemGroup> <ItemGroup> <FxCompile Include="MyShader.hlsl" Condition="%(ShaderVariant.Identity)"> <PreprocessorDefinitions>%(ShaderVariant.Defines)</PreprocessorDefinitions> <ObjectFileOutput>%(ShaderVariant.Output)</ObjectFileOutput> <Unique>Variant_%(ShaderVariant.Identity)</Unique> </FxCompile> </ItemGroup>
内容的提问来源于stack exchange,提问作者Tom Huntington
相关产品推荐
相关产品推荐

