Direct3D 11 Book Demos with Windows 10 and Visual Studio 2015

 

Frank Luna

April 4, 2016

www.d3dcoder.net

 

 

Recently, I’ve received emails about issues with getting the Direct3D 11 book demos to compile using Visual Studio 2015.  This article will explain the necessary steps.  But first a little background on why things broke. 

Starting with Windows 8, DirectX is no longer a separate SDK that you download and install; instead, DirectX ships with the OS and gets updated through Windows Update.  Moreover, the D3DX library has been deprecated and does not ship with Windows, and the XNA Math library now goes by the name DirectX Math.  Also, starting with Visual Studio 2015, the dxerr.lib is no longer compatible with Visual Studio 2015.  So our strategy to get the Direct3D 11 demos to build and run can be summarized as follows:

 

1.      Find replacements for the D3DX functionality the demos use.  This is easier than it sounds; as the DirectX team has open sourced a lot of the D3DX functionality. 

2.      Switch to using DirectX Math—this is pretty easy as the libraries are pretty much the same, we just need to account for DirectX Math putting everything in the DirectX namespace. 

3.      Find a replacement for dxerr.lib or stop using its functionality.  We used this library for our error tracing code:

 

        #define HR(x)                                               \

        {                                                           \

            HRESULT hr = (x);                                       \

            if(FAILED(hr))                                          \

            {                                                       \

                DXTrace(__FILEW__, (DWORD)__LINE__, hr, L#x, true); \

            }                                                       \

        }

 

Note that an alternative strategy would be to install the old June 2010 DirectX SDK to get D3DX and XNA Math, but it creates some additional conflicts that need to be solved, and that SDK is 6 years old at the time of this writing, so we should take the approach that does not require us to download an old SDK. 

Downloads

 

The DirectX 11 book uses the Effects framework.  An open source version of the Effects framework that is compatible with the DirectX versions that ship with Windows 8 and above can be found here:

 

https://github.com/Microsoft/FX11

 

Download the source, open the Effects11_2015 solution file and rebuild the libraries in debug and release mode using Visual Studio 2015.  Name the debug one Effects11d.lib and the release one Effects11.lib.  Copy the files: d3dx11effect.h, Effects11d.lib and Effects11.lib into the book’s Common directory (overwriting the old ones).

            Next, we need a replacement for loading textures.  Again, the D3DX code used for loading textures has been open sourced:

 

https://github.com/Microsoft/DirectXTex

 

Pull DDSTextureLoader, drop DDSTextureLoader.h/.cpp into the book’s Common directory, and add these files to your project.  We will use this code to load textures from disk.

            Finally, we need a replacement for dxerr.lib.  This blog post summarizes the details of why we need this: https://blogs.msdn.microsoft.com/chuckw/2012/04/24/wheres-dxerr-lib/.  In short, the preceding link has a link to dxerr_nov2015.zip, which contains two files dxerr.h and dxerr.cpp that we can drop in the book’s Common directory to get the dxerr.lib functionality we need.  Add these two files to your project.

Readers may recall that D3DX also had some useful mesh based code.  Fortunately, the DirectX team has released this code as well.  Here is the blog post and a link the repository:

 

https://blogs.msdn.microsoft.com/chuckw/2014/06/27/directxmesh/

https://github.com/Microsoft/DirectXMesh

 

For those interested, you can read a lot about the historical changes of DirectX at Chuck Walbourn’s blog: https://blogs.msdn.microsoft.com/chuckw/

 

Project Changes

 

·         In the C/C++ Property Pages > General, add the book’s Common directory to the “Additional Include Directories” list.

·         In the Linker Property Pages > General, add the book’s Common directory to the “Additional Library Directories” list.

Code Changes

 

In this section, we describe the changes needed to get the “BlendDemo” to build and run. 

 

·         Remove all #include <d3dx11.h> and library dependencies to d3dx11.lib/d3dx11d.lib, as D3DX11 is no longer included with DirectX. 

·         Remove the library dependency to dxerr.lib.  Add dxerr.h/.cpp to the project and change #include <dxerr.h> to #include “dxerr.h.”

·         Add a #include “DDSTextureLoader.h” in d3dUtil.h.

·         Replace all references to #include <xnamath.h> with #include <DirectXMath.h> and #include <DirectXPackedVector.h>.

·         All DirectX math types (XMVECTOR, XMFLOAT4X4, XMMatrixTranspose, etc.) will need to be prefixed with “DirectX::” because they now live in the DirectX namespace. 

·         All references to XMCOLOR need to be prefixed with DirectX::PackedVector because XMCOLOR lives in the DirectX::PackedVector namespace.

·         Remove all references to D3DX11INLINE.  You can just delete it or replace with inline.

·         Remove the helper function d3dHelper::CreateTexture2DArraySRV from d3dUtil.h for now.  You can use the texassemble tool (https://directxtex.codeplex.com/wikipage?title=Texassemble&referringTitle=Texconv) to create a texture array offline, which would be the preferred process anyway.

·         In d3dUtil.h, replace __FILE__ in the DXTrace call with __FILEW__ so we get the file as a wide string.

·         In d3dUtil.h, rewrite ExtractFrustumPlanes like so (the change is to convert the input matrix to XMFLOAT4X4 so we can use the overloaded parenthesis operator to get the elements):

void ExtractFrustumPlanes(XMFLOAT4 planes[6], CXMMATRIX T)

{

XMFLOAT4X4 M;

XMStoreFloat4x4(&M, T);

 

//

// Left

//

 

 

planes[0].x = M(0,3) + M(0,0);

planes[0].y = M(1,3) + M(1,0);

planes[0].z = M(2,3) + M(2,0);

planes[0].w = M(3,3) + M(3,0);

 

//

// Right

//

planes[1].x = M(0,3) - M(0,0);

planes[1].y = M(1,3) - M(1,0);

planes[1].z = M(2,3) - M(2,0);

planes[1].w = M(3,3) - M(3,0);

 

//

// Bottom

//

planes[2].x = M(0,3) + M(0,1);

planes[2].y = M(1,3) + M(1,1);

planes[2].z = M(2,3) + M(2,1);

planes[2].w = M(3,3) + M(3,1);

 

//

// Top

//

planes[3].x = M(0,3) - M(0,1);

planes[3].y = M(1,3) - M(1,1);

planes[3].z = M(2,3) - M(2,1);

planes[3].w = M(3,3) - M(3,1);

 

//

// Near

//

planes[4].x = M(0,2);

planes[4].y = M(1,2);

planes[4].z = M(2,2);

planes[4].w = M(3,2);

 

//

// Far

//

planes[5].x = M(0,3) - M(0,2);

planes[5].y = M(1,3) - M(1,2);

planes[5].z = M(2,3) - M(2,2);

planes[5].w = M(3,3) - M(3,2);

 

// Normalize the plane equations.

for(int i = 0; i < 6; ++i)

{

    XMVECTOR v = XMPlaneNormalize(XMLoadFloat4(&planes[i]));

    XMStoreFloat4(&planes[i], v);

}

}

·         Replace texture loading calls D3DX11CreateShaderResourceViewFromFile with the call DirectX::CreateDDSTextureFromFile.  For example, in the “Blend Demo” we replaced

 

HR(D3DX11CreateShaderResourceViewFromFile(md3dDevice,

    L"Textures/grass.dds", 0, 0, &mGrassMapSRV, 0 ));

 

HR(D3DX11CreateShaderResourceViewFromFile(md3dDevice,

    L"Textures/water2.dds", 0, 0, &mWavesMapSRV, 0 ));

 

HR(D3DX11CreateShaderResourceViewFromFile(md3dDevice,

    L"Textures/WireFence.dds", 0, 0, &mBoxMapSRV, 0 ));

 

with

 

ID3D11Resource* texResource = nullptr;

HR(DirectX::CreateDDSTextureFromFile(md3dDevice,

    L"Textures/grass.dds", &texResource, &mGrassMapSRV));

ReleaseCOM(texResource); // view saves reference

 

HR(DirectX::CreateDDSTextureFromFile(md3dDevice,

    L"Textures/water2.dds", &texResource, &mWavesMapSRV));

    ReleaseCOM(texResource); // view saves reference

 

HR(DirectX::CreateDDSTextureFromFile(md3dDevice,

    L"Textures/WireFence.dds", &texResource, &mBoxMapSRV));

ReleaseCOM(texResource); // view saves reference

 

 

 

At this point, the “Blend Demo” should build and run.