xref: /aosp_15_r20/external/skia/src/gpu/graphite/PublicPrecompile.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1 /*
2  * Copyright 2022 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 "include/core/SkColorSpace.h"
9 #include "include/core/SkColorType.h"
10 #include "include/gpu/graphite/PrecompileContext.h"
11 #include "include/gpu/graphite/precompile/Precompile.h"
12 #include "include/gpu/graphite/precompile/PrecompileColorFilter.h"
13 #include "src/gpu/graphite/AndroidSpecificPrecompile.h"
14 #include "src/gpu/graphite/Caps.h"
15 #include "src/gpu/graphite/ContextPriv.h"
16 #include "src/gpu/graphite/ContextUtils.h"
17 #include "src/gpu/graphite/GraphicsPipeline.h"
18 #include "src/gpu/graphite/GraphicsPipelineDesc.h"
19 #include "src/gpu/graphite/KeyContext.h"
20 #include "src/gpu/graphite/Log.h"
21 #include "src/gpu/graphite/PrecompileContextPriv.h"
22 #include "src/gpu/graphite/PrecompileInternal.h"
23 #include "src/gpu/graphite/RenderPassDesc.h"
24 #include "src/gpu/graphite/Renderer.h"
25 #include "src/gpu/graphite/RendererProvider.h"
26 #include "src/gpu/graphite/ResourceProvider.h"
27 #include "src/gpu/graphite/RuntimeEffectDictionary.h"
28 #include "src/gpu/graphite/UniquePaintParamsID.h"
29 #include "src/gpu/graphite/precompile/PaintOptionsPriv.h"
30 
31 namespace {
32 
33 using namespace skgpu::graphite;
34 
compile(const RendererProvider * rendererProvider,ResourceProvider * resourceProvider,const KeyContext & keyContext,UniquePaintParamsID uniqueID,DrawTypeFlags drawTypes,const RenderPassDesc & renderPassDesc,bool withPrimitiveBlender,Coverage coverage)35 void compile(const RendererProvider* rendererProvider,
36              ResourceProvider* resourceProvider,
37              const KeyContext& keyContext,
38              UniquePaintParamsID uniqueID,
39              DrawTypeFlags drawTypes,
40              const RenderPassDesc& renderPassDesc,
41              bool withPrimitiveBlender,
42              Coverage coverage) {
43     for (const Renderer* r : rendererProvider->renderers()) {
44         if (!(r->drawTypes() & drawTypes)) {
45             continue;
46         }
47 
48         if (r->emitsPrimitiveColor() != withPrimitiveBlender) {
49             // UniqueIDs are explicitly built either w/ or w/o primitiveBlending so must
50             // match what the Renderer requires
51             continue;
52         }
53 
54         if (r->coverage() != coverage) {
55             // For now, UniqueIDs are explicitly built with a specific type of coverage so must
56             // match what the Renderer requires
57             continue;
58         }
59 
60         for (auto&& s : r->steps()) {
61             SkASSERT(!s->performsShading() || s->emitsPrimitiveColor() == withPrimitiveBlender);
62 
63             UniquePaintParamsID paintID = s->performsShading() ? uniqueID
64                                                                : UniquePaintParamsID::InvalidID();
65             GraphicsPipelineDesc pipelineDesc(s, paintID);
66 
67             sk_sp<GraphicsPipeline> pipeline = resourceProvider->findOrCreateGraphicsPipeline(
68                     keyContext.rtEffectDict(),
69                     pipelineDesc,
70                     renderPassDesc,
71                     PipelineCreationFlags::kForPrecompilation);
72             if (!pipeline) {
73                 SKGPU_LOG_W("Failed to create GraphicsPipeline in precompile!");
74                 return;
75             }
76         }
77     }
78 }
79 
80 } // anonymous namespace
81 
82 namespace skgpu::graphite {
83 
AndroidSpecificPrecompile(PrecompileContext * precompileContext,RuntimeEffectDictionary * rteDict,const GraphicsPipelineDesc & pipelineDesc,const RenderPassDesc & renderPassDesc)84 bool AndroidSpecificPrecompile(PrecompileContext* precompileContext,
85                                RuntimeEffectDictionary* rteDict,
86                                const GraphicsPipelineDesc& pipelineDesc,
87                                const RenderPassDesc& renderPassDesc) {
88     ResourceProvider* resourceProvider = precompileContext->priv().resourceProvider();
89 
90     sk_sp<GraphicsPipeline> pipeline = resourceProvider->findOrCreateGraphicsPipeline(
91             rteDict,
92             pipelineDesc,
93             renderPassDesc,
94             PipelineCreationFlags::kForPrecompilation);
95     if (!pipeline) {
96         SKGPU_LOG_W("Failed to create GraphicsPipeline in precompile!");
97         return false;
98     }
99 
100     return true;
101 }
102 
Precompile(PrecompileContext * precompileContext,const PaintOptions & options,DrawTypeFlags drawTypes,SkSpan<const RenderPassProperties> renderPassProperties)103 void Precompile(PrecompileContext* precompileContext,
104                 const PaintOptions& options,
105                 DrawTypeFlags drawTypes,
106                 SkSpan<const RenderPassProperties> renderPassProperties) {
107 
108     ShaderCodeDictionary* dict = precompileContext->priv().shaderCodeDictionary();
109     const Caps* caps = precompileContext->priv().caps();
110 
111     auto rtEffectDict = std::make_unique<RuntimeEffectDictionary>();
112 
113     for (const RenderPassProperties& rpp : renderPassProperties) {
114         // TODO: Allow the client to pass in mipmapping and protection too?
115         TextureInfo info = caps->getDefaultSampledTextureInfo(rpp.fDstCT,
116                                                               Mipmapped::kNo,
117                                                               Protected::kNo,
118                                                               Renderable::kYes);
119 
120         Swizzle writeSwizzle = caps->getWriteSwizzle(rpp.fDstCT, info);
121 
122         // TODO(robertphillips): address mismatches between the MSAA requirements of the Renderers
123         // associated w/ the requested drawTypes and the specified MSAA setting
124 
125         // On Native Metal, the LoadOp, StoreOp and clearColor fields don't influence
126         // the actual RenderPassDescKey.
127         // For Dawn, the LoadOp will sometimes matter. We add an extra LoadOp::kLoad combination
128         // when necessary.
129         const LoadOp kLoadOps[2] = { LoadOp::kClear, LoadOp::kLoad };
130 
131         int numLoadOps = 1;
132         if (rpp.fRequiresMSAA &&
133             !caps->msaaRenderToSingleSampledSupport() &&
134             caps->loadOpAffectsMSAAPipelines()) {
135             numLoadOps = 2;
136         }
137 
138         for (int loadOpIndex = 0; loadOpIndex < numLoadOps; ++loadOpIndex) {
139             const RenderPassDesc renderPassDesc =
140                     RenderPassDesc::Make(caps,
141                                          info,
142                                          kLoadOps[loadOpIndex],
143                                          StoreOp::kStore,
144                                          rpp.fDSFlags,
145                                          /* clearColor= */ { .0f, .0f, .0f, .0f },
146                                          rpp.fRequiresMSAA,
147                                          writeSwizzle);
148 
149             SkColorInfo ci(rpp.fDstCT, kPremul_SkAlphaType, nullptr);
150             KeyContext keyContext(caps, dict, rtEffectDict.get(), ci);
151 
152             for (Coverage coverage : { Coverage::kNone, Coverage::kSingleChannel }) {
153                 PrecompileCombinations(
154                         precompileContext->priv().rendererProvider(),
155                         precompileContext->priv().resourceProvider(),
156                         options, keyContext,
157                         static_cast<DrawTypeFlags>(drawTypes & ~(DrawTypeFlags::kBitmapText_Color |
158                                                                  DrawTypeFlags::kBitmapText_LCD |
159                                                                  DrawTypeFlags::kSDFText_LCD |
160                                                                  DrawTypeFlags::kDrawVertices)),
161                         /* withPrimitiveBlender= */ false,
162                         coverage,
163                         renderPassDesc);
164             }
165 
166             if (drawTypes & DrawTypeFlags::kBitmapText_Color) {
167                 // For color emoji text, shaders don't affect the final color
168                 PaintOptions tmp = options;
169                 tmp.setShaders({});
170 
171                 // ARGB text doesn't emit coverage and always has a primitive blender
172                 PrecompileCombinations(precompileContext->priv().rendererProvider(),
173                                        precompileContext->priv().resourceProvider(),
174                                        tmp,
175                                        keyContext,
176                                        DrawTypeFlags::kBitmapText_Color,
177                                        /* withPrimitiveBlender= */ true,
178                                        Coverage::kNone,
179                                        renderPassDesc);
180             }
181 
182             if (drawTypes & (DrawTypeFlags::kBitmapText_LCD | DrawTypeFlags::kSDFText_LCD)) {
183                 // LCD-based text always emits LCD coverage but never has primitiveBlenders
184                 PrecompileCombinations(
185                         precompileContext->priv().rendererProvider(),
186                         precompileContext->priv().resourceProvider(),
187                         options, keyContext,
188                         static_cast<DrawTypeFlags>(drawTypes & (DrawTypeFlags::kBitmapText_LCD |
189                                                                 DrawTypeFlags::kSDFText_LCD)),
190                         /* withPrimitiveBlender= */ false,
191                         Coverage::kLCD,
192                         renderPassDesc);
193             }
194 
195             if (drawTypes & DrawTypeFlags::kDrawVertices) {
196                 // drawVertices w/ colors use a primitiveBlender while those w/o don't. It never
197                 // emits coverage.
198                 for (bool withPrimitiveBlender : { true, false }) {
199                     PrecompileCombinations(precompileContext->priv().rendererProvider(),
200                                            precompileContext->priv().resourceProvider(),
201                                            options, keyContext,
202                                            DrawTypeFlags::kDrawVertices,
203                                            withPrimitiveBlender,
204                                            Coverage::kNone,
205                                            renderPassDesc);
206                 }
207             }
208         }
209     }
210 }
211 
PrecompileCombinations(const RendererProvider * rendererProvider,ResourceProvider * resourceProvider,const PaintOptions & options,const KeyContext & keyContext,DrawTypeFlags drawTypes,bool withPrimitiveBlender,Coverage coverage,const RenderPassDesc & renderPassDescIn)212 void PrecompileCombinations(const RendererProvider* rendererProvider,
213                             ResourceProvider* resourceProvider,
214                             const PaintOptions& options,
215                             const KeyContext& keyContext,
216                             DrawTypeFlags drawTypes,
217                             bool withPrimitiveBlender,
218                             Coverage coverage,
219                             const RenderPassDesc& renderPassDescIn) {
220     if (drawTypes == DrawTypeFlags::kNone) {
221         return;
222     }
223 
224     // Since the precompilation path's uniforms aren't used and don't change the key,
225     // the exact layout doesn't matter
226     PipelineDataGatherer gatherer(Layout::kMetal);
227 
228     options.priv().buildCombinations(
229         keyContext,
230         &gatherer,
231         drawTypes,
232         withPrimitiveBlender,
233         coverage,
234         renderPassDescIn,
235         [rendererProvider, resourceProvider, &keyContext](UniquePaintParamsID uniqueID,
236                                                           DrawTypeFlags drawTypes,
237                                                           bool withPrimitiveBlender,
238                                                           Coverage coverage,
239                                                           const RenderPassDesc& renderPassDesc) {
240                compile(rendererProvider,
241                        resourceProvider,
242                        keyContext,
243                        uniqueID,
244                        drawTypes,
245                        renderPassDesc,
246                        withPrimitiveBlender,
247                        coverage);
248         });
249 }
250 
251 } // namespace skgpu::graphite
252