Shader编程学习笔记(一)—— 图形硬件简史与可编程管线

图形处理器(GPU)简史

GPU发展简史

  GPU英文全称Graphic Processing Unit,中文翻译为“图形处理器”,在现代计算机系统中的作用变得越来越重要。

  20世纪六、七十年代,受硬件条件的限制,图形显示器只是计算机输出的一种工具。限于硬件发展水平,人们只是纯粹从软件实现的角度来考虑图形用户界面的规范问题。此时还没有GPU的概念。

  GPU概念在20世纪70年代末和80年代初被提出,使用单片集成电路(monolithic)作为图形芯片,此时的GPU被用于视频游戏和动画方面,它能够很快地进行几张图片的合成(仅限于此)。在20世纪80年代末到90年代初的这段时间内,基于数字信号处理芯片(digital signal processor chip)的GPU被研发出来。与前代相比速度更快、功能更强,当然价格是非常的昂贵。在1991年,S3 Graphics公司研制出第一个单芯片2D加速器,到了1995年,主流的PC图形芯片厂商都在自己的芯片上增加了对2D加速器的支持。

  1998年NVIDA公司宣布modern GPU的研发成功,标志着GPU研发的历史性突破成为现实。通常将20世纪70年代末到1998年的这一段时间称之为pre-GPU时期,而自1998年往后的GPU成为modern GPU。在pre-GPU时期,一些图形厂商,如SGI、Evans&Sutherland,都研发了各自的GPU,这些GPU在现在并没有被淘汰,依然在持续改进和被广泛使用,当然价格也是非常高昂。modern GPU使用晶体管(transistors)进行计算,在微芯片(microchip)中,GPU所使用的晶体管已经远远超过CPU。例如,Intel在2.4GHz的Pentium IV上使用5千5百万(55 million)个晶体管,而NVIDIA在GeForce FX GPU上使用超过1亿2千5百万(125 million)个晶体管,在NVIDIA 7800 GTX上的晶体管达到3亿2百万(302)个。

  回顾GPU的发展历史,自1998年后可以分为4个阶段。NVDIA于1998年宣布Modern GPU研发成功,这标志着第一代Modern GPU的诞生,第一代GPU包括NVDIA TNT2,ATI的Rage和3Dfx的Voodoo。这些GPU可以独立于CPU进行像素缓存区的更新,并可以光栅化三角面片以及进行纹理操作,但是缺乏三维顶点的空间坐标变换能力,这意味着必须依赖于CPU执行顶点坐标变换的计算。这一时期的GPU功能非常有限,只能用于纹理组合的数学计算或者像素颜色值的计算。

  1999年,NVDIA推出一款可以用“惊变”来形容的显示核心代号为NV10的GeFore 256。NVDIA率先将硬体T&L整合到显示核中。T&L原先有CPU负责,或者由另一个独立处理机处理。T&L是一大进步,原因是显示核心从CPU接管了大量工作。硬件T&L引擎带来的效果是,3D模型可以用更多的多边形来描绘,这样就拥有了更加细腻的效果。而对于Lighting来说,CPU不必再计算大量的光照数据,直接通过显卡就能获得更好的效能。同时,这一阶段的GPU对于纹理的操作也扩展到了立方体纹理(cube map)。NVDIA的GeForce MAX,ATI的Radeon 7500等都是在这一阶段研发的。

  T&L技术是最近在图形加速卡上都可以看得到的规格名称之一,这个名词的原来意义是:Transforming以及Lighting,光影转换。在图形加速卡中,T&L的最大功能是处理图形的整体角度旋转以及光源阴影等三维效果。

  2001年是第三代modern GPU的发展时期,这一时期研发的GPU提供vertex programmability(顶点编程能力),如GeForce 4Ti,ATI的8500等。这些GPU允许应用程序指定一个序列的指令进行顶点操作控制(GPU编程的本质),这同样是一个具有开创意义的时期,这一时期确立的GPU编程思想一直延续到今天,不但深入到工程领域帮助改善人类日常生活(医疗、地质勘探、游戏、电影等),而且开创或延伸了计算机科学的诸多研究领域(体绘制、光照模拟、人体动画、通用计算等)。同时,Direct8和OpenGL都本着与时俱进的精神,提供了支持vertex programmability的扩展。不过,这一时期的GPU还不支持像素级的编程能力,即fragment programmability(片段编程能力)。

  所谓Vertex,就是我们熟悉的组成3D图形的顶点,由于3D模型是基于坐标空间内部设计的,所以Vertex信息包含了3D模型在空间内的坐标等信息。Vertex Shader则是对于Vertex信息的运算编程器,可以通过赋予特定的算法而在工作中改变3D模型的外形,Vertex Shader顶点运算单元可以直接检索显存中的材质数据。现在的游戏场景越来越复杂了。所涉及到的材质和多边形数量都是非常惊人的。并且游戏开发人员还可以利用Vertex Shader的这一新的特性,充分发挥想象,实现很多非常漂亮的特效。例如在星际争霸2 demo片中展示的神族母舰黑洞的技能效果。

  第四代GPU的发展时期从2002年末到2003年。NVDIA的GeForceFX和ATI Radeon 9700同时在市场的舞台上闪亮登场,这两种GPU都支持vertex programmability和fragment programmability。同时DirectX和OpenGL也扩展了自身的API,用以支持vertex programmability和fragment programmability。自2003年起,可编程图形处理器正式诞生,并且由于DirectX和OpenGL锲而不舍地追赶潮流,导致基于图形硬件的编程技术,简称GPU编程,也宣告诞生。

GPU的优越性

  由于GPU具有高并行结构,所以GPU在处理图形数据和复杂算法方面拥有比CPU更高的效率。CPU大部分面积为控制器和寄存器,与之相比,GPU拥有更多的ALU(Arithmetic Logic Unit,逻辑运算单元)用于数据处理,这样的结构适合对密集型数据进行并行处理。

  GPU采用流式并行计算模式,可对每个数据进行独立的并行计算,所谓“对数据进行独立计算”就是流内任意元素的计算不依赖于其他同类型数据。例如,计算一个顶点的世界位置坐标,不依赖于其他顶点的位置,所谓“并行计算”是指多个数据可以同时被使用,多个数据并行运算的时间和一个数据单独实行的时间是一样的。所以,在顶点处理程序中,可以同时处理N个顶点数据。

GPU的缺陷

  由于任意一个元素的计算不依赖于其他同类型数据,导致需要知道数据之间相关性的算法在GPU上难以得到实现。一个典型的例子是射线与物体的求交运算。GPU中的控制器少于CPU,致使控制能力有限。另外,进行GPU编程必须掌握计算机图形学相关知识,以及图形处理API,入门门槛高,学习周期长,尤其国内关于GPU编程的资料较为匮乏,这些都导致了学习的难度。在早期,GPU编程只能使用汇编语言,开发难度高,开发效率低。不过,随着高级Shader Language的兴起,在GPU上编程已经容易多了。

GPU的更多应用

  科学可视化计算:由于人体CT、地质勘探、气象数据、流体力学等科学可视化计算处理的数据量极大,仅仅基于CPU进行计算完全不能满足实时性要求,而在GPU上进行计算则可以在效率上达到质的突破。许多在CPU上非常耗时的算法,如体绘制中的光线投射算法,都可以成功移植到GPU上。所以基于GPU的科学可视化研究目前已经成为主流。

  通用算法:基于GPU进行通用计算的研究逐渐成为热点,被称为GPGPU(General-Purpose Computing on Graphics Procedding Units,也被成为GPGP,或GP2),很多数值计算等通用算法都已经在GPU上得到了实现,并有不俗的性能表现。目前,线性代数、物理仿真和光线跟踪算法都已经成功地移植到GPU上。在国内,中科院计算所进行了基于GPU的串匹配算法的实现。

总结

  这里比较重要的就是从2003年开始GPU正式进入可编程GPU阶段。再者就是GPU的并行处理能力强于CPU,正是因为GPU的并行处理能力强我们才可以在同一时间内让GPU处理很多的顶点数据。最后就是尽管GPU的并行能力很强,但是目前GPU也无法取代CPU,这主要就是因为GPU还无法实现CPU强大的逻辑运算能力。

时间: 2024-08-05 14:55:28

Shader编程学习笔记(一)—— 图形硬件简史与可编程管线的相关文章

Shader编程学习笔记(二)—— Shader和渲染管线

Shader和渲染管线 什么是Shader Shader,中文翻译即着色器,是一种较为短小的程序片段,用于告诉图形硬件如何计算和输出图像,过去由汇编语言来编写,现在也可以使用高级语言来编写.一句话概括:Shader是可编程图形管线的算法片段. 它主要分为两类:Vertex Shader和Fragment Shader. 什么是渲染管线 渲染管线也称为渲染流水线,是显示芯片内部处理图形信号相互独立的并行处理单元.一个流水线是一序列可以并行和按照固定顺序进行的阶段.就像一个在同一时间内,不同阶段不同

Linux Shell脚本编程学习笔记和实战

http://www.1987.name/141.html shell基础 终端打印.算术运算.常用变量 Linux下搜索指定目录下特定字符串并高亮显示匹配关键词 从键盘或文件中获取标准输入 [read命令] 文件的描述符和重定向 数组.关联数组和别名使用 函数的定义.执行.传参和递归函数 条件测试操作与流程控制语句 获取时间日期格式和延时 [date.sleep命令] 内部字段分隔符IFS和脚本的调试DEBUG 显示.读取或拼接文件内容 [cat命令] 文件查找与打印文件列表 [find命令]

linux网络编程学习笔记之二 -----错误异常处理和各种碎碎(更新中)

errno 在unix系统中对大部分系统调用非正常返回时,通常返回值为-1,并设置全局变量errno(errno.h),如socket(), bind(), accept(), listen().erron存放一个正整数来保存上次出错的错误值. 对线程而言,每个线程都有专用的errno变量,不必考虑同步问题. strerror converts to English (Note: use strerror_r for thread safety) perror is simplified str

DirectX 11游戏编程学习笔记之7: 第6章Drawing in Direct3D(在Direct3D中绘制)(重点回顾+勘误)

        本文由哈利_蜘蛛侠原创,转载请注明出处!有问题欢迎联系[email protected]         注:我给的电子版是700多页,而实体书是800多页,所以我在提到相关概念的时候,会使用章节号而非页码.同样的情况适合于"龙书"第二版. 上一期的地址: DX 11游戏编程学习笔记之6 这一章应该是本书最长的一章了,可能也是最难的一章,所以大家一定要好好消化,仔细学习!这一章大致相当于"龙书"第二版的第7章和第8章,还添加了一些别的东西. 由于这一

图像编程学习笔记8——图像的平滑(去噪)

第一种方法:高斯模版 以下文字内容copy于<<数字图像处理编程入门>>,code为自己实现,是win32控制台程序. 先举个例子说明一下什么是平滑(smoothing),如下面两幅图所示:可以看到,图3.2比图3.1柔和一些(也模糊一些).是不是觉得很神奇?其实实现起来很简单.我们将原图中的每一点的灰度和它周围八个点的灰度相加,然后除以9,作为新图中对应点的灰度,就能实现上面的效果. 这么做并非瞎蒙,而是有其道理的.大概想一想,也很容易明白.举个例子,就象和面一样,先在中间加点水

Java并发编程学习笔记

Java编程思想,并发编程学习笔记. 一.基本的线程机制 1.定义任务:Runnable接口 线程可以驱动任务,因此需要一种描述任务的方式,这可以由Runnable接口来提供.要想定义任务,只需实现Runnable接口并编写run方法,使得该任务可以执行你的命令.   class MyTask implements Runnable {    private String mName;     public MyTask(String name) {    mName = name;   }  

JAVA GUI编程学习笔记目录

1.JAVA之GUI编程概述 2.JAVA之GUI编程布局 3.JAVA之GUI编程Frame窗口 4.JAVA之GUI编程事件监听机制 5.JAVA之GUI编程窗体事件 6.JAVA之GUI编程Action事件 7.JAVA之GUI编程鼠标事件 8.JAVA之GUI编程键盘码查询器 9.JAVA之GUI编程列出指定目录内容 10.JAVA之GUI编程弹出对话框Dialog 11.JAVA之GUI编程菜单 12.JAVA之GUI编程打开与保存文件 13.JAVA之GUI编程将程序打包jar JA

黑马程序员_JAVA UDP网络编程学习笔记

一.UDP网络编程概述 采用TCP协议通信时,客户端的Socket必须先与服务器建立连接,连接建立成功后,服务器端也会持有客户端连接的Socket,客户端的Socket与服务器端的Socket是对应的,它们构成了两个端点之间的虚拟通信链路.与TCP通信不同,UDP是面向无连接的.不可靠的基于数据包的传输协议.即应用进程(或程序)在使用UDP协议之前,不必先建立连接.自然,发送数据结束时也没有连接需要释放.因此,减少了开销和发送数据之前的延时.UDP也采用端口来区分进程. 在java中,java.

Java并发编程学习笔记(一)线程安全性 1

什么是线程安全性: 要编写线程安全的代码,其核心在于要对状态访问操作进行管理,特别是对共享的和可变的状态的访问."共享"意味着变量可以由多个线程同时访问,而"可变"则意味着变量的值在其生命周期内可以发生变化. 一个对象是否需要线程安全的,取决于他是否被多个线程访问.这指的是在程序中访问对象的方式,而不是对象要实现的功能.要使得对象时线程安全的,需要采用同步机制来协同对对象可变状态的访问.如果无法实现协同,那么可能导致数据破坏以及其他不该出现的结果. 如果当多个线程访