xref: /aosp_15_r20/external/skia/fuzz/FuzzPrecompile.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1*c8dee2aaSAndroid Build Coastguard Worker /*
2*c8dee2aaSAndroid Build Coastguard Worker  * Copyright 2023 Google LLC
3*c8dee2aaSAndroid Build Coastguard Worker  *
4*c8dee2aaSAndroid Build Coastguard Worker  * Use of this source code is governed by a BSD-style license that can be
5*c8dee2aaSAndroid Build Coastguard Worker  * found in the LICENSE file.
6*c8dee2aaSAndroid Build Coastguard Worker  */
7*c8dee2aaSAndroid Build Coastguard Worker 
8*c8dee2aaSAndroid Build Coastguard Worker #include "fuzz/Fuzz.h"
9*c8dee2aaSAndroid Build Coastguard Worker 
10*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkCanvas.h"
11*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkColorFilter.h"
12*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkColorSpace.h"
13*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkFont.h"
14*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkImageInfo.h"
15*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkPaint.h"
16*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkPathBuilder.h"
17*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkRefCnt.h"
18*c8dee2aaSAndroid Build Coastguard Worker #include "include/effects/SkColorMatrix.h"
19*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/graphite/Context.h"
20*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/graphite/PrecompileContext.h"
21*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/graphite/Surface.h"
22*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/graphite/precompile/Precompile.h"
23*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/graphite/precompile/PrecompileColorFilter.h"
24*c8dee2aaSAndroid Build Coastguard Worker #include "modules/skcms/skcms.h"
25*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkBlenderBase.h"
26*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/ContextPriv.h"
27*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/ContextUtils.h"
28*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/KeyContext.h"
29*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/PaintParams.h"
30*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/PaintParamsKey.h"
31*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/PipelineData.h"
32*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/RecorderPriv.h"
33*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/RenderPassDesc.h"
34*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/Renderer.h"
35*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/RuntimeEffectDictionary.h"
36*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/geom/Geometry.h"
37*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/precompile/PaintOptionsPriv.h"
38*c8dee2aaSAndroid Build Coastguard Worker #include "tools/gpu/GrContextFactory.h"
39*c8dee2aaSAndroid Build Coastguard Worker #include "tools/graphite/ContextFactory.h"
40*c8dee2aaSAndroid Build Coastguard Worker 
41*c8dee2aaSAndroid Build Coastguard Worker using namespace skgpu::graphite;
42*c8dee2aaSAndroid Build Coastguard Worker 
43*c8dee2aaSAndroid Build Coastguard Worker namespace {
44*c8dee2aaSAndroid Build Coastguard Worker 
random_blend_mode(Fuzz * fuzz)45*c8dee2aaSAndroid Build Coastguard Worker SkBlendMode random_blend_mode(Fuzz* fuzz) {
46*c8dee2aaSAndroid Build Coastguard Worker     uint32_t temp;
47*c8dee2aaSAndroid Build Coastguard Worker     fuzz->next(&temp);
48*c8dee2aaSAndroid Build Coastguard Worker     return (SkBlendMode) (temp % kSkBlendModeCount);
49*c8dee2aaSAndroid Build Coastguard Worker }
50*c8dee2aaSAndroid Build Coastguard Worker 
random_opaque_skcolor(Fuzz * fuzz)51*c8dee2aaSAndroid Build Coastguard Worker SkColor random_opaque_skcolor(Fuzz* fuzz) {
52*c8dee2aaSAndroid Build Coastguard Worker     SkColor color;
53*c8dee2aaSAndroid Build Coastguard Worker     fuzz->next(&color);
54*c8dee2aaSAndroid Build Coastguard Worker     return 0xff000000 | color;
55*c8dee2aaSAndroid Build Coastguard Worker }
56*c8dee2aaSAndroid Build Coastguard Worker 
random_color4f(Fuzz * fuzz)57*c8dee2aaSAndroid Build Coastguard Worker SkColor4f random_color4f(Fuzz* fuzz) {
58*c8dee2aaSAndroid Build Coastguard Worker     bool makeOpaque;
59*c8dee2aaSAndroid Build Coastguard Worker     fuzz->next(&makeOpaque);
60*c8dee2aaSAndroid Build Coastguard Worker 
61*c8dee2aaSAndroid Build Coastguard Worker     SkColor4f color;
62*c8dee2aaSAndroid Build Coastguard Worker     fuzz->nextRange(&color.fR, 0, 1);
63*c8dee2aaSAndroid Build Coastguard Worker     fuzz->nextRange(&color.fG, 0, 1);
64*c8dee2aaSAndroid Build Coastguard Worker     fuzz->nextRange(&color.fB, 0, 1);
65*c8dee2aaSAndroid Build Coastguard Worker     if (makeOpaque) {
66*c8dee2aaSAndroid Build Coastguard Worker         color.fA = 1.0;
67*c8dee2aaSAndroid Build Coastguard Worker     } else {
68*c8dee2aaSAndroid Build Coastguard Worker         fuzz->nextRange(&color.fA, 0, 1);
69*c8dee2aaSAndroid Build Coastguard Worker     }
70*c8dee2aaSAndroid Build Coastguard Worker 
71*c8dee2aaSAndroid Build Coastguard Worker     return color;
72*c8dee2aaSAndroid Build Coastguard Worker }
73*c8dee2aaSAndroid Build Coastguard Worker 
make_path()74*c8dee2aaSAndroid Build Coastguard Worker SkPath make_path() {
75*c8dee2aaSAndroid Build Coastguard Worker     SkPathBuilder path;
76*c8dee2aaSAndroid Build Coastguard Worker     path.moveTo(0, 0);
77*c8dee2aaSAndroid Build Coastguard Worker     path.lineTo(8, 2);
78*c8dee2aaSAndroid Build Coastguard Worker     path.lineTo(16, 0);
79*c8dee2aaSAndroid Build Coastguard Worker     path.lineTo(14, 8);
80*c8dee2aaSAndroid Build Coastguard Worker     path.lineTo(16, 16);
81*c8dee2aaSAndroid Build Coastguard Worker     path.lineTo(8, 14);
82*c8dee2aaSAndroid Build Coastguard Worker     path.lineTo(0, 16);
83*c8dee2aaSAndroid Build Coastguard Worker     path.lineTo(2, 8);
84*c8dee2aaSAndroid Build Coastguard Worker     path.close();
85*c8dee2aaSAndroid Build Coastguard Worker     return path.detach();
86*c8dee2aaSAndroid Build Coastguard Worker }
87*c8dee2aaSAndroid Build Coastguard Worker 
88*c8dee2aaSAndroid Build Coastguard Worker //--------------------------------------------------------------------------------------------------
89*c8dee2aaSAndroid Build Coastguard Worker // color spaces
90*c8dee2aaSAndroid Build Coastguard Worker 
random_transfer_function(Fuzz * fuzz)91*c8dee2aaSAndroid Build Coastguard Worker const skcms_TransferFunction& random_transfer_function(Fuzz* fuzz) {
92*c8dee2aaSAndroid Build Coastguard Worker     static constexpr skcms_TransferFunction gTransferFunctions[] = {
93*c8dee2aaSAndroid Build Coastguard Worker             SkNamedTransferFn::kSRGB,
94*c8dee2aaSAndroid Build Coastguard Worker             SkNamedTransferFn::k2Dot2,
95*c8dee2aaSAndroid Build Coastguard Worker             SkNamedTransferFn::kLinear,
96*c8dee2aaSAndroid Build Coastguard Worker             SkNamedTransferFn::kRec2020,
97*c8dee2aaSAndroid Build Coastguard Worker             SkNamedTransferFn::kPQ,
98*c8dee2aaSAndroid Build Coastguard Worker             SkNamedTransferFn::kHLG,
99*c8dee2aaSAndroid Build Coastguard Worker     };
100*c8dee2aaSAndroid Build Coastguard Worker 
101*c8dee2aaSAndroid Build Coastguard Worker     uint32_t xferFunction;
102*c8dee2aaSAndroid Build Coastguard Worker     fuzz->next(&xferFunction);
103*c8dee2aaSAndroid Build Coastguard Worker     xferFunction %= std::size(gTransferFunctions);
104*c8dee2aaSAndroid Build Coastguard Worker     return gTransferFunctions[xferFunction];
105*c8dee2aaSAndroid Build Coastguard Worker }
106*c8dee2aaSAndroid Build Coastguard Worker 
random_gamut(Fuzz * fuzz)107*c8dee2aaSAndroid Build Coastguard Worker const skcms_Matrix3x3& random_gamut(Fuzz* fuzz) {
108*c8dee2aaSAndroid Build Coastguard Worker     static constexpr skcms_Matrix3x3 gGamuts[] = {
109*c8dee2aaSAndroid Build Coastguard Worker             SkNamedGamut::kSRGB,
110*c8dee2aaSAndroid Build Coastguard Worker             SkNamedGamut::kAdobeRGB,
111*c8dee2aaSAndroid Build Coastguard Worker             SkNamedGamut::kDisplayP3,
112*c8dee2aaSAndroid Build Coastguard Worker             SkNamedGamut::kRec2020,
113*c8dee2aaSAndroid Build Coastguard Worker             SkNamedGamut::kXYZ,
114*c8dee2aaSAndroid Build Coastguard Worker     };
115*c8dee2aaSAndroid Build Coastguard Worker 
116*c8dee2aaSAndroid Build Coastguard Worker     uint32_t gamut;
117*c8dee2aaSAndroid Build Coastguard Worker     fuzz->next(&gamut);
118*c8dee2aaSAndroid Build Coastguard Worker     gamut %= std::size(gGamuts);
119*c8dee2aaSAndroid Build Coastguard Worker     return gGamuts[gamut];
120*c8dee2aaSAndroid Build Coastguard Worker }
121*c8dee2aaSAndroid Build Coastguard Worker 
122*c8dee2aaSAndroid Build Coastguard Worker enum class ColorSpaceType {
123*c8dee2aaSAndroid Build Coastguard Worker     kNone,
124*c8dee2aaSAndroid Build Coastguard Worker     kSRGB,
125*c8dee2aaSAndroid Build Coastguard Worker     kSRGBLinear,
126*c8dee2aaSAndroid Build Coastguard Worker     kRGB,
127*c8dee2aaSAndroid Build Coastguard Worker 
128*c8dee2aaSAndroid Build Coastguard Worker     kLast = kRGB
129*c8dee2aaSAndroid Build Coastguard Worker };
130*c8dee2aaSAndroid Build Coastguard Worker 
131*c8dee2aaSAndroid Build Coastguard Worker static constexpr int kColorSpaceTypeCount = static_cast<int>(ColorSpaceType::kLast) + 1;
132*c8dee2aaSAndroid Build Coastguard Worker 
create_colorspace(Fuzz * fuzz,ColorSpaceType csType)133*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkColorSpace> create_colorspace(Fuzz* fuzz, ColorSpaceType csType) {
134*c8dee2aaSAndroid Build Coastguard Worker     switch (csType) {
135*c8dee2aaSAndroid Build Coastguard Worker         case ColorSpaceType::kNone:
136*c8dee2aaSAndroid Build Coastguard Worker             return nullptr;
137*c8dee2aaSAndroid Build Coastguard Worker         case ColorSpaceType::kSRGB:
138*c8dee2aaSAndroid Build Coastguard Worker             return SkColorSpace::MakeSRGB();
139*c8dee2aaSAndroid Build Coastguard Worker         case ColorSpaceType::kSRGBLinear:
140*c8dee2aaSAndroid Build Coastguard Worker             return SkColorSpace::MakeSRGBLinear();
141*c8dee2aaSAndroid Build Coastguard Worker         case ColorSpaceType::kRGB:
142*c8dee2aaSAndroid Build Coastguard Worker             return SkColorSpace::MakeRGB(random_transfer_function(fuzz), random_gamut(fuzz));
143*c8dee2aaSAndroid Build Coastguard Worker     }
144*c8dee2aaSAndroid Build Coastguard Worker 
145*c8dee2aaSAndroid Build Coastguard Worker     SkUNREACHABLE;
146*c8dee2aaSAndroid Build Coastguard Worker }
147*c8dee2aaSAndroid Build Coastguard Worker 
create_random_colorspace(Fuzz * fuzz)148*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkColorSpace> create_random_colorspace(Fuzz* fuzz) {
149*c8dee2aaSAndroid Build Coastguard Worker     uint32_t temp;
150*c8dee2aaSAndroid Build Coastguard Worker     fuzz->next(&temp);
151*c8dee2aaSAndroid Build Coastguard Worker     ColorSpaceType csType = (ColorSpaceType) (temp % kColorSpaceTypeCount);
152*c8dee2aaSAndroid Build Coastguard Worker 
153*c8dee2aaSAndroid Build Coastguard Worker     return create_colorspace(fuzz, csType);
154*c8dee2aaSAndroid Build Coastguard Worker }
155*c8dee2aaSAndroid Build Coastguard Worker 
156*c8dee2aaSAndroid Build Coastguard Worker //--------------------------------------------------------------------------------------------------
157*c8dee2aaSAndroid Build Coastguard Worker // color filters
158*c8dee2aaSAndroid Build Coastguard Worker 
159*c8dee2aaSAndroid Build Coastguard Worker enum class ColorFilterType {
160*c8dee2aaSAndroid Build Coastguard Worker     kNone,
161*c8dee2aaSAndroid Build Coastguard Worker     kBlend,
162*c8dee2aaSAndroid Build Coastguard Worker     kMatrix,
163*c8dee2aaSAndroid Build Coastguard Worker     kHSLAMatrix,
164*c8dee2aaSAndroid Build Coastguard Worker     // TODO: add more color filters
165*c8dee2aaSAndroid Build Coastguard Worker 
166*c8dee2aaSAndroid Build Coastguard Worker     kLast = kHSLAMatrix
167*c8dee2aaSAndroid Build Coastguard Worker };
168*c8dee2aaSAndroid Build Coastguard Worker 
169*c8dee2aaSAndroid Build Coastguard Worker static constexpr int kColorFilterTypeCount = static_cast<int>(ColorFilterType::kLast) + 1;
170*c8dee2aaSAndroid Build Coastguard Worker 
create_blend_colorfilter(Fuzz * fuzz)171*c8dee2aaSAndroid Build Coastguard Worker std::pair<sk_sp<SkColorFilter>, sk_sp<PrecompileColorFilter>> create_blend_colorfilter(
172*c8dee2aaSAndroid Build Coastguard Worker         Fuzz* fuzz) {
173*c8dee2aaSAndroid Build Coastguard Worker 
174*c8dee2aaSAndroid Build Coastguard Worker     sk_sp<SkColorFilter> cf;
175*c8dee2aaSAndroid Build Coastguard Worker 
176*c8dee2aaSAndroid Build Coastguard Worker     // SkColorFilters::Blend is clever and can weed out noop color filters. Loop until we get
177*c8dee2aaSAndroid Build Coastguard Worker     // a valid color filter.
178*c8dee2aaSAndroid Build Coastguard Worker     while (!cf && !fuzz->exhausted()) {
179*c8dee2aaSAndroid Build Coastguard Worker         cf = SkColorFilters::Blend(random_color4f(fuzz),
180*c8dee2aaSAndroid Build Coastguard Worker                                    create_random_colorspace(fuzz),
181*c8dee2aaSAndroid Build Coastguard Worker                                    random_blend_mode(fuzz));
182*c8dee2aaSAndroid Build Coastguard Worker     }
183*c8dee2aaSAndroid Build Coastguard Worker 
184*c8dee2aaSAndroid Build Coastguard Worker     sk_sp<PrecompileColorFilter> o = cf ? PrecompileColorFilters::Blend() : nullptr;
185*c8dee2aaSAndroid Build Coastguard Worker 
186*c8dee2aaSAndroid Build Coastguard Worker     return { cf, o };
187*c8dee2aaSAndroid Build Coastguard Worker }
188*c8dee2aaSAndroid Build Coastguard Worker 
create_matrix_colorfilter()189*c8dee2aaSAndroid Build Coastguard Worker std::pair<sk_sp<SkColorFilter>, sk_sp<PrecompileColorFilter>> create_matrix_colorfilter() {
190*c8dee2aaSAndroid Build Coastguard Worker     sk_sp<SkColorFilter> cf = SkColorFilters::Matrix(
191*c8dee2aaSAndroid Build Coastguard Worker             SkColorMatrix::RGBtoYUV(SkYUVColorSpace::kJPEG_Full_SkYUVColorSpace));
192*c8dee2aaSAndroid Build Coastguard Worker     sk_sp<PrecompileColorFilter> o = PrecompileColorFilters::Matrix();
193*c8dee2aaSAndroid Build Coastguard Worker 
194*c8dee2aaSAndroid Build Coastguard Worker     return { cf, o };
195*c8dee2aaSAndroid Build Coastguard Worker }
196*c8dee2aaSAndroid Build Coastguard Worker 
create_hsla_matrix_colorfilter()197*c8dee2aaSAndroid Build Coastguard Worker std::pair<sk_sp<SkColorFilter>, sk_sp<PrecompileColorFilter>> create_hsla_matrix_colorfilter() {
198*c8dee2aaSAndroid Build Coastguard Worker     sk_sp<SkColorFilter> cf = SkColorFilters::HSLAMatrix(
199*c8dee2aaSAndroid Build Coastguard Worker             SkColorMatrix::RGBtoYUV(SkYUVColorSpace::kJPEG_Full_SkYUVColorSpace));
200*c8dee2aaSAndroid Build Coastguard Worker     sk_sp<PrecompileColorFilter> o = PrecompileColorFilters::HSLAMatrix();
201*c8dee2aaSAndroid Build Coastguard Worker 
202*c8dee2aaSAndroid Build Coastguard Worker     return { cf, o };
203*c8dee2aaSAndroid Build Coastguard Worker }
204*c8dee2aaSAndroid Build Coastguard Worker 
create_colorfilter(Fuzz * fuzz,ColorFilterType type,int depth)205*c8dee2aaSAndroid Build Coastguard Worker std::pair<sk_sp<SkColorFilter>, sk_sp<PrecompileColorFilter>> create_colorfilter(
206*c8dee2aaSAndroid Build Coastguard Worker         Fuzz* fuzz,
207*c8dee2aaSAndroid Build Coastguard Worker         ColorFilterType type,
208*c8dee2aaSAndroid Build Coastguard Worker         int depth) {
209*c8dee2aaSAndroid Build Coastguard Worker     if (depth <= 0) {
210*c8dee2aaSAndroid Build Coastguard Worker         return {};
211*c8dee2aaSAndroid Build Coastguard Worker     }
212*c8dee2aaSAndroid Build Coastguard Worker 
213*c8dee2aaSAndroid Build Coastguard Worker     switch (type) {
214*c8dee2aaSAndroid Build Coastguard Worker         case ColorFilterType::kNone:
215*c8dee2aaSAndroid Build Coastguard Worker             return { nullptr, nullptr };
216*c8dee2aaSAndroid Build Coastguard Worker         case ColorFilterType::kBlend:
217*c8dee2aaSAndroid Build Coastguard Worker             return create_blend_colorfilter(fuzz);
218*c8dee2aaSAndroid Build Coastguard Worker         case ColorFilterType::kMatrix:
219*c8dee2aaSAndroid Build Coastguard Worker             return create_matrix_colorfilter();
220*c8dee2aaSAndroid Build Coastguard Worker         case ColorFilterType::kHSLAMatrix:
221*c8dee2aaSAndroid Build Coastguard Worker             return create_hsla_matrix_colorfilter();
222*c8dee2aaSAndroid Build Coastguard Worker     }
223*c8dee2aaSAndroid Build Coastguard Worker 
224*c8dee2aaSAndroid Build Coastguard Worker     SkUNREACHABLE;
225*c8dee2aaSAndroid Build Coastguard Worker }
226*c8dee2aaSAndroid Build Coastguard Worker 
create_random_colorfilter(Fuzz * fuzz,int depth)227*c8dee2aaSAndroid Build Coastguard Worker std::pair<sk_sp<SkColorFilter>, sk_sp<PrecompileColorFilter>> create_random_colorfilter(
228*c8dee2aaSAndroid Build Coastguard Worker         Fuzz* fuzz,
229*c8dee2aaSAndroid Build Coastguard Worker         int depth) {
230*c8dee2aaSAndroid Build Coastguard Worker 
231*c8dee2aaSAndroid Build Coastguard Worker     uint32_t temp;
232*c8dee2aaSAndroid Build Coastguard Worker     fuzz->next(&temp);
233*c8dee2aaSAndroid Build Coastguard Worker     ColorFilterType cf = (ColorFilterType) (temp % kColorFilterTypeCount);
234*c8dee2aaSAndroid Build Coastguard Worker 
235*c8dee2aaSAndroid Build Coastguard Worker     return create_colorfilter(fuzz, cf, depth);
236*c8dee2aaSAndroid Build Coastguard Worker }
237*c8dee2aaSAndroid Build Coastguard Worker 
238*c8dee2aaSAndroid Build Coastguard Worker //--------------------------------------------------------------------------------------------------
create_random_paint(Fuzz * fuzz,int depth)239*c8dee2aaSAndroid Build Coastguard Worker std::pair<SkPaint, PaintOptions> create_random_paint(Fuzz* fuzz, int depth) {
240*c8dee2aaSAndroid Build Coastguard Worker     if (depth <= 0) {
241*c8dee2aaSAndroid Build Coastguard Worker         return {};
242*c8dee2aaSAndroid Build Coastguard Worker     }
243*c8dee2aaSAndroid Build Coastguard Worker 
244*c8dee2aaSAndroid Build Coastguard Worker     SkPaint paint;
245*c8dee2aaSAndroid Build Coastguard Worker     paint.setColor(random_opaque_skcolor(fuzz));
246*c8dee2aaSAndroid Build Coastguard Worker 
247*c8dee2aaSAndroid Build Coastguard Worker     PaintOptions paintOptions;
248*c8dee2aaSAndroid Build Coastguard Worker 
249*c8dee2aaSAndroid Build Coastguard Worker     {
250*c8dee2aaSAndroid Build Coastguard Worker         auto [cf, o] = create_random_colorfilter(fuzz, depth - 1);
251*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT_RELEASE(!cf == !o);
252*c8dee2aaSAndroid Build Coastguard Worker 
253*c8dee2aaSAndroid Build Coastguard Worker         if (cf) {
254*c8dee2aaSAndroid Build Coastguard Worker             paint.setColorFilter(std::move(cf));
255*c8dee2aaSAndroid Build Coastguard Worker             paintOptions.setColorFilters({o});
256*c8dee2aaSAndroid Build Coastguard Worker         }
257*c8dee2aaSAndroid Build Coastguard Worker     }
258*c8dee2aaSAndroid Build Coastguard Worker 
259*c8dee2aaSAndroid Build Coastguard Worker     return { paint, paintOptions };
260*c8dee2aaSAndroid Build Coastguard Worker }
261*c8dee2aaSAndroid Build Coastguard Worker 
262*c8dee2aaSAndroid Build Coastguard Worker //--------------------------------------------------------------------------------------------------
check_draw(Context * context,Recorder * recorder,const SkPaint & paint,DrawTypeFlags dt,const SkPath & path)263*c8dee2aaSAndroid Build Coastguard Worker void check_draw(Context* context,
264*c8dee2aaSAndroid Build Coastguard Worker                 Recorder* recorder,
265*c8dee2aaSAndroid Build Coastguard Worker                 const SkPaint& paint,
266*c8dee2aaSAndroid Build Coastguard Worker                 DrawTypeFlags dt,
267*c8dee2aaSAndroid Build Coastguard Worker                 const SkPath& path) {
268*c8dee2aaSAndroid Build Coastguard Worker     int before = context->priv().globalCache()->numGraphicsPipelines();
269*c8dee2aaSAndroid Build Coastguard Worker 
270*c8dee2aaSAndroid Build Coastguard Worker     {
271*c8dee2aaSAndroid Build Coastguard Worker         // TODO: vary the colorType of the target surface too
272*c8dee2aaSAndroid Build Coastguard Worker         SkImageInfo ii = SkImageInfo::Make(16, 16,
273*c8dee2aaSAndroid Build Coastguard Worker                                            kRGBA_8888_SkColorType,
274*c8dee2aaSAndroid Build Coastguard Worker                                            kPremul_SkAlphaType);
275*c8dee2aaSAndroid Build Coastguard Worker 
276*c8dee2aaSAndroid Build Coastguard Worker         sk_sp<SkSurface> surf = SkSurfaces::RenderTarget(recorder, ii);
277*c8dee2aaSAndroid Build Coastguard Worker         SkCanvas* canvas = surf->getCanvas();
278*c8dee2aaSAndroid Build Coastguard Worker 
279*c8dee2aaSAndroid Build Coastguard Worker         switch (dt) {
280*c8dee2aaSAndroid Build Coastguard Worker             case DrawTypeFlags::kSimpleShape:
281*c8dee2aaSAndroid Build Coastguard Worker                 canvas->drawRect(SkRect::MakeWH(16, 16), paint);
282*c8dee2aaSAndroid Build Coastguard Worker                 break;
283*c8dee2aaSAndroid Build Coastguard Worker             case DrawTypeFlags::kNonSimpleShape:
284*c8dee2aaSAndroid Build Coastguard Worker                 canvas->drawPath(path, paint);
285*c8dee2aaSAndroid Build Coastguard Worker                 break;
286*c8dee2aaSAndroid Build Coastguard Worker             default:
287*c8dee2aaSAndroid Build Coastguard Worker                 SkASSERT_RELEASE(false);
288*c8dee2aaSAndroid Build Coastguard Worker                 break;
289*c8dee2aaSAndroid Build Coastguard Worker         }
290*c8dee2aaSAndroid Build Coastguard Worker 
291*c8dee2aaSAndroid Build Coastguard Worker         std::unique_ptr<skgpu::graphite::Recording> recording = recorder->snap();
292*c8dee2aaSAndroid Build Coastguard Worker         context->insertRecording({ recording.get() });
293*c8dee2aaSAndroid Build Coastguard Worker         context->submit(SyncToCpu::kYes);
294*c8dee2aaSAndroid Build Coastguard Worker     }
295*c8dee2aaSAndroid Build Coastguard Worker 
296*c8dee2aaSAndroid Build Coastguard Worker     int after = context->priv().globalCache()->numGraphicsPipelines();
297*c8dee2aaSAndroid Build Coastguard Worker 
298*c8dee2aaSAndroid Build Coastguard Worker     // Actually using the SkPaint with the specified type of draw shouldn't have caused
299*c8dee2aaSAndroid Build Coastguard Worker     // any additional compilation
300*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT_RELEASE(before == after);
301*c8dee2aaSAndroid Build Coastguard Worker }
302*c8dee2aaSAndroid Build Coastguard Worker 
fuzz_graphite(Fuzz * fuzz,Context * context,int depth=9)303*c8dee2aaSAndroid Build Coastguard Worker void fuzz_graphite(Fuzz* fuzz, Context* context, int depth = 9) {
304*c8dee2aaSAndroid Build Coastguard Worker     std::unique_ptr<PrecompileContext> precompileContext = context->makePrecompileContext();
305*c8dee2aaSAndroid Build Coastguard Worker     std::unique_ptr<Recorder> recorder = context->makeRecorder();
306*c8dee2aaSAndroid Build Coastguard Worker     ShaderCodeDictionary* dict = context->priv().shaderCodeDictionary();
307*c8dee2aaSAndroid Build Coastguard Worker 
308*c8dee2aaSAndroid Build Coastguard Worker     SkColorInfo ci = SkColorInfo(kRGBA_8888_SkColorType, kPremul_SkAlphaType,
309*c8dee2aaSAndroid Build Coastguard Worker                                  SkColorSpace::MakeSRGB());
310*c8dee2aaSAndroid Build Coastguard Worker 
311*c8dee2aaSAndroid Build Coastguard Worker     std::unique_ptr<RuntimeEffectDictionary> rtDict = std::make_unique<RuntimeEffectDictionary>();
312*c8dee2aaSAndroid Build Coastguard Worker     KeyContext precompileKeyContext(recorder->priv().caps(), dict, rtDict.get(), ci);
313*c8dee2aaSAndroid Build Coastguard Worker 
314*c8dee2aaSAndroid Build Coastguard Worker     DrawTypeFlags kDrawType = DrawTypeFlags::kSimpleShape;
315*c8dee2aaSAndroid Build Coastguard Worker     SkPath path = make_path();
316*c8dee2aaSAndroid Build Coastguard Worker 
317*c8dee2aaSAndroid Build Coastguard Worker     Layout layout = context->backend() == skgpu::BackendApi::kMetal ? Layout::kMetal
318*c8dee2aaSAndroid Build Coastguard Worker                                                                     : Layout::kStd140;
319*c8dee2aaSAndroid Build Coastguard Worker 
320*c8dee2aaSAndroid Build Coastguard Worker     PaintParamsKeyBuilder builder(dict);
321*c8dee2aaSAndroid Build Coastguard Worker     PipelineDataGatherer gatherer(layout);
322*c8dee2aaSAndroid Build Coastguard Worker 
323*c8dee2aaSAndroid Build Coastguard Worker     auto [paint, paintOptions] = create_random_paint(fuzz, depth);
324*c8dee2aaSAndroid Build Coastguard Worker 
325*c8dee2aaSAndroid Build Coastguard Worker     constexpr Coverage coverageOptions[3] = {
326*c8dee2aaSAndroid Build Coastguard Worker             Coverage::kNone, Coverage::kSingleChannel, Coverage::kLCD};
327*c8dee2aaSAndroid Build Coastguard Worker     uint32_t temp;
328*c8dee2aaSAndroid Build Coastguard Worker     fuzz->next(&temp);
329*c8dee2aaSAndroid Build Coastguard Worker     Coverage coverage = coverageOptions[temp % 3];
330*c8dee2aaSAndroid Build Coastguard Worker 
331*c8dee2aaSAndroid Build Coastguard Worker     DstReadRequirement dstReadReq = DstReadRequirement::kNone;
332*c8dee2aaSAndroid Build Coastguard Worker     const SkBlenderBase* blender = as_BB(paint.getBlender());
333*c8dee2aaSAndroid Build Coastguard Worker     if (blender) {
334*c8dee2aaSAndroid Build Coastguard Worker         dstReadReq = GetDstReadRequirement(recorder->priv().caps(),
335*c8dee2aaSAndroid Build Coastguard Worker                                            blender->asBlendMode(),
336*c8dee2aaSAndroid Build Coastguard Worker                                            coverage);
337*c8dee2aaSAndroid Build Coastguard Worker     }
338*c8dee2aaSAndroid Build Coastguard Worker 
339*c8dee2aaSAndroid Build Coastguard Worker     UniquePaintParamsID paintID = ExtractPaintData(recorder.get(),
340*c8dee2aaSAndroid Build Coastguard Worker                                                    &gatherer,
341*c8dee2aaSAndroid Build Coastguard Worker                                                    &builder,
342*c8dee2aaSAndroid Build Coastguard Worker                                                    layout,
343*c8dee2aaSAndroid Build Coastguard Worker                                                    {},
344*c8dee2aaSAndroid Build Coastguard Worker                                                    PaintParams(paint,
345*c8dee2aaSAndroid Build Coastguard Worker                                                                /* primitiveBlender= */ nullptr,
346*c8dee2aaSAndroid Build Coastguard Worker                                                                /* analyticClip= */ {},
347*c8dee2aaSAndroid Build Coastguard Worker                                                                /* clipShader= */ nullptr,
348*c8dee2aaSAndroid Build Coastguard Worker                                                                dstReadReq,
349*c8dee2aaSAndroid Build Coastguard Worker                                                                /* skipColorXform= */ false),
350*c8dee2aaSAndroid Build Coastguard Worker                                                    {},
351*c8dee2aaSAndroid Build Coastguard Worker                                                    ci);
352*c8dee2aaSAndroid Build Coastguard Worker 
353*c8dee2aaSAndroid Build Coastguard Worker     RenderPassDesc unusedRenderPassDesc;
354*c8dee2aaSAndroid Build Coastguard Worker 
355*c8dee2aaSAndroid Build Coastguard Worker     std::vector<UniquePaintParamsID> precompileIDs;
356*c8dee2aaSAndroid Build Coastguard Worker     paintOptions.priv().buildCombinations(precompileKeyContext,
357*c8dee2aaSAndroid Build Coastguard Worker                                           &gatherer,
358*c8dee2aaSAndroid Build Coastguard Worker                                           DrawTypeFlags::kNone,
359*c8dee2aaSAndroid Build Coastguard Worker                                           /* withPrimitiveBlender= */ false,
360*c8dee2aaSAndroid Build Coastguard Worker                                           coverage,
361*c8dee2aaSAndroid Build Coastguard Worker                                           unusedRenderPassDesc,
362*c8dee2aaSAndroid Build Coastguard Worker                                           [&](UniquePaintParamsID id,
363*c8dee2aaSAndroid Build Coastguard Worker                                               DrawTypeFlags,
364*c8dee2aaSAndroid Build Coastguard Worker                                               bool /* withPrimitiveBlender */,
365*c8dee2aaSAndroid Build Coastguard Worker                                               Coverage,
366*c8dee2aaSAndroid Build Coastguard Worker                                               const RenderPassDesc&) {
367*c8dee2aaSAndroid Build Coastguard Worker                                                   precompileIDs.push_back(id);
368*c8dee2aaSAndroid Build Coastguard Worker                                           });
369*c8dee2aaSAndroid Build Coastguard Worker 
370*c8dee2aaSAndroid Build Coastguard Worker     // The specific key generated by ExtractPaintData should be one of the
371*c8dee2aaSAndroid Build Coastguard Worker     // combinations generated by the combination system.
372*c8dee2aaSAndroid Build Coastguard Worker     auto result = std::find(precompileIDs.begin(), precompileIDs.end(), paintID);
373*c8dee2aaSAndroid Build Coastguard Worker 
374*c8dee2aaSAndroid Build Coastguard Worker #ifdef SK_DEBUG
375*c8dee2aaSAndroid Build Coastguard Worker     if (result == precompileIDs.end()) {
376*c8dee2aaSAndroid Build Coastguard Worker         SkDebugf("From paint: ");
377*c8dee2aaSAndroid Build Coastguard Worker         dict->dump(paintID);
378*c8dee2aaSAndroid Build Coastguard Worker 
379*c8dee2aaSAndroid Build Coastguard Worker         SkDebugf("From combination builder:");
380*c8dee2aaSAndroid Build Coastguard Worker         for (auto iter : precompileIDs) {
381*c8dee2aaSAndroid Build Coastguard Worker             dict->dump(iter);
382*c8dee2aaSAndroid Build Coastguard Worker         }
383*c8dee2aaSAndroid Build Coastguard Worker     }
384*c8dee2aaSAndroid Build Coastguard Worker #endif
385*c8dee2aaSAndroid Build Coastguard Worker 
386*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT_RELEASE(result != precompileIDs.end());
387*c8dee2aaSAndroid Build Coastguard Worker 
388*c8dee2aaSAndroid Build Coastguard Worker     {
389*c8dee2aaSAndroid Build Coastguard Worker         static const RenderPassProperties kDefaultRenderPassProperties;
390*c8dee2aaSAndroid Build Coastguard Worker 
391*c8dee2aaSAndroid Build Coastguard Worker         context->priv().globalCache()->resetGraphicsPipelines();
392*c8dee2aaSAndroid Build Coastguard Worker 
393*c8dee2aaSAndroid Build Coastguard Worker         int before = context->priv().globalCache()->numGraphicsPipelines();
394*c8dee2aaSAndroid Build Coastguard Worker         Precompile(precompileContext.get(), paintOptions, kDrawType,
395*c8dee2aaSAndroid Build Coastguard Worker                    { kDefaultRenderPassProperties });
396*c8dee2aaSAndroid Build Coastguard Worker         int after = context->priv().globalCache()->numGraphicsPipelines();
397*c8dee2aaSAndroid Build Coastguard Worker 
398*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT_RELEASE(before == 0);
399*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT_RELEASE(after > before);
400*c8dee2aaSAndroid Build Coastguard Worker 
401*c8dee2aaSAndroid Build Coastguard Worker         check_draw(context, recorder.get(), paint, kDrawType, path);
402*c8dee2aaSAndroid Build Coastguard Worker     }
403*c8dee2aaSAndroid Build Coastguard Worker }
404*c8dee2aaSAndroid Build Coastguard Worker 
405*c8dee2aaSAndroid Build Coastguard Worker } // anonymous namespace
406*c8dee2aaSAndroid Build Coastguard Worker 
DEF_FUZZ(Precompile,fuzz)407*c8dee2aaSAndroid Build Coastguard Worker DEF_FUZZ(Precompile, fuzz) {
408*c8dee2aaSAndroid Build Coastguard Worker     skiatest::graphite::ContextFactory factory;
409*c8dee2aaSAndroid Build Coastguard Worker 
410*c8dee2aaSAndroid Build Coastguard Worker     skgpu::ContextType contextType;
411*c8dee2aaSAndroid Build Coastguard Worker #if defined(SK_METAL)
412*c8dee2aaSAndroid Build Coastguard Worker     contextType = skgpu::ContextType::kMetal;
413*c8dee2aaSAndroid Build Coastguard Worker #elif defined(SK_VULKAN)
414*c8dee2aaSAndroid Build Coastguard Worker     contextType = skgpu::ContextType::kVulkan;
415*c8dee2aaSAndroid Build Coastguard Worker #else
416*c8dee2aaSAndroid Build Coastguard Worker     contextType = skgpu::ContextType::kMock;
417*c8dee2aaSAndroid Build Coastguard Worker #endif
418*c8dee2aaSAndroid Build Coastguard Worker 
419*c8dee2aaSAndroid Build Coastguard Worker     skiatest::graphite::ContextInfo ctxInfo = factory.getContextInfo(contextType);
420*c8dee2aaSAndroid Build Coastguard Worker     skgpu::graphite::Context* context = ctxInfo.fContext;
421*c8dee2aaSAndroid Build Coastguard Worker     if (!context) {
422*c8dee2aaSAndroid Build Coastguard Worker         return;
423*c8dee2aaSAndroid Build Coastguard Worker     }
424*c8dee2aaSAndroid Build Coastguard Worker 
425*c8dee2aaSAndroid Build Coastguard Worker     fuzz_graphite(fuzz, context);
426*c8dee2aaSAndroid Build Coastguard Worker }
427