Cg语言中文说明文档(四)

类型

整型

int整型适用于32位二进制补码。Profiles可以选择将整型看作float浮点类型。

unsigned无符号整型适用于32位顺序型。unsigned可以和其他整型一起形成不同长度的无符号类型。char,short,long都是二进制形式整型的不同长度的类型。唯一需要说明的是,char不能长于short,short不长于int,long至少要和int一样长。浮点类型和IEEE标准的32位浮点精度一致。

浮点类型

Profiles必须支持float数据类型
half类型类似IEEE标准中的低精度浮点数,Profiles必须支持half类型,但可以选择将half类型实现成float精度

fixed类型是有符号类型,其范围在[-2,2)之间,其小数部分至少可以拥有10位的精度。数据溢出时的操作时采取夹逼方式,而不是舍弃位的方式(这个具体不展开了,只要就是关于程序中对有符号,无符号数据溢出舍弃符号位,然后按补码方式重新计算)。栅格化Profile必须支持fixed类型,但可以以half或是float的精度来实现fixed类型。顶点Profile只需提供部分fixed类型的支持。也可以提供全部支持,或者以half,float的精度来实现fixed类型

布尔类型

布尔类型代表布尔值,不是真就是假

cint

cint类型是一个32位二进制补码类型。该类型只在编译时有意义。无法直接声明对象类型为cint

cfloat

cfloat类型是IEEE标准的单精度浮点类型。只在编译时有意义,不能直接声明类型为cfloat类型

void类型

void类型不能在任何表达式中被使用,只能作为没有返回值的函数的返回类型

sampler*类型

用来处理贴图对象。程序或者函数的形参可以是sampler*类型。其他地方都不允许定义sampler*类型变量。一个sampler*类型的变量只能用作in参数来传递给另一个函数,不允许对sampler*类型变量赋值。不允许结果为sampler*类型的表达式

sampler,sampler1D,sampler2D,sampler3D,samplerCUBE,samplerRECT类型是已经定义的。
基本的sampler类型可以用在任何可以使用更加特定的sampler类型的地方。然而一个sampler类型必须在程序中通过贯穿一致的方式来使用,比如,它不能被用在同一段程序其中有sampler1D和sampler2D的地方。sampler类型只支持向前兼容Cg1.0时使用,现在已经被舍弃了

栅格化profile必须完全支持sampler,sampler1D, sampler2D,sampler3D和samplerCUBE。可以部分支持samplerRECT,或是全部支持
顶点profile可以选择部分或全部支持这六种类型

数组类型

数组类型是同一个类型的一个或多个元素的集合。一个数组变量有一个单一的索引。
数组类型可以被packed修饰。使用packed的存储格式和未使用packed的类型的存储格式有区别。packed类型的存储格式其实现是相关的,但必须对任何特定的编译器和profile的组合而言是一致的。一个packed类型在一个特定profile中的操作和没有使用packed的类型有差别。Profile可以定义一个packed的数组的最大的尺寸。对packed的向量类型(1维数组)其长度至少是4,对于矩阵(2维数组)类型,长度至少是4*4。
当在一个单独的数组声明中声明了一个数组,packed修饰服对所有的数组起作用。然后,在packed数组中声明一个unpacked数组,可以通过使用typedef声明一个packed数组,然后使用这个定义的Type再声明第二个数组。不能直接声明一个unpacked数组的packed数组(这话真是绕,估计我回头得重新组织下语言)。

对任何数值类型,实现必须支持下列的packed数组类型,称为向量类型,其中的Type是指在全局范围内已经预定义的类型

typedef packed TYPE TYPE1[1];
typedef packed TYPE TYPE2[2];
typedef packed TYPE TYPE3[3];
typedef packed TYPE TYPE4[4];

例如,实现必须已经按上述样子定义过float1~float4,其中Type此时为float类型。其他数值类型也是如此

对任何数值类型,实现必须支持下列形式的数组类型,称为矩阵类型,其中的Type是指在全局范围内已经预定义过的类型

packed TYPE1 TYPE1x1[1];
packed TYPE2 TYPE1x2[1];
packed TYPE3 TYPE1x3[1];
packed TYPE4 TYPE1x4[1];
packed TYPE1 TYPE2x1[2];
packed TYPE2 TYPE2x2[2];
packed TYPE3 TYPE2x3[2];
packed TYPE4 TYPE2x4[2];
packed TYPE1 TYPE3x1[3];
packed TYPE2 TYPE3x2[3];
packed TYPE3 TYPE3x3[3];
packed TYPE4 TYPE3x4[3];
packed TYPE1 TYPE4x1[4];
packed TYPE2 TYPE4x2[4];
packed TYPE3 TYPE4x3[4];
packed TYPE4 TYPE4x4[4];

例如,实现必须定义过上述中诸如float2x1,float3x3,float4x4等类型。有一个按照矩阵名的typedef,Type行x列,如果我们声明了一个float4x4的a,那么a[3]和a.m30m31m32m33是一样的。

实现必须支持对向量和矩阵的常量索引访问。

结构和接口类型

接口类型在结构类型地方使用关键字interface来定义。接口类型只能声明成员函数,不能有数据成员。接口方法函数只能声明,不能被定义。结构类型可以继承一个接口类型,并且必须对接口类型中每一个声明的成员函数定义实现。

类型的局部支持

一个类型的局部支持必须满足下列条件

  • 定义和声明的类型必须支持的
  • 支持对该类型对象的赋值和赋值。这包括隐形的执行赋值和作为参数传递给函数
  • 入口函数参数可能使用该类型来定义

    如果一个类型是局部支持的,使用该类型来定义的变量,在其上没有可执行的有效操作。类型的局部支持可以使不同的profiles直接方便的来共享数据结构。

类型分类

  • 带符号的整型包括cint,char,short,int和long
  • 无符号整型包括无符号的char,无符号的short,无符号的int,和无符号的long,如果仅仅是unsigned那么等同于无符号int
  • 整数类型包括了无符号和带符号的整数类型
  • 浮点类型包括cfloat,float,half和fixed
  • 数值类型包括整型和浮点型
  • 编译时类型包括了cfloat,cint。这些类型提供编辑器用来做常量转换使用
  • 动态类型包括了接口和unsized数组类型
  • 实数类型包括所有非动态类型,和编译类型在内的其他类型
  • 标量类型包括所有数值类型,布尔类型,所有的编译类型。

常量

常量就和C中的字面量上定义的一样,包括八进制0,和十六进制0x前缀所定义的常量,带有e作为指数后缀的浮点数常量。常量具有显示定义和隐式定义。显示定义和C一样,在常量后跟一到两个标识类型的字符

  • d代表double
  • f代表浮点
  • h代表half
  • i代表int
  • l代表long
  • s代表short
  • t代表char
  • u代表unsigned,后面可以跟s,t,i,l
  • x代表fixed

任何非显示定义的常量就是隐式的,如果常量包含十进制的小数点或者一个e的指数后缀,那就被隐式的定义为cfloat类型。如果没有十进制小数部分,则被隐式定义为cint

默认,常量都是十进制的。为了和C兼容,十六进制整型常量添加前缀0x,八进制整型常量指定前缀0.

编译时常量折叠的精度和运行时执行的操作精度是完全一致的。有一些编译的profile针对某些硬件允许在精度上有一定的弹性。这种情况下,编译器将使用允许的硬件的最高精度来进行常量折叠。

如果常量折叠不能执行运行时精度,那么它将使用下面的类型来选择使用的精度
float,half,fixed,double,int,char,short,long

类型转换

一些类型允许隐式转换,另一些需要一个显示的强制转换。一些隐式转换会有警告信息。使用显示的强制转换可以解决这个问题。显示转换使用C类型的语法,比如将变量v转换为float4类型,可以使用(float4)v

标量转换

标量数值型之间可以隐式转换。如果会发生精度丢失,则会出现警告。隐式的在标量对象类型和兼容标量的对象类型之间的转换是允许的。在不兼容的标量类型和数值类型间的转换即使使用显示的转换也不允许。sampler是和sampler1D,sampler2D,sampler3D,samplerCube, samplerRECT兼容,除此之外没有其他兼容类型(sampler1D和sampler2D之间是不兼容的)

标量类型可以隐式的转变为向量和矩阵的兼容类型。标量会被复制到每一个向量或是矩阵的元素。标量也可以显示的转变为结构类型,如果标量类型可以正常的被转化成每一个结构的成员的话。

向量转换

向量可以选择将一个元素对象转换为标量,这时如果是隐式转换,会产生一个警告。一个向量同样可以被隐式的转换为另一个使用兼容类型,并且长度一致的向量
向量可以转换成一个更小长度的兼容类型的向量,或者一个同样长度的矩阵。但如果是隐式的,会产生警告信息。

矩阵转换

矩阵可以转换为标量类型,选择二维中(0,0)位置的元素。和向量一样,如果是通过隐式完成会产生一个警告。一个矩阵同样可以被隐式的转换为拥有同样行列的兼容类型的矩阵。
一个矩阵可以被转变为一个更新的矩阵(通过从左上角开始选择),或者,转变为一个同样长度的向量,但如果不是使用显示转换完成,会产生一个警告

结构转换

一个结构可以显示的转换成其第一个成员的类型。如果结构的每一个成员可以被转换成新结构的对应成员的话,结构可以转换成拥有同样数量的成员的另一个结构。结构类型不允许隐式转换。

数组转换

一个数组可以显示的转换成另一个有用同样数量元素和兼容数据类型的数组。一个兼容类型的元素的类型必须是和源数组的元素类型发生隐式转换的。数组之间不允许隐式的转换

下表列举了类型之间转换的情况
Source type
| Scalar | Vector | Matrix | Struct | Array |
T —–+——–+——–+——–+——–+——–+
a Scalar | A | W | W | E(3) | - |
r —–+——–+——–+——–+——–+——–+
g Vector | A | A/W(1) | W(2) | E(3) | E(6) |
e —–+——–+——–+——–+——–+——–+
t Matrix | A | W(2) | A/W(1) | E(3) | E(7) |
—–+——–+——–+——–+——–+——–+
t Struct | E | E(4) | E(4) | E(4/5) | E(4) |
y —–+——–+——–+——–+——–+——–+
p Array | - | E(6) | E(7) | E(3) | E(6) |
e —–+——–+——–+——–+——–+——–+

A代表允许,W代表隐式会出警告,E代表只允许显示转换,-代表不允许

表中代表的注意
(1)如果目标长度比源大,是不允许转换的(向量,或是数组的长度)。如果目标比源小,则会出警告
(2)只允许长度一致的源和目标
(3)只有源的第一个成员可以转换成目标
(4)只有目标结构包含目标成为一个单一成员
(5)只有源和目标有同样数量的成员,并且每个源的成员可以被转换成对应的目标成员
(6)源和目标的长度必须一直,并且元素类型必须是兼容的
(7)数组类型必须是向量数组,并且向量类型匹配矩阵的元素类型

显示转换时使用在

  • 编译时类型使用在编译时类型的表达式中时
  • 数值类型使用在数值或编译时类型的表达式中时
  • 数值向量类型使用在同样数量的向量类型时
  • 数值矩阵类型使用在拥有同样行,列的另一个矩阵类型时

类型相等

当下列任一条件为真时,类型T1和T2相当

  • T2等于T1
  • T1,T2是相同的变量,向量,或结构类型。packed数组类型和同样长度的unpacked数值类型是不相当的
  • T1是T2的typedef名
  • T1和T2是同样数量,并且同样类型的数组
  • T1,T2未修饰的类型是相等的,拥有同样修饰的也是相等的(packed,unpacked)
  • T1和T2是拥有相同fanhui类型,相同数量和相同类型参数的函数

类型晋升规则

cflaot和cint类型,除了在通常的数学转换中(下方定义)和函数重载规则中外,其行为表现就是和float,int类似

下面定义了通常使用的二元操作时的数学转换

  1. 如果一个操作元是cint,它将被转换为另一个类型
  2. 如果一个操作数是cfloat,并且另一个是浮点,则cfloat被转换为另一个类型
  3. 如果两个操作数都是浮点型,则精度小的转换成精度大的
  4. 如果一个操作数是浮点,另一个是整型,则整型转换成浮点型
  5. 如果两个操作数都是整型,则精度小的转换成精度大的
  6. 如果一个操作数是有符号整型,另一个是无符号整型,并且那么长度一致,则有符号转换成无符号

注意,类型转换优先于操作执行

猜你喜欢

转载自blog.csdn.net/duotemplar/article/details/78285189