Thanks for the suggestion. By debugging in that way I realised that
JNI overhead is actually not much significant. Rather the code I am executing to apply effects on each frame is taking major time. It's just that the CPU was not able to capture the execution time for functions running on GPU correctly. Adding a flush() command before taking the timestamp on such functions exposed the actual execution time.
But as per my latest observation few Skia library functions are taking unexpectedly high time.
When I am applying Edge feather on a 1920x1080 video at 30 fps. I have written a custom shader in SKSL. The call to CPP layer is coming from Android (through JNI).
1. The time taken to execute GrGLMakeNativeInterface() to get the GL interface is ~3.5 ms for each frame. This is used to get GrDirectContext and then finally create the SkSurface object and the corresponding canvas.
2. Time taken to execute the function responsible for applying edge feather takes ~12 ms. I feel this is way too high for any video editing application. It degrades the performance severely. For more clarity I am putting the code snippet for only edge feather.
Except for the first two lines inside the function, the rest of the code takes ~12 ms. I was initially doubting makeImageSnapshot(). But that is not at al costly. It's the code following that which is taking time.
void doEdgeFeather(SkCanvas* canvas, int featherVal){
SkSurface* surface = canvas->getSurface();
sk_sp<SkImage> image = surface->makeImageSnapshot();
//Using the API to apply effect
const char* sksl = R"(
uniform shader child;
uniform float imHeight;
uniform float imWidth;
uniform float pixWidth;
float max(float a, float b){
return (a>b)?a:b;
}
half4 main(float2 xy) {
float dist;
half4 color = sample(child);
dist = max(max(max(pixWidth-xy.x, xy.x-(imWidth - pixWidth)), pixWidth-xy.y), xy.y-(imHeight - pixWidth));
if(dist>0){
color.a *= (1-dist/pixWidth);
}
return color;
}
)";
SkPaint paint, p2;
sk_sp<SkRuntimeEffect> effect = std::get<0>(SkRuntimeEffect::Make(SkString(sksl)));
sk_sp<SkShader> shader = image->makeShader(SkSamplingOptions());
SkRuntimeShaderBuilder builder(effect);
builder.child("child") = shader;
builder.uniform("imHeight") = float(image->height());
builder.uniform("imWidth") = float(image->width());
builder.uniform("pixWidth") = float(featherVal);
shader = builder.makeShader(nullptr, false);
paint.setShader(shader);
canvas->clear(SK_ColorBLACK);
canvas->drawRect(SkRect::MakeWH(image->width(),image->height()), paint);
canvas->flush();
}
I mainly need suggestion on what should be changed if this is an inefficient way of applying shaders. Then probably I can make performance improvement for all such custom shaders. Edge feather is merely an example of that kind.
Thanks in advance for your help.