Lite2D的渲染线程尝试

项目地址      https://github.com/dreamyouxi/Lite2D

注意:

1.GL只能和一个线程相关,所以纹理产生,初始化等都要放到渲染线程。

2.双缓冲默认是垂直同步的 可用  glfwSwapInterval; 来设置

GL API 参考自      http://www.glfw.org/docs/latest/group__context.html

暂且用以下方案:

1.渲染线程拷贝一个主线程产生的 纹理(暂定)

2.遍历Node的时候吧渲染参数 包装为命令(RenderCmd)  放到渲染队列里面(RenderCmdQueue)

3.因为线程安全问题,GL相关操作都用回调 在渲染线程来处理

逻辑线程执行的时候 会强制同步到渲染线程

逻辑帧数60,渲染帧数11999,逻辑延时0.000467 MS,测试平台 i7 4790K GTX 950

帧数限制:

通过最大帧数的时间来控制渲染次数,当渲染次数和逻辑次数不匹配会自动丢帧,保证当前渲染的始终是最新帧

1static void ThreadFunc(RenderCmdQueue * reder) 2{ 3 Director::getInstance()->getGLView()->init(); // init gl in render thread 4 5 LARGE_INTEGER nLast; 6 LARGE_INTEGER nNow; 7 8 QueryPerformanceFrequency(&nFreq); 9 perFrame.QuadPart = (LONGLONG)(1.0 / DEFAULT_FPS* nFreq.QuadPart); 10 11 QueryPerformanceCounter(&nLast); 12 13 float delta = 0.0f; 14 while (true) 15 { 16 QueryPerformanceCounter(&nNow); 17 if (nNow.QuadPart - nLast.QuadPart > perFrame.QuadPart)//default fps is 120 18 { 19 delta = (float)(nNow.QuadPart - nLast.QuadPart) / (float)nFreq.QuadPart; 20 reder->render(); 21 reder->setRenderFPS(1.0f / delta + 1); 22 23 nLast.QuadPart = nNow.QuadPart; 24 } 25 else 26 { 27 //std::this_thread::sleep_for(std::chrono::microseconds(0)); 28 } 29 } 30 31}

demo项目表现良好

渲染命令

1//.h 2class RenderCmd :public Ref 3{ 4public: 5 virtual void exec(Texture2D*) = 0; 6 float *_coord2f = 0; 7 Vec2 _vertex[4]; 8 float _opacity = 0.0f; 9 Texture2D*tex=nullptr; 10}; 11 12 13class RenderCmd_Quad :public RenderCmd 14{ 15public: 16 virtual void exec(Texture2D*)override; 17}; 18 19 20//.cpp 21 22void RenderCmd_Quad::exec(Texture2D *tex) 23{ 24 25 GLuint id = tex->getTextureID(); 26 tex->getFileName().c_str(); 27 28 29 glLoadIdentity();// vetex can work once 30 31 glBindTexture(GL_TEXTURE_2D, id); 32 33 // able alpha blend for the texture who has alpha 34 glEnable(GL_BLEND); 35 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 36 37 //able opacity 38 glEnable(GL_ALPHA_TEST); 39 glAlphaFunc(GL_GREATER, 0.0f); 40 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); 41 42 glColor4f(1.0f, 1.0f, 1.0f, _opacity); 43 44 45 //start to render 46 47 glBegin(GL_QUADS); 48 49 glTexCoord2f(_coord2f[0], _coord2f[1]); glVertex2f(_vertex[0].x, _vertex[0].y); 50 glTexCoord2f(_coord2f[2], _coord2f[3]); glVertex2f(_vertex[1].x, _vertex[1].y); 51 glTexCoord2f(_coord2f[4], _coord2f[5]); glVertex2f(_vertex[2].x, _vertex[2].y); 52 glTexCoord2f(_coord2f[6], _coord2f[7]); glVertex2f(_vertex[3].x, _vertex[3].y); 53 54 55 glDisable(GL_BLEND); 56 glDisable(GL_ALPHA_TEST); 57 glEnd(); 58} 59

渲染队列(渲染线程)

1class RenderCmdQueue 2{ 3 4public: 5 6 void addFuncToRenderThread(const std::function<Texture2D*(void)> &func); 7 void addCustomFuncToRenderThread(const std::function<void(void)> &func); 8private: 9 10 std::unordered_map<std::string , Texture2D*> tex_pool; 11 12 std::vector<std::function<Texture2D*(void)>> _func; 13 std::vector <std::function<void(void)>> _func1; 14 void processOtherThreadFunc(); 15 16 17 18 std::mutex _mutex; 19 20public: 21 static RenderCmdQueue*create(); 22 void addRenderCmd(RenderCmd*cmd); 23 24 void clear(); 25 void NextTick();//thread safe 26 27 28 void draw(); 29 void setVerticalSynchronization(bool enable); 30 31private: 32 std::atomic<bool> isNextTick = false; 33 std::vector<RenderCmd*> _queue; 34 35 void clearAllRenderCmd(); 36 37 RenderCmdQueue() 38 { 39 _queue.reserve(200); 40 } 41};

.cpp

1static void ThreadFunc(RenderCmdQueue * reder) 2{ 3 Director::getInstance()->getGLView()->init(); // init gl in render thread 4 5 LARGE_INTEGER nLast; 6 LARGE_INTEGER nNow; 7 8 QueryPerformanceFrequency(&nFreq); 9 perFrame.QuadPart = (LONGLONG)(1.0 / 120 * nFreq.QuadPart); 10 11 QueryPerformanceCounter(&nLast); 12 13 float delta = 0.0f; 14 while (true) 15 { 16 QueryPerformanceCounter(&nNow); 17 if (nNow.QuadPart - nLast.QuadPart > perFrame.QuadPart) 18 { 19 delta = (float)(nNow.QuadPart - nLast.QuadPart) / (float)nFreq.QuadPart; 20 reder->render(); 21 reder->setRenderFPS(1.0f / delta + 1); 22 23 nLast.QuadPart = nNow.QuadPart; 24 } 25 else 26 { 27 //std::this_thread::sleep_for(std::chrono::microseconds(0)); 28 } 29 } 30 31} 32 33 34RenderCmdQueue* RenderCmdQueue::create() 35{ 36 RenderCmdQueue*ret = new RenderCmdQueue; 37 38 //Director::getInstance()->getGLView()->init(); 39 40 /*std::thread t([ret]() 41 { 42 Director::getInstance()->getGLView()->init(); 43 44 while (true) 45 { 46 ret->draw(); 47 // Sleep(100); 48 49 } 50 51 }); t.detach();*/ 52 53 static std::thread t(&ThreadFunc, ret); t.detach(); 54 55 return ret; 56} 57 58 59void RenderCmdQueue::addRenderCmd(RenderCmd*cmd) 60{ 61 _mutex.lock(); 62 _queue.push_back(cmd); 63 _mutex.unlock(); 64} 65 66 67 68void RenderCmdQueue::clear() 69{ 70 isNextTick = false; 71 _mutex.lock(); 72 ++_tick_status; 73 if (_tick_status > 5) 74 { 75 _tick_status = 0; 76 auto dir = Director::getInstance(); 77 78 _cache_fps = dir->getFPS(); 79 _cache_last_fps = this->getRenderFPS(); 80 _cache_redertime = dir->getRenderTime(); 81 } 82 this->clearAllRenderCmd(); 83 84 _mutex.unlock(); 85} 86 87void RenderCmdQueue::setVerticalSynchronization(bool enable) 88{ 89 if (enable) 90 { 91 glfwSwapInterval(0xff); 92 } 93 else 94 { 95 glfwSwapInterval(0x0); 96 } 97} 98 99 100void RenderCmdQueue::NextTick()//thread safe 101{ 102 this->isNextTick = true; 103} 104 105void RenderCmdQueue::clearAllRenderCmd() 106{ 107 108 for (int i = 0; i < _queue.size(); i++) 109 { 110 _queue[i]->release(); 111 } 112 _queue.clear(); 113 114} 115 116 117 118 119void RenderCmdQueue::render() 120{ 121 do 122 { 123 if (isNextTick == false)break; 124 125 std::lock_guard<std::mutex> lock(_mutex); 126 127 // if (_queue.empty())break; 128 129 glClear(GL_COLOR_BUFFER_BIT); 130 // glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 131 132 glEnable(GL_TEXTURE_2D); 133 134 for (int i = 0; i < _queue.size(); i++) 135 { 136 137 RenderCmd *cmd = _queue[i]; 138 139 auto it = tex_pool.find(cmd->tex->getFileName()); 140 if (it == tex_pool.end()) 141 { 142 143 Texture2D* tex = new Texture2D; 144 145 auto image = new Image; 146 image->initWithFile(cmd->tex->getFileName()); 147 tex->initWithImage(image); 148 149 cmd->exec(tex); 150 tex_pool[cmd->tex->getFileName()] = tex; 151 } 152 else 153 { 154 cmd->exec((*it).second); 155 } 156 } 157 158 glDisable(GL_TEXTURE_2D); 159 Director::getInstance()->getGLView()->swapBuffers(); 160 161 162 } while (false); 163 164 this->processOtherThreadFunc(); 165 166} 167 168 169 170 171 172void RenderCmdQueue::processOtherThreadFunc() 173{ 174 _mutex.lock(); 175 176 for (auto &func : _func) 177 { 178 Texture2D* tex = func(); 179 tex_pool[tex->getFileName()] = tex; 180 } 181 _func.clear(); 182 183 for (auto &func : _func1) 184 { 185 func(); 186 } 187 _func1.clear(); 188 189 _mutex.unlock(); 190} 191 192 193void RenderCmdQueue::addFuncToRenderThread(const std::function<Texture2D*(void)> &func) 194{ 195 this->_mutex.lock(); 196 197 _func.push_back(func); 198 this->_mutex.unlock(); 199} 200 201 202void RenderCmdQueue::addCustomFuncToRenderThread(const std::function<void(void)> &func) 203{ 204 _mutex.lock(); 205 _func1.push_back(func); 206 _mutex.unlock(); 207}

实测,当object很多时候 渲染效率反而底下,比如1万个同纹理的 单线程依然50+FPS 多线程版本就只有20+FPS,

点赞
收藏

评论区

加载中...

相关推荐

MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1

文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s

Oracle 分组与拼接字符串同时使用

SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(

MySQL部分从库上面因为大量的临时表tmp_table造成慢查询

背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_

皕杰报表之UUID

​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为

手写Java HashMap源码

HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22

Android So动态加载 优雅实现与原理分析

背景:漫品Android客户端集成适配转换功能(基于目标识别(So库35M)和人脸识别库(5M)),导致apk体积50M左右,为优化客户端体验,决定实现So文件动态加载.!(https://oscimg.oschina.net/oscnet/00d1ff90e4b34869664fef59e3ec3fdd20b.png)点击上方“蓝字”关注我

Lite2D的渲染线程尝试 - HelloWorld