在完成初始化Direct3D演示程序时,看到和命令队列和命令列表相关的函数。
比如在重写Draw时
mDirectCmdListAlloc->Reset();
官方注释:重复使用内存。什么内存呢?记录命令的内存
接下来是一个针对mCommandList的命令
mCommandList->Reset(mDirectCmdListAlloc.Get(),nullptr)
官方注释:重置命令列表。以此来复用命令列表及其内存。
接下来也是一个针对mCommandList的命令:
mCommandList->ResourceBarrier(1,
&CD3DX12_RESOURCE_BARRIER::Transition(
CurrentBackBuffer(),
D3D12_RESOURCE_STATE_PRESENT,
D3D12_RESOURCE_STATE_RENDER_TARGET
)
)
这些都是啥?注释是说,堆资源的状态进行转换,将资源从呈现状态转换为渲染目标状态。
问题1.ResourceBarrier是什么。其第一个参数是什么。是资源屏障!
书p101这样说,
我们可以将此资源屏障转换看作是一条告知GPU某资源状态正在进行转换的命令,让它在执行后续的命令时防范一下读写的资源冒险。
接下来也是mCommandList的函数。
mCommandList->RSSetViewports(1,&mScreenViewport);设置视口
mCommandList->RSSetScissorRects(1,&mScissorRect);裁剪矩形
ClearRenderTargetView、ClearDepthStencilView这两个函数均在d3d12.h中被提到。
给了一个virtiual void的STDMETHODCALLTYPE……
mCommandList->ClearRenderTargetView(
CurrentBackBufferView(),
Colors::LightSteelBlue,
0,
nullptr
)
mCommandList->ClearDepthStencilView(
DepthStencilView(),
D3D12_CLEAR_FLAG_DEPTH|D3D12_CLEAR_FLAG_STENCIL,
1.0f,
0,
0,
nullptr
)
上面这两个一个是清除后台缓冲区,一个是清除深度缓冲区。让人注意的是,之前书里有说到,View其实就是描述符,在这里通用吗。另外CurrentBackBufferView和DepthStencilView具体内容是什么?若知道,在这里填补。
找到了它们的情况!果然和描述符有关。
在CurrentBackBufferView()中【函数在d3dApp中被定义】
D3D12_CPU_DESCRIPTOR_HANDLE D3DApp::CurrentBackBufferView()const
{
return CD3DX12_CPU_DESCRIPTOR_HANDLE(
mRtvHeap->GetCPUDescriptorHandleForHeapStart(),
mCurrBackBuffer,
mRtvDescriptorSize);
}
其中,一个是我们创建描述符堆时就用到的 CD3DX12_CPU_DESCRIPTOR_HANDLE(用来获得描述符堆的句柄,……我懂了。
CurrentBackBufferView函数取得了描述符所对应的位置,进行清除。
这样说来,其实描述符是一个参数,通过这个参数,一些函数可以对缓冲区资源进行处理。
然后!指定将要渲染的缓冲区
mCommandList->OMSetRenderTargets(1, &CurrentBackBufferView(),true,&DepthStencilView());
这两个View又来了。这两个描述符又来了。这次它们是真的带着地址来了。
之后这块代码就可以写写写。比如之后我们会写一个立方体在这里
【暂时是空的,但画立方体是在这个位置】
然后再次对资源状态进行转换,将资源从渲染目标状态转换回呈现状态
mCommandList->ResourceBarrier(1,
&CD3DX12_RESOURCE_BARRIER::Transition(
CurrentBackBuffer(),
D3D12_RESOURCE_STATE_RENDER_TARGET,
D3D12_RESOURCE_STATE_PRESENT
))
和从呈现状态->渲染目标状态不同的是:后面这个 D3D12_RESOURCE_STATE_PRESENT_TARGET
和D3D12_RESOURCE_STATE_PRESENT位置调换了。似乎第2个函数参数位表示Transition的过去状态,而第3个函数表示要到达的状态。
ThrowIfFailed(mCommandList->Close())
完成命令的记录。这样说来,也许mCommandList其实……还没有被执行。只是放了很多内容进来
获取函数一开始的那个mDirectCmdListAlloc->Reset()的意思是,我们这次也要新来一个mCommandList了。但是呢,这次这个List的位置还是在Alloc上之类的……
接下来是将待执行的命令列表加入命令队列!!来了来了。非常简单的一串代码。执行。就这样!
ID3D12CommandList* cmdsLists[] ={mCommandList.Get()};
mCommandQueue->ExecuteCommandLists(_countof(cmdsLists),cmdsLists);
ThrowIfFailed(mSwapChain->Presend(0,0));
mCurrBackBuffer=(mCurrBackBuffer +1) % SwapChainBufferCount ;//果然交换链也要仔细研究一下才行。
FlushCommandQueue();//这个函数里面是父类里定义的,加了围栏