Search code examples
directxhlsldirectx-9

Upgrading an existing D3D9 SH3 project to SH4?


I have an old DirectX 3D 9 Visual Stuido project that I have recently been working on.

I have been diving into the world of rendering & HLSL shaders, however it is becoming quite apparent to me that Shader Model 3 is rather limiting. Looking over the MS Docs for Shader Model 3 and 4, it appears that 4 was quite an upgrade. Attempting to compile my project with any HLSL shader higher than 3_0 yields error X3506: Only 3_x and earlier targets are supported on this compiler., hence I figured that my project needs it's compiler upgraded.

It appears that my project automatically loads D3DCompiler_43.dll from SysWOW64, however after looking into that system folder, it appears I already do have D3DCompiler_47.dll. I also read online that there is a supposed "legacy" mode for SH4, however I'm a bit confused on how to implement it properly. After looking at the MS Docs for the compile syntax (https://learn.microsoft.com/en-us/windows/win32/direct3dtools/dx-graphics-tools-fxc-syntax), when compiling my pixel shader, using keywords such as ps_4_0_level_9_0 would allow it to be ran on D3D9, however that yields error X3523: DX9-style intrinsics are disabled when not in dx9 compatibility mode.. I'm kinda lost at this point as to what needs to be done to upgrade my project.

Is upgrading an existing SH3 project to SH4 even possible to do in D3D9? Is it even possible to get my project to run D3DCompiler_47.dll instead of D3DCompiler_43.dll?

Any help is appreciated, thank you for reading my post!


Solution

  • Shader Model 4.0 is only supported by Direct3D 10 or later. To make use of it, you must move past legacy Direct3D 9. The recommendation would be to move to Direct3D 11.

    Shader Model 4.0+ shaders are not supported by Direct3D 9 era hardware. The "10level9" HLSL profiles for modern Direct3D that are required to build shaders compatible with Direct3D Hardware Feature Level 9.x actually produces TWO shader blobs: Shader Model 4.0 for D3D10+ hardware and Shader Model 2.x for D3D9 hardware.

    The error X3506 is output whenever you attempt to use Shader Model 4 or later via the D3DX9 interfaces to the compiler. It works if you use the D3DCompile APIs, although #43 is quite old. You can use the D3DCompiler_47.DLL to build Shader Model 2.0 and Shader Model 3.0 for Direct3D 9. The DLL itself works on Windows 7 SP1 or later, but won't load on Windows XP. See this blog post for more on the #47 compiler and it's uses.

    There is a 'compatibility mode' for the HLSL compiler to accept the older DX9-style shader syntax. This is the /Gec switch or the D3DCOMPILE_ENABLE_BACKWARDS_COMPATIBILITY flag. These 'breaking changes' were introduced in the March 2008 legacy DirectX SDK:

    • Type double cannot be used.
    • Type half no longer can be used as a global variable type. This can be suppressed using the compatibility compilation flag (/Gec).
    • Built-in types such as float4 no longer can be redefined as other types via typedef.
    • Type void no longer is legal as a parameter or member type.
    • Floating-point literals are now an "any float" type, changing overload resolution in some cases.
    • Default parameters are now always resolved statically. It is no longer legal to give default parameters in a function definition if there is a prototype. Defaults can only be given in the prototype.
    • Default parameter values are no longer legal for inout and out parameters.
    • Target qualifiers (i.e., ps_4_0) no longer can be specified for functions.
    • All semantic target strings now are validated at parse time and must match valid target names.
    • All global variables now are implicitly const. This can be suppressed by using the compatibility compilation flag (/Gec).
    • Comparisons between signed and unsigned values now produce a warning.
    • Redefining a loop variable in a following loop generates a warning that the variable has been redefined.
    • Techniques names now are contained in the global scope. Therefore, you cannot have multiple techniques of the same name, and you cannot have a function and a technique of the same name.
    • For Direct3D 10 targets, developers no longer can bind two different variables to the same constant register.

    If you are using D3DCompiler_43.DLL, then you still have the legacy DirectX SDK. Note that there's a better option for using D3DX9/D3DX10/D3DX11 these days via NuGet that avoids numerous conflicts with modern Windows SDK headers. See this blog post.