在硬件中高效实现 DXT1 纹理解压缩

Efficiently implementing DXT1 texture decompression in hardware

DXT1 compression 被设计为在纹理采样器中使用的硬件中快速解压缩。维基百科文章说,在某些情况下,您可以计算出插值颜色的系数:

c2 = (2/3)*c0+(1/3)*c1

或重新排列:

c2 = (1/3)*(2*c0+c1)

无论你如何重新排列上面的等式,你最终总是不得不乘以 1/3(或除以 3,同样的交易甚至更贵)。在我看来,设计用于在硬件中快速解压缩的纹理格式需要乘法或除法,这对我来说似乎很奇怪。我在其上实现我的 GPU 的 FPGA 只有有限的乘法资源,我想将它们保存在真正需要的地方。

我是不是漏掉了什么?有没有一种有效的方法可以避免将颜色通道乘以 1/3?还是我应该吃那个乘法的成本?

我能想到的最佳答案是我可以使用身份:

x/3 = sum(n=1 to infinity) (x/2^(2n))

然后取前n项。使用 4 个术语,我得到:

(x/4)+(x/16)+(x/64)+(x/256)

等于

x*0.33203125

这可能已经足够了。

这依赖于硬件中免费的 2 的固定幂乘法,然后我可以并行地进行 3 次加法 运行 2。

如有更好的答案,我们将不胜感激。

** 编辑 **:结合使用这个和@dyslexicgruffalo 的答案,我制作了一个简单的 c++ 程序,它迭代了各种序列并尝试了所有序列并记录了各种 average/max 错误。

我这样做是为了 0 <= x <= 189(因为 189 是 2*c0.g + c1.g 的值,当 g(6 位)达到最大值时。

最短的好序列(最大误差为 2,平均误差为 0.62)并且是 4 次操作:

1 + x/4 + x/16 + x/64.

最大误差为 1,平均误差为 0.32,但有 6 次操作的最佳序列是:

x/2 - x/4 + x/8 - x/16 + x/32 - x/64.

对于 5 位值(红色和蓝色),最大值为 31*3,上面的序列仍然不错,但不是最好的。它们是:

x/4 + x/8 - x/16 + x/32 [max error of 1, average 0.38]

1 + x/4 + x/16 [max error of 2, average of 0.68]

(而且,幸运的是,上述序列中的 none 曾经猜测过一个太大的答案,因此即使它们并不完美也不需要限制)

这可能是一种糟糕的想象方式,但您能否通过使用连续的一半(轮班)addition/subtraction 来实现它?

因为你有 16 位,这使你能够通过连续的加法和减法得到相当准确的结果。

三分之一可以表示为

a(n+1) = a(n) +/- A>>1,其中,列表[0, 0, 1, 0, 1, etc]表示是否加或减移位后的结果.

我相信这叫做分数数学。

但是,在 FPGA 中,很难知道这是否真的比提供的原生 DSP 模块(例如 DSP48E1)更节能。