SkPictureGpuAnalyzer
Stateful helper for gathering multi-picture GPU stats. Exposes the existing SkPicture GPU veto semantics, while preserving the SKP impl (which has some nice properties: lazy, hierarchical, cached per pic). R=reed@google.com,bsalomon@google.com GOLD_TRYBOT_URL= https://gold.skia.org/search2?unt=true&query=source_type%3Dgm&master=false&issue=1974833003 Review-Url: https://codereview.chromium.org/1974833003
This commit is contained in:
parent
b2df0c2702
commit
796e365999
@ -206,6 +206,7 @@
|
||||
'<(skia_src_path)/core/SkPathRef.cpp',
|
||||
'<(skia_src_path)/core/SkPerspIter.h',
|
||||
'<(skia_src_path)/core/SkPicture.cpp',
|
||||
'<(skia_src_path)/core/SkPictureAnalyzer.cpp',
|
||||
'<(skia_src_path)/core/SkPictureCommon.h',
|
||||
'<(skia_src_path)/core/SkPictureContentInfo.cpp',
|
||||
'<(skia_src_path)/core/SkPictureContentInfo.h',
|
||||
@ -385,6 +386,7 @@
|
||||
'<(skia_include_path)/core/SkPathMeasure.h',
|
||||
'<(skia_include_path)/core/SkPathRef.h',
|
||||
'<(skia_include_path)/core/SkPicture.h',
|
||||
'<(skia_include_path)/core/SkPictureAnalyzer.h',
|
||||
'<(skia_include_path)/core/SkPictureRecorder.h',
|
||||
'<(skia_include_path)/core/SkPixelRef.h',
|
||||
'<(skia_include_path)/core/SkPoint.h',
|
||||
|
@ -153,8 +153,10 @@ public:
|
||||
static bool InternalOnly_StreamIsSKP(SkStream*, SkPictInfo*);
|
||||
static bool InternalOnly_BufferIsSKP(SkReadBuffer*, SkPictInfo*);
|
||||
|
||||
#ifdef SK_SUPPORT_LEGACY_PICTURE_GPUVETO
|
||||
/** Return true if the picture is suitable for rendering on the GPU. */
|
||||
bool suitableForGpuRasterization(GrContext*, const char** whyNot = NULL) const;
|
||||
#endif
|
||||
|
||||
// Sent via SkMessageBus from destructor.
|
||||
struct DeletionMessage { int32_t fUniqueID; }; // TODO: -> uint32_t?
|
||||
@ -190,6 +192,7 @@ private:
|
||||
friend class SkPictureData;
|
||||
|
||||
virtual int numSlowPaths() const = 0;
|
||||
friend class SkPictureGpuAnalyzer;
|
||||
friend struct SkPathCounter;
|
||||
|
||||
// V35: Store SkRect (rather then width & height) in header
|
||||
|
52
include/core/SkPictureAnalyzer.h
Normal file
52
include/core/SkPictureAnalyzer.h
Normal file
@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright 2016 Google Inc.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#ifndef SkPictureAnalyzer_DEFINED
|
||||
#define SkPictureAnalyzer_DEFINED
|
||||
|
||||
#include "SkRefCnt.h"
|
||||
#include "SkTypes.h"
|
||||
|
||||
#if SK_SUPPORT_GPU
|
||||
#include "GrContext.h"
|
||||
|
||||
class SkPicture;
|
||||
|
||||
/** \class SkPictureGpuAnalyzer
|
||||
|
||||
Gathers GPU-related statistics for one or more SkPictures.
|
||||
*/
|
||||
class SK_API SkPictureGpuAnalyzer final : public SkNoncopyable {
|
||||
public:
|
||||
explicit SkPictureGpuAnalyzer(sk_sp<GrContextThreadSafeProxy> = nullptr);
|
||||
explicit SkPictureGpuAnalyzer(const sk_sp<SkPicture>& picture,
|
||||
sk_sp<GrContextThreadSafeProxy> = nullptr);
|
||||
|
||||
/**
|
||||
* Process the given picture and accumulate its stats.
|
||||
*/
|
||||
void analyze(const SkPicture*);
|
||||
|
||||
/**
|
||||
* Reset all accumulated stats.
|
||||
*/
|
||||
void reset();
|
||||
|
||||
/**
|
||||
* Returns true if the analyzed pictures are suitable for rendering on the GPU.
|
||||
*/
|
||||
bool suitableForGpuRasterization(const char** whyNot = nullptr) const;
|
||||
|
||||
private:
|
||||
uint32_t fNumSlowPaths;
|
||||
|
||||
typedef SkNoncopyable INHERITED;
|
||||
};
|
||||
|
||||
#endif // SK_SUPPORT_GPU
|
||||
|
||||
#endif // SkPictureAnalyzer_DEFINED
|
@ -219,6 +219,7 @@ void SkPicture::flatten(SkWriteBuffer& buffer) const {
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef SK_SUPPORT_LEGACY_PICTURE_GPUVETO
|
||||
bool SkPicture::suitableForGpuRasterization(GrContext*, const char** whyNot) const {
|
||||
if (this->numSlowPaths() > 5) {
|
||||
if (whyNot) { *whyNot = "Too many slow paths (either concave or dashed)."; }
|
||||
@ -226,6 +227,7 @@ bool SkPicture::suitableForGpuRasterization(GrContext*, const char** whyNot) con
|
||||
}
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Global setting to disable security precautions for serialization.
|
||||
void SkPicture::SetPictureIOSecurityPrecautionsEnabled_Dangerous(bool set) {
|
||||
|
50
src/core/SkPictureAnalyzer.cpp
Normal file
50
src/core/SkPictureAnalyzer.cpp
Normal file
@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright 2016 Google Inc.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include "SkPicture.h"
|
||||
#include "SkPictureAnalyzer.h"
|
||||
|
||||
#if SK_SUPPORT_GPU
|
||||
|
||||
namespace {
|
||||
|
||||
inline bool veto_predicate(uint32_t numSlowPaths) {
|
||||
return numSlowPaths > 5;
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
SkPictureGpuAnalyzer::SkPictureGpuAnalyzer(sk_sp<GrContextThreadSafeProxy> /* unused ATM */)
|
||||
: fNumSlowPaths(0) { }
|
||||
|
||||
SkPictureGpuAnalyzer::SkPictureGpuAnalyzer(const sk_sp<SkPicture>& picture,
|
||||
sk_sp<GrContextThreadSafeProxy> ctx)
|
||||
: SkPictureGpuAnalyzer(std::move(ctx)) {
|
||||
this->analyze(picture.get());
|
||||
}
|
||||
|
||||
void SkPictureGpuAnalyzer::analyze(const SkPicture* picture) {
|
||||
if (!picture || veto_predicate(fNumSlowPaths)) {
|
||||
return;
|
||||
}
|
||||
|
||||
fNumSlowPaths += picture->numSlowPaths();
|
||||
}
|
||||
|
||||
void SkPictureGpuAnalyzer::reset() {
|
||||
fNumSlowPaths = 0;
|
||||
}
|
||||
|
||||
bool SkPictureGpuAnalyzer::suitableForGpuRasterization(const char** whyNot) const {
|
||||
if(veto_predicate(fNumSlowPaths)) {
|
||||
if (whyNot) { *whyNot = "Too many slow paths (either concave or dashed)."; }
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif // SK_SUPPORT_GPU
|
@ -20,6 +20,7 @@
|
||||
#include "SkMD5.h"
|
||||
#include "SkPaint.h"
|
||||
#include "SkPicture.h"
|
||||
#include "SkPictureAnalyzer.h"
|
||||
#include "SkPictureRecorder.h"
|
||||
#include "SkPictureUtils.h"
|
||||
#include "SkPixelRef.h"
|
||||
@ -158,7 +159,8 @@ static void test_gpu_veto(skiatest::Reporter* reporter) {
|
||||
// path effects currently render an SkPicture undesireable for GPU rendering
|
||||
|
||||
const char *reason = nullptr;
|
||||
REPORTER_ASSERT(reporter, !picture->suitableForGpuRasterization(nullptr, &reason));
|
||||
REPORTER_ASSERT(reporter,
|
||||
!SkPictureGpuAnalyzer(picture).suitableForGpuRasterization(&reason));
|
||||
REPORTER_ASSERT(reporter, reason);
|
||||
|
||||
canvas = recorder.beginRecording(100, 100);
|
||||
@ -181,7 +183,7 @@ static void test_gpu_veto(skiatest::Reporter* reporter) {
|
||||
}
|
||||
picture = recorder.finishRecordingAsPicture();
|
||||
// A lot of small AA concave paths should be fine for GPU rendering
|
||||
REPORTER_ASSERT(reporter, picture->suitableForGpuRasterization(nullptr));
|
||||
REPORTER_ASSERT(reporter, SkPictureGpuAnalyzer(picture).suitableForGpuRasterization());
|
||||
|
||||
canvas = recorder.beginRecording(100, 100);
|
||||
{
|
||||
@ -203,7 +205,7 @@ static void test_gpu_veto(skiatest::Reporter* reporter) {
|
||||
}
|
||||
picture = recorder.finishRecordingAsPicture();
|
||||
// A lot of large AA concave paths currently render an SkPicture undesireable for GPU rendering
|
||||
REPORTER_ASSERT(reporter, !picture->suitableForGpuRasterization(nullptr));
|
||||
REPORTER_ASSERT(reporter, !SkPictureGpuAnalyzer(picture).suitableForGpuRasterization());
|
||||
|
||||
canvas = recorder.beginRecording(100, 100);
|
||||
{
|
||||
@ -227,7 +229,7 @@ static void test_gpu_veto(skiatest::Reporter* reporter) {
|
||||
}
|
||||
picture = recorder.finishRecordingAsPicture();
|
||||
// hairline stroked AA concave paths are fine for GPU rendering
|
||||
REPORTER_ASSERT(reporter, picture->suitableForGpuRasterization(nullptr));
|
||||
REPORTER_ASSERT(reporter, SkPictureGpuAnalyzer(picture).suitableForGpuRasterization());
|
||||
|
||||
canvas = recorder.beginRecording(100, 100);
|
||||
{
|
||||
@ -243,7 +245,7 @@ static void test_gpu_veto(skiatest::Reporter* reporter) {
|
||||
}
|
||||
picture = recorder.finishRecordingAsPicture();
|
||||
// fast-path dashed effects are fine for GPU rendering ...
|
||||
REPORTER_ASSERT(reporter, picture->suitableForGpuRasterization(nullptr));
|
||||
REPORTER_ASSERT(reporter, SkPictureGpuAnalyzer(picture).suitableForGpuRasterization());
|
||||
|
||||
canvas = recorder.beginRecording(100, 100);
|
||||
{
|
||||
@ -257,18 +259,18 @@ static void test_gpu_veto(skiatest::Reporter* reporter) {
|
||||
}
|
||||
picture = recorder.finishRecordingAsPicture();
|
||||
// ... but only when applied to drawPoint() calls
|
||||
REPORTER_ASSERT(reporter, !picture->suitableForGpuRasterization(nullptr));
|
||||
REPORTER_ASSERT(reporter, !SkPictureGpuAnalyzer(picture).suitableForGpuRasterization());
|
||||
|
||||
// Nest the previous picture inside a new one.
|
||||
canvas = recorder.beginRecording(100, 100);
|
||||
{
|
||||
canvas->drawPicture(picture.get());
|
||||
canvas->drawPicture(picture);
|
||||
}
|
||||
picture = recorder.finishRecordingAsPicture();
|
||||
REPORTER_ASSERT(reporter, !picture->suitableForGpuRasterization(nullptr));
|
||||
REPORTER_ASSERT(reporter, !SkPictureGpuAnalyzer(picture).suitableForGpuRasterization());
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif // SK_SUPPORT_GPU
|
||||
|
||||
static void test_savelayer_extraction(skiatest::Reporter* reporter) {
|
||||
static const int kWidth = 100;
|
||||
@ -1346,3 +1348,38 @@ DEF_TEST(Picture_preserveCullRect, r) {
|
||||
REPORTER_ASSERT(r, deserializedPicture->cullRect().right() == 3);
|
||||
REPORTER_ASSERT(r, deserializedPicture->cullRect().bottom() == 4);
|
||||
}
|
||||
|
||||
#if SK_SUPPORT_GPU
|
||||
|
||||
DEF_TEST(PictureGpuAnalyzer, r) {
|
||||
SkPictureRecorder recorder;
|
||||
|
||||
{
|
||||
SkCanvas* canvas = recorder.beginRecording(10, 10);
|
||||
SkPaint paint;
|
||||
SkScalar intervals [] = { 10, 20 };
|
||||
paint.setPathEffect(SkDashPathEffect::Make(intervals, 2, 25));
|
||||
|
||||
for (int i = 0; i < 50; ++i) {
|
||||
canvas->drawRect(SkRect::MakeWH(10, 10), paint);
|
||||
}
|
||||
}
|
||||
sk_sp<SkPicture> vetoPicture(recorder.finishRecordingAsPicture());
|
||||
|
||||
SkPictureGpuAnalyzer analyzer;
|
||||
REPORTER_ASSERT(r, analyzer.suitableForGpuRasterization());
|
||||
|
||||
analyzer.analyze(vetoPicture.get());
|
||||
REPORTER_ASSERT(r, !analyzer.suitableForGpuRasterization());
|
||||
|
||||
analyzer.reset();
|
||||
REPORTER_ASSERT(r, analyzer.suitableForGpuRasterization());
|
||||
|
||||
recorder.beginRecording(10, 10)->drawPicture(vetoPicture);
|
||||
sk_sp<SkPicture> nestedVetoPicture(recorder.finishRecordingAsPicture());
|
||||
|
||||
analyzer.analyze(nestedVetoPicture.get());
|
||||
REPORTER_ASSERT(r, !analyzer.suitableForGpuRasterization());
|
||||
}
|
||||
|
||||
#endif // SK_SUPPORT_GPU
|
||||
|
@ -7,6 +7,7 @@
|
||||
|
||||
#include "SkCommandLineFlags.h"
|
||||
#include "SkPicture.h"
|
||||
#include "SkPictureAnalyzer.h"
|
||||
#include "SkPictureRecorder.h"
|
||||
#include "SkStream.h"
|
||||
|
||||
@ -57,7 +58,7 @@ int tool_main(int argc, char** argv) {
|
||||
nullptr, 0));
|
||||
sk_sp<SkPicture> recorded(recorder.finishRecordingAsPicture());
|
||||
|
||||
if (recorded->suitableForGpuRasterization(nullptr)) {
|
||||
if (SkPictureGpuAnalyzer(recorded).suitableForGpuRasterization(nullptr)) {
|
||||
SkDebugf("suitable\n");
|
||||
} else {
|
||||
SkDebugf("unsuitable\n");
|
||||
|
Loading…
Reference in New Issue
Block a user