浅谈 OpenGL 中相关阻塞问题
昨天我遇到一个问题,问题如下:
我使用了延迟渲染,我的渲染流程是:Pass1 --> CUDA并行计算 -->Pass2
CUDA并行计算中需要使用Pass1渲染生成的两张纹理,然而我在GPU端使用CUDA计算时发现纹理为空(数据全是0值),但是如果将两张纹理的数据传回CPU端,打印出来是有值的,且是正确的值。如果在CUDA并行计算之前先将纹理数据传回CPU,这时发现CUDA并行计算中纹理是正常有值的。。。这个现象很奇怪,我开始想了想会不会是阻塞啥原因,但我对OpenGL阻塞过程不了解,没看到过相关的资料,简单思考了一下觉得不是阻塞的原因,我觉得可能是其中的一张纹理有问题,牵连导致这个问题。。。。。最终验证发现还是OpenGL阻塞的原因。在CUDA并行计算之前加上 glFinish()函数即可。
为啥加上glFinish()函数就解决了呢? 解释这个之前,先说一下glFlush()和glFinish()函数的作用:
一个OpenGL渲染程序会调用很多的OpenGL命令,而OpenGL是异步的,CPU将这些耗时的命令发送到GPU端,然后直接返回继续执行,这些OpenGL相关指令存储在GPU的缓存中一条条的执行,但是CPU也不是直接发送给GPU的,CPU自己有缓存,先存储在自己的缓存中,之后再发送过去(有时机,例如遇到某些刷新的命令等)。现在开始介绍以上两个函数的作用。
glFlush():将缓存在CPU端的命令发送到GPU上,清空缓存,发送完立即返回。
glFinish():将缓存在CPU端的命令发送到GPU上,清空缓存,发送完,等待GPU执行完在返回。
看到这里就可以理解我加上 glFinish() 可以解决问题的原因了。我没加 glFinish() 时,CUDA并行计算时,这时Pass1实际没有执行完,故纹理为空,CUDA中拿不到正确的纹理数据,加上 glFinish() 后实际就是加入了GPU阻塞,等待Pass1执行完,然后执行CUDA并行计算。
注:说到这里,谈点我思考的问题:
1、在OpenGL渲染中,不管是 Pass1 --> CUDA并行计算 -->Pass2, 或者 Pass1 --> Pass2 或者Pass(只有一个Pass),我们统计两次渲染之间的时间差值就可以计算帧率,为啥不会因为异步问题计算不准呢? 因为 glfwSwapBuffers(glfw_window) 命令会将所有CPU端的命令发送到GPU端,并等待其执行完,然后再交换前后缓冲。
2、对于Pass1 --> Pass2这样的延迟渲染,Pass1和Pass2都是作为命令发送到GPU端,按序执行,故不会出现Pass2拿到的数据(由Pass1处理的)不正确情况,我们不需要加阻塞保障其执行。
另外不要错误以为,CPU运行到Pass2处看见Pass1还在执行,CPU阻塞等待Pass1执行完然后发送Pass2指令。
3、为啥在CUDA并行计算前,对纹理进行一次数据传回可以让CUDA获取正确的纹理数据 ?我觉得(差不多肯定是这样,哈哈,自信……)拷贝纹理数据的OpenGL API虽然与GPU相关,但是其与CPU也相关,需要在CPU端的内存上接收传回的数据,从CPU端考虑它也会阻塞的。
4、Pass1 和 CUDA并行计算 都是在GPU上执行的,而CUDA拿不到正确的纹理数据,可以认为 Pass1 和 CUDA并行计算 同时在GPU上并行执行(我猜的,应该是吧……)。
浅谈 OpenGL 中相关阻塞问题的更多相关文章
- 浅谈Linux中的信号处理机制(二)
		
首先谢谢 @小尧弟 这位朋友对我昨天夜里写的一篇<浅谈Linux中的信号处理机制(一)>的指正,之前的题目我用的“浅析”一词,给人一种要剖析内核的感觉.本人自知功力不够,尚且不能对着Lin ...
 - Java网络编程和NIO详解7:浅谈 Linux 中NIO Selector 的实现原理
		
Java网络编程和NIO详解7:浅谈 Linux 中NIO Selector 的实现原理 转自:https://www.jianshu.com/p/2b71ea919d49 本系列文章首发于我的个人博 ...
 - 浅谈Java中的对象和引用
		
浅谈Java中的对象和对象引用 在Java中,有一组名词经常一起出现,它们就是“对象和对象引用”,很多朋友在初学Java的时候可能经常会混淆这2个概念,觉得它们是一回事,事实上则不然.今天我们就来一起 ...
 - 【转】浅谈Java中的hashcode方法(这个demo可以多看看)
		
浅谈Java中的hashcode方法 哈希表这个数据结构想必大多数人都不陌生,而且在很多地方都会利用到hash表来提高查找效率.在Java的Object类中有一个方法: public native i ...
 - 【转】浅谈Java中的hashcode方法
		
哈希表这个数据结构想必大多数人都不陌生,而且在很多地方都会利用到hash表来提高查找效率.在Java的Object类中有一个方法: public native int hashCode(); 根据这个 ...
 - 视频基础知识:浅谈视频会议中H.264编码标准的技术发展
		
浅谈视频会议中H.264编码标准的技术发展 浅谈视频会议中H.264编码标准的技术发展 数字视频技术广泛应用于通信.计算机.广播电视等领域,带来了会议电视.可视电话及数字电视.媒体存储等一系列应用,促 ...
 - 浅谈 .NET 中的对象引用、非托管指针和托管指针  理解C#中的闭包
		
浅谈 .NET 中的对象引用.非托管指针和托管指针 目录 前言 一.对象引用 二.值传递和引用传递 三.初识托管指针和非托管指针 四.非托管指针 1.非托管指针不能指向对象引用 2.类成员指针 五 ...
 - 浅谈jvm中的垃圾回收策略
		
下面小编就为大家带来一篇浅谈jvm中的垃圾回收策略.小编觉得挺不错的,现在就分享给大家,也给大家做个参考.一起跟随小编过来看看吧 java和C#中的内存的分配和释放都是由虚拟机自动管理的,此前我已 ...
 - 浅谈HTTP中GET和POST请求方式的区别
		
浅谈HTTP中GET和POST请求的区别 HTTP认知: HTTP是基于TCP/IP的关于数据如何在万维网中如何通信的协议.HTTP的底层是TCP/IP.所以GET和POST的底层也是TCP/IP,也 ...
 
随机推荐
- @atcoder - Japanese Student Championship 2019 Qualification - F@ Candy Retribution
			
目录 @description@ @solution@ @accepted code@ @details@ @description@ 请找到满足以下条件的长度为 N 的非负整数序列 A1, A2, ...
 - Android教程-03 常见布局的总结
			
常见的布局 视频建议采用超清模式观看, 欢迎点击订阅我的优酷 Android的图形用户界面是由多个View和ViewGroup构建出来的.View是通用的UI窗体小组件,比如按钮(Button)或者文 ...
 - 基于Mysql实现分布式锁
			
一.分布式锁要解决的问题 可以保证在分布式部署的应用集群中,同一个方法在同一时间只能被一台机器上的一个线程执行. 这把锁要是一把可重入锁(避免死锁) 这把锁最好是一把阻塞锁(根据业务需求考虑要不要这条 ...
 - Bert源码阅读
			
前言 对Google开源出来的bert代码,来阅读下.不纠结于代码组织形式,而只是梳理下其训练集的生成,训练的self-attention和multi-head的具体实现. 训练集的生成 主要实现在c ...
 - oracle用>=替代>
			
如果DEPTNO上有一个索引, 高效: SELECT * FROM EMP WHERE DEPTNO >=4 低效: SELECT * FROM EMP WHERE DEPTNO >3 两 ...
 - laravel怎么开启调试模式
			
在.env文件里有个APP_DEBUG=true,如果是false,改成true就好了.
 - 对象转json字符串案例
			
测试对象与json字符串的转换 json字符串转对象 Stringstr = "{\"id\":\"1001\",\"name\" ...
 - hihocoeder1384
			
hihocoeder1384 算法竞赛进阶指南上的题目 我们肯定是吧最大值和最小值匹配,次大值和次小值匹配以此类推 首先,类似于区间覆盖的思想,我们对于一个\(L\),找到最大的满足条件的\(R\) ...
 - js  的this指向问题
			
this指向的,永远只可能是对象! this指向谁,永远不取决于this写在哪!而是取决于函数在哪调用. this指向的对象,我们称之为函数的上下文context,也叫函数的调用者. 1:通过函数名直 ...
 - 深度解读 - Windows 7核心图形架构细致分析(来自微软)
			
编辑:马志文 时间: 2009-12-29 如现在大家所想的那样, Windows7 其实是 Windows Vista 的改进版. Windows 7 在 Windows Vista 的基础上进行了 ...