在GLSL中,一个浮点的全局变量的定义很简单,如下:
float var;
在SPIRV中,如何定义一个浮点的变量呢?SPIR-V中没有预定义任何类型,在定义一个变量之前,需要定义一个类型。
浮点类型
在SPIR-V手册中,浮点的类型的定义为:
OpTypeFloat
对于 OpTypeFloat
指令,文档中的指令格式为:
3 | 22 | Result<id> | Literal Width |
- 其中3表示指令的长度,22为指令的操作码。这部分内容在手册2.3章节中的表格2 指令物理布局中有更多描述。
- Result<id>为可阅读的SPIR-V代码中=左边的内容。这并不总是第一个参数,如果有一个类型参数<id>,则它总是在指令布局中排在第一位。
- Literal Width为一个立即数,表示数据类型的宽度。
对于SPIR-V规范代码转为可阅读的的SPIR-V代码,有下列三种情况:
- 没有结果
length | opCode | Param1 | ... -> OpX Param1 ...
2. 有结果,但没有类型
length | opcode | Result <id> | Param1 | ... -> %id = OpX param1 ...
3. 有结果,有类型
length | opcode | Result Type <tid> | Result <id> | Param1 | ... -> %id = OpX %tid Param1 ...
回到GLSL中的浮点变量的第一步,对于SPIR-V我们需要定义浮点类型:
%float = OpTypeFloat 32
类型指针
SPIR-V中的基本类型用于指示中间结果的类型。变量不是类型,是指向类型的指针。类型指针除了它所指向的类型之外,还携带一条额外的信息:存储类。
4 | 32 | Result<id> | Storage Class | <id> Type |
指令中的Storage Class可以为UniformConstant,Input,Uniform等等。关于Storage Class值的更多介绍,可参考手册3.7章节的存储类。
<id> Type 就是我们在之前定义的数据类型。
所以对于浮点数据的类型指针为:
%floatPtr = OpTypePointer Private %float
变量
终于到了定义一个变量的最后一步。对于OpVariable,手册中指令为:
4+variable | 59 | <id> Result Type | Result<id> | Storage Class | Optional <id> Initializer |
对于Result Type,必须为上一步中的OpTypePointer。
Initializer用于初始化变量的值,是可选的。如果有Initializer必须来自于常量指令或者全局变量,且与Result Type相同类型。
所以GLSL中的浮点定义,SPIR-V中最后一步为:
%var = OpVariable %floatPtr private
总结
在SPIR-V中定义一个变量需要:
1.定义一个类型
2. 定义类型指针(OpTypePointer)
3.定义一个变量(OpVariable)