xref: /aosp_15_r20/external/skia/tests/graphite/precompile/ChromePrecompileTest.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
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 "include/gpu/graphite/PrecompileContext.h"
14 #include "include/gpu/graphite/precompile/PaintOptions.h"
15 #include "include/gpu/graphite/precompile/Precompile.h"
16 #include "include/gpu/graphite/precompile/PrecompileColorFilter.h"
17 #include "include/gpu/graphite/precompile/PrecompileShader.h"
18 #include "src/gpu/graphite/ContextPriv.h"
19 #include "src/gpu/graphite/ContextUtils.h"
20 #include "src/gpu/graphite/GraphicsPipelineDesc.h"
21 #include "src/gpu/graphite/PrecompileContextPriv.h"
22 #include "src/gpu/graphite/RenderPassDesc.h"
23 #include "src/gpu/graphite/RendererProvider.h"
24 #include "tools/graphite/UniqueKeyUtils.h"
25 
26 using namespace::skgpu::graphite;
27 
28 namespace {
29 
30 // "SolidColor SrcOver"
solid_srcover()31 PaintOptions solid_srcover() {
32     PaintOptions paintOptions;
33     paintOptions.setBlendModes({ SkBlendMode::kSrcOver });
34     return paintOptions;
35 }
36 
37 // "SolidColor Src"
solid_src()38 PaintOptions solid_src() {
39     PaintOptions paintOptions;
40     paintOptions.setBlendModes({ SkBlendMode::kSrc });
41     return paintOptions;
42 }
43 
44 // "LocalMatrix [ Compose [ HardwareImage(0) ColorSpaceTransform ] ] SrcOver"
image_srcover()45 PaintOptions image_srcover() {
46     PaintOptions paintOptions;
47     paintOptions.setShaders({ PrecompileShaders::Image() });
48     paintOptions.setBlendModes({ SkBlendMode::kSrcOver });
49     return paintOptions;
50 }
51 
52 // "LocalMatrix [ Compose [ HardwareImage(0) ColorSpaceTransform ] ] Src"
image_src()53 PaintOptions image_src() {
54     PaintOptions paintOptions;
55     paintOptions.setShaders({ PrecompileShaders::Image() });
56     paintOptions.setBlendModes({ SkBlendMode::kSrc });
57     return paintOptions;
58 }
59 
60 // "LocalMatrix [ Compose [ LinearGradient4 ColorSpaceTransform ] ] SrcOver"
lineargrad_srcover()61 PaintOptions lineargrad_srcover() {
62     PaintOptions paintOptions;
63     paintOptions.setShaders({ PrecompileShaders::LinearGradient() });
64     paintOptions.setBlendModes({ SkBlendMode::kSrcOver });
65     return paintOptions;
66 }
67 
68 // "Compose [ LocalMatrix [ Compose [ LinearGradient4 ColorSpaceTransform ] ] Dither ] SrcOver"
lineargrad_srcover_dithered()69 PaintOptions lineargrad_srcover_dithered() {
70     PaintOptions paintOptions;
71     paintOptions.setShaders({ PrecompileShaders::LinearGradient() });
72     paintOptions.setBlendModes({ SkBlendMode::kSrcOver });
73     paintOptions.setDither(/* dither= */ true);
74     return paintOptions;
75 }
76 
77 // "Compose [ SolidColor Blend [ SolidColor Passthrough BlendModeBlender ] ] SrcOver"
blend_color_filter_srcover()78 [[maybe_unused]] PaintOptions blend_color_filter_srcover() {
79     PaintOptions paintOptions;
80     paintOptions.setBlendModes({ SkBlendMode::kSrcOver });
81     paintOptions.setColorFilters({ PrecompileColorFilters::Blend() });
82     return paintOptions;
83 }
84 
85 // "RP(color: Dawn(f=23,s=1), resolve: {}, ds: Dawn(f=39,s=1), samples: 1, swizzle: rgba)"
86 // Single sampled BGRA w/ just depth
bgra_1_depth()87 RenderPassProperties bgra_1_depth() {
88     return { DepthStencilFlags::kDepth, kBGRA_8888_SkColorType, /* requiresMSAA= */ false };
89 }
90 
91 // "RP(color: Dawn(f=23,s=4), resolve: Dawn(f=23,s=1), ds: Dawn(f=39,s=4), samples: 4, swizzle: rgba)"
92 // MSAA BGRA w/ just depth
bgra_4_depth()93 RenderPassProperties bgra_4_depth() {
94     return { DepthStencilFlags::kDepth, kBGRA_8888_SkColorType, /* requiresMSAA= */ true };
95 }
96 
97 // "RP(color: Dawn(f=23,s=4), resolve: Dawn(f=23,s=1), ds: Dawn(f=41,s=4), samples: 4, swizzle: rgba)"
98 // MSAA BGRA w/ depth and stencil
bgra_4_depth_stencil()99 RenderPassProperties bgra_4_depth_stencil() {
100     return { DepthStencilFlags::kDepthStencil, kBGRA_8888_SkColorType, /* requiresMSAA= */ true };
101 }
102 
103 // Precompile with the provided paintOptions, drawType, and RenderPassSettings then verify that
104 // the expected string is in the generated set.
105 // Additionally, verify that overgeneration is within expected tolerances.
106 // If you add an additional RenderStep you may need to increase the tolerance values.
run_test(PrecompileContext * precompileContext,skiatest::Reporter * reporter,const char * expectedString,size_t caseID,const PaintOptions & paintOptions,DrawTypeFlags drawType,const RenderPassProperties & renderPassSettings,unsigned int allowedOvergeneration)107 void run_test(PrecompileContext* precompileContext,
108               skiatest::Reporter* reporter,
109               const char* expectedString, size_t caseID,
110               const PaintOptions& paintOptions,
111               DrawTypeFlags drawType,
112               const RenderPassProperties& renderPassSettings,
113               unsigned int allowedOvergeneration) {
114 
115     precompileContext->priv().globalCache()->resetGraphicsPipelines();
116 
117     Precompile(precompileContext, paintOptions, drawType, { &renderPassSettings, 1 });
118 
119     std::vector<std::string> generated;
120 
121     {
122         const RendererProvider* rendererProvider = precompileContext->priv().rendererProvider();
123         const ShaderCodeDictionary* dict = precompileContext->priv().shaderCodeDictionary();
124 
125         std::vector<skgpu::UniqueKey> generatedKeys;
126 
127         UniqueKeyUtils::FetchUniqueKeys(precompileContext, &generatedKeys);
128 
129         for (const skgpu::UniqueKey& key : generatedKeys) {
130             GraphicsPipelineDesc pipelineDesc;
131             RenderPassDesc renderPassDesc;
132             UniqueKeyUtils::ExtractKeyDescs(precompileContext, key, &pipelineDesc, &renderPassDesc);
133 
134             const RenderStep* renderStep = rendererProvider->lookup(pipelineDesc.renderStepID());
135             generated.push_back(GetPipelineLabel(dict, renderPassDesc, renderStep,
136                                                  pipelineDesc.paintParamsID()));
137         }
138     }
139 
140     bool correctGenerationAmt = generated.size() == allowedOvergeneration;
141     REPORTER_ASSERT(reporter, correctGenerationAmt,
142                     "case %zu overgenerated - %zu > %d\n",
143                     caseID, generated.size(), allowedOvergeneration);
144 
145     const size_t len = strlen(expectedString);
146 
147     bool foundIt = false;
148     for (size_t i = 0; i < generated.size(); ++i) {
149         // The generated strings have trailing whitespace
150         if (!strncmp(expectedString, generated[i].c_str(), len)) {
151             foundIt = true;
152             break;
153         }
154     }
155 
156     REPORTER_ASSERT(reporter, foundIt);
157 
158 #ifdef SK_DEBUG
159     if (foundIt && correctGenerationAmt) {
160         return;
161     }
162 
163     SkDebugf("Expected string:\n%s\n%s in %zu strings:\n",
164              expectedString,
165              foundIt ? "found" : "NOT found",
166              generated.size());
167 
168     for (size_t i = 0; i < generated.size(); ++i) {
169         SkDebugf("%zu: %s\n", i, generated[i].c_str());
170     }
171 #endif
172 }
173 
174 // The pipeline strings were created using the Dawn Metal backend so that is the only viable
175 // comparison
is_dawn_metal_context_type(skgpu::ContextType type)176 bool is_dawn_metal_context_type(skgpu::ContextType type) {
177     return type == skgpu::ContextType::kDawn_Metal;
178 }
179 
180 } // anonymous namespace
181 
182 
183 DEF_GRAPHITE_TEST_FOR_CONTEXTS(ChromePrecompileTest, is_dawn_metal_context_type,
184                                reporter, context, /* testContext */, CtsEnforcement::kNever) {
185 
186     std::unique_ptr<PrecompileContext> precompileContext = context->makePrecompileContext();
187     const skgpu::graphite::Caps* caps = precompileContext->priv().caps();
188 
189     TextureInfo textureInfo = caps->getDefaultSampledTextureInfo(kBGRA_8888_SkColorType,
190                                                                  skgpu::Mipmapped::kNo,
191                                                                  skgpu::Protected::kNo,
192                                                                  skgpu::Renderable::kYes);
193 
194     TextureInfo msaaTex = caps->getDefaultMSAATextureInfo(textureInfo, Discardable::kYes);
195 
196     if (msaaTex.numSamples() <= 1) {
197         // The following pipelines rely on having MSAA
198         return;
199     }
200 
201 #ifdef SK_ENABLE_VELLO_SHADERS
202     if (caps->computeSupport()) {
203         // The following pipelines rely on not utilizing Vello
204         return;
205     }
206 #endif
207 
208     // In the following, here is the Dawn mapping from surface type to ID
209     //    RGBA8Unorm = 18
210     //    BGRA8Unorm = 23
211     //    Depth16Unorm = 39
212     //    Depth24PlusStencil8 = 41
213 
214     const char* kCases[] = {
215         // Wikipedia 2018 - these are reordered from the spreadsheet
216         /*  0 */ "RP(color: Dawn(f=23,s=4), resolve: Dawn(f=23,s=1), ds: Dawn(f=41,s=4), samples: 4, swizzle: rgba) + "
217                  "TessellateWedgesRenderStep[winding] + "
218                  "(empty)",
219         /*  1 */ "RP(color: Dawn(f=23,s=4), resolve: Dawn(f=23,s=1), ds: Dawn(f=41,s=4), samples: 4, swizzle: rgba) + "
220                  "TessellateWedgesRenderStep[evenodd] + "
221                  "(empty)",
222         /*  2 */ "RP(color: Dawn(f=23,s=4), resolve: Dawn(f=23,s=1), ds: Dawn(f=41,s=4), samples: 4, swizzle: rgba) + "
223                  "CoverBoundsRenderStep[non-aa-fill] + "
224                  "SolidColor SrcOver",
225         /*  3 */ "RP(color: Dawn(f=23,s=4), resolve: Dawn(f=23,s=1), ds: Dawn(f=41,s=4), samples: 4, swizzle: rgba) + "
226                  "CoverBoundsRenderStep[non-aa-fill] + "
227                  "SolidColor Src",
228         /*  4 */ "RP(color: Dawn(f=23,s=4), resolve: Dawn(f=23,s=1), ds: Dawn(f=41,s=4), samples: 4, swizzle: rgba) + "
229                  "PerEdgeAAQuadRenderStep + "
230                  "LocalMatrix [ Compose [ Image(0) ColorSpaceTransform ] ] SrcOver",
231         /*  5 */ "RP(color: Dawn(f=23,s=4), resolve: Dawn(f=23,s=1), ds: Dawn(f=41,s=4), samples: 4, swizzle: rgba) + "
232                  "PerEdgeAAQuadRenderStep + "
233                  "LocalMatrix [ Compose [ HardwareImage(0) ColorSpaceTransform ] ] SrcOver",
234         /*  6 */ "RP(color: Dawn(f=23,s=4), resolve: Dawn(f=23,s=1), ds: Dawn(f=41,s=4), samples: 4, swizzle: rgba) + "
235                  "CoverBoundsRenderStep[non-aa-fill] + "
236                  "LocalMatrix [ Compose [ HardwareImage(0) ColorSpaceTransform ] ] SrcOver",
237         /*  7 */ "RP(color: Dawn(f=23,s=4), resolve: Dawn(f=23,s=1), ds: Dawn(f=41,s=4), samples: 4, swizzle: rgba) + "
238                  "AnalyticRRectRenderStep + "
239                  "Compose [ LocalMatrix [ Compose [ LinearGradient4 ColorSpaceTransform ] ] Dither ] SrcOver",
240         /*  8 */ "RP(color: Dawn(f=23,s=4), resolve: Dawn(f=23,s=1), ds: Dawn(f=41,s=4), samples: 4, swizzle: rgba) + "
241                  "CoverBoundsRenderStep[non-aa-fill] + "
242                  "Compose [ LocalMatrix [ Compose [ LinearGradient4 ColorSpaceTransform ] ] Dither ] SrcOver",
243         /*  9 */ "RP(color: Dawn(f=23,s=4), resolve: Dawn(f=23,s=1), ds: Dawn(f=41,s=4), samples: 4, swizzle: rgba) + "
244                  "BitmapTextRenderStep[mask] + "
245                  "LocalMatrix [ Compose [ LinearGradient4 ColorSpaceTransform ] ] SrcOver",
246         /* 10 */ "RP(color: Dawn(f=23,s=4), resolve: Dawn(f=23,s=1), ds: Dawn(f=41,s=4), samples: 4, swizzle: rgba) + "
247                  "BitmapTextRenderStep[mask] + "
248                  "SolidColor SrcOver",
249         /* 11 */ "RP(color: Dawn(f=23,s=1), resolve: {}, ds: Dawn(f=39,s=1), samples: 1, swizzle: rgba) + "
250                  "AnalyticRRectRenderStep + "
251                  "SolidColor SrcOver",
252         /* 12 */ "RP(color: Dawn(f=23,s=1), resolve: {}, ds: Dawn(f=39,s=1), samples: 1, swizzle: rgba) + "
253                  "CoverBoundsRenderStep[non-aa-fill] + "
254                  "SolidColor SrcOver",
255         /* 13 */ "RP(color: Dawn(f=23,s=1), resolve: {}, ds: Dawn(f=39,s=1), samples: 1, swizzle: rgba) + "
256                  "PerEdgeAAQuadRenderStep + "
257                  "LocalMatrix [ Compose [ HardwareImage(0) ColorSpaceTransform ] ] Src",
258         /* 14 */ "RP(color: Dawn(f=23,s=1), resolve: {}, ds: Dawn(f=39,s=1), samples: 1, swizzle: rgba) + "
259                  "CoverBoundsRenderStep[non-aa-fill] + "
260                  "LocalMatrix [ Compose [ HardwareImage(0) ColorSpaceTransform ] ] SrcOver",
261         /* 15 */ "RP(color: Dawn(f=23,s=4), resolve: Dawn(f=23,s=1), ds: Dawn(f=39,s=4), samples: 4, swizzle: rgba) + "
262                  "TessellateWedgesRenderStep[convex] + "
263                  "SolidColor SrcOver",
264         /* 16 */ "RP(color: Dawn(f=23,s=4), resolve: Dawn(f=23,s=1), ds: Dawn(f=39,s=4), samples: 4, swizzle: rgba) + "
265                  "TessellateStrokesRenderStep + "
266                  "SolidColor SrcOver",
267         /* 17 */ "RP(color: Dawn(f=23,s=1), resolve: {}, ds: Dawn(f=39,s=1), samples: 1, swizzle: rgba) + "
268                  "AnalyticBlurRenderStep + "
269                  "Compose [ SolidColor Blend [ SolidColor Passthrough BlendModeBlender ] ] SrcOver",
270         /* 18 */ "RP(color: Dawn(f=23,s=1), resolve: {}, ds: Dawn(f=39,s=1), samples: 1, swizzle: rgba) + "
271                  "CoverBoundsRenderStep[non-aa-fill] + "
272                  "SolidColor Src",
273         /* 19 */ "RP(color: Dawn(f=23,s=1), resolve: {}, ds: Dawn(f=39,s=1), samples: 1, swizzle: rgba) + "
274                  "CoverBoundsRenderStep[non-aa-fill] + "
275                  "Compose [ LocalMatrix [ Compose [ LinearGradient4 ColorSpaceTransform ] ] Dither ] SrcOver",
276     };
277 
278     for (size_t i = 0; i < std::size(kCases); ++i) {
279         PaintOptions paintOptions;
280         DrawTypeFlags drawTypeFlags = DrawTypeFlags::kSimpleShape;
281         RenderPassProperties renderPassSettings;
282         unsigned int allowedOvergeneration = 0;
283 
284         switch (i) {
285             case 0:            [[fallthrough]];
286             case 1:
287                 paintOptions = solid_srcover();
288                 drawTypeFlags = DrawTypeFlags::kNonSimpleShape;
289                 renderPassSettings = bgra_4_depth_stencil();
290                 allowedOvergeneration = 11;
291                 break;
292             case 2:
293                 paintOptions = solid_srcover();
294                 drawTypeFlags = DrawTypeFlags::kSimpleShape;
295                 renderPassSettings = bgra_4_depth_stencil();
296                 allowedOvergeneration = 5;
297                 break;
298             case 3: // only differs from 18 by MSAA and depth vs depth-stencil
299                 paintOptions = solid_src();
300                 drawTypeFlags = DrawTypeFlags::kSimpleShape;
301                 renderPassSettings = bgra_4_depth_stencil();
302                 allowedOvergeneration = 5; // a lot for a rectangle clear - all RenderSteps
303                 break;
304             case 4: // 4 is part of an AA image rect draw that can't use HW tiling
305             case 5: // 5 & 6 together make up an AA image rect draw w/ a filled center
306             case 6:
307                 paintOptions = image_srcover();
308                 drawTypeFlags = DrawTypeFlags::kSimpleShape;
309                 renderPassSettings = bgra_4_depth_stencil();
310                 allowedOvergeneration = 30;
311                 break;
312             case 7: // 7 & 8 are combined pair
313             case 8:
314                 paintOptions = lineargrad_srcover_dithered();
315                 drawTypeFlags = DrawTypeFlags::kSimpleShape;
316                 renderPassSettings = bgra_4_depth_stencil();
317                 allowedOvergeneration = 15; // 3x from gradient, 12x from RenderSteps
318                 break;
319             case 9:
320                 paintOptions = lineargrad_srcover();
321                 drawTypeFlags = DrawTypeFlags::kBitmapText_Mask;
322                 renderPassSettings = bgra_4_depth_stencil();
323                 allowedOvergeneration = 3; // from the 3 internal gradient alternatives
324                 break;
325             case 10:
326                 paintOptions = solid_srcover();
327                 drawTypeFlags = DrawTypeFlags::kBitmapText_Mask;
328                 renderPassSettings = bgra_4_depth_stencil();
329                 allowedOvergeneration = 1;
330                 break;
331             case 11: // 11 & 12 are a pair - an RRect draw w/ a non-aa-fill center
332             case 12:
333                 paintOptions = solid_srcover();
334                 drawTypeFlags = DrawTypeFlags::kSimpleShape;
335                 renderPassSettings = bgra_1_depth();
336                 allowedOvergeneration = 5;  // all from RenderSteps
337                 break;
338             case 13:
339                 paintOptions = image_src();
340                 drawTypeFlags = DrawTypeFlags::kSimpleShape;
341                 renderPassSettings = bgra_1_depth();
342                 // This is a lot for a kSrc image draw:
343                 allowedOvergeneration = 30; // 3x of this are the paint combos,
344                                             // the rest are the RenderSteps!!
345                 break;
346             case 14:
347                 paintOptions = image_srcover();
348                 drawTypeFlags = DrawTypeFlags::kSimpleShape;
349                 renderPassSettings = bgra_1_depth();
350                 allowedOvergeneration = 30; // !!!! - a lot for just a non-aa image rect draw
351                 break;
352             case 15:
353             case 16:
354                 paintOptions = solid_srcover();
355                 drawTypeFlags = DrawTypeFlags::kNonSimpleShape;
356                 renderPassSettings = bgra_4_depth();
357                 allowedOvergeneration = 11;
358                 break;
359             case 17:
360                 // After https://skia-review.googlesource.com/c/skia/+/887476 ([graphite] Split up
361                 // universal blend shader snippet) this case no longer exists/is reproducible.
362                 //
363                 //  paintOptions = blend_color_filter_srcover();
364                 //  drawTypeFlags = DrawTypeFlags::kSimpleShape;
365                 //  renderPassSettings = bgra_1_depth();
366                 //  allowedOvergeneration = 4;
367                 continue;
368             case 18: // only differs from 3 by MSAA and depth vs depth-stencil
369                 paintOptions = solid_src();
370                 drawTypeFlags = DrawTypeFlags::kSimpleShape;
371                 renderPassSettings = bgra_1_depth();
372                 allowedOvergeneration = 5; // a lot for a rectangle clear - all RenderSteps
373                 break;
374             case 19:
375                 paintOptions = lineargrad_srcover_dithered();
376                 drawTypeFlags = DrawTypeFlags::kSimpleShape;
377                 renderPassSettings = bgra_1_depth();
378                 allowedOvergeneration = 15; // 3x from gradient, rest from RenderSteps
379                 break;
380             default:
381                 continue;
382         }
383 
384         if (renderPassSettings.fRequiresMSAA && caps->loadOpAffectsMSAAPipelines()) {
385             allowedOvergeneration *= 2; // due to ExpandResolveTextureLoadOp
386         }
387 
388         run_test(precompileContext.get(), reporter,
389                  kCases[i], i,
390                  paintOptions, drawTypeFlags, renderPassSettings, allowedOvergeneration);
391     }
392 }
393 
394 #endif // SK_GRAPHITE
395