? ? ? ? 所谓双缓冲就是定义两个缓冲区,一个是当前缓冲区用来读取信息,另一个是后台缓冲区,用来在后台写入信息。当前缓冲区的数据使用完毕后,交换两个缓冲区(可以仅仅是两个引用的交换),当前缓冲区变成后台缓冲区,后台缓冲区变成当前缓冲区。
? ? ? ? 这是一个你在需要时自然会想起的设计方式。当下面这些条件成立时,适用双缓冲:
????????1. 我们需要维护一些被逐步改变着的状态量。
????????2. 同个状态可能会在其被修改的同时被访问到。
????????3. 我们希望避免访问状态的代码能看到具体的工作过程。
????????4. 我们希望能够读取状态但不希望等待写入操作的完成。
? ? ? ? 讲解双缓冲最常见的例子就是屏幕的绘制过程。屏幕绘制过程中我们的GPU通过运算那些疯狂的高级图形算法计算一帧中屏幕上每一个像素点显示需要的像素数据,这些数据会写到RAM上一个叫做缓冲区的内存块上(也就是我们为了绘制图形分配的一块内存)。然后我们的显卡从缓冲区上读取像素数据用来刷新屏幕,这就是我们屏幕绘制过程的简单描述。
? ? ? ? 如果我们使用单个缓冲,就可能出现一种情况,我们的显卡正在读取数据显示到屏幕上,此时GPU不知道当前缓冲区的数据是否使用完毕,开始往缓冲区上写入数据,这就会导致当前没有显示完成的数据被覆盖了,然后屏幕上就显示了错误的数据。
? ? ? ? 使用两个缓冲的话,就可以保证一个缓冲用于往屏幕上显示数据,另一个缓冲用来写入GPU的计算数据。这样屏幕上一帧渲染完毕后,就可以通过交换两个缓冲区的引用,立马拿到一帧新的数据用来渲染屏幕,同时GPU可以利用被交换下去的缓冲区继续往里面写入数据。这样不仅避免了的单缓冲的写入读取冲突问题,还可以保证屏幕帧的刷新不会因为当前帧渲染完毕后还没有准备好下一帧的数据而出现卡顿现象。
? ? ? ? 使用双缓冲的话它也有两个缺点:
? ? ? ? 1. 交换本身需要时间。如果你交换的只是两块内存区的应用(指针),或者两个缓冲仅仅是两个状态值得交换,那这样的交换时间可以忽略不计。如果是两块内存量大的缓存交换,那就要权衡一下了。
? ? ? ? 2. 两个缓冲当然也会增加内存的使用了。如果你的使用场景对内存比较苛刻,那么你也要权衡一下了。
? ? ? ?如果你对图形绘制接口熟悉的话,那么你会发现双缓模式在这些软件包中都有应用。例如,OpenGL中的swapBuffers()函数,Direct3D中的“swap chains”,微软XNA框架在endDraw()方法中也使用了帧缓冲区的交换。
参考:?http://gameprogrammingpatterns.com/double-buffer.html
|