[graphite] Update ChromePrecompileTest for upcoming changes This CL doesn't swap out the old kCases for the new set but does update the surrounding infrastructure. This test is split between: documenting how one can go from a Pipeline label to Precompile inputs - i.e., the get_render_pass_properties/get_draw_type_flags methods aggregating Precompile inputs that can just be copied over to Chrome - each paintOptions/drawTypeFlags/renderPassSetting trio gauging how bad the over-generation is going to be for Chrome - the expectedNumPipelines values Bug: b/358074434 Change-Id: I900994629c34fc71a3cf90d811fd4f1c738f5b24 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/961517 Reviewed-by: Michael Ludwig <michaelludwig@google.com> Commit-Queue: Robert Phillips <robertphillips@google.com>
diff --git a/include/gpu/graphite/precompile/Precompile.h b/include/gpu/graphite/precompile/Precompile.h index dd95aec..3660fe5 100644 --- a/include/gpu/graphite/precompile/Precompile.h +++ b/include/gpu/graphite/precompile/Precompile.h
@@ -8,6 +8,7 @@ #ifndef skgpu_graphite_precompile_Precompile_DEFINED #define skgpu_graphite_precompile_Precompile_DEFINED +#include "include/core/SkColorSpace.h" #include "include/core/SkSpan.h" #include "include/gpu/graphite/GraphiteTypes.h" @@ -23,6 +24,14 @@ * a pipeline. */ struct SK_API RenderPassProperties { + bool operator==(const RenderPassProperties& other) const { + return fDSFlags == other.fDSFlags && + fDstCT == other.fDstCT && + fRequiresMSAA == other.fRequiresMSAA && + SkColorSpace::Equals(fDstCS.get(), other.fDstCS.get()); + } + bool operator!= (const RenderPassProperties& other) const { return !(*this == other); } + DepthStencilFlags fDSFlags = DepthStencilFlags::kNone; SkColorType fDstCT = kRGBA_8888_SkColorType; sk_sp<SkColorSpace> fDstCS = nullptr;
diff --git a/tests/graphite/precompile/ChromePrecompileTest.cpp b/tests/graphite/precompile/ChromePrecompileTest.cpp index 5a86af1..f8248b6 100644 --- a/tests/graphite/precompile/ChromePrecompileTest.cpp +++ b/tests/graphite/precompile/ChromePrecompileTest.cpp
@@ -82,44 +82,142 @@ return paintOptions; } +// "RP(color: Dawn(f=R8,s=1), resolve: {}, ds: Dawn(f=D16,s=1), samples: 1, swizzle: a000)", +// Single sampled R w/ just depth +static const RenderPassProperties kR_1_Depth { DepthStencilFlags::kDepth, + kAlpha_8_SkColorType, + /* fDstCS= */ nullptr, + /* fRequiresMSAA= */ false }; + +// "RP(color: Dawn(f=R8,s=4), resolve: Dawn(f=R8,s=1), ds: Dawn(f=D24_S8,s=4), samples: 4, swizzle: a000)", +// MSAA R w/ depth and stencil +static const RenderPassProperties kR_4_DepthStencil { DepthStencilFlags::kDepthStencil, + kAlpha_8_SkColorType, + /* fDstCS= */ nullptr, + /* fRequiresMSAA= */ true }; + // "RP(color: Dawn(f=BGRA8,s=1), resolve: {}, ds: Dawn(f=D16,s=1), samples: 1, swizzle: rgba)" // Single sampled BGRA w/ just depth -RenderPassProperties bgra_1_depth() { - return { DepthStencilFlags::kDepth, - kBGRA_8888_SkColorType, - /* dstColorSpace= */ nullptr, - /* requiresMSAA= */ false }; -} +static const RenderPassProperties kBGRA_1_Depth { DepthStencilFlags::kDepth, + kBGRA_8888_SkColorType, + /* fDstCS= */ nullptr, + /* fRequiresMSAA= */ false }; // "RP(color: Dawn(f=BGRA8,s=4), resolve: Dawn(f=BGRA8,s=1), ds: Dawn(f=D16,s=4), samples: 4, swizzle: rgba)" // MSAA BGRA w/ just depth -RenderPassProperties bgra_4_depth() { - return { DepthStencilFlags::kDepth, - kBGRA_8888_SkColorType, - /* dstColorSpace= */ nullptr, - /* requiresMSAA= */ true }; -} +static const RenderPassProperties kBGRA_4_Depth { DepthStencilFlags::kDepth, + kBGRA_8888_SkColorType, + /* fDstCS= */ nullptr, + /* fRequiresMSAA= */ true }; // "RP(color: Dawn(f=BGRA8,s=4), resolve: Dawn(f=BGRA8,s=1), ds: Dawn(f=D24_S8,s=4), samples: 4, swizzle: rgba)" // MSAA BGRA w/ depth and stencil -RenderPassProperties bgra_4_depth_stencil() { - return { DepthStencilFlags::kDepthStencil, - kBGRA_8888_SkColorType, - /* dstColorSpace= */ nullptr, - /* requiresMSAA= */ true }; +static const RenderPassProperties kBGRA_4_DepthStencil { DepthStencilFlags::kDepthStencil, + kBGRA_8888_SkColorType, + /* fDstCS= */ nullptr, + /* fRequiresMSAA= */ true }; + + +// This helper maps from the RenderPass string in the Pipeline label to the +// RenderPassProperties needed by the Precompile system +// TODO(robertphillips): converting this to a more piecemeal approach might better illuminate +// the mapping between the string and the RenderPassProperties +RenderPassProperties get_render_pass_properties(const char* str) { + static const struct { + const char* fStr; + RenderPassProperties fRenderPassProperties; + } kRenderPassPropertiesMapping[] = { + { "RP(color: Dawn(f=R8,s=1), resolve: {}, ds: Dawn(f=D16,s=1), samples: 1, swizzle: a000)", + kR_1_Depth }, + { "RP(color: Dawn(f=R8,s=4), resolve: Dawn(f=R8,s=1), ds: Dawn(f=D24_S8,s=4), samples: 4, swizzle: a000)", + kR_4_DepthStencil}, + { "RP(color: Dawn(f=BGRA8,s=1), resolve: {}, ds: Dawn(f=D16,s=1), samples: 1, swizzle: rgba)", + kBGRA_1_Depth }, + { "RP(color: Dawn(f=BGRA8,s=4), resolve: Dawn(f=BGRA8,s=1), ds: Dawn(f=D16,s=4), samples: 4, swizzle: rgba)", + kBGRA_4_Depth }, + { "RP(color: Dawn(f=BGRA8,s=4), resolve: Dawn(f=BGRA8,s=1), ds: Dawn(f=D24_S8,s=4), samples: 4, swizzle: rgba)", + kBGRA_4_DepthStencil }, + }; + + for (const auto& rppm : kRenderPassPropertiesMapping) { + if (strstr(str, rppm.fStr)) { + return rppm.fRenderPassProperties; + } + } + + SkAssertResult(0); + return {}; } +// This helper maps from the RenderStep's name in the Pipeline label to the DrawTypeFlag that +// resulted in its use. +DrawTypeFlags get_draw_type_flags(const char* str) { + static const struct { + const char* fStr; + DrawTypeFlags fFlags; + } kDrawTypeFlagsMapping[] = { + { "BitmapTextRenderStep[Mask]", DrawTypeFlags::kBitmapText_Mask }, + { "BitmapTextRenderStep[LCD]", DrawTypeFlags::kBitmapText_LCD }, + { "BitmapTextRenderStep[Color]", DrawTypeFlags::kBitmapText_Color }, + + { "SDFTextRenderStep", DrawTypeFlags::kSDFText }, + { "SDFTextLCDRenderStep", DrawTypeFlags::kSDFText_LCD }, + + { "VerticesRenderStep[Tris]", DrawTypeFlags::kDrawVertices }, + { "VerticesRenderStep[TrisTexCoords]", DrawTypeFlags::kDrawVertices }, + { "VerticesRenderStep[TrisColor]", DrawTypeFlags::kDrawVertices }, + { "VerticesRenderStep[TrisColorTexCoords]", DrawTypeFlags::kDrawVertices }, + { "VerticesRenderStep[Tristrips]", DrawTypeFlags::kDrawVertices }, + { "VerticesRenderStep[TristripsTexCoords]", DrawTypeFlags::kDrawVertices }, + { "VerticesRenderStep[TristripsColor]", DrawTypeFlags::kDrawVertices }, + { "VerticesRenderStep[TristripsColorTexCoords]", DrawTypeFlags::kDrawVertices }, + + // TODO: AnalyticBlurRenderStep and CircularArcRenderStep should be split out into their + // own DrawTypeFlags (e.g., kAnalyticBlur and kCircularArc) + { "AnalyticBlurRenderStep", DrawTypeFlags::kSimpleShape }, + { "AnalyticRRectRenderStep", DrawTypeFlags::kSimpleShape }, + { "CircularArcRenderStep", DrawTypeFlags::kSimpleShape }, + { "CoverBoundsRenderStep[NonAAFill]", DrawTypeFlags::kSimpleShape }, + { "PerEdgeAAQuadRenderStep", DrawTypeFlags::kSimpleShape }, + + { "CoverageMaskRenderStep", DrawTypeFlags::kNonSimpleShape }, + { "CoverBoundsRenderStep[RegularCover]", DrawTypeFlags::kNonSimpleShape }, + { "CoverBoundsRenderStep[InverseCover]", DrawTypeFlags::kNonSimpleShape }, + { "MiddleOutFanRenderStep[EvenOdd]", DrawTypeFlags::kNonSimpleShape }, + { "MiddleOutFanRenderStep[Winding]", DrawTypeFlags::kNonSimpleShape }, + { "TessellateCurvesRenderStep[EvenOdd]", DrawTypeFlags::kNonSimpleShape }, + { "TessellateCurvesRenderStep[Winding]", DrawTypeFlags::kNonSimpleShape }, + { "TessellateStrokesRenderStep", DrawTypeFlags::kNonSimpleShape }, + { "TessellateWedgesRenderStep[Convex]", DrawTypeFlags::kNonSimpleShape }, + { "TessellateWedgesRenderStep[EvenOdd]", DrawTypeFlags::kNonSimpleShape }, + { "TessellateWedgesRenderStep[Winding]", DrawTypeFlags::kNonSimpleShape }, + }; + + for (const auto& dtfm : kDrawTypeFlagsMapping) { + if (strstr(str, dtfm.fStr)) { + SkAssertResult(dtfm.fFlags != DrawTypeFlags::kNone); + return dtfm.fFlags; + } + } + + SkAssertResult(0); + return DrawTypeFlags::kNone; +} + + // Precompile with the provided paintOptions, drawType, and RenderPassSettings then verify that // the expected string is in the generated set. // Additionally, verify that overgeneration is within expected tolerances. // If you add an additional RenderStep you may need to increase the tolerance values. void run_test(PrecompileContext* precompileContext, skiatest::Reporter* reporter, - const char* expectedString, size_t caseID, + SkSpan<const char*> cases, + size_t caseID, const PaintOptions& paintOptions, DrawTypeFlags drawType, const RenderPassProperties& renderPassSettings, unsigned int allowedOvergeneration) { + const char* expectedString = cases[caseID]; precompileContext->priv().globalCache()->resetGraphicsPipelines(); @@ -280,84 +378,89 @@ for (size_t i = 0; i < std::size(kCases); ++i) { PaintOptions paintOptions; - DrawTypeFlags drawTypeFlags = DrawTypeFlags::kSimpleShape; RenderPassProperties renderPassSettings; - unsigned int allowedOvergeneration = 0; + DrawTypeFlags drawTypeFlags = DrawTypeFlags::kNone; + + // TODO(robertphillips): splitting kCases[i] into substrings (based on a " + " separator) + // before passing to the helpers would make this prettier + RenderPassProperties expectedRenderPassSettings = get_render_pass_properties(kCases[i]); + DrawTypeFlags expectedDrawTypeFlags = get_draw_type_flags(kCases[i]); + unsigned int expectedNumPipelines = 0; switch (i) { case 0: [[fallthrough]]; case 1: paintOptions = solid_srcover(); drawTypeFlags = DrawTypeFlags::kNonSimpleShape; - renderPassSettings = bgra_4_depth_stencil(); - allowedOvergeneration = 11; + renderPassSettings = kBGRA_4_DepthStencil; + expectedNumPipelines = 11; break; case 2: paintOptions = solid_srcover(); drawTypeFlags = DrawTypeFlags::kSimpleShape; - renderPassSettings = bgra_4_depth_stencil(); - allowedOvergeneration = 5; + renderPassSettings = kBGRA_4_DepthStencil; + expectedNumPipelines = 5; break; case 3: // only differs from 18 by MSAA and depth vs depth-stencil paintOptions = solid_src(); drawTypeFlags = DrawTypeFlags::kSimpleShape; - renderPassSettings = bgra_4_depth_stencil(); - allowedOvergeneration = 5; // a lot for a rectangle clear - all RenderSteps + renderPassSettings = kBGRA_4_DepthStencil; + expectedNumPipelines = 5; // a lot for a rectangle clear - all RenderSteps break; case 4: // 4 is part of an AA image rect draw that can't use HW tiling case 5: // 5 & 6 together make up an AA image rect draw w/ a filled center case 6: paintOptions = image_srcover(); drawTypeFlags = DrawTypeFlags::kSimpleShape; - renderPassSettings = bgra_4_depth_stencil(); - allowedOvergeneration = 80; + renderPassSettings = kBGRA_4_DepthStencil; + expectedNumPipelines = 80; break; case 7: // 7 & 8 are combined pair case 8: paintOptions = lineargrad_srcover_dithered(); drawTypeFlags = DrawTypeFlags::kSimpleShape; - renderPassSettings = bgra_4_depth_stencil(); - allowedOvergeneration = 15; // 3x from gradient, 12x from RenderSteps + renderPassSettings = kBGRA_4_DepthStencil; + expectedNumPipelines = 15; // 3x from gradient, 12x from RenderSteps break; case 9: paintOptions = lineargrad_srcover(); drawTypeFlags = DrawTypeFlags::kBitmapText_Mask; - renderPassSettings = bgra_4_depth_stencil(); - allowedOvergeneration = 3; // from the 3 internal gradient alternatives + renderPassSettings = kBGRA_4_DepthStencil; + expectedNumPipelines = 3; // from the 3 internal gradient alternatives break; case 10: paintOptions = solid_srcover(); drawTypeFlags = DrawTypeFlags::kBitmapText_Mask; - renderPassSettings = bgra_4_depth_stencil(); - allowedOvergeneration = 1; + renderPassSettings = kBGRA_4_DepthStencil; + expectedNumPipelines = 1; break; case 11: // 11 & 12 are a pair - an RRect draw w/ a non-aa-fill center case 12: paintOptions = solid_srcover(); drawTypeFlags = DrawTypeFlags::kSimpleShape; - renderPassSettings = bgra_1_depth(); - allowedOvergeneration = 5; // all from RenderSteps + renderPassSettings = kBGRA_1_Depth; + expectedNumPipelines = 5; // all from RenderSteps break; case 13: paintOptions = image_src(); drawTypeFlags = DrawTypeFlags::kSimpleShape; - renderPassSettings = bgra_1_depth(); + renderPassSettings = kBGRA_1_Depth; // This is a lot for a kSrc image draw: - allowedOvergeneration = 80; // 8x of this are the paint combos, - // the rest are the RenderSteps!! + expectedNumPipelines = 80; // 8x of this are the paint combos, + // the rest are the RenderSteps!! break; case 14: paintOptions = image_srcover(); drawTypeFlags = DrawTypeFlags::kSimpleShape; - renderPassSettings = bgra_1_depth(); - allowedOvergeneration = 80; // !!!! - a lot for just a non-aa image rect draw + renderPassSettings = kBGRA_1_Depth; + expectedNumPipelines = 80; // !!!! - a lot for just a non-aa image rect draw break; case 15: case 16: paintOptions = solid_srcover(); drawTypeFlags = DrawTypeFlags::kNonSimpleShape; - renderPassSettings = bgra_4_depth(); - allowedOvergeneration = 11; + renderPassSettings = kBGRA_4_Depth; + expectedNumPipelines = 11; break; case 17: // After https://skia-review.googlesource.com/c/skia/+/887476 ([graphite] Split up @@ -371,26 +474,29 @@ case 18: // only differs from 3 by MSAA and depth vs depth-stencil paintOptions = solid_src(); drawTypeFlags = DrawTypeFlags::kSimpleShape; - renderPassSettings = bgra_1_depth(); - allowedOvergeneration = 5; // a lot for a rectangle clear - all RenderSteps + renderPassSettings = kBGRA_1_Depth; + expectedNumPipelines = 5; // a lot for a rectangle clear - all RenderSteps break; case 19: paintOptions = lineargrad_srcover_dithered(); drawTypeFlags = DrawTypeFlags::kSimpleShape; - renderPassSettings = bgra_1_depth(); - allowedOvergeneration = 15; // 3x from gradient, rest from RenderSteps + renderPassSettings = kBGRA_1_Depth; + expectedNumPipelines = 15; // 3x from gradient, rest from RenderSteps break; default: continue; } + SkAssertResult(renderPassSettings == expectedRenderPassSettings); + SkAssertResult(drawTypeFlags == expectedDrawTypeFlags); + if (renderPassSettings.fRequiresMSAA && caps->loadOpAffectsMSAAPipelines()) { - allowedOvergeneration *= 2; // due to ExpandResolveTextureLoadOp + expectedNumPipelines *= 2; // due to wgpu::LoadOp::ExpandResolveTexture } run_test(precompileContext.get(), reporter, - kCases[i], i, - paintOptions, drawTypeFlags, renderPassSettings, allowedOvergeneration); + { kCases, std::size(kCases) }, i, + paintOptions, drawTypeFlags, renderPassSettings, expectedNumPipelines); } }