顶点着色器和像素着色器从早期着色器版本中大大简化。 如果在硬件中实现着色器,则不能将vs_3_0或ps_3_0用于任何其他着色器版本,并且不能将任何着色器类型与固定函数管道一起使用。 这些更改可以简化驱动程序和运行时。 唯一的例外是,仅软件vs_3_0着色器可用于任何像素着色器版本。 此外,如果将仅软件vs_3_0着色器与以前的像素着色器版本一起使用,顶点着色器只能使用与灵活顶点格式(FVF)代码兼容的输出语义。
顶点着色器输出上使用的语义必须在像素着色器输入上使用。 语义用于将顶点着色器输出映射到像素着色器输入,类似于顶点声明映射到顶点着色器输入寄存器和以前的着色器模型的方式。 请参阅 vs 3.0 和 ps 3.0 着色器的匹配语义。
添加了其他环绕模式呈现状态,以覆盖此新方案中其他纹理坐标的可能性。 设置相应的 D3DRS_WRAP* 时,具有D3DDECLUSAGE_TEXCOORD和使用情况索引的属性在包装模式下内插。
- 顶点着色器模型 3 特征
- 像素着色器模型 3 功能
- vs_3_0和ps_3_0着色器上的语义
- 雾、深度和底纹模式更改
- 浮点和整数转换
- 指定全精度或部分精度
- 软件顶点和像素着色器
顶点着色器模型 3 功能
顶点着色器输出寄存器类型已折叠为十二个寄存器(请参阅 输出寄存器)。 需要使用 dcl 指令和语义(例如,dcl_color0 o0.xyzw)声明所使用的每个寄存器。
3_0 顶点着色器模型(vs_3_0)vs_2_0 扩展了具有更强大的寄存器索引、一组简化的输出寄存器、采样顶点着色器中的纹理的功能以及控制着色器输入初始化速率的功能。
为任何寄存器编制索引
所有寄存器(输入寄存器 和 输出寄存器)都可以使用 循环计数器寄存器 编制索引(只有常量寄存器可以在早期版本中编制索引)。
在为输入和输出寄存器编制索引之前,必须声明输入和输出寄存器。 但是,不能为任何使用位置或点大小语义声明的输出寄存器编制索引。 事实上,如果使用索引编制,则必须分别在 o0 和 o1 寄存器中声明位置和 psize 语义。
仅允许为连续寄存器范围编制索引;也就是说,不能跨尚未声明的寄存器编制索引。 虽然此限制可能不方便,但它允许进行硬件优化。 尝试跨非连续寄存器编制索引将产生未定义的结果。 着色器验证不会强制实施此限制。
简化输出寄存器
所有类型的输出寄存器已折叠为 12 个输出寄存器:1 表示位置,2 表示颜色,8 表示纹理,1 表示雾或点大小。 这些寄存器将内插它们为像素着色器包含的任何数据。 输出寄存器声明是必需的,并将语义分配给每个寄存器。
可以按如下方式细分寄存器:
- 必须至少将一个寄存器声明为四分量位置寄存器。 这是唯一必需的顶点着色器寄存器。
- 着色器使用的前十个寄存器最多可以使用四个组件(xyzw)。
- 最后一个(或第十二个)寄存器只能包含标量(如点大小)。
有关寄存器的列表,请参阅 寄存器 - vs_3_0。
顶点着色器中的纹理示例
顶点着色器 3_0 支持使用 texldl - vs 顶点着色器中的纹理查找。
像素着色器模型 3 功能
像素着色器颜色和纹理寄存器已折叠为十个输入寄存器(请参阅 输入寄存器类型)。 人脸寄存器是浮点标量寄存器。 只有此寄存器的符号有效。 如果该符号为负数,则基元为后脸。 例如,这可以在像素着色器内使用,以实现双面照明。 位置寄存器引用当前 (x,y) 像素。
可以使用以下命令设置着色器常量寄存器:
匹配vs_3_0和ps_3_0着色器的语义
语义使用vs_3_0和ps_3_0存在一些限制。 通常,在使用与着色器输出中使用的语义匹配的着色器输入的语义时,需要小心。
例如,此像素着色器将多个名称打包到一个寄存器中:
ps_3_0
dcl_texcoord0 v0.x
dcl_texcoord1 v0.yz // Valid to pack multiple names into one register
dcl_texcoord2_centroid v1.w
...
每个寄存器都有不同的语义。 请注意,由于使用写入掩码,还可以使用不同的(多个)语义命名 v0.x 和 v0.yz。
给定像素着色器,以下vs_3_0着色器无法与它配对:
vs_3_0
...
dcl_texcoord0 o5.x
dcl_texcoord1 o6.yzw
...
这两个着色器与使用 D3DDECLUSAGE_TEXCOORD0 And D3DDECLUSAGE_TEXCOORD1 语义冲突。
重写如下所示的顶点着色器,以避免语义冲突:
vs_3_0
...
dcl_texcoord2 o3
dcl_texcoord3 o9
...
同样,在此顶点着色器中的单个输出寄存器中,不能在此顶点着色器中的单个输出寄存器中使用在像素着色器(v0 和 v1)上声明的语义名称。 例如,此顶点着色器不能与像素着色器配对,因为D3DDECLUSAGE_TEXCOORD1用于像素着色器输入寄存器(v0,v1)和顶点着色器输出寄存器 o3。
vs_3_0
...
dcl_texcoord0 o3.x
dcl_texcoord1 o3.yz
dcl_texcoord2 o3.w // BAD! Would be valid if this were not o3
dcl_texcoord3 o9 ...
另一方面,此顶点着色器无法与像素着色器配对,因为具有给定语义的参数的输出掩码不提供像素着色器请求的数据:
vs_3_0
...
dcl_texcoord0 o5.x
dcl_texcoord1 o5.yzw
dcl_texcoord2 o7.yz // BAD! Would be valid if w were included
dcl_texcoord3 o9
...
此顶点着色器不提供具有像素着色器请求的语义名称之一的输出,因此着色器配对无效:
vs_3_0
...
dcl_texcoord0 o5.x
dcl_texcoord1 o5.yzw
dcl_texcoord3 o9
// The pixel shader wants texcoord2, with a w component,
// but it isn't output by this vertex shader at all!
...
雾、深度和底纹模式更改
当在剪裁和三角形光栅化期间为平面底纹设置D3DRS_SHADEMODE时,具有D3DDECLUSAGE_COLOR的属性将作为平面着色进行内插。 如果寄存器的任何组件都使用颜色语义声明,但同一寄存器的其他组件具有不同的语义,则不带颜色语义的寄存器中的组件上将未定义平面底纹内插(线性与平面)。
如果需要雾渲染,vs_3_0和ps_3_0着色器必须实现雾。 着色器之外不会执行雾计算。 vs_3_0中没有雾寄存器,并且添加了其他语义D3DDECLUSAGE_FOG(对于每个顶点计算的雾混合因子)和D3DDECLUSAGE_DEPTH(用于将深度值传递给像素着色器以计算雾混合因子)。
使用像素着色器 3.0 时,将忽略纹理阶段状态D3DTSS_TEXCOORDINDEX。
添加了以下值以适应这些更改:
// Fog and Depth usages
D3DDECLUSAGE_FOG
D3DDECLUSAGE_DEPTH
// Additional wrap states for vs_3_0 attributes with D3DDECLUSAGE_TEXCOORD
D3DRS_WRAP8
D3DRS_WRAP9
D3DRS_WRAP10
D3DRS_WRAP11
D3DRS_WRAP12
D3DRS_WRAP13
D3DRS_WRAP14
D3DRS_WRAP15
浮点和整数转换
浮点数学发生在管道的不同部分的不同精度和范围(16 位、24 位和 32 位)。 大于输入该管道的管道的动态范围(例如,将 32 位浮点纹理映射采样到 ps_2_0 中的 24 位浮点管道)的值将创建未定义的结果。 对于可预测的行为,应将此类值固定到动态范围最大值。
从浮点值到整数的转换发生在以下几个位置:
- 遇到 mova 时 - vs 指令。
- 在纹理寻址期间。
- 写出到非浮点呈现目标时。
指定完整精度或部分精度
ps_3_0和ps_2_x都支持两种精度级别:
ps_3_0 | ps_2_0 | 精度 | 价值 |
---|---|---|---|
x | 满 | fp32 或更高版本 | |
x | 部分精度 | fp16=s10e5 | |
x | x | 满 | fp24=s16e7 或更高版本 |
x | x | 部分精度 | fp16=s10e5 |
ps_3_0支持比ps_2_0更高的精度。 默认情况下,所有作都以完全精度级别进行。
部分精度(请参阅 像素着色器寄存器修饰符)是通过向着色器代码添加_pp修饰符(前提是基础实现支持)。 实现始终可以自由地忽略修饰符,并完全精确执行受影响的作。
_pp修饰符可以在两个上下文中发生:
- 在纹理坐标声明中,将部分精度纹理坐标传递给像素着色器。 当纹理坐标将颜色数据中继到像素着色器时,这可能比某些实现中的全精度更快。
- 在请求使用部分精度的任何指令上,包括纹理加载指令。 这表示允许实现以部分精度执行指令,并存储部分精度结果。 如果没有显式修饰符,则必须以完全精度执行指令(无论输入作数的精度如何)。
应用程序可能会故意选择权衡性能的精度。 有多种类型的着色器输入数据是部分精度处理的自然候选项:
- 颜色迭代器由部分精度值很好地表示。
- 大多数格式的纹理值都可以由部分精度值准确表示(从 32 位、浮点格式纹理采样的值是明显的异常)。
- 常量可以按着色器适当的部分精度表示形式来表示。
在所有这些情况下,开发人员可以选择指定部分精度来处理数据,知道不会丢失任何输入数据精度。 在某些情况下,着色器可能需要以完全精度执行计算的内部步骤,即使输入和最终输出值没有超过部分精度也是如此。
软件顶点和像素着色器
版本 2_0 着色器及更高版本的软件实现(顶点着色器和像素着色器的参考)的运行时和参考具有一些宽松的验证。 这对于调试和原型制作非常有用。 应用程序向运行时/汇编程序指示,它需要使用汇编程序中的_sw标志(例如,vs_2_sw)放宽某些验证。 软件着色器不适用于硬件。
vs_2_sw是vs_2_x最大上限的放松:同样,ps_2_sw是ps_2_x最大上限的放松。 具体而言,以下验证是宽松的:
着色器模型 | 资源 | 限制 |
---|---|---|
vs_2_sw、vs_3_sw、ps_2_sw、ps_3_sw | 指令计数 | 无限 |
vs_2_sw、vs_3_sw、ps_2_sw、ps_3_sw | Float 常量寄存器 | 8192 |
vs_2_sw、vs_3_sw、ps_2_sw、ps_3_sw | 整数常量寄存器 | 2048 |
vs_2_sw、vs_3_sw、ps_2_sw、ps_3_sw | 布尔常量寄存器 | 2048 |
ps_2_sw | 从属读取深度 | 无限 |
vs_2_sw | 流控制指令和标签 | 无限 |
vs_2_sw、vs_3_sw、ps_2_sw、ps_3_sw | 循环启动/步骤/计数 | 代表指令和循环指令的迭代开始和迭代步骤大小为 32 位有符号整数。 计数最多可为 MAX_INT/64。 |
vs_2_sw、vs_3_sw、ps_2_sw、ps_3_sw | 端口限制 | 所有注册文件的端口限制都会放宽。 |
vs_3_sw | 内插器数 | vs_3_sw中的 16 个输出寄存器。 |
ps_3_sw | 内插器数 | 14(16-2) 输入寄存器用于ps_3_sw。 |
相关主题