D3D12渲染技术之初始化流程

掌握了矩阵向量运算后,接下来我们要做的事情利用D3D12图形库API编程,也就是我们通常说的初始化D3D12,D3D12的初始化工作与以前的D3D9是完全不一样的,D3D12做了大幅的升级。但是每个D3D图形API都有自己的初始化流程,大家只要记住这个流程,学习起来就比较容易,就跟生产车架的流水线作业一样的原理,先做什么后做什么。其他的内容向里面添加就可以了,我们先聊聊D3D12的初始化流程,然后再编程实现。

D3D初始化

1、创建窗体
2、创建ID3D12Device设备
3、创建 ID3D12Fence用于查询descriptor 大小
4、检查设备是否支持4X MSAA
5、创建指令队列,指令列表和主指令列表。
6、创建交换链
7、创建描述符堆(descriptor heaps)
8、创建渲染目标视图。
9、创建深度/模板缓冲区及其关联的深度/模板视图。
10、设置视口

共分为10步,严格来说,第一步不属于D3D12初始化里面的内容,因为我们要显示D3D12中的内容,必须要要有窗体作为载体,在这里就把他们加进来了,我们下面就按照这10步去编写程序实现我们的D3D12的初始化工作。

  • 创建窗体
    窗体是一个载体,用于显示D3D12内容的,首先需要注册窗体类,把它们里面的参数填满,代码如下所示:
bool D3DApp::InitMainWindow()
{
    WNDCLASS wc;
    wc.style         = CS_HREDRAW | CS_VREDRAW;
    wc.lpfnWndProc   = MainWndProc; 
    wc.cbClsExtra    = 0;
    wc.cbWndExtra    = 0;
    wc.hInstance     = mhAppInst;
    wc.hIcon         = LoadIcon(0, IDI_APPLICATION);
    wc.hCursor       = LoadCursor(0, IDC_ARROW);
    wc.hbrBackground = (HBRUSH)GetStockObject(NULL_BRUSH);
    wc.lpszMenuName  = 0;
    wc.lpszClassName = L"MainWnd";

    if( !RegisterClass(&wc) )
    {
        MessageBox(0, L"RegisterClass Failed.", 0, 0);
        return false;
    }

    // Compute window rectangle dimensions based on requested client area dimensions.
    RECT R = { 0, 0, mClientWidth, mClientHeight };
    AdjustWindowRect(&R, WS_OVERLAPPEDWINDOW, false);
    int width  = R.right - R.left;
    int height = R.bottom - R.top;

    mhMainWnd = CreateWindow(L"MainWnd", mMainWndCaption.c_str(), 
        WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, width, height, 0, 0, mhAppInst, 0); 
    if( !mhMainWnd )
    {
        MessageBox(0, L"CreateWindow Failed.", 0, 0);
        return false;
    }

    ShowWindow(mhMainWnd, SW_SHOW);
    UpdateWindow(mhMainWnd);

    return true;
}

这个在DX9或者MFC中都会用到,这里就不介绍了,接下来开始进的入D3D12编程的正题了。

  • 创建ID3D12Device设备
    创建D3D12的设备,自然想到函数:D3D12CreateDevice,在D3D12中我们还需要做一件事情就是调用函数:CreateDXGIFactory1在这个函数中有DXGI字样,DXGI它是DirectX Graphics Infrastructure的缩写,DXGI 可以操控一些普通的图形功能,这其中包括全屏转换、枚举图形系统信息(比如显示适配器、显示器、被支持的显示模式(分辨率,刷新率等等)),它还定义了各种纹理格式(DXGI_FORMAT)。CreateDXGIFactory1就是DXGI下面的一个接口函数,可以枚举显示适配器。
    函数调用代码如下:
CreateDXGIFactory1(IID_PPV_ARGS(&mdxgiFactory))

其中 IID_PPV_ARGS 宏用来返回 COM 接口的 ID
接下来调用D3D12CreateDevice函数,代码实现如下:

HRESULT hardwareResult = D3D12CreateDevice(
        nullptr,             // default adapter
        D3D_FEATURE_LEVEL_11_0,
        IID_PPV_ARGS(&md3dDevice));


    if(FAILED(hardwareResult))
    {
        ComPtr<IDXGIAdapter> pWarpAdapter;
        ThrowIfFailed(mdxgiFactory->EnumWarpAdapter(IID_PPV_ARGS(&pWarpAdapter)));

        ThrowIfFailed(D3D12CreateDevice(
            pWarpAdapter.Get(),
            D3D_FEATURE_LEVEL_11_0,
            IID_PPV_ARGS(&md3dDevice)));
    }

if条件语句内部就是枚举适配器的代码,设备创建好了以后,下面就是创建Fence了。

  • 创建 ID3D12Fence
    接下来我们需要创建Fence对象用于CPU/GPU同步,另外,一旦我们开始使用描述符,我们将需要知道它们的大小, 描述符大小可能因GPU而异,因此我们需要查询此信息, 我们缓存描述符的大小,以便在我们需要它时可用于各种描述符类型,代码如下所示:
    ThrowIfFailed(md3dDevice->CreateFence(0, D3D12_FENCE_FLAG_NONE,
        IID_PPV_ARGS(&mFence)));

    mRtvDescriptorSize = md3dDevice->GetDescriptorHandleIncrementSize(D3D12_
  • 7
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

海洋_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值