Hi,
Like any other enthousiast, before releasing my top selling FPS game, I'd like to make my 3d engine/ apps hardware variants proof
I see doing this with the following steps:
1. Check top 5 items while creating device and select 'lower' value if a specific adapter or bufferformat is not available (same for MSAA). Let's call this the basics (i.e. if MSAA not available, though requested, I select no MSAA and let the user continue). In place today and working fine.
2. Create a list of D3D (related) caps that are needed for the current functionalities, and check if these are available.
For now not available means, too bad. Application quits. I keep these up to date as soon as I add new functionality in my engine.
3. Create backwards compability variances for situaties in '2' where a device doesn't meet the requirements.
Same for the vertex and pixel shaders.
Step 3 is something I'll postpone for now, since I'm using D3D9 and PS/VS 2.0, which most devices today support.
I really to hear your advice and tips to make step 2 more efficient, I've posted the code I have now
(accepting that I send away users with hardware that doesn't meet the requirements )
bool CD3d::CheckDeviceCaps()
{
int nrReqDevCaps = 9;
DWORD reqDevCaps[9] = { D3DDEVCAPS_DRAWPRIMTLVERTEX, D3DDEVCAPS_HWRASTERIZATION, D3DDEVCAPS_TLVERTEXSYSTEMMEMORY,
D3DDEVCAPS_TLVERTEXVIDEOMEMORY, D3DPRASTERCAPS_ZBUFFERLESSHSR, D3DPRASTERCAPS_ZTEST,
D3DDEVCAPS_EXECUTESYSTEMMEMORY, D3DDEVCAPS_EXECUTEVIDEOMEMORY, D3DDEVCAPS_TEXTUREVIDEOMEMORY };
int nrReqPresentCaps = 3;
DWORD reqPresentCaps[3] = { D3DPRESENT_INTERVAL_ONE, D3DPRESENT_INTERVAL_TWO, D3DPRESENT_INTERVAL_IMMEDIATE };
int nrReqTexFilterCaps = 4;
DWORD reqTexFilterCaps[4]= {D3DPTFILTERCAPS_MAGFLINEAR, D3DPTFILTERCAPS_MINFLINEAR, D3DPTFILTERCAPS_MIPFLINEAR,
D3DPTFILTERCAPS_MINFANISOTROPIC };
int nrReqPrimMiscCaps =3;
DWORD reqPrimMiscCaps[3] = {D3DPMISCCAPS_CULLNONE, D3DPMISCCAPS_CULLCW, D3DPMISCCAPS_CULLCCW };
int nrReqTextureCaps = 2;
DWORD reqTextureCaps[2] = { D3DPTEXTURECAPS_MIPMAP, D3DPTEXTURECAPS_ALPHA }; // CUBEMAP and VOLUMEMAP later
int nrReqTexAddrCaps = 5;
DWORD reqTexAddrCaps[5] = { D3DPTADDRESSCAPS_BORDER, D3DPTADDRESSCAPS_CLAMP, D3DPTADDRESSCAPS_WRAP,
D3DPTADDRESSCAPS_INDEPENDENTUV, D3DPTADDRESSCAPS_MIRROR };
int nrReqRasterCaps = 2;
DWORD reqRasterCaps[2] = { D3DPRASTERCAPS_ANISOTROPY, D3DPRASTERCAPS_DITHER };
int nrReqShadeCaps = 3;
DWORD reqShadeCaps[3] = { D3DPSHADECAPS_ALPHAGOURAUDBLEND,D3DPSHADECAPS_SPECULARGOURAUDRGB,
D3DPSHADECAPS_COLORGOURAUDRGB };
if(mD3d != NULL)
{
D3DCAPS9 caps;
if(D3D_OK != mD3d->GetDeviceCaps(D3DADAPTER_DEFAULT, mDevType, &caps)) return false;
for(cc=0;cc<nrReqDevCaps;++cc) { if(!(caps.DevCaps & reqDevCaps[cc])) return false; }
for(cc=0;cc<nrReqPresentCaps;++cc) { if(!(caps.PresentationIntervals & reqPresentCaps[cc])) return false; }
for(cc=0;cc<nrReqTexFilterCaps;++cc){ if(!(caps.VertexTextureFilterCaps & reqTexFilterCaps[cc])) return false; }
for(cc=0;cc<nrReqTexAddrCaps;++cc) { if(!(caps.TextureAddressCaps & reqTexAddrCaps[cc])) return false; }
for(cc=0;cc<nrReqPrimMiscCaps;++cc) { if(!(caps.PrimitiveMiscCaps & reqPrimMiscCaps[cc])) return false; }
for(cc=0;cc<nrReqRasterCaps;++cc) { if(!(caps.RasterCaps & reqRasterCaps[cc])) return false; }
for(cc=0;cc<nrReqShadeCaps;++cc) { if(!(caps.ShadeCaps & reqShadeCaps[cc])) return false; }
if(D3D_OK != mD3d->CheckDeviceFormat(D3DADAPTER_DEFAULT, mDevType, mAdapterFormat, D3DUSAGE_AUTOGENMIPMAP, D3DRTYPE_TEXTURE, D3DFMT_X8R8G8B8)) return false;
if(!(caps.Caps2 & D3DCAPS2_CANAUTOGENMIPMAP)) return false;
if(caps.VertexShaderVersion < D3DVS_VERSION(2,0)) return false;
if(caps.PixelShaderVersion < D3DPS_VERSION(2,0)) return false;
if(caps.MaxAnisotropy < 4) return false;
if(caps.MaxTextureWidth < 256) return false;
if(caps.MaxTextureHeight < 256) return false;
if(caps.TextureCaps & D3DPTEXTURECAPS_SQUAREONLY) return false;
return true;
}
else return false;
}
Can this be done, easier? (i.e. with an array of DWORD values / caps and the corresponding caps.'' etc.)