- 啥是视图?
- 为何要创建视图?
- 顺序咋样?
- 效果咋样?
- 要创建几次?
- 怎样创建?
在创建第一个初始化程序的时候,在DRAW函数中我们会
- 清除后台缓冲区和深度缓冲区
- 指定将要渲染的缓冲区
- 交换后台缓冲区和前台缓冲区。
这些缓冲区buffer和我们题目中的视图view有什么关系?
还见过一种说法:“顶点缓冲区的视图”与“索引缓冲区的视图”,这又是什么意思呢?
描述堆也会遇到以VIEW这类词语位结尾的标记,意思表达了是不同的缓冲区的情况。这又有什么干系?
这篇一定要弄懂。用几个知识点拼在一起,找到其中关联并梳理。
一、缓冲区的建立。
- 建立的原因:使GPU可以访问一些资源(比如顶点、索引数组)
- 形态:这些资源就储存在这里。
- 类别:储存了什么资源,就是什么类别,比如有顶点缓冲区、索引缓冲区、(常量缓冲区-给着色器的)等。
- 程序表示:ID3D12Resource
- 创建方法:a.填写D3D12_RESOURCE_DESC结构体。b.调用ID3D12Device::CreateCommittedResource方法。
- 视图:缓冲区有视图这个概念。通过D3D12_VERTEX_BUFFER_VIEW进行描述。
- 绑定到渲染流水线(IA阶段。这是啥阶段?小点研究)通过ID3D12GraphicsCommandList::IASetVertexBuffers方法。
- 绘制!:借助ID3D12GraphicsCommandList::DrawIndexedInstanced方法进行绘制。
- List item
二、资源与描述符(p83页)
- GPU通过描述符与渲染流水线相连。
- 资源是一个普通的内存块。
- 资源绑定在渲染流水线上。
- 描述符帮助GPU获得数据,和数据的信息。
- 我们也通过指定描述符的方式把绘制要引用的资源绑定到渲染流水线。
- 描述符告诉我们资源如何使用,比如绑定在流水线上的哪个阶段。
- 我们用多个描述符引用同一个资源,或资源中不同的局部数据。
- 当一个纹理需要用作渲染目标和着色器资源时,我们需要为它分别创建两个描述符:一个RTV,一个SRV。
- 问:描述符本身带着类别,它被储存在哪里?又是怎么在GPU要获取资源时发现它的呢?是我们必须要时刻记住的存在吗?还是可以自动读取数据自动读取描述符进行渲染呢?
- 描述符应该在初始化时创建。
- 视图view和描述符descriptor是同义词。常量缓冲区视图和常量缓冲区描述符是同一事物。
- 问:描述符的形态是不是就是一个词?
- 描述符的具体类型有:
CSV:常量缓冲区视图
SRV:着色器资源视图
UAV:无序访问视图
sampler:采样器
RTV:表示的是渲染目标视图资源
DSV:深度/模板视图资源
————————准备阶段结束-学习阶段开始——————————
我们在为谁创建描述符?资源。
为了将资源妥善地绑定到流水线阶段供GPU使用。
比如,为了将后台缓冲区绑定到流水线的输出合并阶段,我们需要为该后台缓冲区创建一个渲染目标视图。
步骤1. 获得存于交换链中的缓冲区资源。
HRESULT IDXGISwapChain::GetBuffer(
UINT Buffer,//希望获得的特定后台缓冲区的索引。是索引!!!后台缓冲区不只有一个,所以要用索引指明。
REFIID riid,//希望获得的ID3D12Resource接口的COMID
void **ppSurface//返回一个指向ID3D12Resourse接口的指针。这便是希望获得的后台缓冲区
)
【注意,这个函数会增加相关后台缓冲区的COM引用计数,所以在每次使用后一定要将其释放。
通过ComPtr便可以自动做到这一点。】
步骤2.为获取的后台缓冲区创建 渲染目标视图。
void ID3D12Device::CreateRenderTargetView(
ID3D12Resource *pResource,//用作渲染目标的资源
const D3D12_RENDER_TARGET_VIEW_DESC *pDesc,//
D3D12_CPU_DESCRIPTOR_HANDLE DestDescriptor,
)
分析一下如上函数,意思是为获得的后台缓冲区(这个缓冲区里面具有了数据和资源。后台缓冲区中的一个缓冲区。)创建它的描述符。根据这三个参数一个是输入,一个是输出来看,唯一可以处理的就是那个D3D12_RENDER_TARGET_VIEW_DESC了。在这里写入标记吗?对的。这是一个结构体。里面包含了很多数据。
这个结构体描述了资源中元素的数据类型(格式),但是如果已经指定了格式,那么就可以写nullptr。
惊了。我完全有点明白了。
这个DESC并不处理描述符的情况,而是数据类型,比如浮点数呀32位或者其他。
那么真正处理描述符的应该是描述符了!就是DestDescriptor了,它会怎么被使用的呢。
交换链是什么(起一个小点研究)
步骤3.使用演示
以下示例通过调用这两种方法位交换链中的每一个缓冲区都创建了一个RTV。
ComPtr<ID3D12Resource> mSwapChainBuffer[SwapChainBufferCount];
上面一下子建立了好多个后台缓冲区。然后要干嘛?
CD3DX12_CPU_DESCRIPTOR_HANDLE rtvHeapHeadle(
mRtvHeap->GetCPUDescriptorHandleForHeapStart()
)
这个函数是获得了一个描述符堆的第一个符的位置。这个mRtvHeap是在一开始创建好的,已经建立好的一个描述符堆
里面储存了SwapChainBufferCount个RTV。
RTV那个标签,也是在建立这个mRtvHeap的时候放入进去的。
我们现在一手拿着这个堆,需要缝合资源和这个堆!
for(UINT i=0;i<SwapChainBufferCount;i++)
{
ThrowIfFailed(mSwapChain->GetBuffer(i,IID_PPV_ARGS(&mSwapChainBuffer[i])));
md3dDevice->CreateRenderTargetView(mSwapChainBuffer[i].Get(),nullptr,rtvHeapHandle);
//很明显,这里的这个rtvHeapHandle就是最早获得的那个早早写好的描述符堆的地址。
//在这里就是为这个后台缓冲区创建了一个描述符堆里的描述符。
//问:这个描述符是已经像是印记那样和这个后台缓冲区不可分割了呢,?还是这个描述符本身带着后台缓冲区的信息。是如何起效果的?
rtvHeapHandle.Offset(1,mRtvDescriptorSize);//偏移到描述符堆中的下一个缓冲区。
)
}
这里便是步骤一:获得位于交换链中的缓冲区资源。
然后是步骤二,为获取的后台缓冲区创建 渲染目标视图