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