Shader Multicompile - PullRequest
       1

Shader Multicompile

1 голос
/ 11 июля 2011

Я создал эту задачу, которая позволяет мне включать fxc (шейдер HLSL) в мой процесс сборки. Теперь с шейдерами дело в том, что довольно часто вы получаете один исходный файл и хотите, чтобы он несколько раз компилировался с разными флагами для получения нескольких выходных данных. Я не могу просто добавить новый элемент, ссылающийся на один и тот же файл несколько раз с разными метаданными, поскольку я хочу, чтобы это интегрировалось в Visual Studio, и по крайней мере VS кричит на меня за попытку сделать это. Я не эксперт, когда дело доходит до MSBuild, и я действительно не уверен, что будет лучшим способом сделать это. Конечно, одним из решений было бы просто добавить некоторое значение метаданных к каждому элементу, который указывает мою задачу fxc на какой-нибудь пользовательский скрипт multicompile-build-script. Но если есть хороший способ решить эту проблему исключительно в MSBuild, я бы предпочел это, а не систему, созданную на заказ. Я попытался с помощью Target генерировать несколько элементов во время сборки (HLSL - это элементы, которые проходят через fxc):

<?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>

Это в принципе работает, но мне нужно, чтобы метаданные типа <Multicompile>vs;ps</Multicompile> генерировали оба элемента, и, кажется, нет простого способа выполнить необходимые строковые операции без некоторого взлома. Я также мог бы добавить отдельные значения метаданных для каждого вида элемента для генерации. Но я почему-то чувствую, что мне не хватает настоящего решения, поэтому я обращаюсь к вашему совету специалиста;)

1 Ответ

1 голос
/ 12 июля 2011

Я решил это сейчас, используя дополнительную задачу для разделения мультикомпиляционных метаданных и создания новых элементов для каждого элемента. После этого я могу запустить другие цели, чтобы сгенерировать финальные элементы, например:

<!-- 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>

Кажется, это работает довольно хорошо. Спасибо всем:)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...