cms开源网站管理系统,北京网站建设策划解决方案,公众号开发者密码忘了怎么办,企业电子商务网站的建设方式双缓冲模式的意图
双缓冲模式#xff0c;使用序列操作来模拟瞬间或者同时发生的事情
具体定义
双缓冲模式定义缓冲类封装了缓冲#xff1a;一段可改变的状态。 这个缓冲被增量地修改#xff0c;但我们想要外部的代码将修改视为单一的原子操作。 为了实现这点#xff0c;…双缓冲模式的意图
双缓冲模式使用序列操作来模拟瞬间或者同时发生的事情
具体定义
双缓冲模式定义缓冲类封装了缓冲一段可改变的状态。 这个缓冲被增量地修改但我们想要外部的代码将修改视为单一的原子操作。 为了实现这点类保存了两个缓冲的实例下一缓冲和当前缓冲。 当信息从缓冲区中读取它总是读取当前的缓冲区。 当信息需要写到缓存它总是在下一缓冲区上操作。 当改变完成后一个交换操作会立刻将当前缓冲区和下一缓冲区交换 这样新缓冲区就是公共可见的了。旧的缓冲区成为下一个重用的缓冲区。
举个例子
接触过渲染系统的同学应该知道图形渲染的任务就是将指定颜色的像素存储到一个缓冲区中缓冲区中有一个二维的数组 GPU负责读取这个数组根据数组中的颜色信息将图像绘制在屏幕上。我们可以这样定义这个缓冲区
class Framebuffer
{
public:Framebuffer() { clear(); }void clear(){for (int i 0; i WIDTH * HEIGHT; i){pixels_[i] WHITE;}}void draw(int x, int y){pixels_[(WIDTH * y) x] BLACK;}const char* getPixels(){return pixels_;}private:static const int WIDTH 160;static const int HEIGHT 120;char pixels_[WIDTH * HEIGHT];
};其中pixels就是我们说的二维数组GPU会频繁调用函数将缓冲区中的数据通常是颜色信息输送到屏幕上。 我们将整个缓冲区封装在Scene类中。渲染某物需要做的是在这块缓冲区上调用一系列draw()。
class Scene
{
public:void draw(){buffer_.clear();buffer_.draw(1, 1);buffer_.draw(4, 1);buffer_.draw(1, 3);buffer_.draw(2, 4);buffer_.draw(3, 4);buffer_.draw(4, 3);}Framebuffer getBuffer() { return buffer_; }private:Framebuffer buffer_;
};当draw()绘制完毕后GPU就可以调用getBuffer()将数组中的颜色信息读取出来然后在屏幕上绘制对应的信息了。 问题在于我们的GPU会在固定的渲染帧频率期间调用 getBuffer()方法读取pixel中的数据。如果我们绘制的任务比较重那么就有可能出现draw()还没结束GPU就迫不及待读取了这就会造成画面错误。 当上面的情况发生时用户就会看到脸的眼睛但是这一帧中嘴却消失了。 下一帧又可能在某些别的地方发生冲突。最终结果是糟糕的闪烁图形。 我们会用双缓冲模式修复这点
class Scene
{
public:Scene(): current_(buffers_[0]),next_(buffers_[1]){}void draw(){next_-clear();next_-draw(1, 1);// ...next_-draw(4, 3);swap();}Framebuffer getBuffer() { return *current_; }private:void swap(){// 只需交换指针Framebuffer* temp current_;current_ next_;next_ temp;}Framebuffer buffers_[2];Framebuffer* current_;Framebuffer* next_;
};现在scene中有两个缓冲区next_是我们正在绘制的数组。Current_是已经准备就绪CPU可以访问到的数组。每次绘制完毕我们只要交换一下两个数组的指针就好了。在需要时GPU读取current_获取数据绘制图像。因为GPU不会接触到正在施工的数据所以可以保证每次都是正确的图像。
一些要点
Swap本身也需要时间我们必须要保证swap的操作是原子的也就是说在这个过程中没有人可以接触到这两个缓冲区的任何数据这样才能保证双缓冲模式正确运行。 双缓冲需要保存两个缓冲区这可能是个问题你得看看自己的内存够不够用。原文里还用扇耳光游戏说明了双缓冲模式在别的地方的运用这里没有做相关笔记。大体上来说双缓冲模式保证了这个游戏所有人对于巴掌的反应都在下一帧才生效这让它们在同一帧中更新的顺序不该对结果有影响。
使用场合
我们需要维护一些被增量修改的状态。在修改到一半的时候状态可能会被外部请求。我们想要防止请求状态的外部代码知道内部的工作方式。我们想要随时可以读取状态而且不想等着修改完成。