AGAL seq操作码适用于硬件,但不适用于软件仿真(两者的浮点数比较不同?)

时间:2017-01-31 08:51:30

标签: shader fragment-shader stage3d agal

来自文档:seq set-if-equal destination = source1 == source2? 1:0,分量

我还没有彻底测试过,但到目前为止,我的片段着色器在两台机器(台式机)上工作,其中context3D初始化成功为DirectX,但在闪存回落到软件渲染的机器上不起作用。 / p>

seq ft2.x, ft0.x, fc0.x

当存储在ft.x中的当前像素红色值等于存储1的常量ft0.x时,

fc0.x在硬件上设置为50/255。所以我想要发生的事情确实发生在硬件上的#32????(50 == 0x32)彩色像素上,但不会发生在软件上。

我已经测试了一种解决方法,我可以使用更复杂的算法替换seq操作码,该算法涉及slt(如果小于设置)或sge(如果大于或等于则设置)

所以看起来问题在于对GPU(50/255)的常量I供应与实际红色值(纹理中的50)的比较。如果是其他任何内容(例如RGBA值的顺序不同),sltsge也会失败。

我在这里做错了吗?我应该以某种方式对比较值进行舍入(例如,乘以255然后删除小数),以确保它能在所有设备和模式下工作吗?

更新 其中一台具有软件渲染回退功能的机器设置为16位图形,但将其更改为32位并未解决问题。我也盲目地尝试将颜色值除以256,128和127而不是255,希望它可以解决问题,如果浮点数具有不同的精度(并且更高和更低的数字将工作,只要它们等于256px长梯度内的一个像素),但我的希望没有得到回报。

然后我尝试了将常量存储为整数的方法,并在内部着色器中将值乘以255并删除小数,令我惊讶的是,当它在GPU上工作时,它在软件渲染上失败了:

mul ft0.x, ft0.x, fc0.y ft0.x (红色通道)转换为整数,方法是将其乘以 255

frc ft4.x, ft0.x获得分数

sub ft0.x, ft0.x, ft4.x删除小数,以截断整数

现在进行比较,例如seq ft2.x, ft0.x, fc0.x

add ft0.x, ft0.x, ft4.x添加小数部分,此步骤可能不是必需的

div ft0.x, ft0.x, fc0.y将整数值除以255以将其转换回浮点数(我的意思是0..1范围内的数字)

接下来我将尝试作为一种解决方法是简单地进行一系列小于比较,将temp寄存器设置为1,将其添加到另一个临时寄存器(计数器),以便通过检查我可以在柜台内看到哪个范围是值。

1 个答案:

答案 0 :(得分:2)

这是最终为我做了诀窍的解决方法。

我在红色Alpha通道上有4种颜色,它们通知着色器该做什么。如果红色值为50,则着色器将左侧像素作为源,如果为100,则将采用顶部像素,依此类推。所以我所要做的只是4 seq个命令,将0或1个偏移设置为寄存器的4个分量,我可以稍后在寄存器中添加或删除带有采样器位置的寄存器。

因为seq未能将第一次采样中的像素的红色值与提供的常数进行比较,所以我制作了一个“梯形图”,其中包含set-if-greater-or-equal操作码:

"mov ft3.x, fc0.x \n" + //ft3 = 49/0xFF

"sge ft2.x, ft0.x, ft3.x \n" + //if red > 49/0xFF, set 1 to ft2.x

"add ft3.x, ft3.x, fc0.x \n" + //ft3 = 98/0xFF
"sge ft4.x, ft0.x, ft3.x \n" + //if red > 98/0xFF, set 1 to ft4.x
"add ft2.x, ft2.x, ft4.x \n" + //if 49 < red < 98, ft2.x = 1, if red > 98, ft2.x = 2

"add ft3.x, ft3.x, fc0.x \n" + //ft3 = 147/0xFF
"sge ft4.x, ft0.x, ft3.x \n" + //if red > 147/0xFF, set 1 to ft4.x
"add ft2.x, ft2.x, ft4.x \n" + //if 49 < red < 98, ft2.x = 1, if 98 < red < 147, ft2.x = 2, if red > 147, ft2.x = 3

"add ft3.x, ft3.x, fc0.x \n" + //ft3 = 196/0xFF
"sge ft4.x, ft0.x, ft3.x \n" + //if red > 196/0xFF, set 1 to ft4.x
"add ft2.x, ft2.x, ft4.x \n" + //ft2.x is between 0 and 4 including, where 0 means no control color

现在我有一个寄存器ft2存储:

0红色低于49(实际上所有这些红色值都除以255,如上面代码中的注释所示)

1代表4998

之间的红色

2代表98147

之间的红色

3代表147196

之间的红色 对于4

以上的红色,

196

然后我不是将像素颜色与常数进行比较,而是将ft2.x计数器状态与常数进行比较(常数为1,2,3,4而不是50,100,150,200)。

不幸的是,这意味着上面的整个代码是一个额外的开销,我可以省去GPU,但无法避免在CPU上,除非我能找到seq操作码的解决方案总是在CPU上返回0时比较a像素颜色和常数。