抄“GPU Programming And Cg Language Primer 1rd Edition” 中文名“GPU编程与CG语言之阳春白雪下里巴人”
计算机只能理解和执行由0、1序列(电压序列)构成的机器语言,所以汇编语言和高级语言程序都需要进行翻译才能被计算机所理解,担负这一任务的程序称为语言处理程序,通常也被称为编译程序。例如C或者C++ 编写的程序,需要首先编译成可执行文件(.exe文件),然后才能在GPU上运行,且一旦编译后,除非改变程序代码,否则不需要重新编译,这种方式称为静态编译(static coompilation)。静态编译最重要的特征是:一旦编译为可执行文件,在可执行文件运行期间不再需要源码信息。而动态编译(dynamic compilation)与之相反,编译程序和源码都要参与到程序的运行过程中。
Cg语言通常采用动态编译的方式,即,在宿主程序运行时利用Cg运行库( Cg Runtime library)动态编译Cg代码,使用动态编译的方式,可以将Cg程序当作一个脚本,随时修改随时运行,节省大量的时间,在OGRE图形引擎中就是采用这样的方法。在文献[2]的1.4.2章节中提到Cg语言同样支持静态编译方式,即,Cg源码编译成汇编代码后,这部分目标代码被链接到宿主程序最后的可执行程序中。使用静态编译的好处是只要发布可执行文件即可,源码不会被公开。
Cg编译器首先将Cg程序翻译成可被图形API(OpenGL和Direct3D)所接受的形式,然后应用程序使用适当的OpenGL和Direct3D 命令将翻译后的Cg程序传递给图形处理器,OpenGL和Direct3D驱动程序最后把它翻译成图形处理器所需要的硬件可执行格式。NVIDIA提供的 Cg编译器为cgc.exe。
Cg程序的编译不但依赖于宿主程序所使用的三维编程接口,而且依赖于图形硬件环境,因为图形硬件自身的限制,不一定支持某种Cg语句,例如,如果你所使用的GPU并不支持循环控制指令,那么在Cg程序中编写的循环控制语句将无法通过编译。被特定的图形硬件环境或AIP所支持的Cg语言子集,被称为Cg Profiles。需要注意的是: pro
Cg Profiles是Cg语言的重要组成部分,在使用Cg语言编写着色程序时,首先要考虑的一点就是“当前的图形硬件环境支持那个Cg Pro
4.3.1 CGC编译命令
如果Cg Toolkit安装正确,在NVIDIA Corporation\Cg\bin文件夹下会看到cgc.exe文件。首先打开命令行窗口,输入“cgc –h”(引号不用输入),如果安装正确,则会出现图 12所示的提示信息。
Cg程序编译的命令形式为:
cgc [options] file
[options]表示可选配置项,file表示Cg程序文件名。可选配置项包括编译时选择使用的pro
cgc –pro
-pro
需要强调如下几点:
1. 着色程序分为顶点着色程序和片段着色程序,pro
cgc –pro
所以,如果您的着色程序中同时存在顶点着色程序和片段着色程序,在编译前切记分别选择各自的pro
2. 选择pro
cgc –pro
则会出现错误提示信息:
error C3004: function “tex2D” not supported in this pro
改用fp30,进行编译就会通过。
cgc –pro
尤其需要注意的是,循环语句for,while只被vs_2_x, vp30, vp40,fp40等少量的profiles所支持。在CgUsersManual中提到:
“In other profiles, for and while loops may on
这句话的意思是“在其他的profiles中,for和while循环只有当确切的知道循环次数时才能被使用”。但经过试验,通常在其他profiles编译含义for,while语句时会出现错误提示信息:
error c6003:instruction limit of exceeded……
因此,如果没有确切的把握,不要在低级的profiles中使用循环控制语句。
3. 被编译的着色程序文件名必须加上.cg后缀。如果没有加后缀,写成如下的形式:
cgc –pro
则会出现错误提示信息:fatal error C9999: Can’t open file:test
4. 另外cgc还提供一种比较特殊的功能:就是将Cg语言所写的着色程序转换为使用GLSL或HLSL所编写的程序。例如,将代码写成如下形式,表示编译文件 test.cg中的顶点着色程序,入口函数名为main_v,并将顶点着色程序转换为glsl程序,然后保存成文件direct.glsl。
cgc –pro
5. 还有一个非常隐蔽的编译情况是:如果着色程序中的某些变量并没有为最终的输出做出贡献,则编译时会将该部分代码忽略(会检查语法错误,但并不编译成汇编代码)。通常这一点不会造成太大的影响,但是如果这些变量刚好是从外部宿主程序中传入的变量,并且在着色程序中没有被使用,则宿主程序传入变量的接口函数可能会报错“找不到该变量”。这种情况比较少遇到,但并非不存在,且一旦遇上问题的原因难以查明,故而我在此写上,希望可以有所帮助。
基于GPU编程,最令人崩溃的一点是:无法跟踪调试着色程序!这一点目前还没有解决方案出现。对于一个着色程序,语法错误可以通过编译器发现,而代码逻辑错误只能是人为查找。常会遇到这种情况,一段代码编译通过,但是运行结果不在预期之中,如果是C++\JAVA程序就可以进行跟踪调试,但是着色程序不能被调试,只能一行代码一行代码的进行逻辑分析。
所以,编译着色程序要非常注意逻辑的严密性,和代码的组织结构,这是为了更加容易的暴露错误和维护代码。一个良好的习惯是加入注释语句。
4.4 CG Profiles
Pro
即一个Cg pro
当前Cg compiler所支持的profiles有:
? OpenGL ARB vertex programs
Runtime pro
Compiler option: _pro
? OpenGL ARB fragment programs
Runtime pro
Compiler option: _pro
? OpenGL NV40 vertex programs
Runtime pro
Compiler option: _pro
? OpenGL NV40 fragment programs
Runtime pro
Compiler option: _pro
? OpenGL NV30 vertex programs
Runtime pro
Compiler option: _pro
? OpenGL NV30 fragment programs
Runtime pro
Compiler option: _pro
? OpenGL NV2X vertex programs
Runtime pro
Compiler option: _pro
? OpenGL NV2X fragment programs
Runtime pro
Compiler option: _pro
? DirectX 9 vertex shaders
Runtime profiles: CG_PRO
CG_PRO
Compiler options:-pro
-pro
? DirectX 9 pixel shaders
Runtime profiles: CG_PRO
CG_PRO
Compiler options: -pro
-pro
? DirectX 8 vertex shaders
Runtime profiles: CG_PRO
Compiler options:-pro
? DirectX 8 pixel shaders
Runtime profiles: CG_PRO
CG_PRO
CG_PRO
Compiler options: -pro
-pro
-pro
-pro
附:截止到2009年10月,出现的pro