### double buffer 双缓存

简单说: 当一个缓存被读取的时候,往另一个缓存里写入, 如此交替

#### the pattern
有两个缓存实例,一个是 current buffer, 一个是next buffer 从current buffer读取信息, 往next buffer里写入信息.
swap操作,进行两种buff的身份切换 #### 何时使用
需要增量修改的状态
在修改的过程中需要进行访问
当访问数据的时候,不会发现数据正在被写入
读操作不用等待写的操作完成 #### 注意事项 swap操作比较耗时
必须有两个buffer, 内存消耗变大 #### Sample Code ####一个帧缓存的例子 ```
class Framebuffer
{
public:
Framebuffer() { clear(); } void clear()
{
for (int i = ; 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 = ;
static const int HEIGHT = ; char pixels_[WIDTH * HEIGHT];
}; // 问题版本
class Scene
{
public: // 每一帧执行 void draw()
{
buffer_.clear(); buffer_.draw(, );
buffer_.draw(, );
// 问题! video driver 可以在任何时候读取pixels, 可能会读到非法值
buffer_.draw(, );
buffer_.draw(, );
buffer_.draw(, );
buffer_.draw(, );
} Framebuffer& getBuffer() { return buffer_; } private:
Framebuffer buffer_; void swap()
{
// Just switch the pointers.
Framebuffer* temp = current_; current_ = next_;
next_ = temp;
} }; // 使用double buffer
class Scene
{
public:
Scene()
: current_(&buffers_[]),
next_(&buffers_[])
{} // video driver 只会从 current里获取pixel
void draw()
{
next_->clear(); next_->draw(, );
// ...
next_->draw(, ); swap();
} Framebuffer& getBuffer() { return *current_; } private:
void swap()
{
// Just switch the pointers.
Framebuffer* temp = current_;
current_ = next_;
next_ = temp;
} Framebuffer buffers_[];
Framebuffer* current_;
Framebuffer* next_;
}; ``` ##### Artificial unintelligence ```
class Actor
{
public:
Actor() : slapped_(false) {} virtual ~Actor() {}
virtual void update() = ; void reset() { slapped_ = false; }
void slap() { slapped_ = true; }
bool wasSlapped() { return slapped_; } private:
bool slapped_;
}; // 每一帧都会调用actor的update, ,所有的actor需要同时进行更新
// actor之间可以交互, 例如击打 class Stage
{
public:
void add(Actor* actor, int index)
{
actors_[index] = actor;
} void update()
{
for (int i = ; i < NUM_ACTORS; i++)
{
actors_[i]->update();
actors_[i]->reset();
}
} private:
static const int NUM_ACTORS = ; Actor* actors_[NUM_ACTORS];
}; // 同一时间, 只会有一个actor执行update class Comedian : public Actor
{
public:
void face(Actor* actor) { facing_ = actor; } virtual void update()
{
if (wasSlapped()) facing_->slap();
} private:
Actor* facing_;
}; // 面对某人
harry ------> balay ------> chump
^ |
|
-------------------------------v Stage stage; Comedian* harry = new Comedian();
Comedian* baldy = new Comedian();
Comedian* chump = new Comedian(); harry->face(baldy);
baldy->face(chump);
chump->face(harry); stage.add(harry, );
stage.add(baldy, );
stage.add(chump, ); harry->slap(); stage.update(); // slap
harry ---slap---> balay --slap----> chump
^ |
|
----------------slap---------------v
正确的结果 #如果把三人的执行顺序换一下, 结果将不正确#
stage.add(harry, );
stage.add(baldy, );
stage.add(chump, ); 只有harry slap 了baldy buffered slaps // 把slap用buffer记录下来 class Actor
{
public:
Actor() : currentSlapped_(false) {} virtual ~Actor() {}
virtual void update() = ; void swap()
{
// Swap the buffer.
currentSlapped_ = nextSlapped_; // Clear the new "next" buffer.
nextSlapped_ = false;
} void slap() { nextSlapped_ = true; }
bool wasSlapped() { return currentSlapped_; } private:
bool currentSlapped_;
bool nextSlapped_;
}; void Stage::update()
{
for (int i = ; i < NUM_ACTORS; i++)
{
actors_[i]->update();
} for (int i = ; i < NUM_ACTORS; i++)
{
actors_[i]->swap();
}
} ``` #### buffer swap
swap需要锁住两个buffer, 所需需要尽量的轻量快速
交换指针 引用
.快速
.外部代码不能保存buffer指针
当前的数据,是两帧之前的数据(读current的同时,数据写入了next) buffer之间拷贝数据
如果无法进行swap,可以把next的数据copy到current
如果数量小则没什么问题,如果大则会耗时 ```
当很多对象都有需要swap操作时, 会很慢
下面这个例子,不用swap,而是slap的时候修改了next的值 class Actor
{
public:
static void init() { current_ = ; }
static void swap() { current_ = next(); } void slap() { slapped_[next()] = true; }
bool wasSlapped() { return slapped_[current_]; } private:
static int current_;
static int next() { return - current_; } bool slapped_[];
};
``` #### See also
double buffer 模式在图形编程上应用广泛 You can find the Double Buffer pattern in use in almost every graphics API out there. For example, OpenGL has swapBuffers(), Direct3D has “swap chains”, and Microsoft’s XNA framework swaps the framebuffers within its endDraw() method.

7_DoubleBuffer 游戏编程中的双缓存模式的更多相关文章

  1. 第28月第21天 记事本Unicode 游戏编程中的人工智能技术

    1. Windows平台,有一个最简单的转化方法,就是使用内置的记事本小程序notepad.exe.打开文件后,点击文件菜单中的另存为命令,会跳出一个对话框,在最底部有一个编码的下拉条. 里面有四个选 ...

  2. 游戏编程系列[1]--游戏编程中RPC协议的使用

    RPC(Remote Procedure Call Protocol)--远程过程调用协议,它是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的协议.RPC协议假定某些传输协议的存在 ...

  3. windows游戏编程X86 32位保护模式下的内存管理概述(二)

    本系列文章由jadeshu编写,转载请注明出处.http://blog.csdn.net/jadeshu/article/details/22448323 作者:jadeshu   邮箱: jades ...

  4. 游戏编程系列[1]--游戏编程中RPC协议的使用[3]--体验

    运行环境,客户端一般编译为.Net 3.5 Unity兼容,服务端因为用了一些库,所以一般为4.0 或往上.同一份代码,建立拥有2个项目.客户端引用: WindNet.Client服务端引用: OpL ...

  5. 游戏编程系列[2]--游戏编程中RPC与OpLog协议的结合--序

    在系列[1]中,我们展示了RPC调用协议的定义以及演示,通过方法定义以及协议约定,进行了协议约定以及调用过程的约定.然而,实际上在游戏中,调用过程之后,需要传输相对多的数据给服务端. 常用场景,客户端 ...

  6. 游戏编程系列[1]--游戏编程中RPC协议的使用[2]--Aop PostSharp篇

    上一篇我们使用了一个通用JSON协议约定来进行达到远程调用的目的.但是从实现上,我们需要不断的在所有的方法上添加拦截,并且判断拦截,然后执行,这就达到了一个比较繁琐的目的. 之前我们尝试过使用代码生成 ...

  7. windows游戏编程X86 32位保护模式下的内存管理概述(一)

    本系列文章由jadeshu编写,转载请注明出处.http://blog.csdn.net/jadeshu/article/details/22445945 作者:jadeshu   邮箱: jades ...

  8. 如何系统掌握游戏编程中3D图形学相关的基础?

    https://www.zhihu.com/question/27544895 三维几何学基础:三维坐标系统点与矢量矩阵与几何变换四元数与三维旋转

  9. 《逐梦旅程 WINDOWS游戏编程之从零开始》笔记5——Direct3D中的顶点缓存和索引缓存

    第12章 Direct3D绘制基础 1. 顶点缓存 计算机所描绘的3D图形是通过多边形网格来构成的,网网格勾勒出轮廓,然后在网格轮廓的表面上贴上相应的图片,这样就构成了一个3D模型.三角形网格是构建物 ...

随机推荐

  1. web开发之html5---html5 动画特效舞动的雨伞

    http://www.cnblogs.com/stoneniqiu/p/4199294.html

  2. Unity3D研究院之在开始学习拓展编辑器

    Unity拥有非常丰富的拓展编辑器接口,如果是在网上下载过别人写的插件,你会发现为什么它的监测面板视图和普通的不一样?其实是他通过代码自己绘制的监测面板,这篇博文MOMO带大家来学习编辑器.如下图所示 ...

  3. a byte of vim -- 学习摘要

    说在前面的话 -- a byte of vim 是我见过的最介绍vim 最好的书,想了解强大的vim的人,或者是已经在使用vim而打算进一步了解的人,我感觉都应该看看这个,内容精炼但涵盖非常广,--& ...

  4. c/c++的一些小知识点3

    ---恢复内容开始--- ---恢复内容结束---

  5. 【BZOJ3720】Gty的妹子树 块状树

    [BZOJ3720]Gty的妹子树 我曾在弦歌之中听过你,檀板声碎,半出折子戏.舞榭歌台被风吹去,岁月深处尚有余音一缕……Gty神(xian)犇(chong)从来不缺妹子……他来到了一棵妹子树下,发现 ...

  6. 【BZOJ1125】[POI2008]Poc hash+map+SBT

    [BZOJ1125][POI2008]Poc Description n列火车,每条有l节车厢.每节车厢有一种颜色(用小写字母表示).有m次车厢交换操作.求:对于每列火车,在交换车厢的某个时刻,与其颜 ...

  7. mysql中的乐观锁和悲观锁

    mysql中的乐观锁和悲观锁的简介以及如何简单运用. 关于mysql中的乐观锁和悲观锁面试的时候被问到的概率还是比较大的. mysql的悲观锁: 其实理解起来非常简单,当数据被外界修改持保守态度,包括 ...

  8. 开始翻译《Beginning SharePoint 2013 Development》

    伙同涂曙光@kaneboy 和柴晓伟@WindieChai 翻译Beginning SharePoint 2013 Development 作者是Steve Fox,传说中的Andrew Connel ...

  9. plsql 详细安装及汉化步骤

    方法/步骤   双击运行plsqldev715 安装完成后我们装中文补丁: 双击运行‘Chinese’应用程序 找到PLSQL的安装目录添加进来 中文补丁安装完成后我们需要进行orcl的配置,配置好才 ...

  10. But what exactly do we mean by "gets closer to"?

    https://rdipietro.github.io/friendly-intro-to-cross-entropy-loss/ [将输入转化为输出:概率分布] When we develop a ...