If you came across the infamous DirectX Viewer SDK bug where DXViewer.exe crashes when loading X files or where DXViewer.exe crashes with the following message “This application has failed to start because d3dx10d_33.dll was not found…” then you probably came to the right place.
The solution is to fix the bugs in the code and project settings and build the DirectX Viewer from source code(found at [install path of DirectXSDK]\Utilities\Source\DxViewer).
There are 2 problems with the DXViewer.exe executable. Below are the descriptions of the problems and their solutions.
Both problems stem from the fact that although the code was written to work on both DirectX 9 and 10 the code fails miserably in DirectX 9 environments.
Problem1: The executable tries to load a DirectX 10 DLL (d3dx10d_33.dll) which does not necessarily exist on a developer’s machine (For example in the obvious case where the user does not have DirectX 10 installed…). The code actually tries to handle the case where the DLL is missing but because it binds to the DLL at load time it does not help.
Solution 1: Force the executable to delay load the DirectX 10 DLL. To do that, go to the project properties and then go to the linker/input settings and enter d3dx10d_33.dll in the “Delay Loaded DLLs” edit box.
Problem 2: The code does not properly use the DirectX 9 legacy shader compiler. This causes the program to crash when loading .x files.
Solution 2: To solve this problem modify the code to force the shader compiler to use the legacy DirectX 9 mode using the D3DXSHADER_USE_LEGACY_D3DX9_31_DLL flag.
Note below are quick and dirty instructions for fixing the bug in the code. They are only intended to fix the crash on a development environment where the code crashes.
1. Change the ModelLoader9::CreateMaterial member function in Model9.cpp (changes marked in bold):
Material* ModelLoader9::CreateMaterial(ModelSubset* pModelSubset, Sas::SourceInfo& si)
{
HRESULT hr = S_OK;
std::vector<D3DXMACRO> macroArray;
ModelLoader9::MakeMacroArray( STATE_GET( Defines ), macroArray );
Material* pResult = new Material;
bool dbgVS = STATE_GET( DebugVertexShaders );
bool dbgPS = STATE_GET( DebugPixelShaders );
DWORD flags = ((dbgVS|dbgPS)? D3DXSHADER_DEBUG : 0) |
((dbgVS)? D3DXSHADER_FORCE_VS_SOFTWARE_NOOPT : 0) |
((dbgPS)? D3DXSHADER_FORCE_PS_SOFTWARE_NOOPT : 0) |
(STATE_GET(OptimizeShaders) ? 0 : D3DXSHADER_SKIPOPTIMIZATION) |
(STATE_GET(ValidateShaders) ? 0 : D3DXSHADER_SKIPVALIDATION) |
(STATE_GET(Preshaders) ? 0 : D3DXSHADER_NO_PRESHADER) |
(STATE_GET(PartialPrecision) ? D3DXSHADER_PARTIALPRECISION : 0) |
(STATE_GET(PreferDynamicFlow) ? D3DXSHADER_PREFER_FLOW_CONTROL : D3DXSHADER_AVOID_FLOW_CONTROL);
// begin fix sdk ps1.1 shader bug
flags |= D3DXSHADER_USE_LEGACY_D3DX9_31_DLL;
// end fix sdk ps1.1 shader bug
wstring includes = si.GetDirectoryPath()? si.GetDirectoryPath() : L"";
includes += L";";
includes += STATE_GET(Includes);
V( Sas::Effect9::FromSource(
DXUTGetD3D9Device(),
si,
¯oArray.front(),
&DXVGetIncludeHandler9(includes.c_str()),
flags,
(Sas::Effect9**)&pResult->Effect ) );
if(SUCCEEDED(hr))
{
std::vector<TechniqueInfo>& EffectInfo = DXVGetRender9().GetEffectInfo();
if(!STATE_GET(FileFX).empty() && EffectInfo.empty() )
{
UINT iTec, iPass;
ID3DXEffect* pEffect = ((Sas::Effect9*)pResult->Effect)->GetD3DXEffect();
D3DXEFFECT_DESC effectDesc;
V(pEffect->GetDesc( &effectDesc ));
EffectInfo.resize( effectDesc.Techniques );
for(iTec = 0 ; iTec < effectDesc.Techniques ; iTec++ )
{
TechniqueInfo& techInfo = EffectInfo[iTec];
D3DXHANDLE technique = pEffect->GetTechnique(iTec);
D3DXTECHNIQUE_DESC techniqueDesc;
V( pEffect->GetTechniqueDesc( technique, &techniqueDesc ) );
CharToWString( techniqueDesc.Name, techInfo.Name);
techInfo.Passes.resize(techniqueDesc.Passes);
for( iPass = 0; iPass < techniqueDesc.Passes; iPass++ )
{
D3DXHANDLE pass = pEffect->GetPass(technique, iPass);
D3DXPASS_DESC passDesc;
pEffect->GetPassDesc( pass, &passDesc );
CharToWString( passDesc.Name, techInfo.Passes[iPass] );
}
}
}
}
if( FAILED(hr) )
SAFE_DELETE( pResult);
return pResult;
}
2. Change the CShowBounds9::SetBounds member function in ShowBounds9.cpp (changes marked in bold):
void CShowBounds9::SetBounds(const D3DXVECTOR3& minVec, const D3DXVECTOR3& maxVec)
{
HRESULT hr = S_OK;
IDirect3DDevice9* device = DXUTGetD3D9Device();
// begin fix sdk ps1.1 shader bug
DWORD flags = 0;
flags |= D3DXSHADER_USE_LEGACY_D3DX9_31_DLL;
// end fix sdk ps1.1 shader bug
{//EFFECT
LPD3DXBUFFER pErrorsAndWarnings= NULL;
if(FAILED( D3DXCreateEffectFromResource( device, NULL, MAKEINTRESOURCE(IDR_SHOWLINES9FX),
// begin fix sdk ps1.1 shader bug
NULL, NULL, flags, NULL, &Effect, &pErrorsAndWarnings )) )
// end fix sdk ps1.1 shader bug
{
MessageBoxA(NULL, (LPCSTR)(!pErrorsAndWarnings?"":pErrorsAndWarnings->GetBufferPointer()), "ShowBounds: Error loading Effect", 0 );
}
SAFE_RELEASE(pErrorsAndWarnings);
}//EFFECT
V( device->CreateVertexDeclaration( Elements, &Declaration ) );
V( device->CreateIndexBuffer( 12*2*sizeof(WORD), D3DUSAGE_WRITEONLY, D3DFMT_INDEX16, D3DPOOL_MANAGED, &IB, NULL) );
WORD* pSrcIB=NULL;
V( IB->Lock(0, 0, (void**)&pSrcIB, 0 ) );
pSrcIB[0*2+0] = 0; pSrcIB[0*2+1] = 1;
pSrcIB[1*2+0] = 1; pSrcIB[1*2+1] = 2;
pSrcIB[2*2+0] = 2; pSrcIB[2*2+1] = 3;
pSrcIB[3*2+0] = 3; pSrcIB[3*2+1] = 0;
pSrcIB[4*2+0] = 4; pSrcIB[4*2+1] = 5;
pSrcIB[5*2+0] = 5; pSrcIB[5*2+1] = 6;
pSrcIB[6*2+0] = 6; pSrcIB[6*2+1] = 7;
pSrcIB[7*2+0] = 7; pSrcIB[7*2+1] = 4;
pSrcIB[8*2+0] = 0; pSrcIB[8*2+1] = 4;
pSrcIB[9*2+0] = 1; pSrcIB[9*2+1] = 5;
pSrcIB[10*2+0] = 2; pSrcIB[10*2+1] = 6;
pSrcIB[11*2+0] = 3; pSrcIB[11*2+1] = 7;
V( IB->Unlock() );
V( device->CreateVertexBuffer( 8*Stride , D3DUSAGE_WRITEONLY, 0, D3DPOOL_MANAGED, &VB, NULL) );
Vertex* pSrcVB=NULL;
V( VB->Lock(0, 0, (void**)&pSrcVB, 0 ) );
GetBox(&pSrcVB[0].Position, sizeof(Vertex), minVec, maxVec);
V( VB->Unlock() );
}
That’s it you should be good to go…