android 多次调用texture2D时片段着色器非常慢

35g0bw71  于 2023-02-06  发布在  Android
关注(0)|答案(1)|浏览(163)

我有一个模糊皮肤的碎片着色器。输入是YUV纹理(它包括y纹理,u纹理,v纹理)。与帧分辨率是1280x720运行在Galaxy A6,它需要80ms-120ms/帧。我在greenvalue发现了瓶颈()函数调用。如果我像下面的代码那样调用它,它会花费很多时间。如果我只调用"sampleColor = greenValue(blurCoordinates[0]);\n" ...(而不是"sampleColor += greenValue(blurCoordinates[0]);\n" ...),它会非常快。

+ "float greenValue(vec2 coord)\n"
+ "{\n"
+ " return texture2D(y_tex, coord).r - 0.344 * (texture2D(u_tex, coord).r - 0.5) - 0.714 * (texture2D(v_tex, coord).r - 0.5);\n"
+ "}\n";
+ "// some code .... if (current pixel is skin color)" 
+ "vec2 blurCoordinates[20];\n"
+ "blurCoordinates[0] = interp_tc.xy + singleStepOffset * vec2(0.0, -10.0);\n" +
+ "blurCoordinates[1] = interp_tc.xy + singleStepOffset * vec2(0.0, 10.0);\n" +
+ "blurCoordinates[2] = interp_tc.xy + singleStepOffset * vec2(-10.0, 0.0);\n" +
+ "blurCoordinates[3] = interp_tc.xy + singleStepOffset * vec2(10.0, 0.0);\n" +
+ "blurCoordinates[4] = interp_tc.xy + singleStepOffset * vec2(5.0, -8.0);\n" +
+ "blurCoordinates[5] = interp_tc.xy + singleStepOffset * vec2(5.0, 8.0);\n" +
+ "blurCoordinates[6] = interp_tc.xy + singleStepOffset * vec2(-5.0, 8.0);\n" +
+ "blurCoordinates[7] = interp_tc.xy + singleStepOffset * vec2(-5.0, -8.0);\n" +
+ "blurCoordinates[8] = interp_tc.xy + singleStepOffset * vec2(8.0, -5.0);\n" +
+ "blurCoordinates[9] = interp_tc.xy + singleStepOffset * vec2(8.0, 5.0);\n" +
+ "blurCoordinates[10] = interp_tc.xy + singleStepOffset * vec2(-8.0, 5.0);\n" +
+ "blurCoordinates[11] = interp_tc.xy + singleStepOffset * vec2(-8.0, -5.0);\n" +
+ "blurCoordinates[12] = interp_tc.xy + singleStepOffset * vec2(0.0, -6.0);\n" +
+ "blurCoordinates[13] = interp_tc.xy + singleStepOffset * vec2(0.0, 6.0);\n" +
+ "blurCoordinates[14] = interp_tc.xy + singleStepOffset * vec2(6.0, 0.0);\n" +
+ "blurCoordinates[15] = interp_tc.xy + singleStepOffset * vec2(-6.0, 0.0);\n" +
+ "blurCoordinates[16] = interp_tc.xy + singleStepOffset * vec2(-4.0, -4.0);\n" +
+ "blurCoordinates[17] = interp_tc.xy + singleStepOffset * vec2(-4.0, 4.0);\n" +
+ "blurCoordinates[18] = interp_tc.xy + singleStepOffset * vec2(4.0, -4.0);\n" +
+ "blurCoordinates[19] = interp_tc.xy + singleStepOffset * vec2(4.0, 4.0);\n";
+ "// some code ...." 
+ "float sampleColor = centralColor.g * 20.0;\n"
+ "sampleColor += greenValue(blurCoordinates[0]);\n"
+ "sampleColor += greenValue(blurCoordinates[1]);\n"
+ "sampleColor += greenValue(blurCoordinates[2]);\n"
+ "sampleColor += greenValue(blurCoordinates[3]);\n"
+ "sampleColor += greenValue(blurCoordinates[4]);\n"
+ "sampleColor += greenValue(blurCoordinates[5]);\n"
+ "sampleColor += greenValue(blurCoordinates[6]);\n"
+ "sampleColor += greenValue(blurCoordinates[7]);\n"
+ "sampleColor += greenValue(blurCoordinates[8]);\n"
+ "sampleColor += greenValue(blurCoordinates[9]);\n"
+ "sampleColor += greenValue(blurCoordinates[10]);\n"
+ "sampleColor += greenValue(blurCoordinates[11]);\n"
+ "sampleColor += greenValue(blurCoordinates[12]) * 2.0;\n"
+ "sampleColor += greenValue(blurCoordinates[13]) * 2.0;\n"
+ "sampleColor += greenValue(blurCoordinates[14]) * 2.0;\n"
+ "sampleColor += greenValue(blurCoordinates[15]) * 2.0;\n"
+ "sampleColor += greenValue(blurCoordinates[16]) * 2.0;\n"
+ "sampleColor += greenValue(blurCoordinates[17]) * 2.0;\n"
+ "sampleColor += greenValue(blurCoordinates[18]) * 2.0;\n"
+ "sampleColor += greenValue(blurCoordinates[19]) * 2.0;\n";

有没有更好的解决方案来解决这个问题,或者有没有什么方法来优化这个着色器?

    • 更新**

1.如果帧分辨率为1280x720,则texture2D()调用次数= 1280x720x20x3 = 55,296,000(调用)/帧
1.如果我把(u_tex和v_tex)替换成y_tex(用于测试),它会非常快。所以,可能访问3个不同的纹理会造成瓶颈。

pftdvrlh

pftdvrlh1#

你在一个入门级的手机上每像素做60个纹理样本!是的,这会很慢。
不确定您使用的是哪种设备,但假设它是Mali-T830 MP1,那么您可以在每个时钟周期进行1次纹理采样。假设它的频率为550Mhz左右,为了便于讨论和计算,那么:

550M / 55M samples = 100ms / frame

...这是关于你所看到的。这个着色器对这个设备来说太复杂了。
翻转一下这个,你可以根据你想要实现的目标来设置预算。IidoEe.在60 fps

550M / 60 = 9.16M cycles/frame.
9.16M / (1280 * 720) = 9.95 samples per pixel.

对于YUV数据,请尝试直接从外部采样器中提取。为此,您可以直接从原始YUV数据中采样,包括颜色转换,在较新的设备上,这将比手动滚动自己的采样代码快得多,因为大多数GPU可以本机采样YUV(注意-但在Mali-T830上没有太大帮助)。
有没有更好的解决方案来解决这个问题,或者有没有什么方法来优化这个着色器?
学习使用分析器-帮助避免猜测工作。
有关Mali GPU,请参阅Arm Mobile Studio(https://developer.arm.com/mobile-studio)中的Streamline刻画器。
如果我只调用"sampleColor = greenValue(blurCoordinates [0]);\n "..."(非"样本颜色+=绿色值(blurCoordinates [0]);\n "...它会非常快。
是的,编译器会优化掉20个样本中的19个,所以你只做了5%的工作,所以你会期望它快20倍。
如果我用y_tex替换(u_tex和v_tex)(对于test),它会非常快。
这使得三个纹理操作相同,因此您移除3个纹理采样中的2个,编译器可以合并大量数学运算。

相关问题