D3D12的资源管理已经移交到上层应用了,为此我们需要自己做资源管理,我们先来看一下一个资源从创建到销毁需要经过哪些步骤:
- 磁盘的文件读取,不同的资源有自己的文件格式,其中还可能涉及文件的压缩,因此一个文件首先要从磁盘加载到内存,然后解压缩,解析,最后再转换成显卡识别的内存布局。
- 申请上传堆或者默认堆的内存空间,也就是创建ID3D12Resource资源。
- 接下来使用memcpy函数将资源上传到驱动内存(cpu和gpu共享的内存)。
- 将资源通过PCIE总线上传到默认堆。
- 创建资源的View,也就是通过资源描述符告诉显卡这个内存里面存的是什么,内存布局是怎样的
- 将资源的View设置到根参数中,资源与Shader绑定
- 设置围栏来侦测资源是否已经被显卡使用完毕
- 调用DrawCall使用资源
- 上传指令
- GPU执行Shader
- 销毁资源
从上面的过程中我们可以看到,一个资源其实占用多份内存,比如最先读取的压缩资源,解析后的资源,上传堆中的资源,默认堆中的资源。我们在做资源管理的时候不仅要考虑最终的资源,还要考虑中间生成的临时资源。对于资源的生命周期是逻辑决定的,比如这个资源已经没有Pass使用了,那么我们是否需要销毁它呢?从正确性的角度这个资源已经没有用了,完全可以销毁,但是从逻辑的角度来说下一帧还会用到这个资源,那这个资源是不是应该销毁呢?假如内存和显存足够大,我们其实完全没有必要销毁资源,可是往往我们做的游戏都是在有限的资源里面运行超额的数据,因此所谓资源管理的本质就是尽量减少资源创建和销毁的次数,保证游戏能够正常运行。