Update Constant Buffer的驱动实现
【摘要】 在使用经典的图形API(比如Direct3D11)时,一个典型的场景渲染过程可以用伪代码描述如下:Map Constant Buffer For View //For example, View Transform, Projection Transformfor each Mesh{ Map_Write_Discard Call For [Constant Buffer ...
在使用经典的图形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)可以根据应用层自身的实际情况进行定制)。
本文转载自异步社区
原文链接:https://www.epubit.com/articleDetails?id=NC7E3EF95B12000016E901B811990D900
【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
评论(0)