• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2024 Google LLC
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7 
8 #include "tests/Test.h"
9 
10 #if defined(SK_GRAPHITE)
11 
12 #include "include/gpu/graphite/Context.h"
13 #include "src/gpu/graphite/ContextPriv.h"
14 #include "src/gpu/graphite/ContextUtils.h"
15 #include "src/gpu/graphite/GraphicsPipelineDesc.h"
16 #include "src/gpu/graphite/PrecompileContextPriv.h"
17 #include "src/gpu/graphite/RenderPassDesc.h"
18 #include "src/gpu/graphite/RendererProvider.h"
19 #include "tools/graphite/UniqueKeyUtils.h"
20 
21 /*** From here to the matching banner can be cut and pasted into Chrome's graphite_precompile.cc **/
22 #include "include/gpu/graphite/PrecompileContext.h"
23 #include "include/gpu/graphite/precompile/PaintOptions.h"
24 #include "include/gpu/graphite/precompile/Precompile.h"
25 #include "include/gpu/graphite/precompile/PrecompileColorFilter.h"
26 #include "include/gpu/graphite/precompile/PrecompileShader.h"
27 
28 namespace {
29 
30 using ::skgpu::graphite::DepthStencilFlags;
31 using ::skgpu::graphite::DrawTypeFlags;
32 using ::skgpu::graphite::PaintOptions;
33 using ::skgpu::graphite::RenderPassProperties;
34 
35 // "SolidColor SrcOver"
solid_srcover()36 PaintOptions solid_srcover() {
37     PaintOptions paintOptions;
38     paintOptions.setBlendModes({ SkBlendMode::kSrcOver });
39     return paintOptions;
40 }
41 
42 // "SolidColor SrcOver"
43 // "SolidColor Src"
44 // "SolidColor Clear"
solid_clear_src_srcover()45 PaintOptions solid_clear_src_srcover() {
46     PaintOptions paintOptions;
47     paintOptions.setBlendModes({ SkBlendMode::kClear,
48                                  SkBlendMode::kSrc,
49                                  SkBlendMode::kSrcOver });
50     return paintOptions;
51 }
52 
53 // "LocalMatrix [ Compose [ HardwareImage(0) ColorSpaceTransformPremul ] ] SrcOver"
54 // "LocalMatrix [ Compose [ Image(0) ColorSpaceTransformPremul ] ] SrcOver"
image_premul_srcover()55 PaintOptions image_premul_srcover() {
56     SkColorInfo ci { kRGBA_8888_SkColorType, kPremul_SkAlphaType, nullptr };
57     PaintOptions paintOptions;
58     paintOptions.setShaders({ skgpu::graphite::PrecompileShaders::Image({ &ci, 1 }) });
59     paintOptions.setBlendModes({ SkBlendMode::kSrcOver });
60     return paintOptions;
61 }
62 
63 // "LocalMatrix [ Compose [ HardwareImage(0) ColorSpaceTransformPremul ] ] Src"
64 // "LocalMatrix [ Compose [ HardwareImage(0) ColorSpaceTransformPremul ] ] SrcOver"
65 // "LocalMatrix [ Compose [ Image(0) ColorSpaceTransformPremul ] ] SrcOver"
image_premul_src_srcover()66 PaintOptions image_premul_src_srcover() {
67     SkColorInfo ci { kRGBA_8888_SkColorType, kPremul_SkAlphaType, nullptr };
68     PaintOptions paintOptions;
69     paintOptions.setShaders({ skgpu::graphite::PrecompileShaders::Image({ &ci, 1 }) });
70     paintOptions.setBlendModes({ SkBlendMode::kSrc,
71                                  SkBlendMode::kSrcOver });
72     return paintOptions;
73 }
74 
75 // "LocalMatrix [ Compose [ HardwareImage(0) ColorSpaceTransformSRGB ] ] Src"
image_srgb_src()76 PaintOptions image_srgb_src() {
77     SkColorInfo ci { kRGBA_8888_SkColorType,
78                      kPremul_SkAlphaType,
79                      SkColorSpace::MakeRGB(SkNamedTransferFn::kSRGB,
80                                            SkNamedGamut::kAdobeRGB) };
81     PaintOptions paintOptions;
82     paintOptions.setShaders({ skgpu::graphite::PrecompileShaders::Image({ &ci, 1 }) });
83     paintOptions.setBlendModes({ SkBlendMode::kSrc });
84     return paintOptions;
85 }
86 
87 // "Compose [ SolidColor BlendCompose [ SolidColor Passthrough PorterDuffBlender ] ] SrcOver"
blend_porter_duff_cf_srcover()88 PaintOptions blend_porter_duff_cf_srcover() {
89     PaintOptions paintOptions;
90     // kSrcOver will trigger the PorterDuffBlender
91     paintOptions.setColorFilters(
92             { skgpu::graphite::PrecompileColorFilters::Blend({ SkBlendMode::kSrcOver }) });
93     paintOptions.setBlendModes({ SkBlendMode::kSrcOver });
94 
95     return paintOptions;
96 }
97 
98 // "RP(color: Dawn(f=R8,s=1), resolve: {}, ds: Dawn(f=D16,s=1), samples: 1, swizzle: a000)",
99 // Single sampled R w/ just depth
100 const RenderPassProperties kR_1_D { DepthStencilFlags::kDepth,
101                                     kAlpha_8_SkColorType,
102                                     /* fDstCS= */ nullptr,
103                                     /* fRequiresMSAA= */ false };
104 
105 // "RP(color: Dawn(f=R8,s=4), resolve: Dawn(f=R8,s=1), ds: Dawn(f=D24_S8,s=4), samples: 4, swizzle: a000)",
106 // MSAA R w/ depth and stencil
107 const RenderPassProperties kR_4_DS { DepthStencilFlags::kDepthStencil,
108                                      kAlpha_8_SkColorType,
109                                      /* fDstCS= */ nullptr,
110                                      /* fRequiresMSAA= */ true };
111 
112 // "RP(color: Dawn(f=BGRA8,s=1), resolve: {}, ds: Dawn(f=D16,s=1), samples: 1, swizzle: rgba)"
113 // Single sampled BGRA w/ just depth
114 const RenderPassProperties kBGRA_1_D { DepthStencilFlags::kDepth,
115                                        kBGRA_8888_SkColorType,
116                                        /* fDstCS= */ nullptr,
117                                        /* fRequiresMSAA= */ false };
118 
119 // "RP(color: Dawn(f=BGRA8,s=4), resolve: Dawn(f=BGRA8,s=1), ds: Dawn(f=D16,s=4), samples: 4, swizzle: rgba)"
120 // MSAA BGRA w/ just depth
121 const RenderPassProperties kBGRA_4_D { DepthStencilFlags::kDepth,
122                                        kBGRA_8888_SkColorType,
123                                        /* fDstCS= */ nullptr,
124                                        /* fRequiresMSAA= */ true };
125 
126 // "RP(color: Dawn(f=BGRA8,s=4), resolve: Dawn(f=BGRA8,s=1), ds: Dawn(f=D24_S8,s=4), samples: 4, swizzle: rgba)"
127 // MSAA BGRA w/ depth and stencil
128 const RenderPassProperties kBGRA_4_DS { DepthStencilFlags::kDepthStencil,
129                                         kBGRA_8888_SkColorType,
130                                         /* fDstCS= */ nullptr,
131                                         /* fRequiresMSAA= */ true };
132 
133 // The same as kBGRA_1_D but w/ an SRGB colorSpace
134 const RenderPassProperties kBGRA_1_D_SRGB { DepthStencilFlags::kDepth,
135                                             kBGRA_8888_SkColorType,
136                                             SkColorSpace::MakeSRGB(),
137                                             /* fRequiresMSAA= */ false };
138 
139 const struct PrecompileSettings {
140     PaintOptions fPaintOptions;
141     DrawTypeFlags fDrawTypeFlags = DrawTypeFlags::kNone;
142     RenderPassProperties fRenderPassProps;
143 } kPrecompileCases[] = {
144     { blend_porter_duff_cf_srcover(), DrawTypeFlags::kNone,           kBGRA_1_D }, // unused
145     { blend_porter_duff_cf_srcover(), DrawTypeFlags::kNonSimpleShape, kBGRA_1_D }, // 13
146     { solid_srcover(), DrawTypeFlags::kNonSimpleShape,  kR_4_DS },    // 2,3
147     { solid_srcover(), DrawTypeFlags::kBitmapText_Mask, kBGRA_1_D },  // 7
148     { solid_srcover(), DrawTypeFlags::kBitmapText_Mask, kBGRA_4_DS }, // 24
149     { solid_srcover(), DrawTypeFlags::kNonSimpleShape,  kBGRA_4_D },  // 21,22
150     { solid_srcover(), DrawTypeFlags::kNonSimpleShape,  kBGRA_4_DS }, // 28,34,35,57,58,61,62,65
151     { solid_srcover(), DrawTypeFlags::kCircularArc,     kBGRA_4_DS }, //26
152     { solid_clear_src_srcover(),  DrawTypeFlags::kSimpleShape, kBGRA_1_D },      // 6,8,9,10,15
153     { solid_clear_src_srcover(),  DrawTypeFlags::kSimpleShape, kBGRA_4_DS },     // 23,30,31,53
154     { image_premul_src_srcover(), DrawTypeFlags::kSimpleShape, kBGRA_1_D },      // 11,16,17,19,38
155     { image_premul_srcover(),     DrawTypeFlags::kSimpleShape, kBGRA_4_DS },     // 32,33,60
156     { image_srgb_src(),           DrawTypeFlags::kSimpleShape, kBGRA_1_D_SRGB }, // 18
157 };
158 
159 /*********** Here ends the part that can be pasted into Chrome's graphite_precompile.cc ***********/
160 
161 // This helper maps from the RenderPass string in the Pipeline label to the
162 // RenderPassProperties needed by the Precompile system
163 // TODO(robertphillips): converting this to a more piecemeal approach might better illuminate
164 // the mapping between the string and the RenderPassProperties
get_render_pass_properties(const char * str)165 RenderPassProperties get_render_pass_properties(const char* str) {
166     static const struct {
167         const char* fStr;
168         RenderPassProperties fRenderPassProperties;
169     } kRenderPassPropertiesMapping[] = {
170         { "RP(color: Dawn(f=R8,s=1), resolve: {}, ds: Dawn(f=D16,s=1), samples: 1, swizzle: a000)",
171           kR_1_D },
172         { "RP(color: Dawn(f=R8,s=4), resolve: Dawn(f=R8,s=1), ds: Dawn(f=D24_S8,s=4), samples: 4, swizzle: a000)",
173           kR_4_DS },
174         { "RP(color: Dawn(f=BGRA8,s=1), resolve: {}, ds: Dawn(f=D16,s=1), samples: 1, swizzle: rgba)",
175           kBGRA_1_D },
176         { "RP(color: Dawn(f=BGRA8,s=4), resolve: Dawn(f=BGRA8,s=1), ds: Dawn(f=D16,s=4), samples: 4, swizzle: rgba)",
177           kBGRA_4_D },
178         { "RP(color: Dawn(f=BGRA8,s=4), resolve: Dawn(f=BGRA8,s=1), ds: Dawn(f=D24_S8,s=4), samples: 4, swizzle: rgba)",
179            kBGRA_4_DS },
180     };
181 
182     for (const auto& rppm : kRenderPassPropertiesMapping) {
183         if (strstr(str, rppm.fStr)) {
184             return rppm.fRenderPassProperties;
185         }
186     }
187 
188     SkAssertResult(0);
189     return {};
190 }
191 
192 // This helper maps from the RenderStep's name in the Pipeline label to the DrawTypeFlag that
193 // resulted in its use.
get_draw_type_flags(const char * str)194 DrawTypeFlags get_draw_type_flags(const char* str) {
195     static const struct {
196         const char* fStr;
197         DrawTypeFlags fFlags;
198     } kDrawTypeFlagsMapping[] = {
199         { "BitmapTextRenderStep[Mask]",                  DrawTypeFlags::kBitmapText_Mask  },
200         { "BitmapTextRenderStep[LCD]",                   DrawTypeFlags::kBitmapText_LCD   },
201         { "BitmapTextRenderStep[Color]",                 DrawTypeFlags::kBitmapText_Color },
202 
203         { "SDFTextRenderStep",                           DrawTypeFlags::kSDFText      },
204         { "SDFTextLCDRenderStep",                        DrawTypeFlags::kSDFText_LCD  },
205 
206         { "VerticesRenderStep[Tris]",                    DrawTypeFlags::kDrawVertices },
207         { "VerticesRenderStep[TrisTexCoords]",           DrawTypeFlags::kDrawVertices },
208         { "VerticesRenderStep[TrisColor]",               DrawTypeFlags::kDrawVertices },
209         { "VerticesRenderStep[TrisColorTexCoords]",      DrawTypeFlags::kDrawVertices },
210         { "VerticesRenderStep[Tristrips]",               DrawTypeFlags::kDrawVertices },
211         { "VerticesRenderStep[TristripsTexCoords]",      DrawTypeFlags::kDrawVertices },
212         { "VerticesRenderStep[TristripsColor]",          DrawTypeFlags::kDrawVertices },
213         { "VerticesRenderStep[TristripsColorTexCoords]", DrawTypeFlags::kDrawVertices },
214 
215         { "CircularArcRenderStep",                       DrawTypeFlags::kCircularArc  },
216 
217         { "AnalyticRRectRenderStep",                     DrawTypeFlags::kSimpleShape  },
218         { "CoverBoundsRenderStep[NonAAFill]",            DrawTypeFlags::kSimpleShape  },
219         { "PerEdgeAAQuadRenderStep",                     DrawTypeFlags::kSimpleShape  },
220 
221         { "CoverageMaskRenderStep",                      DrawTypeFlags::kNonSimpleShape },
222         { "CoverBoundsRenderStep[RegularCover]",         DrawTypeFlags::kNonSimpleShape },
223         { "CoverBoundsRenderStep[InverseCover]",         DrawTypeFlags::kNonSimpleShape },
224         { "MiddleOutFanRenderStep[EvenOdd]",             DrawTypeFlags::kNonSimpleShape },
225         { "MiddleOutFanRenderStep[Winding]",             DrawTypeFlags::kNonSimpleShape },
226         { "TessellateCurvesRenderStep[EvenOdd]",         DrawTypeFlags::kNonSimpleShape },
227         { "TessellateCurvesRenderStep[Winding]",         DrawTypeFlags::kNonSimpleShape },
228         { "TessellateStrokesRenderStep",                 DrawTypeFlags::kNonSimpleShape },
229         { "TessellateWedgesRenderStep[Convex]",          DrawTypeFlags::kNonSimpleShape },
230         { "TessellateWedgesRenderStep[EvenOdd]",         DrawTypeFlags::kNonSimpleShape },
231         { "TessellateWedgesRenderStep[Winding]",         DrawTypeFlags::kNonSimpleShape },
232     };
233 
234     for (const auto& dtfm : kDrawTypeFlagsMapping) {
235         if (strstr(str, dtfm.fStr)) {
236             SkAssertResult(dtfm.fFlags != DrawTypeFlags::kNone);
237             return dtfm.fFlags;
238         }
239     }
240 
241     SkAssertResult(0);
242     return DrawTypeFlags::kNone;
243 }
244 
245 
246 // Precompile with the provided paintOptions, drawType, and RenderPassSettings then verify that
247 // the expected string is in the generated set.
248 // Additionally, verify that overgeneration is within expected tolerances.
249 // If you add an additional RenderStep you may need to increase the tolerance values.
run_test(skgpu::graphite::PrecompileContext * precompileContext,skiatest::Reporter * reporter,SkSpan<const char * > cases,size_t caseID,const PrecompileSettings & settings,unsigned int expectedNumPipelines)250 void run_test(skgpu::graphite::PrecompileContext* precompileContext,
251               skiatest::Reporter* reporter,
252               SkSpan<const char*> cases,
253               size_t caseID,
254               const PrecompileSettings& settings,
255               unsigned int expectedNumPipelines) {
256     using namespace skgpu::graphite;
257 
258     const char* expectedString = cases[caseID];
259 
260     precompileContext->priv().globalCache()->resetGraphicsPipelines();
261 
262     Precompile(precompileContext,
263                settings.fPaintOptions,
264                settings.fDrawTypeFlags,
265                { &settings.fRenderPassProps, 1 });
266 
267     std::vector<std::string> generated;
268 
269     {
270         const RendererProvider* rendererProvider = precompileContext->priv().rendererProvider();
271         const ShaderCodeDictionary* dict = precompileContext->priv().shaderCodeDictionary();
272 
273         std::vector<skgpu::UniqueKey> generatedKeys;
274 
275         UniqueKeyUtils::FetchUniqueKeys(precompileContext, &generatedKeys);
276 
277         for (const skgpu::UniqueKey& key : generatedKeys) {
278             GraphicsPipelineDesc pipelineDesc;
279             RenderPassDesc renderPassDesc;
280             UniqueKeyUtils::ExtractKeyDescs(precompileContext, key, &pipelineDesc, &renderPassDesc);
281 
282             const RenderStep* renderStep = rendererProvider->lookup(pipelineDesc.renderStepID());
283             generated.push_back(GetPipelineLabel(dict, renderPassDesc, renderStep,
284                                                  pipelineDesc.paintParamsID()));
285         }
286     }
287 
288     bool correctGenerationAmt = generated.size() == expectedNumPipelines;
289     REPORTER_ASSERT(reporter, correctGenerationAmt,
290                     "case %zu generated unexpected amount - a: %zu != e: %d\n",
291                     caseID, generated.size(), expectedNumPipelines);
292 
293     const size_t len = strlen(expectedString);
294 
295     bool foundIt = false;
296     for (size_t i = 0; i < generated.size(); ++i) {
297         // The generated strings have trailing whitespace
298         if (!strncmp(expectedString, generated[i].c_str(), len)) {
299             foundIt = true;
300             break;
301         }
302     }
303 
304     REPORTER_ASSERT(reporter, foundIt);
305 
306 #ifdef SK_DEBUG
307     if (foundIt && correctGenerationAmt) {
308         return;
309     }
310 
311     SkDebugf("Expected string:\n%s\n%s in %zu strings:\n",
312              expectedString,
313              foundIt ? "found" : "NOT found",
314              generated.size());
315 
316     for (size_t i = 0; i < generated.size(); ++i) {
317         SkDebugf("%zu: %s\n", i, generated[i].c_str());
318     }
319 #endif
320 }
321 
322 // The pipeline strings were created using the Dawn Metal backend so that is the only viable
323 // comparison
is_dawn_metal_context_type(skgpu::ContextType type)324 bool is_dawn_metal_context_type(skgpu::ContextType type) {
325     return type == skgpu::ContextType::kDawn_Metal;
326 }
327 
328 } // anonymous namespace
329 
330 
331 DEF_GRAPHITE_TEST_FOR_CONTEXTS(ChromePrecompileTest, is_dawn_metal_context_type,
332                                reporter, context, /* testContext */, CtsEnforcement::kNever) {
333     using namespace skgpu::graphite;
334 
335     std::unique_ptr<PrecompileContext> precompileContext = context->makePrecompileContext();
336     const skgpu::graphite::Caps* caps = precompileContext->priv().caps();
337 
338     TextureInfo textureInfo = caps->getDefaultSampledTextureInfo(kBGRA_8888_SkColorType,
339                                                                  skgpu::Mipmapped::kNo,
340                                                                  skgpu::Protected::kNo,
341                                                                  skgpu::Renderable::kYes);
342 
343     TextureInfo msaaTex = caps->getDefaultMSAATextureInfo(textureInfo, Discardable::kYes);
344 
345     if (msaaTex.numSamples() <= 1) {
346         // The following pipelines rely on having MSAA
347         return;
348     }
349 
350 #ifdef SK_ENABLE_VELLO_SHADERS
351     if (caps->computeSupport()) {
352         // The following pipelines rely on not utilizing Vello
353         return;
354     }
355 #endif
356 
357     //
358     // These Pipelines are candidates for inclusion in Chrome's precompile. They were generated
359     // by collecting all the Pipelines from the following stories:
360     //
361     //    animometer_webgl_attrib_arrays, balls_javascript_canvas, canvas_05000_pixels_per_second,
362     //    chip_tune, css_value_type_shadow, fill_shapes, ie_chalkboard, main_30fps_impl_60fps,
363     //    new_tilings, transform_transitions_js_block, web_animations_staggered_infinite_iterations,
364     //    wikipedia_2018
365     //
366     const char* kCases[] = {
367           //---- Single-sample - R8Unorm/Depth16Unorm --> kR_1_D
368 /* 0 */  "RP(color: Dawn(f=R8,s=1), resolve: {}, ds: Dawn(f=D16,s=1), samples: 1, swizzle: a000) + "
369          "CoverBoundsRenderStep[NonAAFill] + "
370          "KnownRuntimeEffect_1DBlur12 [ LocalMatrix [ Compose [ Image(0) ColorSpaceTransform ] ] ] Src",
371 
372 /* 1 */  "RP(color: Dawn(f=R8,s=1), resolve: {}, ds: Dawn(f=D16,s=1), samples: 1, swizzle: a000) + "
373          "CoverBoundsRenderStep[NonAAFill] + "
374          "KnownRuntimeEffect_1DBlur8  [ LocalMatrix [ Compose [ Image(0) ColorSpaceTransform ] ] ] Src",
375 
376           //---- MSAA4 - R8Unorm/Depth24PlusStencil8 --> kR_4_DS
377 /* 2 */  "RP(color: Dawn(f=R8,s=4), resolve: Dawn(f=R8,s=1), ds: Dawn(f=D24_S8,s=4), samples: 4, swizzle: a000) + "
378          "TessellateWedgesRenderStep[EvenOdd] + "
379          "(empty)",
380 
381 /* 3 */  "RP(color: Dawn(f=R8,s=4), resolve: Dawn(f=R8,s=1), ds: Dawn(f=D24_S8,s=4), samples: 4, swizzle: a000) + "
382          "CoverBoundsRenderStep[RegularCover] + "
383          "SolidColor SrcOver",
384 
385          //---- Single-sample - BGRA8Unorm/Depth16Unorm -> kBGRA_1_D
386 /* 4 */  "RP(color: Dawn(f=BGRA8,s=1), resolve: {}, ds: Dawn(f=D16,s=1), samples: 1, swizzle: rgba) + "
387          "AnalyticBlurRenderStep + "
388          "Compose [ SolidColor BlendCompose [ SolidColor Passthrough PorterDuffBlender ] ] SrcOver",
389 
390           // For now, we're going to pass on the AnalyticClip Pipelines
391 /* 5 */  "RP(color: Dawn(f=BGRA8,s=1), resolve: {}, ds: Dawn(f=D16,s=1), samples: 1, swizzle: rgba) + "
392          "AnalyticBlurRenderStep + "
393          "Compose [ SolidColor BlendCompose [ SolidColor Passthrough PorterDuffBlender ] ] SrcOver AnalyticClip",
394 
395 /* 6 */  "RP(color: Dawn(f=BGRA8,s=1), resolve: {}, ds: Dawn(f=D16,s=1), samples: 1, swizzle: rgba) + "
396          "AnalyticRRectRenderStep + "
397          "SolidColor SrcOver",
398 
399 /* 7 */  "RP(color: Dawn(f=BGRA8,s=1), resolve: {}, ds: Dawn(f=D16,s=1), samples: 1, swizzle: rgba) + "
400          "BitmapTextRenderStep[Mask] + "
401          "SolidColor SrcOver",
402 
403 /* 8 */  "RP(color: Dawn(f=BGRA8,s=1), resolve: {}, ds: Dawn(f=D16,s=1), samples: 1, swizzle: rgba) + "
404          "CoverBoundsRenderStep[NonAAFill] + "
405          "SolidColor SrcOver",
406 
407 /* 9 */ "RP(color: Dawn(f=BGRA8,s=1), resolve: {}, ds: Dawn(f=D16,s=1), samples: 1, swizzle: rgba) + "
408          "CoverBoundsRenderStep[NonAAFill] + "
409          "SolidColor Src",
410 
411 /* 10 */ "RP(color: Dawn(f=BGRA8,s=1), resolve: {}, ds: Dawn(f=D16,s=1), samples: 1, swizzle: rgba) + "
412          "CoverBoundsRenderStep[NonAAFill] + "
413          "SolidColor Clear",
414 
415 /* 11 */ "RP(color: Dawn(f=BGRA8,s=1), resolve: {}, ds: Dawn(f=D16,s=1), samples: 1, swizzle: rgba) + "
416          "CoverBoundsRenderStep[NonAAFill] + "
417          "LocalMatrix [ Compose [ HardwareImage(0) ColorSpaceTransformPremul ] ] Src",
418 
419           // For now, we're going to pass on the AnalyticClip Pipelines
420 /* 12 */ "RP(color: Dawn(f=BGRA8,s=1), resolve: {}, ds: Dawn(f=D16,s=1), samples: 1, swizzle: rgba) + "
421          "CoverBoundsRenderStep[NonAAFill] + "
422          "LocalMatrix [ Compose [ HardwareImage(0) ColorSpaceTransformPremul ] ] SrcOver AnalyticClip",
423 
424 /* 13 */ "RP(color: Dawn(f=BGRA8,s=1), resolve: {}, ds: Dawn(f=D16,s=1), samples: 1, swizzle: rgba) + "
425          "CoverageMaskRenderStep + "
426          "Compose [ SolidColor BlendCompose [ SolidColor Passthrough PorterDuffBlender ] ] SrcOver",
427 
428          // This is the only AlphaOnlyPaintColor case so, we're going to pass for now
429 /* 14 */ "RP(color: Dawn(f=BGRA8,s=1), resolve: {}, ds: Dawn(f=D16,s=1), samples: 1, swizzle: rgba) + "
430          "PerEdgeAAQuadRenderStep + "
431          "BlendCompose [ LocalMatrix [ Compose [ HardwareImage(0) ColorSpaceTransformPremul ] ] AlphaOnlyPaintColor SrcIn ] SrcOver",
432 
433 /* 15 */ "RP(color: Dawn(f=BGRA8,s=1), resolve: {}, ds: Dawn(f=D16,s=1), samples: 1, swizzle: rgba) + "
434          "PerEdgeAAQuadRenderStep + "
435          "SolidColor SrcOver",
436 
437 /* 16 */ "RP(color: Dawn(f=BGRA8,s=1), resolve: {}, ds: Dawn(f=D16,s=1), samples: 1, swizzle: rgba) + "
438          "PerEdgeAAQuadRenderStep + "
439          "LocalMatrix [ Compose [ HardwareImage(0) ColorSpaceTransformPremul ] ] Src",
440 
441 /* 17 */ "RP(color: Dawn(f=BGRA8,s=1), resolve: {}, ds: Dawn(f=D16,s=1), samples: 1, swizzle: rgba) + "
442          "PerEdgeAAQuadRenderStep + "
443          "LocalMatrix [ Compose [ HardwareImage(0) ColorSpaceTransformPremul ] ] SrcOver",
444 
445 /* 18 */ "RP(color: Dawn(f=BGRA8,s=1), resolve: {}, ds: Dawn(f=D16,s=1), samples: 1, swizzle: rgba) + "
446          "PerEdgeAAQuadRenderStep + "
447          "LocalMatrix [ Compose [ HardwareImage(0) ColorSpaceTransformSRGB ] ] Src",
448 
449 /* 19 */ "RP(color: Dawn(f=BGRA8,s=1), resolve: {}, ds: Dawn(f=D16,s=1), samples: 1, swizzle: rgba) + "
450          "PerEdgeAAQuadRenderStep + "
451          "LocalMatrix [ Compose [ Image(0) ColorSpaceTransformPremul ] ] SrcOver",
452 
453          //---- MSAA4 - BGRA8Unorm/Depth16Unorm -> bgra_4_D
454          // For now, we're going to pass on the AnalyticClip Pipelines
455 /* 20 */ "RP(color: Dawn(f=BGRA8,s=4), resolve: Dawn(f=BGRA8,s=1), ds: Dawn(f=D16,s=4), samples: 4, swizzle: rgba) + "
456          "CoverBoundsRenderStep[NonAAFill] + "
457          "LocalMatrix [ Compose [ HardwareImage(0) ColorSpaceTransformPremul ] ] SrcOver AnalyticClip",
458 
459 /* 21 */ "RP(color: Dawn(f=BGRA8,s=4), resolve: Dawn(f=BGRA8,s=1), ds: Dawn(f=D16,s=4), samples: 4, swizzle: rgba) + "
460          "TessellateStrokesRenderStep + "
461          "SolidColor SrcOver",
462 
463 /* 22 */ "RP(color: Dawn(f=BGRA8,s=4), resolve: Dawn(f=BGRA8,s=1), ds: Dawn(f=D16,s=4), samples: 4, swizzle: rgba) + "
464          "TessellateWedgesRenderStep[Convex] + "
465          "SolidColor SrcOver",
466 
467          //---- MSAA4 - BGRA8Unorm/Depth24PlusStencil8 --> kBGRA_4_DS
468 /* 23 */ "RP(color: Dawn(f=BGRA8,s=4), resolve: Dawn(f=BGRA8,s=1), ds: Dawn(f=D24_S8,s=4), samples: 4, swizzle: rgba) + "
469          "AnalyticRRectRenderStep + "
470          "SolidColor SrcOver",
471 
472 /* 24 */ "RP(color: Dawn(f=BGRA8,s=4), resolve: Dawn(f=BGRA8,s=1), ds: Dawn(f=D24_S8,s=4), samples: 4, swizzle: rgba) + "
473          "BitmapTextRenderStep[Mask] + "
474          "SolidColor SrcOver",
475 
476          // This seems like a quirk of our test set. Is linear gradient text that common? Pass for now.
477 /* 25 */ "RP(color: Dawn(f=BGRA8,s=4), resolve: Dawn(f=BGRA8,s=1), ds: Dawn(f=D24_S8,s=4), samples: 4, swizzle: rgba) + "
478          "BitmapTextRenderStep[Mask] + "
479          "LocalMatrix [ Compose [ LinearGradient4 ColorSpaceTransformPremul ] ] SrcOver",
480 
481 /* 26 */ "RP(color: Dawn(f=BGRA8,s=4), resolve: Dawn(f=BGRA8,s=1), ds: Dawn(f=D24_S8,s=4), samples: 4, swizzle: rgba) + "
482          "CircularArcRenderStep + "
483          "SolidColor SrcOver",
484 
485 /* 27 */ "RP(color: Dawn(f=BGRA8,s=4), resolve: Dawn(f=BGRA8,s=1), ds: Dawn(f=D24_S8,s=4), samples: 4, swizzle: rgba) + "
486          "CoverBoundsRenderStep[InverseCover] + "
487          "(empty)",
488 
489 /* 28 */ "RP(color: Dawn(f=BGRA8,s=4), resolve: Dawn(f=BGRA8,s=1), ds: Dawn(f=D24_S8,s=4), samples: 4, swizzle: rgba) + "
490          "CoverBoundsRenderStep[RegularCover] + "
491          "SolidColor SrcOver",
492 
493 /* 29 */ "RP(color: Dawn(f=BGRA8,s=4), resolve: Dawn(f=BGRA8,s=1), ds: Dawn(f=D24_S8,s=4), samples: 4, swizzle: rgba) + "
494          "CoverBoundsRenderStep[RegularCover] + "
495          "(empty)",
496 
497 /* 30 */ "RP(color: Dawn(f=BGRA8,s=4), resolve: Dawn(f=BGRA8,s=1), ds: Dawn(f=D24_S8,s=4), samples: 4, swizzle: rgba) + "
498          "CoverBoundsRenderStep[NonAAFill] + "
499          "SolidColor SrcOver",
500 
501 /* 31 */ "RP(color: Dawn(f=BGRA8,s=4), resolve: Dawn(f=BGRA8,s=1), ds: Dawn(f=D24_S8,s=4), samples: 4, swizzle: rgba) + "
502          "CoverBoundsRenderStep[NonAAFill] + "
503          "SolidColor Clear",
504 
505 /* 32 */ "RP(color: Dawn(f=BGRA8,s=4), resolve: Dawn(f=BGRA8,s=1), ds: Dawn(f=D24_S8,s=4), samples: 4, swizzle: rgba) + "
506          "CoverBoundsRenderStep[NonAAFill] + "
507          "LocalMatrix [ Compose [ HardwareImage(0) ColorSpaceTransformPremul ] ] SrcOver",
508 
509 /* 33 */ "RP(color: Dawn(f=BGRA8,s=4), resolve: Dawn(f=BGRA8,s=1), ds: Dawn(f=D24_S8,s=4), samples: 4, swizzle: rgba) + "
510          "PerEdgeAAQuadRenderStep + "
511          "LocalMatrix [ Compose [ HardwareImage(0) ColorSpaceTransformPremul ] ] SrcOver",
512 
513 /* 34 */ "RP(color: Dawn(f=BGRA8,s=4), resolve: Dawn(f=BGRA8,s=1), ds: Dawn(f=D24_S8,s=4), samples: 4, swizzle: rgba) + "
514          "TessellateWedgesRenderStep[Winding] + "
515          "(empty)",
516 
517 /* 35 */ "RP(color: Dawn(f=BGRA8,s=4), resolve: Dawn(f=BGRA8,s=1), ds: Dawn(f=D24_S8,s=4), samples: 4, swizzle: rgba) + "
518          "TessellateWedgesRenderStep[EvenOdd] + "
519          "(empty)",
520 
521 /* 36 */ "RP(color: Dawn(f=BGRA8,s=4), resolve: Dawn(f=BGRA8,s=1), ds: Dawn(f=D24_S8,s=4), samples: 4, swizzle: rgba) + "
522          "TessellateWedgesRenderStep[Convex] + "
523          "SolidColor SrcOver",
524 
525 //----------------------------
526 // These are leftover Pipelines that were generated by the stories but are pretty infrequently used.
527 // Some of them get picked up in the preceding cases
528           //---- Single-sample - BGRA8Unorm/Depth16Unorm -> kBGRA_1_D
529 /* 37 */ "RP(color: Dawn(f=BGRA8,s=1), resolve: {}, ds: Dawn(f=D16,s=1), samples: 1, swizzle: rgba) + "
530          "CoverBoundsRenderStep[NonAAFill] + "
531          "Compose [ LocalMatrix [ Compose [ LinearGradient4 ColorSpaceTransformPremul ] ] Dither ] SrcOver",
532 
533 /* 38 */ "RP(color: Dawn(f=BGRA8,s=1), resolve: {}, ds: Dawn(f=D16,s=1), samples: 1, swizzle: rgba) + "
534          "CoverBoundsRenderStep[NonAAFill] + "
535          "LocalMatrix [ Compose [ HardwareImage(0) ColorSpaceTransformPremul ] ] SrcOver",
536 
537 /* 39 */ "RP(color: Dawn(f=BGRA8,s=1), resolve: {}, ds: Dawn(f=D16,s=1), samples: 1, swizzle: rgba) + "
538          "CoverBoundsRenderStep[NonAAFill] + "
539          "LocalMatrix [ Compose [ Image(0) ColorSpaceTransformPremul ] ] SrcOver",
540 
541 /* 40 */ "RP(color: Dawn(f=BGRA8,s=1), resolve: {}, ds: Dawn(f=D16,s=1), samples: 1, swizzle: rgba) + "
542          "CoverBoundsRenderStep[NonAAFill] + "
543          "LocalMatrix [ Compose [ HardwareImage(0) ColorSpaceTransformSRGB ] ] SrcOver",
544 
545 /* 41 */ "RP(color: Dawn(f=BGRA8,s=1), resolve: {}, ds: Dawn(f=D16,s=1), samples: 1, swizzle: rgba) + "
546          "CoverBoundsRenderStep[NonAAFill] + "
547          "LocalMatrix [ Compose [ HardwareImage(0) ColorSpaceTransformSRGB ] ] Src",
548 
549 /* 42 */ "RP(color: Dawn(f=BGRA8,s=1), resolve: {}, ds: Dawn(f=D16,s=1), samples: 1, swizzle: rgba) + "
550          "CoverBoundsRenderStep[NonAAFill] + "
551          "LocalMatrix [ Compose [ HWYUVImage ColorSpaceTransformSRGB ] ] SrcOver",
552 
553 /* 43 */ "RP(color: Dawn(f=BGRA8,s=1), resolve: {}, ds: Dawn(f=D16,s=1), samples: 1, swizzle: rgba) + "
554          "PerEdgeAAQuadRenderStep + "
555          "LocalMatrix [ Compose [ HWYUVImage ColorSpaceTransformSRGB ] ] SrcOver",
556 
557          //---- MSAA4 - BGRA8Unorm/Depth16Unorm -> kBGRA_4_D
558 /* 44 */ "RP(color: Dawn(f=BGRA8,s=4), resolve: Dawn(f=BGRA8,s=1), ds: Dawn(f=D16,s=4), samples: 4, swizzle: rgba) + "
559          "AnalyticRRectRenderStep + "
560          "SolidColor SrcOver",
561 
562 /* 45 */ "RP(color: Dawn(f=BGRA8,s=4), resolve: Dawn(f=BGRA8,s=1), ds: Dawn(f=D16,s=4), samples: 4, swizzle: rgba) + "
563          "BitmapTextRenderStep[Mask] + "
564          "SolidColor SrcOver",
565 
566 /* 46 */ "RP(color: Dawn(f=BGRA8,s=4), resolve: Dawn(f=BGRA8,s=1), ds: Dawn(f=D16,s=4), samples: 4, swizzle: rgba) + "
567          "CoverBoundsRenderStep[NonAAFill] + "
568          "SolidColor SrcOver",
569 
570 /* 47 */ "RP(color: Dawn(f=BGRA8,s=4), resolve: Dawn(f=BGRA8,s=1), ds: Dawn(f=D16,s=4), samples: 4, swizzle: rgba) + "
571          "CoverBoundsRenderStep[NonAAFill] + "
572          "SolidColor Src",
573 
574 /* 48 */ "RP(color: Dawn(f=BGRA8,s=4), resolve: Dawn(f=BGRA8,s=1), ds: Dawn(f=D16,s=4), samples: 4, swizzle: rgba) + "
575          "CoverBoundsRenderStep[NonAAFill] + "
576          "Compose [ LocalMatrix [ Compose [ LinearGradient4 ColorSpaceTransformPremul ] ] Dither ] SrcOver",
577 
578 /* 49 */ "RP(color: Dawn(f=BGRA8,s=4), resolve: Dawn(f=BGRA8,s=1), ds: Dawn(f=D16,s=4), samples: 4, swizzle: rgba) + "
579          "CoverBoundsRenderStep[NonAAFill] + "
580          "LocalMatrix [ Compose [ HWYUVImage ColorSpaceTransformSRGB ] ] SrcOver",
581 
582 /* 50 */ "RP(color: Dawn(f=BGRA8,s=4), resolve: Dawn(f=BGRA8,s=1), ds: Dawn(f=D16,s=4), samples: 4, swizzle: rgba) + "
583          "PerEdgeAAQuadRenderStep + "
584          "LocalMatrix [ Compose [ HardwareImage(0) ColorSpaceTransformPremul ] ] SrcOver",
585 
586 /* 51 */ "RP(color: Dawn(f=BGRA8,s=4), resolve: Dawn(f=BGRA8,s=1), ds: Dawn(f=D16,s=4), samples: 4, swizzle: rgba) + "
587          "PerEdgeAAQuadRenderStep + "
588          "LocalMatrix [ Compose [ HWYUVImage ColorSpaceTransformSRGB ] ] SrcOver",
589 
590          //---- MSAA4 - BGRA8Unorm/Depth24PlusStencil8 --> kBGRA_4_DS
591 /* 52 */ "RP(color: Dawn(f=BGRA8,s=4), resolve: Dawn(f=BGRA8,s=1), ds: Dawn(f=D24_S8,s=4), samples: 4, swizzle: rgba) + "
592          "AnalyticRRectRenderStep + "
593          "Compose [ LocalMatrix [ Compose [ LinearGradient4 ColorSpaceTransformPremul ] ] Dither ] SrcOver",
594 
595 /* 53 */ "RP(color: Dawn(f=BGRA8,s=4), resolve: Dawn(f=BGRA8,s=1), ds: Dawn(f=D24_S8,s=4), samples: 4, swizzle: rgba) + "
596          "CoverBoundsRenderStep[NonAAFill] + "
597          "SolidColor Src",
598 
599 /* 54 */ "RP(color: Dawn(f=BGRA8,s=4), resolve: Dawn(f=BGRA8,s=1), ds: Dawn(f=D24_S8,s=4), samples: 4, swizzle: rgba) + "
600          "CoverBoundsRenderStep[NonAAFill] + "
601          "Compose [ LocalMatrix [ Compose [ LinearGradient4 ColorSpaceTransformPremul ] ] Dither ] SrcOver",
602 
603          // For now, we're going to pass on the AnalyticClip Pipelines
604 /* 55 */ "RP(color: Dawn(f=BGRA8,s=4), resolve: Dawn(f=BGRA8,s=1), ds: Dawn(f=D24_S8,s=4), samples: 4, swizzle: rgba) + "
605          "CoverBoundsRenderStep[NonAAFill] + "
606          "SolidColor SrcOver AnalyticClip",
607 
608 /* 56 */ "RP(color: Dawn(f=BGRA8,s=4), resolve: Dawn(f=BGRA8,s=1), ds: Dawn(f=D24_S8,s=4), samples: 4, swizzle: rgba) + "
609          "CoverBoundsRenderStep[RegularCover] + "
610          "Compose [ LocalMatrix [ Compose [ LinearGradient8 ColorSpaceTransformPremul ] ] Dither ] SrcOver",
611 
612 /* 57 */ "RP(color: Dawn(f=BGRA8,s=4), resolve: Dawn(f=BGRA8,s=1), ds: Dawn(f=D24_S8,s=4), samples: 4, swizzle: rgba) + "
613          "MiddleOutFanRenderStep[Winding] + "
614          "(empty)",
615 
616 /* 58 */ "RP(color: Dawn(f=BGRA8,s=4), resolve: Dawn(f=BGRA8,s=1), ds: Dawn(f=D24_S8,s=4), samples: 4, swizzle: rgba) + "
617          "MiddleOutFanRenderStep[EvenOdd] + "
618          "(empty)",
619 
620 /* 59 */ "RP(color: Dawn(f=BGRA8,s=4), resolve: Dawn(f=BGRA8,s=1), ds: Dawn(f=D24_S8,s=4), samples: 4, swizzle: rgba) + "
621          "PerEdgeAAQuadRenderStep + "
622          "BlendCompose [ LocalMatrix [ Compose [ HardwareImage(0) ColorSpaceTransformPremul ] ] AlphaOnlyPaintColor SrcIn ] SrcOver",
623 
624 /* 60 */ "RP(color: Dawn(f=BGRA8,s=4), resolve: Dawn(f=BGRA8,s=1), ds: Dawn(f=D24_S8,s=4), samples: 4, swizzle: rgba) + "
625          "PerEdgeAAQuadRenderStep + "
626          "LocalMatrix [ Compose [ Image(0) ColorSpaceTransformPremul ] ] SrcOver",
627 
628 /* 61 */ "RP(color: Dawn(f=BGRA8,s=4), resolve: Dawn(f=BGRA8,s=1), ds: Dawn(f=D24_S8,s=4), samples: 4, swizzle: rgba) + "
629          "TessellateCurvesRenderStep[Winding] + "
630          "(empty)",
631 
632 /* 62 */ "RP(color: Dawn(f=BGRA8,s=4), resolve: Dawn(f=BGRA8,s=1), ds: Dawn(f=D24_S8,s=4), samples: 4, swizzle: rgba) + "
633          "TessellateCurvesRenderStep[EvenOdd] + "
634          "(empty)",
635 
636 /* 63 */ "RP(color: Dawn(f=BGRA8,s=4), resolve: Dawn(f=BGRA8,s=1), ds: Dawn(f=D24_S8,s=4), samples: 4, swizzle: rgba) + "
637          "TessellateWedgesRenderStep[Convex] + "
638          "Compose [ LocalMatrix [ Compose [ LinearGradientBuffer ColorSpaceTransformPremul ] ] Dither ] SrcOver",
639 
640 /* 64 */ "RP(color: Dawn(f=BGRA8,s=4), resolve: Dawn(f=BGRA8,s=1), ds: Dawn(f=D24_S8,s=4), samples: 4, swizzle: rgba) + "
641          "TessellateWedgesRenderStep[Convex] + "
642          "Compose [ LocalMatrix [ Compose [ LinearGradient8 ColorSpaceTransformPremul ] ] Dither ] SrcOver",
643 
644 /* 65 */ "RP(color: Dawn(f=BGRA8,s=4), resolve: Dawn(f=BGRA8,s=1), ds: Dawn(f=D24_S8,s=4), samples: 4, swizzle: rgba) + "
645          "TessellateStrokesRenderStep + "
646          "SolidColor SrcOver",
647     };
648 
649     for (size_t i = 0; i < std::size(kCases); ++i) {
650         PrecompileSettings settings;
651 
652         // TODO(robertphillips): splitting kCases[i] into substrings (based on a " + " separator)
653         // before passing to the helpers would make this prettier
654         RenderPassProperties expectedRenderPassSettings = get_render_pass_properties(kCases[i]);
655         unsigned int expectedNumPipelines = 0;
656 
657         switch (i) {
658 #if 0
659             // Punting on the blur cases for now since they horribly over-generate
660             case 0:             [[fallthrough]];
661             case 1:
662                 renderPassSettings = kR_1_D;
663                 drawTypeFlags = DrawTypeFlags::kSimpleShape;
664                 paintOptions = blur_image();
665                 expectedNumPipelines = 11;
666                 break;
667 #endif
668 
669             // 2 and 3 form a single-draw pair and are, thus, addressed by the same settings
670             case 2: [[fallthrough]];   // TessellateWedgesRenderStep[EvenOdd]
671             case 3:                    // kSrcOver - CoverBoundsRenderStep[RegularCover]
672                 // solid_srcover, kNonSimpleShape, kR_4_DS
673                 settings = kPrecompileCases[2];
674                 expectedNumPipelines = 11;   // This is pretty bad for just 2 Pipelines
675                 break;
676 
677             // 4 and 13 share the same paintOptions
678             case 4:  // AnalyticBlurRenderStep
679 #if 0
680                 // We need to handle AnalyticBlurs differently (b/403264070)
681                 // blend_porter_duff_color_filter_srcover(), kAnalyticBlur, kBGRA_1_D
682                 settings = kPrecompileCases[0];
683                 expectedNumPipelines = 1;
684                 break;
685 #else
686                 continue;
687 #endif
688 
689             case 13: // CoverageMaskRenderStep
690                 // this case could be greatly reduced if CoverageMaskRenderStep were split out
691                 // blend_porter_duff_color_filter_srcover(), kNonSimpleShape, kBGRA_1_D
692                 settings = kPrecompileCases[1];
693                 expectedNumPipelines = 11; // This is pretty bad for just 1 Pipeline
694                 break;
695 
696             // This is the only AlphaOnlyPaintColor case so, we're going to pass for now
697             case 14:
698                 continue;
699 
700             // For now, we're passing on the AnalyticClip Pipelines
701             case 5:  // same as 4 but with an AnalyticClip
702             case 12:
703             case 20:
704             case 55:
705                 continue;
706 
707             // The two text pipelines (7 and 24) just differ in render pass settings (one MSAA, the
708             // other not)
709             case 7:
710                 // solid_srcover(), kBitmapText_Mask, kBGRA_1_D
711                 settings = kPrecompileCases[3];
712                 expectedNumPipelines = 1;
713                 break;
714             case 24:
715                 // solid_srcover(), kBitmapText_Mask, kBGRA_4_DS
716                 settings = kPrecompileCases[4];
717                 expectedNumPipelines = 1;
718                 break;
719 
720             // 21 & 22 form a pair (since they both need kNonSimpleShape)
721             case 21: // kSrcOver - TessellateStrokesRenderStep
722             case 22: // kSrcOver - TessellateWedgesRenderStep[Convex]
723                 // solid_srcover(), kNonSimpleShape,  kBGRA_4_D
724                 settings = kPrecompileCases[5];
725                 expectedNumPipelines = 11;  // very bad for 2 pipelines
726                 break;
727 
728             // Skipping linear gradient text draw. It doesn't seem representative.
729             case 25:
730                 continue;
731 
732             // TODO(robertphillips): these two cases aren't being generated!
733             case 27:  // CoverBoundsRenderStep[InverseCover]
734             case 29:  // CoverBoundsRenderStep[RegularCover]
735                 continue; // they should normally just fall through
736 
737             // the next 9 form a block (since they all need kNonSimpleShape)
738             case 28: // kSrcOver - CoverBoundsRenderStep[RegularCover]
739             case 34: // TessellateWedgesRenderStep[Winding]
740             case 35: // TessellateWedgesRenderStep[EvenOdd]
741             case 36: // kSrcOver - TessellateWedgesRenderStep[Convex]
742             // related utility Pipelines
743             case 57: // MiddleOutFanRenderStep[Winding]
744             case 58: // MiddleOutFanRenderStep[EvenOdd]
745             case 61: // TessellateCurvesRenderStep[Winding]
746             case 62: // TessellateCurvesRenderStep[EvenOdd]
747             case 65: // kSrcOver - TessellateStrokesRenderStep
748                 // solid_srcover(), kNonSimpleShape,  kBGRA_4_DS
749                 settings = kPrecompileCases[6];
750                 expectedNumPipelines = 11;  // not so bad for 9 pipelines
751                 break;
752 
753             // These are the same except for the blend mode
754             // kSrcOver seems fine (since it gets 3 pipelines). kSrc and kClear seem like they
755             // should be narrowed (since they're over-generating a lot)
756             case 6:  // kSrcOver - AnalyticRRectRenderStep
757             case 8:  // kSrcOver - CoverBoundsRenderStep[NonAAFill]
758             case 9:  // kSrc     - CoverBoundsRenderStep[NonAAFill]
759             case 10: // kClear   - CoverBoundsRenderStep[NonAAFill]
760             case 15: // kSrcOver - PerEdgeAAQuadRenderStep
761                 // solid_clear_src_srcover(), kSimpleShape, kBGRA_1_D
762                 settings = kPrecompileCases[8];
763                 // This is 3 each for kClear, kSrc and kSrcOver:
764                 //     AnalyticRRectRenderStep
765                 //     CoverBoundsRenderStep[NonAAFill]
766                 //     PerEdgeAAQuadRenderStep
767                 expectedNumPipelines = 9; // This is pretty bad for 5 pipelines
768                 break;
769 
770             case 26: // kSrcOver - CircularArcRenderStep
771                 // solid_srcover(), kCircularArc, kBGRA_4_DS
772                 settings = kPrecompileCases[7];
773                 expectedNumPipelines = 1;
774                 break;
775 
776             case 23: // kSrcOver - AnalyticRRectRenderStep
777             case 30: // kSrcOver - CoverBoundsRenderStep[NonAAFill]
778             case 31: // kClear   - CoverBoundsRenderStep[NonAAFill]
779             case 53: // kSrc     - CoverBoundsRenderStep[NonAAFill]
780                 //  solid_clear_src_srcover(), kSimpleShape, kBGRA_4_DS
781                 settings = kPrecompileCases[9];
782                 // This is 3 each for kClear, kSrc and kSrcOver:
783                 //     AnalyticRRectRenderStep
784                 //     CoverBoundsRenderStep[NonAAFill]
785                 //     PerEdgeAAQuadRenderStep
786                 expectedNumPipelines = 9; // This is pretty bad for 4 pipelines
787                 break;
788 
789             // For all the image paintOptions we could add the option to exclude cubics to
790             // the public API
791             case 11: // CoverBoundsRenderStep[NonAAFill] + HardwareImage(0) + kSrc
792             case 16: // PerEdgeAAQuadRenderStep + HardwareImage(0) + kSrc
793             case 17: // PerEdgeAAQuadRenderStep + HardwareImage(0) + kSrcOver
794             case 19: // PerEdgeAAQuadRenderStep + Image(0) + kSrcOver
795             case 38: // CoverBoundsRenderStep[NonAAFill] + HardwareImage(0) + kSrcOver
796                 // image_premul_src_srcover(), kSimpleShape, kBGRA_1_D
797                 settings = kPrecompileCases[10];
798                 expectedNumPipelines = 24; // a bad deal for 5 pipelines
799                 break;
800 
801             // same as except 16 except it has ColorSpaceTransformSRGB
802             case 18: // PerEdgeAAQuadRenderStep + HardwareImage(0) + kSrc
803                 // image_srgb_src(), kSimpleShape, kBGRA_1_D_SRGB
804                 settings = kPrecompileCases[12];
805                 expectedRenderPassSettings.fDstCS = SkColorSpace::MakeSRGB();
806                 expectedNumPipelines = 12;  // a bad deal for 1 pipeline
807                 break;
808 
809             case 32: // CoverBoundsRenderStep[NonAAFill] + HardwareImage(0) + kSrcOver
810             case 33: // PerEdgeAAQuadRenderStep + HardwareImage(0) + kSrcOver
811             case 60: // PerEdgeAAQuadRenderStep + Image(0) + kSrcOver
812                 // image_premul_srcover(), kSimpleShape, kBGRA_4_DS
813                 settings = kPrecompileCases[11];
814                 expectedNumPipelines = 12; // a bad deal for 3 pipelines
815                 break;
816             default:
817                 continue;
818         }
819 
820         SkAssertResult(settings.fRenderPassProps == expectedRenderPassSettings);
821         DrawTypeFlags expectedDrawTypeFlags = get_draw_type_flags(kCases[i]);
822         SkAssertResult(settings.fDrawTypeFlags == expectedDrawTypeFlags);
823 
824         if (settings.fRenderPassProps.fRequiresMSAA && caps->loadOpAffectsMSAAPipelines()) {
825             expectedNumPipelines *= 2; // due to wgpu::LoadOp::ExpandResolveTexture
826         }
827 
828         run_test(precompileContext.get(), reporter,
829                  { kCases, std::size(kCases) }, i,
830                  settings, expectedNumPipelines);
831     }
832 }
833 
834 #endif // SK_GRAPHITE
835