昨天我遇到一个问题,问题如下:

    我使用了延迟渲染,我的渲染流程是: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 中相关阻塞问题的更多相关文章

  1. 浅谈Linux中的信号处理机制(二)

    首先谢谢 @小尧弟 这位朋友对我昨天夜里写的一篇<浅谈Linux中的信号处理机制(一)>的指正,之前的题目我用的“浅析”一词,给人一种要剖析内核的感觉.本人自知功力不够,尚且不能对着Lin ...

  2. Java网络编程和NIO详解7:浅谈 Linux 中NIO Selector 的实现原理

    Java网络编程和NIO详解7:浅谈 Linux 中NIO Selector 的实现原理 转自:https://www.jianshu.com/p/2b71ea919d49 本系列文章首发于我的个人博 ...

  3. 浅谈Java中的对象和引用

    浅谈Java中的对象和对象引用 在Java中,有一组名词经常一起出现,它们就是“对象和对象引用”,很多朋友在初学Java的时候可能经常会混淆这2个概念,觉得它们是一回事,事实上则不然.今天我们就来一起 ...

  4. 【转】浅谈Java中的hashcode方法(这个demo可以多看看)

    浅谈Java中的hashcode方法 哈希表这个数据结构想必大多数人都不陌生,而且在很多地方都会利用到hash表来提高查找效率.在Java的Object类中有一个方法: public native i ...

  5. 【转】浅谈Java中的hashcode方法

    哈希表这个数据结构想必大多数人都不陌生,而且在很多地方都会利用到hash表来提高查找效率.在Java的Object类中有一个方法: public native int hashCode(); 根据这个 ...

  6. 视频基础知识:浅谈视频会议中H.264编码标准的技术发展

    浅谈视频会议中H.264编码标准的技术发展 浅谈视频会议中H.264编码标准的技术发展 数字视频技术广泛应用于通信.计算机.广播电视等领域,带来了会议电视.可视电话及数字电视.媒体存储等一系列应用,促 ...

  7. 浅谈 .NET 中的对象引用、非托管指针和托管指针 理解C#中的闭包

    浅谈 .NET 中的对象引用.非托管指针和托管指针   目录 前言 一.对象引用 二.值传递和引用传递 三.初识托管指针和非托管指针 四.非托管指针 1.非托管指针不能指向对象引用 2.类成员指针 五 ...

  8. 浅谈jvm中的垃圾回收策略

    下面小编就为大家带来一篇浅谈jvm中的垃圾回收策略.小编觉得挺不错的,现在就分享给大家,也给大家做个参考.一起跟随小编过来看看吧   java和C#中的内存的分配和释放都是由虚拟机自动管理的,此前我已 ...

  9. 浅谈HTTP中GET和POST请求方式的区别

    浅谈HTTP中GET和POST请求的区别 HTTP认知: HTTP是基于TCP/IP的关于数据如何在万维网中如何通信的协议.HTTP的底层是TCP/IP.所以GET和POST的底层也是TCP/IP,也 ...

随机推荐

  1. vue filter使用方法

    Vue.js 允许你自定义过滤器,可被用于一些常见的文本格式化. 过滤器可以用在两个地方:双花括号插值和 v-bind 表达式 (后者从 2.1.0+ 开始支持). 过滤器应该被添加在 JavaScr ...

  2. OracleSpatial函数

    Oracle_spatial的函数 一sdo_Geom包的函数: 用于表示两个几何对象的关系(结果为True/False)的函数:RELATE,WITHIN_DISTANCE 验证的函数:VALIDA ...

  3. 二叉堆&&左偏堆 代码实现

    今天打算学习左偏堆,可是想起来自己二叉堆都没有看懂,于是就跑去回顾二叉堆了.发现以前看不懂的二叉堆,今天看起来特简单,随手就写好了一个堆了. 简单的说一下我对二叉堆操作的理解.我不从底层函数说上去,相 ...

  4. mybatis PageHelper分页插件 和 LRU算法缓存读取数据

    分页: PageHelper的优点是,分页和Mapper.xml完全解耦.实现方式是以插件的形式,对Mybatis执行的流程进行了强化,添加了总数count和limit查询.属于物理分页. 一.首先注 ...

  5. Python--day40--主线程和子线程代码讲解

    1,最简单的线程例子: 2,多线程并发: import time from threading import Thread #多线程并发 def func(n): time.sleep(1) prin ...

  6. LA 3942 ——Trie (前缀树)、DP

    #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> ...

  7. UVa 1627 - Team them up!——[0-1背包]

    Your task is to divide a number of persons into two teams, in such a way, that: everyone belongs to ...

  8. P1076 单词覆盖还原

    题目描述 一个长度为 \(l(3\le l\le 255)\) 的字符串中被反复贴有 boy 和 girl 两单词,后贴上的可能覆盖已贴上的单词(没有被覆盖的用句点表示),最终每个单词至少有一个字符没 ...

  9. H3C STP可选配置

  10. H3C VLAN基本配置