由于有两个并行运行的处理器(CPU和GPU),会出现许多同步问题。
假设我们有一些资源R存储了我们希望绘制的某些几何体的位置。 此外,假设CPU更新R的数据以存储位置p1,然后将引用R的绘图命令C添加到命令队列,目的是在位置p1处绘制图形。 将命令添加到命令队列不会阻塞CPU,因此CPU会继续运行。 在GPU执行绘图命令C之前,CPU继续并覆盖R的数据以存储新位置p2将会导致错误(参见下图)。

这种情况的一种解决方案是强制CPU等待GPU完成处理队列中的所有命令直到指定的栅栏点(fence point)。 我们称之为刷新命令队列(flushing the command queue)。 我们可以使用栅栏(fence)来做到这一点。 栅栏由ID3D12Fence接口表示,用于同步GPU和CPU。 可以使用以下方法创建fence对象:

HRESULT ID3D12Device::CreateFence(
UINT64 InitialValue,
D3D12_FENCE_FLAGS Flags,
REFIID riid,
void **ppFence); // Example
ThrowIfFailed(md3dDevice->CreateFence(
,
D3D12_FENCE_FLAG_NONE,
IID_PPV_ARGS(&mFence)));

fence对象维护UINT64值,该值只是一个整数,用于标识栅栏时间点。 我们从零开始,每次我们需要标记一个新的栅栏点时,我们只是递增整数。 现在,以下代码/注释显示了我们如何使用fence来刷新命令队列。

UINT64 mCurrentFence = ;
void D3DApp::FlushCommandQueue()
{
// Advance the fence value to mark commands up to this fence point.
mCurrentFence++; // Add an instruction to the command queue to set a new fence point.
// Because we are on the GPU timeline, the new fence point won’t be
// set until the GPU finishes processing all the commands prior to
// this Signal().
ThrowIfFailed(mCommandQueue->Signal(mFence.Get(), mCurrentFence)); // Wait until the GPU has completed commands up to this fence point.
if(mFence->GetCompletedValue() < mCurrentFence)
{
HANDLE eventHandle = CreateEventEx(nullptr, false, false, EVENT_ALL_ACCESS); // Fire event when GPU hits current fence.
ThrowIfFailed(mFence->SetEventOnCompletion(mCurrentFence, eventHandle));
// Wait until the GPU hits current fence event is fired.
WaitForSingleObject(eventHandle, INFINITE);
CloseHandle(eventHandle);
}
}

图4.8以图形方式解释了此代码。

图4.8。 在这个快照中,GPU已经处理了直到xgpu之前的命令,而CPU刚刚调用了ID3D12CommandQueue :: Signal(fence,n + 1)方法。 这实质上是在队列末尾添加一条指令,将fence值更改为n + 1.但是,mFence-> GetCompletedValue()将继续返回n,直到GPU处理完队列中在Signal指令之前的所有命令。

因此在前面的示例中,在CPU发出绘图命令C之后,它将在覆盖R的数据之前刷新命令队列以存储新位置p2。 这个解决方案并不理想,因为它意味着CPU在等待GPU完成时处于空闲状态,但它提供了一个简单的解决方案,我们将在第7章之前使用它。您几乎可以在任何时候刷新命令队列(每帧不一定只有一次); 比如如果您有一些初始化GPU命令,则可以在进入主渲染循环之前刷新命令队列以执行初始化。
请注意,刷新命令队列也可用于解决我们在上一节末尾提到的问题; 也就是说,我们可以刷新命令队列,以确保在重置命令分配器之前已经执行了所有GPU命令。

【D3D12学习手记】CPU/GPU Synchronization的更多相关文章

  1. 【D3D12学习手记】The Command Queue and Command Lists

    GPU有一个命令队列,CPU通过Direct3D API将命令提交到队列里来使用命令列表(command lists),如下图.当一套命令(a set of commands)已经被提交到命令队列,他 ...

  2. 【D3D12学习手记】4.3.8 Create the Depth/Stencil Buffer and View

    我们现在需要创建深度/模板缓冲区. 如§4.1.5所述,深度缓冲区只是一个2D纹理,用于存储最近的可见对象的深度信息(如果使用模板(stencil),则也会存储模板信息). 纹理是一种GPU资源,因此 ...

  3. 【D3D12学习手记】4.1.6 Resources and Descriptors

    在渲染过程中,GPU将写资源(resources)(例如,后缓冲区,深度/模板缓冲区),读资源(例如,描述表面外观的纹理,存储场景中几何体3D位置的缓冲区).在我们发出绘图命令之前,我们需要将资源绑定 ...

  4. 【D3D12学习手记】The Swap Chain and Page Flipping

    为了避免动画中的闪烁,最好将整个动画帧绘制到称为后台缓冲区的屏幕外纹理(off-screen texture)中.一旦整个场景被绘制到给定动画帧的后缓冲区,它就作为一个完整的帧呈现给屏幕;以这种方式, ...

  5. Linux.NET学习手记(7)

    前一篇中,我们简单的讲述了下如何在Linux.NET中部署第一个ASP.NET MVC 5.0的程序.而目前微软已经提出OWIN并致力于发展VNext,接下来系列中,我们将会向OWIN方向转战. 早在 ...

  6. Raspberry Pi B+ 定时向物联网yeelink上传CPU GPU温度

     Raspberry Pi B+ 定时向物联网yeelink上传CPU GPU温度 硬件平台: Raspberry Pi B+ 软件平台: Raspberry 系统与前期安装请参见:树莓派(Ros ...

  7. 舌尖上的硬件:CPU/GPU芯片制造解析(高清)(组图)

    一沙一世界,一树一菩提,我们这个世界的深邃全部蕴藏于一个个普通的平凡当中.小小的厨房所容纳的不仅仅是人们对味道的情感,更有推动整个世界前进的动力.要想理解我们的世界,有的时候只需要细细品味一下我们所喜 ...

  8. CPU/GPU/TPU/NPU...XPU都是什么意思?

    CPU/GPU/TPU/NPU...XPU都是什么意思? 现在这年代,技术日新月异,物联网.人工智能.深度学习等概念遍地开花,各类芯片名词GPU, TPU, NPU,DPU层出不穷......都是什么 ...

  9. 深度学习框架:GPU

    深度学习框架:GPU Deep Learning Frameworks 深度学习框架通过高级编程接口为设计.训练和验证深度神经网络提供了构建块.广泛使用的深度学习框架如MXNet.PyTorch.Te ...

随机推荐

  1. View相关面试问题-事件分发面试问题讲解

    为什么会有事件分发机制: 安卓上面的View是树形结构的,View可能会重叠在一起,当我们点击的地方有多个View都可以响应的时候,这个点击事件应该给谁呢?为了解决这一问题,就有了事件分发机制.用图来 ...

  2. IntelliJ IDEA安装后几个重要的目录及配置文件讲解

    本文大概记录了IntelliJ IDEA安装之后比较重要的目录和几个核心文件 重要的安装目录 安装完之后的bin目录大致如下 IntelliJ IDEA 的安装目录并不复杂,上图为最常改动的 bin ...

  3. Web Api(4)

    参考原文链接https://www.cnblogs.com/JamelAr/,本文大部分内容是根据这位博主进行实验测试的,非常感谢分享,另外也参考了https://www.cnblogs.com/vi ...

  4. https://openmaptiles.org/

    docker save klokantech/tileserver-gl:latest -o tileserver-gl.tar docker load -i tileserver-gl.tar do ...

  5. MariaDB基本命令

    --查看当前日期select current_date();--查看当前时间select current_time();--查看当前日期.时间select now();--查看当前用户select u ...

  6. java常见问题 ——运行报错1

    错误1 打印乱码 相关代码 response.getWriter().print(tbItem.toString()); response.setContentType("text/html ...

  7. HTML+JS中网页跳转的写法

    1.html中使用meta中跳转,通过meta可以设置跳转时间和页面 <head> <!--只是刷新不跳转到其他页面 --> <meta http-equiv=" ...

  8. UBUNTU 15.10 CAFFE安装教程(测试可用)

    转帖:https://github.com/BVLC/caffe/wiki/Ubuntu-15.10-Installation-Guide Ubuntu 15.10 have been release ...

  9. OpenCV使用Cmake来管理工程

    写篇入门级别的文章,对于配置OpenCV很多人不知道有这种方法,其实这种方法在OpenCV编译过程中已经使用到的了,如果有手动编译OpenCV经验的同学可以很快的学会这种工程管理方法 方法优点,只要有 ...

  10. 【知识库】-数据库_MySQL 的七种 join

    掘金作者:haifeisi 文章出处: MySQL 的七种 join Learn [已经过测试校验] 一.内连接 二.左外连接 三.右外连接 四.左连接 五.右连接 六.全连接 七.两张表中都没有出现 ...