Search code examples
directxhlslfragment-shadermsbuild-task

Replacing PixelShaderCompile task with fxc.exe (necessitated by moving to VS2022). Getting same functionality. Putting in resource (embedded?)


As some may know, support for PixelShaderCompile has been done away with as of VS2022. One is suppose to use fxc.exe (I believe). For a discussion of this, see:

Build pixel shader project in VS2022

I inherited a LARGE project I need to build. I'm not familiar with the DirectX parts of it, and I don't think I need to be right away. However, I do need to build and run it. The build line for the shader stuff was:

 <Target Name="EffectCompile" Condition="'@(Effect)' != '' ">
    <PixelShaderCompile Sources="@(Effect)">
      <Output TaskParameter="Outputs" ItemName="Resource" />
    </PixelShaderCompile>
  </Target>

Based on the article above (mostly from https://stackoverflow.com/users/403671/simon-mourier) I tried the following code:

<Target Name="EffectCompile" Condition="'@(Effect)' != '' ">
  <Exec Command="&quot;$(MSBuildProgramFiles32)\Windows Kits\10\bin\10.0.22621.0\x64\fxc.exe&quot; /T ps_3_0 /Fo %(Effect.Identity).ps %(Effect.Identity)"/>
</Target>

which compiles fine and produces .ps files. However, I believe the first code block is somehow embedding said .ps files in a "resource" or something? To be honest, I'm not familiar with the syntax of either command and am having trouble finding documentation and/or examples. Is this something DirectX gurus do all the time?

How can I get started?

Update

Thanks once again to Simon Mourier (see below) and Build pixel shader project in VS2022

In case anyone wants to see a full project file for reference, here is one (below). Most relevant stuff is towards the bottom.

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
 
  <PropertyGroup>
    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
    <ProductVersion>9.0.30729</ProductVersion>
    <SchemaVersion>2.0</SchemaVersion>
    <ProjectGuid>{4EB52AEE-95E0-42AC-89F5-251B832CF7CE}</ProjectGuid>
    <OutputType>Library</OutputType>
    <AppDesignerFolder>Properties</AppDesignerFolder>
    <RootNamespace>Cyntellect.ShaderEffects</RootNamespace>
    <AssemblyName>ShaderEffects</AssemblyName>
    <TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
    <FileAlignment>512</FileAlignment>
    <SccProjectName>SAK</SccProjectName>
    <SccLocalPath>SAK</SccLocalPath>
    <SccAuxPath>SAK</SccAuxPath>
    <SccProvider>SAK</SccProvider>
    <FileUpgradeFlags>
    </FileUpgradeFlags>
    <OldToolsVersion>3.5</OldToolsVersion>
    <UpgradeBackupLocation />
    <TargetFrameworkProfile />
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
    <DebugSymbols>true</DebugSymbols>
    <OutputPath>..\..\bin\Debug\</OutputPath>
    <DefineConstants>DEBUG;TRACE</DefineConstants>
    <DocumentationFile>..\..\doc\ShaderEffects.xml</DocumentationFile>
    <NoWarn>1607</NoWarn>
    <DebugType>full</DebugType>
    <PlatformTarget>x64</PlatformTarget>
    <ErrorReport>prompt</ErrorReport>
    <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
    <OutputPath>..\..\bin\Release\</OutputPath>
    <DefineConstants>TRACE</DefineConstants>
    <DocumentationFile>..\..\doc\ShaderEffects.xml</DocumentationFile>
    <Optimize>true</Optimize>
    <DebugType>pdbonly</DebugType>
    <PlatformTarget>x64</PlatformTarget>
    <ErrorReport>prompt</ErrorReport>
    <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Test|x64'">
    <DebugSymbols>true</DebugSymbols>
    <OutputPath>..\..\bin\Test\</OutputPath>
    <DefineConstants>DEBUG;TRACE</DefineConstants>
    <DocumentationFile>..\..\doc\ShaderEffects.xml</DocumentationFile>
    <NoWarn>1607</NoWarn>
    <DebugType>full</DebugType>
    <PlatformTarget>x64</PlatformTarget>
    <ErrorReport>prompt</ErrorReport>
    <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
  </PropertyGroup>
  <ItemGroup>
    <Reference Include="System" />
    <Reference Include="System.Core">
    </Reference>
    <Reference Include="WindowsBase">
    </Reference>
    <Reference Include="PresentationCore">
    </Reference>
    <Reference Include="PresentationFramework">
    </Reference>
  </ItemGroup>
  <ItemGroup>
    <Compile Include="..\..\VersionAssemblyInfo.cs">
      <Link>Properties\VersionAssemblyInfo.cs</Link>
    </Compile>
    <Compile Include="..\CPAssemblyInfo.cs">
      <Link>Properties\CPAssemblyInfo.cs</Link>
    </Compile>
    <Compile Include="EffectFiles\BandedSwirlEffect.cs" />
    <Compile Include="EffectFiles\BloomEffect.cs" />
    <Compile Include="EffectFiles\BrightExtractEffect.cs" />
    <Compile Include="EffectFiles\ColorKeyAlphaEffect.cs" />
    <Compile Include="EffectFiles\ColorToneEffect.cs" />
    <Compile Include="EffectFiles\CompensationEffect.cs" />
    <Compile Include="EffectFiles\CompensationEffect2Channels.cs" />
    <Compile Include="EffectFiles\CompensationEffect3Channels.cs" />
    <Compile Include="EffectFiles\CompensationEffect5Channels.cs" />
    <Compile Include="EffectFiles\CompensationEffect4Channels.cs" />
    <Compile Include="EffectFiles\ContrastAdjustEffect.cs" />
    <Compile Include="EffectFiles\DirectionalBlurEffect.cs" />
    <Compile Include="EffectFiles\EmbossedEffect.cs" />
    <Compile Include="EffectFiles\GloomEffect.cs" />
    <Compile Include="EffectFiles\GrowablePoissonDiskEffect.cs" />
    <Compile Include="EffectFiles\InvertColorEffect.cs" />
    <Compile Include="EffectFiles\LightStreakEffect.cs" />
    <Compile Include="EffectFiles\MagnifyEffect.cs" />
    <Compile Include="EffectFiles\MonochromeEffect.cs" />
    <Compile Include="EffectFiles\PinchEffect.cs" />
    <Compile Include="EffectFiles\PixelateEffect.cs" />
    <Compile Include="EffectFiles\RippleEffect.cs" />
    <Compile Include="EffectFiles\SharpenEffect.cs" />
    <Compile Include="EffectFiles\SmoothMagnifyEffect.cs" />
    <Compile Include="EffectFiles\SwirlEffect.cs" />
    <Compile Include="EffectFiles\ToneMappingEffect.cs" />
    <Compile Include="EffectFiles\ToonShaderEffect.cs" />
    <Compile Include="EffectFiles\ZoomBlurEffect.cs" />
    <Compile Include="EffectLibrary.cs">
    </Compile>
    <Compile Include="Properties\AssemblyInfo.cs" />
    <Service Include="{94E38DFF-614B-4cbd-B67C-F211BB35CE8B}" />
  </ItemGroup>
  <ItemGroup>
    <Effect Include="ShaderSource\BandedSwirl.fx" />
    <Effect Include="ShaderSource\Bloom.fx" />
    <Effect Include="ShaderSource\BrightExtract.fx" />
    <Effect Include="ShaderSource\ColorKeyAlpha.fx" />
    <Effect Include="ShaderSource\ColorTone.fx" />
    <Effect Include="ShaderSource\Compensation.fx" />
    <Effect Include="ShaderSource\Compensation2Channels.fx" />
    <Effect Include="ShaderSource\Compensation3Channels.fx" />
    <Effect Include="ShaderSource\Compensation4Channels.fx" />
    <Effect Include="ShaderSource\ContrastAdjust.fx" />
    <Effect Include="ShaderSource\DirectionalBlur.fx" />
    <Effect Include="ShaderSource\Embossed.fx" />
    <Effect Include="ShaderSource\Gloom.fx" />
    <Effect Include="ShaderSource\GrowablePoissonDisk.fx" />
    <Effect Include="ShaderSource\InvertColor.fx" />
    <Effect Include="ShaderSource\LightStreak.fx" />
    <Effect Include="ShaderSource\Magnify.fx" />
    <Effect Include="ShaderSource\Monochrome.fx" />
    <Effect Include="ShaderSource\Pinch.fx" />
    <Effect Include="ShaderSource\Pixelate.fx" />
    <Effect Include="ShaderSource\Ripple.fx" />
    <Effect Include="ShaderSource\Sharpen.fx" />
    <Effect Include="ShaderSource\SmoothMagnify.fx" />
    <Effect Include="ShaderSource\Swirl.fx" />
    <Effect Include="ShaderSource\ToneMapping.fx" />
    <Effect Include="ShaderSource\ToonShader.fx" />
    <Effect Include="ShaderSource\WaveEffect.fx" />
    <Effect Include="ShaderSource\ZoomBlur.fx" />
  </ItemGroup>
  <ItemGroup>
    <Effect Include="ShaderSource\Compensation5Channels.fx" />
  </ItemGroup>
  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
  
 <Target Name="EffectCompile" Condition="'@(Effect)' != '' ">
  <Exec Command="&quot;$(MSBuildProgramFiles32)\Windows Kits\10\bin\10.0.22621.0\x64\fxc.exe&quot; /T ps_3_0 /Fo %(Effect.RelativeDir)%(Effect.FileName).ps %(Effect.Identity)"/>
  <!-- Add this if you need to embed the file as WPF resources -->
  <ItemGroup>
    <Resource Include="%(Effect.RelativeDir)%(Effect.FileName).ps" />
  </ItemGroup>
</Target>
  <PropertyGroup>
    <!-- Add effect compilation to the PrepareResourcesDependsOn so that the effect fx  get compiled before resources are collected -->
    <PrepareResourcesDependsOn>EffectCompile;$(PrepareResourcesDependsOn)</PrepareResourcesDependsOn>
  </PropertyGroup>
  <PropertyGroup>
    <PreBuildEvent>
    </PreBuildEvent>
  </PropertyGroup>
</Project>

Solution

  • The original PixelShaderCompile task was declared like this in a .csproj:

    <Target Name="EffectCompile" Condition="'@(Effect)' != '' ">
      <PixelShaderCompile Sources="@(Effect)">
        <Output TaskParameter="Outputs" ItemName="Resource" />
      </PixelShaderCompile>
    </Target>
    

    What this did is 1) compile the .fx files as .ps files (compiled effects) and 2) declare them as Resource for the MSBuild system (same as Visual Studio Build Action Resource) which is understood by WPF project types as WPF resources:

    enter image description here

    So, when you're building for WPF, you want to emulate that behavior, which you can do like this (my original answer initially only had the Exec command):

    <Target Name="EffectCompile" Condition="'@(Effect)' != '' ">
      <Exec Command="&quot;$(MSBuildProgramFiles32)\Windows Kits\10\bin\10.0.22621.0\x64\fxc.exe&quot; /T ps_3_0 /Fo %(Effect.RelativeDir)%(Effect.FileName).ps %(Effect.Identity)"/>
    
      <!-- Add this if you need to embed the file as WPF resources -->
      <ItemGroup>
        <Resource Include="%(Effect.RelativeDir)%(Effect.FileName).ps" />
      </ItemGroup>
    </Target>