流控制限制
像素着色器流控制指令具有限制,这些限制会影响指令中可包含多少级别的嵌套。 此外,使用渐变指令实现每像素流控制还有一些限制。
注意
使用 *_4_0_level_9_x HLSL 着色器配置文件时,隐式使用 着色器模型 2.x 配置文件来支持支持 Direct3D 9 的硬件。 着色器模型 2.x 配置文件支持比 着色器模型 4.x 及更高版本的配置文件更有限的流控制行为。
像素着色器指令深度计数
ps_2_0不支持流控制。 下面列出了其他像素着色器版本的限制。
ps_2_x指令深度计数
每个指令针对一个或多个嵌套深度限制进行计数。 下表列出了每个指令从现有深度添加或减去的深度计数。
指令 | 静态嵌套 | 动态嵌套 | 循环/代表嵌套 | 调用嵌套 |
---|---|---|---|---|
布尔 - ps | 1 | 0 | 0 | 0 |
if_comp - ps | 0 | 1 | 0 | 0 |
pred - ps | 0 | 1 | 0 | 0 |
其他 - ps | 0 | 0 | 0 | 0 |
endif - ps | -1(如果布尔 - ps) | -1( 如果 pred - ps 或 if_comp - ps) | 0 | 0 |
rep - ps | 0 | 0 | 1 | 0 |
endrep - ps | 0 | 0 | -1 | 0 |
中断 - ps | 0 | 0 | 0 | 0 |
break_comp - ps | 0 | 1、-1 | 0 | 0 |
断点 - ps | 0 | 0 | 0 | 0 |
呼叫 - ps | 0 | 0 | 0 | 1 |
callnz bool - ps | 0 | 0 | 0 | 1 |
callnz pred - ps | 0 | 1 | 0 | 1 |
重试 - ps | 0 | -1(callnz pred - ps) | 0 | -1 |
setp_comp - ps | 0 | 0 | 0 | 0 |
嵌套深度
嵌套深度定义可以从彼此内部调用指令数。 每种类型的指令都有一个或多个嵌套限制,如下表所示。
指令类型 | 最大 |
---|---|
静态嵌套 | 24 如果 (D3DCAPS9.D3DPSHADERCAPS2_0.StaticFlowControlDepth > 0;否则为 0 |
动态嵌套 | 0 到 24,请参阅D3DCAPS9。D3DPSHADERCAPS2_0.DynamicFlowControlDepth |
rep 嵌套 | 0 到 4,请参阅D3DCAPS9。D3DPSHADERCAPS2_0.StaticFlowControlDepth |
调用嵌套 | 0 到 4,请参阅D3DCAPS9。D3DPSHADERCAPS2_0.StaticFlowControlDepth (独立于代表限制) |
ps_2_sw指令深度计数
每个指令针对一个或多个嵌套深度限制进行计数。 此表显示每个指令从现有深度添加或减去的深度计数。
指令 | 静态嵌套 | 动态嵌套 | 循环/代表嵌套 | 调用嵌套 |
---|---|---|---|---|
布尔 - ps | 1 | 0 | 0 | 0 |
pred - ps | 0 | 1 | 0 | 0 |
if_comp - ps | 0 | 1 | 0 | 0 |
其他 - ps | 0 | 0 | 0 | 0 |
endif - ps | -1(如果布尔 - ps) | -1( 如果 pred - ps 或 if_comp - ps) | 0 | 0 |
rep - ps | 0 | 0 | 1 | 0 |
endrep - ps | 0 | 0 | -1 | 0 |
循环 - ps | n/a | n/a | n/a | n/a |
endloop - ps | n/a | n/a | n/a | n/a |
中断 - ps | 0 | 0 | 0 | 0 |
break_comp - ps | 0 | 1、-1 | 0 | 0 |
断点 - ps | 0 | 0 | 0 | 0 |
呼叫 - ps | 0 | 0 | 0 | 1 |
callnz bool - ps | 0 | 0 | 0 | 1 |
callnz pred - ps | 0 | 1 | 0 | 1 |
重试 - ps | 0 | -1(callnz pred - ps) | 0 | -1 |
setp_comp - ps | 0 | 0 | 0 | 0 |
嵌套深度
嵌套深度定义可从彼此内部调用的指令数。 每种类型的指令都有一个或多个嵌套限制,如下表所示。
指令类型 | 最大 |
---|---|
静态嵌套 | 24 |
动态嵌套 | 24 |
rep 嵌套 | 4 |
调用嵌套 | 4 |
ps_3_0指令深度计数
每个指令针对一个或多个嵌套深度限制进行计数。 此表显示每个指令从现有深度添加或减去的深度计数。
指令 | 静态嵌套 | 动态嵌套 | 循环/代表嵌套 | 调用嵌套 |
---|---|---|---|---|
布尔 - ps | 1 | 0 | 0 | 0 |
pred - ps | 0 | 1 | 0 | 0 |
if_comp - ps | 0 | 1 | 0 | 0 |
其他 - ps | 0 | 0 | 0 | 0 |
endif - ps | -1(如果布尔 - ps) | -1( 如果 pred - ps 或 if_comp - ps) | 0 | 0 |
rep - ps | 0 | 0 | 1 | 0 |
endrep - ps | 0 | 0 | -1 | 0 |
循环 - ps | 0 | 0 | 1 | 0 |
endloop - ps | 0 | 0 | -1 | 0 |
中断 - ps | 0 | 0 | 0 | 0 |
break_comp - ps | 0 | 1、-1 | 0 | 0 |
断点 - ps | 0 | 0 | 0 | 0 |
呼叫 - ps | 0 | 0 | 0 | 1 |
callnz bool - ps | 0 | 0 | 0 | 1 |
callnz pred - ps | 0 | 1 | 0 | 1 |
重试 - ps | 0 | -1(callnz pred - ps) | 0 | -1 |
setp_comp - ps | 0 | 0 | 0 | 0 |
嵌套深度
嵌套深度定义可从彼此内部调用的指令数。 每种类型的指令都有一个或多个嵌套限制,如下表所示。
指令类型 | 最大 |
---|---|
静态嵌套 | 24 |
动态嵌套 | 24 |
循环/代表嵌套 | 4 |
调用嵌套 | 4 |
ps_3_sw指令深度计数
每个指令针对一个或多个嵌套深度限制进行计数。 此表显示每个指令从现有深度添加或减去的深度计数。
指令 | 静态嵌套 | 动态嵌套 | 循环/代表嵌套 | 调用嵌套 |
---|---|---|---|---|
布尔 - ps | 1 | 0 | 0 | 0 |
pred - ps | 0 | 1 | 0 | 0 |
if_comp - ps | 0 | 1 | 0 | 0 |
其他 - ps | 0 | 0 | 0 | 0 |
endif - ps | -1(如果布尔 - ps) | -1( 如果 pred - ps 或 if_comp - ps) | 0 | 0 |
rep - ps | 0 | 0 | 1 | 0 |
endrep - ps | 0 | 0 | -1 | 0 |
循环 - ps | 0 | 0 | 1 | 0 |
endloop - ps | 0 | 0 | -1 | 0 |
中断 - ps | 0 | 0 | 0 | 0 |
break_comp - ps | 0 | 1、-1 | 0 | 0 |
断点 - ps | 0 | 0 | 0 | 0 |
呼叫 - ps | 0 | 0 | 0 | 1 |
callnz bool - ps | 0 | 0 | 0 | 1 |
callnz pred - ps | 0 | 1 | 0 | 1 |
重试 - ps | 0 | -1(callnz pred - ps) | 0 | -1 |
setp_comp - ps | 0 | 0 | 0 | 0 |
嵌套深度
嵌套深度定义可从彼此内部调用的指令数。 每种类型的指令都有一个或多个嵌套限制,如下表所示。
指令类型 | 最大 |
---|---|
静态嵌套 | 24 |
动态嵌套 | 24 |
循环/代表嵌套 | 4 |
调用嵌套 | 4 |
Per-Pixel 流控件与屏幕渐变的交互
像素着色器指令集包括多个指令,这些指令生成或使用屏幕空间 x 和 y 方面的数量渐变。 渐变的最常见用途是计算纹理采样的详细级别计算,在异性筛选的情况下,选择各向异性轴上的样本。 通常,硬件实现同时在多个像素上运行像素着色器(例如 2x2 网格),以便着色器中计算的数量渐变可以合理地近似为相邻像素执行点的值的增量。
当流控制存在于着色器中时,给定分支路径中请求的渐变计算的结果在相邻像素可能执行单独的流控制路径时不明确。 因此,使用任何像素着色器作是非法的,该作请求在流控制构造内的位置发生渐变计算,该位置可能会因给定基元光栅化而有所不同。
所有像素着色器指令都分区到允许的作以及流控制中不允许的作中:
方案 A:不允许在流控制内执行的作,这些作可能会因基元中的像素而异。 这些作包括下表中列出的作。
指令 在以下情况下允许在流控制中: texld - ps_2_0 和 up,texldb - ps 和 texldp - ps 临时寄存器用于纹理坐标。 dsx - ps 和 dsy - ps 临时寄存器用于作数。 方案 B:允许在任何位置执行的作。 这些作包括下表中列出的作。
指令 允许在: texld - ps_2_0 和 up,texldb - ps 和 texldp - ps 只读数量用于纹理坐标(可能因像素而异,例如内插纹理坐标)。 dsx - ps 和 dsy - ps 只读数量用于输入作数(可能因像素而异,例如内插纹理坐标)。 texldl - ps 用户提供详细级别作为参数,因此没有渐变,因此流控制没有问题。 texldd - ps 用户提供渐变作为输入参数,因此流控制没有问题。
在着色器验证中严格执行这些限制。 具有分支条件的方案(看起来会一致地跨基元分支),即使条件表达式中的作数是像素着色器计算的数量,但仍属于方案 A 且不允许。 同样,在某些着色器计算数量 x 上从动态流控制中请求渐变的方案,但似乎 X 未在任何分支中修改,但仍属于方案 A,不允许。
流控制限制中包含谓词,以便实现可以简单地将分支指令的实现与谓词指令交换。
用户可以使用 A 和 B 方案中的说明。 例如,假设用户需要给定着色器计算纹理坐标的向异性纹理样本;但是,只有满足某些每像素条件的像素才需要纹理加载。 为了满足这些要求,用户可以使用 dsx - ps 和 dsy - ps 指令立即计算每个像素外部的所有像素的纹理坐标。 然后,在每像素 如果 bool - ps/endif - ps 块,则用户可以使用 texldd - ps(具有用户提供的渐变的纹理加载),传递预计算渐变。 描述此使用模式的另一种方法是,虽然基元中的所有像素必须计算纹理坐标并涉及渐变计算,但只有对纹理进行采样所需的像素才能实际执行此作。
无论这些规则如何,用户仍会承担负担,以确保在计算任何渐变(或执行隐式计算渐变的纹理样本)之前,必须事先为所有执行路径初始化包含源数据的寄存器。 临时寄存器的初始化通常不会验证或强制实施。
相关主题