2011-07-11 2 views
1

J'ai créé cette tâche qui me permet d'inclure fxc (compilateur shaders HLSL) dans mon processus de construction. Maintenant, la chose avec les shaders est que souvent vous avez un seul fichier source et que vous voulez qu'il soit compilé plusieurs fois avec des drapeaux différents pour produire plusieurs sorties. Je ne peux pas simplement ajouter un nouvel élément référençant le même fichier plusieurs fois avec des métadonnées différentes puisque je veux que cela s'intègre dans Visual Studio et au moins VS me crie dessus pour essayer de le faire. Je ne suis pas un expert quand il s'agit de MSBuild et je ne suis donc pas sûr de la meilleure façon de le faire. Bien sûr, une solution consisterait simplement à ajouter une valeur de métadonnées à chaque élément qui pointe ma tâche fxc vers un script multicompile-build personnalisé. Mais s'il y a une bonne façon de résoudre cela purement dans MSBuild, je préférerais cela sur un système construit sur mesure. J'ai essayé d'avoir une cible générer plusieurs éléments lors de la construction (HLSL sont les éléments qui traversent FXC):Shader Multicompile

<?xml version="1.0" encoding="utf-8"?> 
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> 

    <ItemGroup> 
    <HLSL Include="default.hlsl"> 
     <Multicompile>vs</Multicompile> 
    </HLSL> 
    <HLSL Include="shadow.hlsl" /> 
    </ItemGroup> 


    <Target Name="ShaderMulticompile" BeforeTargets="HLSL" DependsOnTargets="HLSLSelectedFiles"> 
    <ItemGroup> 
     <HLSL Include="@(HLSL)" Condition="'%(HLSL.Multicompile)' == 'vs'"> 
     <TargetFile>$(OutDir)%(Filename).vsh</TargetFile> 
     <TargetProfile>vs_4_0</TargetProfile> 
     <EntryPoint>VertexShader</EntryPoint> 
     <Multicompile /> 
     </HLSL> 
     <HLSL Include="@(HLSL)" Condition="'%(HLSL.Multicompile)' == 'ps'"> 
     <TargetFile>$(OutDir)%(Filename).psh</TargetFile> 
     <TargetProfile>ps_4_0</TargetProfile> 
     <EntryPoint>PixelShader</EntryPoint> 
     <Multicompile /> 
     </HLSL> 
    </ItemGroup> 
    </Target> 

    <Target Name="RemoveShaderMulticompileSourceItems" AfterTargets="ShaderMulticompile"> 
    <ItemGroup> 
     <HLSL Remove="@(HLSL)" Condition="'%(HLSL.Multicompile)' != ''" /> 
    </ItemGroup> 
    </Target> 

    <Target Name="CleanShaderMulticompile" BeforeTargets="HLSLClean" DependsOnTargets="ShaderMulticompile" /> 
</Project> 

Cela fonctionne essentiellement mais je aurais besoin d'avoir des métadonnées comme <Multicompile>vs;ps</Multicompile> générer les deux éléments et il semble être pas un moyen facile de faire les opérations de chaîne nécessaires sans un peu de piratage. Je pourrais également ajouter des valeurs de métadonnées individuelles pour chaque type d'élément à générer. Mais j'ai l'impression de manquer la vraie solution ici, donc je cherche votre avis d'expert;)

Répondre

1

Je l'ai résolu maintenant en utilisant une tâche supplémentaire pour scinder les métadonnées multicompiles et générer de nouveaux éléments pour chaque élément. Après que je peux exécuter d'autres cibles pour générer les produits finaux comme celui-ci:

<!-- This Task splits up the Multicompile Metadata and spawns new Items based on this info --> 
<Target Name="HLSLMulticompile" BeforeTargets="HLSL;HLSLClean" DependsOnTargets="HLSLSelectedFiles"> 
    <HLSLBuild.Multicompile Inputs="@(HLSL)" Condition="'%(HLSL.Multicompile)' != ''"> 
    <Output TaskParameter="Outputs" ItemName="HLSLMulti" /> 
    </HLSLBuild.Multicompile> 
    <ItemGroup> 
    <HLSL Remove="@(HLSL)" Condition="'%(HLSL.Multicompile)' != ''" /> 
    </ItemGroup> 
</Target> 

<!-- These Tasks generate the final Items --> 
<Target Name="VertexShader" AfterTargets="HLSLMulticompile"> 
    <ItemGroup> 
    <HLSL Include="@(HLSLMulti)" Condition="'%(HLSLMulti.Multicompile)' == 'vs'"> 
     <TargetFile>$(OutDir)%(Filename).vsh</TargetFile> 
     <EntryPoint>VSMain</EntryPoint> 
    </HLSL> 
    </ItemGroup> 
</Target> 
<Target Name="PixelShader" AfterTargets="HLSLMulticompile"> 
    <ItemGroup> 
    <HLSL Include="@(HLSLMulti)" Condition="'%(HLSLMulti.Multicompile)' == 'ps'"> 
     <TargetFile>$(OutDir)%(Filename).psh</TargetFile> 
     <EntryPoint>PSMain</EntryPoint> 
    </HLSL> 
    </ItemGroup> 
</Target> 

Cela semble fonctionner assez bien. Merci à tous :)