Most Direct3D books and articles are crap. Microsoft’s documentation is ok but sparse, and really meant for experts. You also need to know a little bit about COM.

Compiling Shaders

If shaders aren’t changed a lot, then it’s probably best to compile them with fxc, perhaps to header files. Otherwise, you’ll want to distribute d3dcompiler_46.dll or d3dcompiler_47.dll with your program. But contrary to earlier information, as of Windows 8.1, d3dcompiler_47.dll is part of the OS.

Pixel shaders - the number is shader model, and is also hardware-dependent

  • ps_5_0: Direct3D 11.0/11.1
  • ps_4_1: Direct3D 10.1
  • ps_4_0: Direct3D 10.0
  • ps_4_0_level_9_3: Direct3D 9.3
  • ps_3_0: Direct3D 9 legacy

Vertex shaders

  • vs_5_0: Direct3D 11.0/11.1
  • vs_4_1: Direct3D 10.1
  • vs_4_0: Direct3D 10.0
  • vs_4_0_level_9_3: Direct3D 9.3
  • vs_3_0: Direct3D 9 legacy

Effects are considered legacy now.

DXGI Overview

  • DXGI 1.0: Windows Vista+
  • DXGI 1.1: Windows Vista with Service Pack 2, Windows 7+
  • DXGI 1.2: Windows 7 with Platform Update, Windows 8+
  • DXGI 1.3: Windows 8.1+

CreateDXGIFactory

In Direct3D 10 and up, this is the gateway function. It has several overrides

DllMain cannot call CreateDXGIFactory[N], so that LoadLibrary dependency loops don’t form.

After creating a factory, use EnumAdapters to find the IDXGIAdapter interfaces.

You should not mix DXGI factories in an application. Use one of IDXGIFactory, IDXGIFactory1 etc.

IDXGIFactory

This is the interface used to create DXGI objects like swap chains.

If you have a device, you can get the factory from it, so that you can create a compatible swap chain

IDXGIDevice * pDXGIDevice = nullptr;
hr = g_pd3dDevice->QueryInterface(__uuidof(IDXGIDevice), (void **)&pDXGIDevice);

IDXGIAdapter * pDXGIAdapter = nullptr;
hr = pDXGIDevice->GetAdapter( &pDXGIAdapter );

IDXGIFactory * pIDXGIFactory = nullptr;
pDXGIAdapter->GetParent(__uuidof(IDXGIFactory), (void **)&pIDXGIFactory);

IDXGIAdapter

This is basically a video card, which can be one or more GPUs, DACs and video memory.

One way to get an adapter is to call IDXGIFactory::EnumAdapters. Note that if adapters are added or removed (e.g. a laptop), you need to destroy and recreate the factory before you enumerate again.

EnumAdapters(0, &adapter) returns the adapter that holds the output that is considered the primary monitor.

DXGIOutput

This represents an output of an adapter, typically a monitor.

Call IDXGIAdapter::EnumOutputs to get the outputs for a specific adapter.

The number of outputs can change dynamically (monitors plugged or unplugged). There will be a WM_DISPLAYCHANGE message, and at that point applications should check to make sure that all HMONITORs are valid. I assume this means re-enumerate? Also, I’m not sure what this line means: “A physical display has the same HMONITOR as long as it is part of the desktop”. Or maybe use GetMonitorInfo to see if the HMONITOR is valid?

EnumOutputs(0, &output) returns the output that is considered the primary monitor.

Introduction to Multithreading in Direct3D 11

High DPI

Positioning Objects on a Multiple Display Setup