我有一个Android应用程序,可以拍照,模糊,
输出get绘制在画布(SurfaceView)上。这样,应用程序可以有效地创建带有动画模糊效果的图像视图。
所有这些图像处理步骤都是通过 RenderScript 实现的。
我将省略步骤1的代码,使图片模糊,因为这与我面临的问题无关。
我有一个自定义内核,该内核接受 Inlocation 作为参数,并保存了 2个全局变量,也就是Allocations 。>
这3个分配都使用 Allocation.copyFrom(bitmap)从位图获取数据。
这里我也有一个自定义内核,该内核以 Inlocation 作为参数并保存了 3个全局变量,其中1个是分配和2是浮动。
这些内核的工作方式与这个问题无关,只是为了确保在下面包含一些简化的片段。
要注意的另一件事是,我将遵循所有最佳做法,以确保有关分配,RenderScript和SurfaceView的性能达到最佳状态。
因此可以忽略常见的错误,例如每次创建一个新的RenderScript实例,在可能的情况下不重新使用Allocations。
blurMask.rs
#pragma version(1)
#pragma rs java_package_name(com.example.rs)
#pragma rs_fp_relaxed
// Extra allocations
rs_allocation allocBlur;
rs_allocation allocBlurMask;
/*
* RenderScript kernel that performs a masked blur manipulation.
* Blur Pseudo: out = original * blurMask + blur * (1.0 - blurMask)
* -> Execute this for all channels
*/
uchar4 __attribute__((kernel)) blur_mask(uchar4 inOriginal, uint32_t x, uint32_t y) {
// Manually getting current element from the blur and mask allocations
uchar4 inBlur = rsGetElementAt_uchar4(allocBlur, x, y);
uchar4 inBlurMask = rsGetElementAt_uchar4(allocBlurMask, x, y);
// normalize to 0.0 -> 1.0
float4 inOriginalNorm = rsUnpackColor8888(inOriginal);
float4 inBlurNorm = rsUnpackColor8888(inBlur);
float4 inBlurMaskNorm = rsUnpackColor8888(inBlurMask);
inBlurNorm.rgb = inBlurNorm.rgb * 0.7 + 0.3;
float4 outNorm = inOriginalNorm;
outNorm.rgb = inOriginalNorm.rgb * inBlurMaskNorm.rgb + inBlurNorm.rgb * (1.0 - inBlurMaskNorm.rgb);
return rsPackColorTo8888(outNorm);
}
myKernel.rs
#pragma version(1)
#pragma rs java_package_name(com.example.rs)
#pragma rs_fp_relaxed
// Extra allocations
rs_allocation allocExtra;
// Randoms; Values are set from kotlin, the values below just act as a min placeholder.
float randB = 0.1f;
float randW = 0.75f;
/*
* RenderScript kernel that performs a manipulation.
*/
uchar4 __attribute__((kernel)) my_kernel(uchar4 inOriginal, uint32_t x, uint32_t y) {
// Manually getting current element from the extra allocation
uchar4 inExtra = rsGetElementAt_uchar4(allocExtra, x, y);
// normalize to 0.0 -> 1.0
float4 inOriginalNorm = rsUnpackColor8888(inOriginal);
float4 inExtraNorm = rsUnpackColor8888(inExtra);
float4 outNorm = inOriginalNorm;
if (inExtraNorm.r > 0.0) {
outNorm.rgb = inOriginalNorm.rgb * 0.7 + 0.3;
// Separate channel operation since we are using inExtraNorm.r everywhere
outNorm.r = outNorm.r * inExtraNorm.r + inOriginalNorm.r * (1.0 - inExtraNorm.r);
outNorm.g = outNorm.g * inExtraNorm.r + inOriginalNorm.g * (1.0 - inExtraNorm.r);
outNorm.b = outNorm.b * inExtraNorm.r + inOriginalNorm.b * (1.0 - inExtraNorm.r);
}
else if (inExtraNorm.g > 0.0) {
...
}
return rsPackColorTo8888(outNorm);
}
因此,该应用程序在各种设备上都可以很好地运行,即使在低端设备上也是如此。我手动将FPS的上限设置为15,但是移除此上限后,结果范围从低端设备上的15-20到高端设备上的35-40。
出现问题的原因是 Samsung Galaxy S8 。由于某种原因,我只能设法达到10 FPS。如果我使用 adb 强制RenderScript改为使用CPU:
adb shell setprop debug.rs.default-CPU-driver 1
我得到约12-15 FPS,但显然我希望它在GPU上运行。
如果我触发触摸事件,则无论在何处(甚至不在应用程序外),性能都会显着提高到35-40 FPS。如果我再次从屏幕上抬起手指,FPS会降回10 FPS。
注意:可以排除在SurfaceView上绘制结果作为影响因素,因为结果与RenderScript中的计算相同,而没有绘制实际结果。
所以我确实有多个问题: