1
votes

I have HLSL shaders added to my Visual Studio project and they're getting compiled automatically to cso files as part of the build process. The problem which I'm facing is, that I need to compile them multiple times using different Shader models because i.e. "/4_0_level_9_3" works on DirectX 11, but not on DirectX 9, while "/3_0" only works on DirectX 9 but not on DirectX 11.

Adding the same files more than once to the Visual Studio project is not working and I would like to avoid copying the HLSL source files as it increases maintenance efforts and potential error causes. I can't create separate targets/configuration in Visual Studio to achieve this either, because I need to support both DirectX versions in the executable (switchable at runtime).

Is there any way to specify multiple compilations (different shader models and different output file) for a single HLSL file in Visual Studio?

1

1 Answers

3
votes

Put your shader code into an .hlsli file, add that to your project. Create for each shader and model combination an .hlsl file which does a #include of your .hlsli file. Add each .hlsl to your project and set the file settings appropriately.

File 1 (set to exclude from build)

// MyShader.hlsli

PS_INPUT VertexShader( VS_INPUT input )
{
...
}

float4 PixelShader( PS_INPUT input)
{
...
}

File 2 (set to build as a Vertex Shader, Shader Model 9_3, Entry-point VertexShader)

// MyShader_VS.hlsl

#include "MyShader.hlsl"    

File 3 (set to build as a Pixel Shader, Shader Model 9_3, Entry-point PixelShader)

// MyShader_PS.hlsl

#include "MyShader.hlsl"    

File 4 (set to build as a Vertex Shader, Shader Model 4.0, Entry-point VertexShader)

// MyShader_VS4.hlsl

#include "MyShader.hlsl"    

File 5 (set to build as a Pixel Shader, Shader Model 4.0, Entry-point PixelShader)

// MyShader_PS4.hlsl

#include "MyShader.hlsl"    

Note that you can make life a little easier by manually editing your vcxproj file with a text editor. Look for the Label="UserMacros" and then in the ItemDefinitionGroup for each configuration right after that add a section for <FXCompile> to set better defaults (rather than 4.0_level_9_1):

<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Link>
...
</Link>
<ClCompile>
...
</ClCompile>
<FXCompile>
  <ShaderModel>4.0_level_9_3</ShaderModel>
</FXCompile>

Unless you are specifically targeting Windows XP systems, there's not much value in using the legacy Direc3D 9 API at all. Just use DirectX 11 Feature Level 9.3+ to target Shader Model 2.0/3.0 era video cards. The main value of Shader Model 3.0 was vertex texture fetch which was never implemented by one of the major vendors anyhow. The 4_0_level_9_3 profile already builds the shader as both 2.0 and 4.0 in the same blob.