【FPGA】Buffer专题介绍(一)
614
2022-05-30
在使用经典的图形API(比如Direct3D11)时,一个典型的场景渲染过程可以用伪代码描述如下:
Map Constant Buffer For View //For example, View Transform, Projection Transform
for each Mesh
{
Map_Write_Discard Call For [Constant Buffer For Per Mesh Data] //For example, Model Transform
...... //For example, CPU Write to It
Unmap Call For It
Draw Call For Mesh
}
尽管应用层绘制了很多个Mesh,但是应用层只创建了一个Constant Buffer。
那么问题来了!当我们在绘制第2个Mesh时,该Constant Buffer中存放着第1个Mesh的相关数据,很可能正在被GPU读取;但是,我们仍可以用CPU将第2个Mesh的相关数据写入到该Constant Buffer中,并不会与GPU的读取发生冲突,这是为什么呢?
注:虽然下文中的讨论是针对Direct3D的Map_Write_Discard,但是,在使用OpenGL时,应用层时也是在只创建一个UniformBuffer的情况下绘制多个Mesh;这意味着OpenGL中的DRAW_DYNAMIC的实现也是如此;虽然按照OpenGL规范,DRAW_DYNAMIC只是应用层的Hint,并不保证驱动实现,但是应用层的用法已经假定了驱动的实现(否则应用层在绘制时需要分配和Mesh个数一样多的Uniform Buffer了(滑稽脸))。
MSDN / Direct3D11 / How to: Use dynamic resources
https://docs.microsoft.com/en-us/windows/desktop/direct3d11/how-to--use-dynamic-resources
MSDN上的Direct3D11文档中对Map_Write_Discard的实现方式进行了说明:当应用层以Write_Discard的方式Map一个Buffer时,驱动会返回一块新的内存区域给应用层,从而避免了CPU与GPU之间的读写冲突。
Holger Gruen. "Constant Buffers without Constant Pain". NVIDIA GameWorks Blog 2015.
http://developer.nvidia.com/content/constant-buffers-without-constant-pain-0
NVIDIA GameWorks Blog上的一篇文章对Map_Write_Discard的驱动实现进行了说明:驱动根据某个配额(目前是128MB)预先分配一大块内存,当应用层调用Map_Write_Discard时,驱动以类似于线性分配器的方式不断将指针后移,并将新的内存区域返回给应用层。
同时该文章中指出:驱动将应用层对UpdateSubresource的调用转发到Map_Write_Discard,UpdateSubresource和Map_Write_Discard在本质上是等价的。
//分界线---------------------------------------------------------------------------------------------------------------------------
MSDN / Direct3D12 / Fence-Based Resource Management / Ring Buffer
https://docs.microsoft.com/en-us/windows/desktop/direct3d12/fence-based-resource-management
在使用次世代的图形API(比如Direct3D12)时,Map_Write_Discard不再被API支持,需要在应用层实现相关的语义,MSDN上的Direct3D12文档中给出了一种基于RingBuffer的实现方式(本质上即模仿驱动实现Map_Write_Discard的方式,只不过配额(即上文中的128MB)可以根据应用层自身的实际情况进行定制)。
本文转载自异步社区
软件开发 软件开发
版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。