From 2e4dc863da042f272705bcebec6805fe4f9cd89b Mon Sep 17 00:00:00 2001 From: Florin Malita Date: Thu, 9 Sep 2021 10:35:33 -0400 Subject: [PATCH] Fix skottie2movie gpu async crash We need to ensure all async reads are completed before we finish encoding -- otherwise late reads will fire from the GrContext destructor and crash because the encoder is no longer valid. Change-Id: I0065561d2411ddd202897e625a187592e40ced87 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/447184 Commit-Queue: Florin Malita Reviewed-by: Brian Salomon --- tools/skottie2movie.cpp | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/tools/skottie2movie.cpp b/tools/skottie2movie.cpp index e4effef98e..5081fd48da 100644 --- a/tools/skottie2movie.cpp +++ b/tools/skottie2movie.cpp @@ -93,7 +93,7 @@ int main(int argc, char** argv) { SkVideoEncoder encoder; - GrDirectContext* context = nullptr; + GrDirectContext* grctx = nullptr; sk_sp surf; sk_sp data; @@ -109,15 +109,15 @@ int main(int argc, char** argv) { // lazily allocate the surfaces if (!surf) { if (FLAGS_gpu) { - context = factory.getContextInfo(contextType).directContext(); - surf = SkSurface::MakeRenderTarget(context, + grctx = factory.getContextInfo(contextType).directContext(); + surf = SkSurface::MakeRenderTarget(grctx, SkBudgeted::kNo, info, 0, GrSurfaceOrigin::kTopLeft_GrSurfaceOrigin, nullptr); if (!surf) { - context = nullptr; + grctx = nullptr; } } if (!surf) { @@ -135,7 +135,7 @@ int main(int argc, char** argv) { produce_frame(surf.get(), animation.get(), frame); AsyncRec asyncRec = { info, &encoder }; - if (context) { + if (grctx) { auto read_pixels_cb = [](SkSurface::ReadPixelsContext ctx, std::unique_ptr result) { if (result && result->count() == 1) { @@ -147,13 +147,18 @@ int main(int argc, char** argv) { SkSurface::RescaleGamma::kSrc, SkImage::RescaleMode::kNearest, read_pixels_cb, &asyncRec); - context->submit(); + grctx->submit(); } else { SkPixmap pm; SkAssertResult(surf->peekPixels(&pm)); encoder.addFrame(pm); } } + + if (grctx) { + // ensure all pending reads are completed + grctx->flushAndSubmit(true); + } data = encoder.endRecording(); if (FLAGS_loop) {