DirectX12 3D 初始化

1.创建设备

   设备代表显示适配器(如显卡)。设备即可以检测系统对功能的支持情况,又能创建其他接口对象(如资源,视图,命令列表)。

//创建设备
HRESULT hardwareResult = D3D12CreateDevice(
	nullptr,                      // 创建设备时用的显示适配器,nullptr表示使用主显示适配器
	D3D_FEATURE_LEVEL_11_0,       // 应用程序需要硬件支持的最低功能级别
	IID_PPV_ARGS(&md3dDevice));   // 返回创建的D3D设备

2.创建围栏并获取描述符的大小

    围栏用于GPU/CPU的同步。

md3dDevice->CreateFence(
        0,                      //标识围栏点的整数,初始为0,标记新的围栏点时就将它加1
		D3D12_FENCE_FLAG_NONE,
		IID_PPV_ARGS(&mFence)
        );

    使用描述符时,需要了解它们的大小。

//RTV(渲染目标视图)的大小
mRtvDescriptorSize = md3dDevice->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV);
//DSV(深度/模板视图)的大小
mDsvDescriptorSize = md3dDevice->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_DSV);
//CBV_SRV_UAV(常量缓冲视图,着色器资源视图,无序访问视图)的大小
mCbvSrvUavDescriptorSize = md3dDevice->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);

3.检测对4X MSAA 质量级别的支持

    检测对多重采样 MSAA(MultiSample Anti-Aliasing)的支持情况。

D3D12_FEATURE_DATA_MULTISAMPLE_QUALITY_LEVELS msQualityLevels;
msQualityLevels.Format = mBackBufferFormat;            //纹理格式
msQualityLevels.SampleCount = 4;                       //采样数量
msQualityLevels.Flags = D3D12_MULTISAMPLE_QUALITY_LEVELS_FLAG_NONE; //多重采样支持的标志
msQualityLevels.NumQualityLevels = 0;                    //图像质量级别
ThrowIfFailed(md3dDevice->CheckFeatureSupport(
	D3D12_FEATURE_MULTISAMPLE_QUALITY_LEVELS,    //检测对多重采样
	&msQualityLevels,                            //对多重采样功能的支持信息。兼有输入输出属性,输出信息为图像质量级别
	sizeof(msQualityLevels)));                   //数据结构的大小

m4xMsaaQuality = msQualityLevels.NumQualityLevels;

4.创建命令列表和命令队列

//队列描述
D3D12_COMMAND_QUEUE_DESC queueDesc = {};
queueDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT;
queueDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE;
//创建队列
ThrowIfFailed(md3dDevice->CreateCommandQueue(&queueDesc, IID_PPV_ARGS(&mCommandQueue)));
//创建命令分配器(命令列表里的命令,实际上是存储在与之关联的命令分配器里)
ThrowIfFailed(md3dDevice->CreateCommandAllocator(
	D3D12_COMMAND_LIST_TYPE_DIRECT,                      //命令列表的类型,存储的是GPU可以直接执行的命令
	IID_PPV_ARGS(mDirectCmdListAlloc.GetAddressOf())));  //指向命令分配器的指针
//创建命令列表
ThrowIfFailed(md3dDevice->CreateCommandList(
	0,                                            //0表示系统仅有一个GPU
	D3D12_COMMAND_LIST_TYPE_DIRECT,               //命令列表的类型,存储的是GPU可以直接执行的命令
	mDirectCmdListAlloc.Get(),                   // 相关联命令分配器
	nullptr,                                     // 初始化流水线状态对象
	IID_PPV_ARGS(mCommandList.GetAddressOf())));  //指向命令列表的指针  
//将命令列表置于关闭状态。因为第一次引用命令列表时,要对它重置,而在调用重置方法之前又需要先将其关闭。
mCommandList->Close();

5.描述并创建交换链

//交换链描述
DXGI_SWAP_CHAIN_DESC sd;                        //BufferDesc描述待创建后台缓冲区的属性
sd.BufferDesc.Width = mClientWidth;             //缓冲区分辨率宽度
sd.BufferDesc.Height = mClientHeight;           //缓冲区分辨率高度
sd.BufferDesc.RefreshRate.Numerator = 60;       //刷新频率
sd.BufferDesc.RefreshRate.Denominator = 1;
sd.BufferDesc.Format = mBackBufferFormat;         //缓冲区的显示格式   
sd.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;  //逐行扫描vs隔行扫描
sd.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;                  //图像如何相对于屏幕进行拉伸
sd.SampleDesc.Count = m4xMsaaState ? 4 : 1;                             //多重采样每个像素的采样次数
sd.SampleDesc.Quality = m4xMsaaState ? (m4xMsaaQuality - 1) : 0;        //多重采样的质量级别
sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;    //将数据渲染至后台缓冲区(即用它作为渲染目标)
sd.BufferCount = SwapChainBufferCount;             //交换链中缓冲区数量
sd.OutputWindow = mhMainWnd;                       //渲染窗口的句柄
sd.Windowed = true;                                //true表示程序在窗口模式下运行,false表示采用全屏模式
sd.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD;
sd.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH; //切换到全屏模式时,他将选择最适于当前应用程序窗口尺寸的显示模式。

//创建交换链
ThrowIfFailed(mdxgiFactory->CreateSwapChain(
	mCommandQueue.Get(),                     //指向命令队列的指针 (交换链需要通过队列对其进行刷新)
	&sd,                                     //指向描述符的指针
	mSwapChain.GetAddressOf()));             //返回所创建的交换链

6.创建描述符堆

    描述符堆用来存储程序中用到的描述符。此处创建应用程序所需的RTV(渲染目标视图)和DSV(深度/模板视图)。

D3D12_DESCRIPTOR_HEAP_DESC rtvHeapDesc;
rtvHeapDesc.NumDescriptors = SwapChainBufferCount;
rtvHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV;
rtvHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE;
rtvHeapDesc.NodeMask = 0;
//创建描述符堆,用来存储程序中用到的描述符/视图(渲染目标视图)
ThrowIfFailed(md3dDevice->CreateDescriptorHeap(
    &rtvHeapDesc, IID_PPV_ARGS(mRtvHeap.GetAddressOf())));

D3D12_DESCRIPTOR_HEAP_DESC dsvHeapDesc;
dsvHeapDesc.NumDescriptors = 1;
dsvHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_DSV;
dsvHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE;
dsvHeapDesc.NodeMask = 0;
//创建描述符堆,用来存储程序中用到的描述符/视图(深度/模板视图)
ThrowIfFailed(md3dDevice->CreateDescriptorHeap(
    &dsvHeapDesc, IID_PPV_ARGS(mDsvHeap.GetAddressOf())));

7.创建渲染目标视图

    资源不能和渲染流水线直接绑定,需要先为资源创建视图(描述符),再将其绑定到流水线阶段。

//记录当前后台缓冲区的索引
mCurrBackBuffer = 0; 
//获取描述符堆中,第一个描述符的的句柄
CD3DX12_CPU_DESCRIPTOR_HANDLE rtvHeapHandle(mRtvHeap->GetCPUDescriptorHandleForHeapStart());
for (UINT i = 0; i < SwapChainBufferCount; i++)
{
	//获取交换链中的第i个缓冲区
	ThrowIfFailed(mSwapChain->GetBuffer(i,IID_PPV_ARGS(&mSwapChainBuffer[i])));
	//为此缓冲区创建一个RTV(渲染目标视图)
	md3dDevice->CreateRenderTargetView(mSwapChainBuffer[i].Get(),    //用作渲染目标的资源,后台缓冲区
										nullptr,                    //资源中元素的数据格式,nullptr表示使用该资源创建时的格式
										rtvHeapHandle);            //RTV(渲染目标视图)的描述符句柄
	//偏移到描述符堆中的下一个缓冲区
	rtvHeapHandle.Offset(1, mRtvDescriptorSize);
}

8.创建深度/模板缓冲区及其视图

    深度缓冲区是一种2D纹理,存储着深度信息(模板有模板信息)。

//创建深度/模板缓冲区及其视图
D3D12_RESOURCE_DESC depthStencilDesc;
depthStencilDesc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D;   //资源的维度 2D纹理
depthStencilDesc.Alignment = 0;
depthStencilDesc.Width = mClientWidth;        //纹理宽度                
depthStencilDesc.Height = mClientHeight;      //纹理高度
depthStencilDesc.DepthOrArraySize = 1;      //以纹素为单位表示纹理深度或者纹理数组的大小
depthStencilDesc.MipLevels = 1;            //mipmap层级的数量
depthStencilDesc.Format = DXGI_FORMAT_R24G8_TYPELESS;   //纹素的格式
depthStencilDesc.SampleDesc.Count = m4xMsaaState ? 4 : 1;                     //多重采样对每个像素的采样次数
depthStencilDesc.SampleDesc.Quality = m4xMsaaState ? (m4xMsaaQuality - 1) : 0; //多重采样的质量级别
depthStencilDesc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN;                       //纹理布局
depthStencilDesc.Flags = D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL;            //与资源相关的标记

D3D12_CLEAR_VALUE optClear;
optClear.Format = mDepthStencilFormat;
optClear.DepthStencil.Depth = 1.0f;
optClear.DepthStencil.Stencil = 0;
//根据属性创建一个资源和一个堆,并把资源提交到这个堆中
ThrowIfFailed(md3dDevice->CreateCommittedResource(
    &CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT),   //默认堆 
	D3D12_HEAP_FLAG_NONE,                                //与堆相关的标记
    &depthStencilDesc,                                   //资源描述
	D3D12_RESOURCE_STATE_COMMON,                         //资源的使用状态
    &optClear,                                           //用于清除资源的优化值
    IID_PPV_ARGS(mDepthStencilBuffer.GetAddressOf())));   //返回一个指向ID3D12Resource的指针,即新建的资源

//在使用深度/模板缓冲区之前,一定要创建相关的深度/模板视图,并将它绑定到渲染流水线上
D3D12_DEPTH_STENCIL_VIEW_DESC dsvDesc;   //此结构体描述资源中元素的数据类型(格式)
dsvDesc.Flags = D3D12_DSV_FLAG_NONE;
dsvDesc.ViewDimension = D3D12_DSV_DIMENSION_TEXTURE2D;
dsvDesc.Format = mDepthStencilFormat;
dsvDesc.Texture2D.MipSlice = 0;
md3dDevice->CreateDepthStencilView(mDepthStencilBuffer.Get(), &dsvDesc, DepthStencilView());

//将资源从初始状态转换为深度缓冲区
mCommandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(mDepthStencilBuffer.Get(),
	D3D12_RESOURCE_STATE_COMMON, D3D12_RESOURCE_STATE_DEPTH_WRITE));

9.设置视口

 //定义了视口矩形相对于后台缓冲区的绘制范围
D3D12_VIEWPORT mScreenViewport;
mScreenViewport.TopLeftX = 0;        
mScreenViewport.TopLeftY = 0;
mScreenViewport.Width    = static_cast<float>(mClientWidth);
mScreenViewport.Height   = static_cast<float>(mClientHeight);
mScreenViewport.MinDepth = 0.0f;
mScreenViewport.MaxDepth = 1.0f;
mCommandList->RSSetViewports(1, &mScreenViewport);

 10.设置裁剪矩形

mScissorRect = { 0, 0, mClientWidth, mClientHeight };
mCommandList->RSSetScissorRects(1, &mScissorRect);

   

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值