用DirectX 12进行3D游戏编程入门「1」——初始化

初始化 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:创建的命令列表分配器

创建命令列表分配器如下:

// 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:创建的命令列表

创建命令列表如下:

// 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);

猜你喜欢

转载自blog.csdn.net/a39547a/article/details/80792756