初始化 DirectX 12 管道(pipeline)
创建设备(device)
Direct3D 设备代表显示适配器,用于查询特性支持和创建所有其他的Direct3D 接口对象如:资源、视图和命令列表。
使用「D3d12CreateDevice」函数创建设备。函数原型如下:
HRESULT WINAPI D3D12CreateDevice(IUnknown* pAdapter, D3D_FEATURE_LEVEL MinimumFeatureLevel, REFIID riid, ID3D12Device void** ppDevice);
- pAdapter:设备所代表的显示适配器,nullptr 为默认适配器
- MinimumFeatureLevel:设备所支持的最低特性级别
- riid:ID3D12Device 接口的 COM ID
- ppDevice:创建的设备
创建设备如下:
ComPtr<ID3D12Device> mDevice;
// create the device
D3D12CreateDevice(nullptr, D3D_FEATURE_LEVEL_12_0, IID_PPV_ARGS(&mDevice));
创建命令队列、命令列表分配器和命令列表
CPU将命令记录到命令列表,然后将命令列表插入到命令队列。GPU从命令队列中取出命令,然后执行命令。
创建命令队列
使用「D3D12_COMMAND_QUEUE_DESC」结构描述命令队列。结构定义如下:
typedef struct D3D12_COMMAND_QUEUE_DESC
{
D3D12_COMMAND_LIST_TYPE Type;
INT Priority;
D3D12_COMMAND_QUEUE_FLAGS Flags;
UINT NodeMask;
} D3D12_COMMAND_QUEUE_DESC;
- Type:队列中命令列表的类型
- Priority:优先级
- Flags:指定为 D3D12_COMMAND_QUEUE_FLAG_NONE
- NodeMask:指定GPU节点
使用「ID3D12Device::CreateCommandQueue」方法创建命令队列。函数原型如下:
HRESULT CreateCommandQueue(const D3D12_COMMAND_QUEUE_DESC *pDesc, REFIID riid,void **ppCommandQueue);
- pDesc:命令队列描述
- riid:ID3D12CommandQueue 接口的 COM ID
- ppCommandQueue:创建的命令队列
创建命令队列如下:
ComPtr<ID3D12CommandQueue> mCommandQueue;
// create command queue descriptor
D3D12_COMMAND_QUEUE_DESC queueDesc;
ZeroMemory(&queueDesc, sizeof(queueDesc));
queueDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE;
queueDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT;
// create command queue
mDevice->CreateCommandQueue(&queueDesc, IID_PPV_ARGS(&mCommandQueue));
创建命令列表分配器
命令记录到命令列表时,实际上是记录到命令列表分配器的内存上。
使用「ID3D12Device::CreateCommandAllocator」方法创建命令列表分配器。函数原型如下:
HRESULT ID3D12Device::CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE type, REFIID riid, void **ppCommandAllocator);
- type:命令列表类型
- riid:ID3D12CommandAllocator的 COM ID
- ppCommandAllocator:创建的命令列表分配器
创建命令列表分配器如下:
ComPtr<ID3D12CommandAllocator> mCommandAllocator;
// create the command allocator object
mDevice->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(&mCommandAllocator));
创建命令列表
使用「ID3D12Device::CreateCommandList」方法创建命令列表。函数原理如下:
HRESULT ID3D12Device::CreateCommandList(UINT nodeMask, D3D12_COMMAND_LIST_TYPE type, ID3D12CommandAllocator *pCommandAllocator, ID3D12PipelineState *pInitialState, REFIID riid, void **ppCommandList);
- nodeMask:GPU节点
- type:命令列表类型
- pCommandAllocator:命令列表分配器
- pInitialStage:管道状态
- riid:ID3D12GraphicsCommandList的 COM ID
- ppCommandList:创建的命令列表
创建命令列表如下:
ComPtr<ID3D12GraphicsCommandList> mCommandList;
// create command list
mDevice->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, mCommandAllocator.Get(), nullptr, IID_PPV_ARGS(&mCommandList));
创建交换链(swap chain)
后台缓冲(back buffer)渲染,前台缓冲(front buffer)显示,交替进行。
使用「DXGI_SWAP_CHAIN_DESC」结构描述交换链。结构定义如下:
typedef struct DXGI_SWAP_CHAIN_DESC
{
DXGI_MODE_DESC BufferDesc;
DXGI_SAMPLE_DESC SampleDesc;
DXGI_USAGE BufferUsage;
UINT BufferCount;
HWND OutputWindow;
BOOL Windowed;
DXGI_SWAP_EFFECT SwapEffect;
UINT Flags;
} DXGI_SWAP_CHAIN_DESC;
- BufferDesc:缓冲属性的描述
- SampleDesc:多重采样属性的描述
- BufferUsage:指定 DXGI_USAGE_RENDER_TARGET_OUTPUT
- BufferCount:缓冲数
- OutputWindow:渲染窗口
- Windowed: true 窗口模式,false 全屏模式
- SwapEffect:指定 DXGI_SWAP_EFFECT_FLIP_DISCARD
- Flags:可选标识
使用「IDXGIFactory::CreateSwapChain」方法创建交换链。函数原型如下:
HRESULT IDXGIFactory::CreateSwapChain(IUnknown *pCommandQueue, DXGI_SWAP_CHAIN_DESC *pDesc, IDXGISwapChain **ppSwapChain);
- pCommandQueue:命令队列
- pDesc:交换链描述
- ppSwapChain:创建的交换链
创建交换链如下:
int cNumSwapBufs = 2;
ComPtr<IDXGISwapChain> mSwapChain;
// create dxgi factory
ComPtr<IDXGIFactory> pDxgiFactory;
CreateDXGIFactory1(IID_PPV_ARGS(&pDxgiFactory));
// create swap chain descriptor
DXGI_SWAP_CHAIN_DESC descSwapChain;
ZeroMemory(&descSwapChain, sizeof(descSwapChain));
descSwapChain.BufferCount = cNumSwapBufs;
descSwapChain.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
descSwapChain.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
descSwapChain.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL;
descSwapChain.OutputWindow = hWnd;
descSwapChain.SampleDesc.Count = 1;
descSwapChain.Windowed = TRUE;
// create the swap chain
pDxgiFactory->CreateSwapChain(mCommandQueue.Get(), &descSwapChain, &mSwapChain);
初始化 Assets
创建描述符堆(descriptor heap)
GPU 通过描述符/视图(descriptor/view)读写资源(resource)。描述符堆存储描述符。
使用「D3D12_DESCRIPTOR_HEAP_DESC」结构描述描述符堆。结构定义如下:
typedef struct D3D12_DESCRIPTOR_HEAP_DESC
{
D3D12_DESCRIPTOR_HEAP_TYPE Type;
UINT NumDescriptors;
D3D12_DESCRIPTOR_HEAP_FLAGS Flags;
UINT NodeMask;
} D3D12_DESCRIPTOR_HEAP_DESC;
- Type:描述符类型
- NumDescriptors:描述符数
- Flags:指定为D3D12_DESCRIPTOR_HEAP_FLAG_NONE
- NodeMask:GPU 节点
使用「ID3D12Device::CreateDescriptorHeap」方法创建描述符堆。函数原型如下:
HRESULT CreateDescriptorHeap(const D3D12_DESCRIPTOR_HEAP_DESC pDescriptorHeapDesc, REFIID