I've decided to make a demo for this year's Riverwash demoscene party. For that purpose recently I've prepared my framework and coded loading of display settings from either command line parameters, configuration file or my brand new dialog box:
Coding it reminded me of my thoughts about display settings from user's versus programmer's perspective. User is usually able to change screen resolution and sometimes also change refresh rate, turn vertical synchronization on/off, toggle between fullsreen and windowed mode, choose antialiasting, texture filtering quality and some general quality/performance parameters. On the other hand, programmer passes bunch of parameters to Direct3D as D3DDPRESENT_PARAMETERS structure and other arguments to functions CreateDevice and Reset. The question is how to map between these parameters?
Here are my current beliefs on this subject:
[+] Adapter: I just pass D3DADAPTER_DEFAULT constant. Sure it would be better to give a choice of an adapter (one can enumerate adapters using IDirect3D9 methods), but it's useful only on multi-monitor systems and not many games expose such setting.
[+] DeviceType: I always pass D3DDEVTYPE_HAL. Using software reference rasterizer D3DDEVTYPE_REF makes no sense, as it gives SPF instead of FPS :)
[+] BehaviorFlags: Now I always pass D3DCREATE_HARDWARE_VERTEXPROCESSING. Using software or mixed verex processing made sense only on old hardware, especially on old Intel laptop graphics chips, which had Pixel Shader 2.0 but no Vertex Shader at all.
[+] BackBufferWidth, BackBufferHeight: I give a choice of display modes available on default adapter with format hardcoded as constant (D3DFMT_X8R8G8B8). One can enumerate available display modes using IDirect3D9 methods. In windowed mode it could also be reasonable to be able to set any given resolution (Width and Height as text fields), as well as manually resize application's window.
[+] BackBufferFormat: I just use D3DFMT_A8R8G8B8. Choice between X8R8G8B8 and A8R8G8B8 just the matter of having additional fourth channel available (alpha), which is obviously not visible, but can be written, used in alpha blending and thus utilized to do some special effects (like masking intensity of some effect in screen space).
[+] BackBufferCount: I just give 0 here, which resolves to default value of 1 back buffer. I'm aware that using value 2 can change the way rendering is performed a bit.
[+] SwapEffect: I always use constant D3DSWAPEFFECT_DISCARD, as it is the fastest one. It says that entire content of the back buffer can be discarded after frame was presented and program have to render new frame from scratch (which is what we always do in game development).
[+] AutoDepthStencilFormat: Direct3D defines many of them, but for real all the D3D9 generation hardware supports only three: D3DFMT_D16, D24X8 and D24S8. So the choice is only based on the decision whether we need higher, 24-bit precision or stencil buffer.
[+] Flags: For the best performance possible I always give D3DPRESENTFLAG_DISCARD_DEPTHSTENCIL and never give D3DPRESENTFLAG_LOCKABLE_BACKBUFFER.
[+] FullScreen_RefreshRateInHz: Nowadays, when many (most?) people have LCD displays, standard refresh rate is 60 Hz and maybe 75 Hz. In the CRT era setting good refresh rate was crucial for playing comfort and thus it was very annoying when a game didn't expose setting of refresh rate, but used default 60 Hz instead. I believe refresh rates should be enumerated and given as a choice next to the resolution.
[+] PresentationInterval: This is the value the "VSync" setting is converted to. It looks like D3DPRESENT_INTERVAL_DEFAULT behaves as VSync turned on (FPS <= RefreshRate) and D3DPRESENT_INTERVAL_IMMEDIATE means VSync off (FPS as high as possible), but once during my experiments I've observed that flag D3DPRESENT_INTERVAL_ONE behaves slightly different than D3DPRESENT_INTERVAL_DEFAULT (I can't remember the details now).
I know I would sound more "professional" if I considered all other constant values available and their possible uses, but I don't care :) My point here was to simplify the problem to be able to map these technical parameters to the display settings exposed to the user. Multisampling is separate subject so I don't cover it here.