Frank
Luna
April
4, 2016
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.
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/
·
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.
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.