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 "src/gpu/graphite/PublicPrecompile.h"
9 
10 #include "include/core/SkColorSpace.h"
11 #include "include/core/SkColorType.h"
12 #include "src/gpu/graphite/AttachmentTypes.h"
13 #include "src/gpu/graphite/Caps.h"
14 #include "src/gpu/graphite/ContextPriv.h"
15 #include "src/gpu/graphite/GraphicsPipeline.h"
16 #include "src/gpu/graphite/GraphicsPipelineDesc.h"
17 #include "src/gpu/graphite/KeyContext.h"
18 #include "src/gpu/graphite/Log.h"
19 #include "src/gpu/graphite/PaintOptionsPriv.h"
20 #include "src/gpu/graphite/Renderer.h"
21 #include "src/gpu/graphite/RendererProvider.h"
22 #include "src/gpu/graphite/ResourceProvider.h"
23 #include "src/gpu/graphite/RuntimeEffectDictionary.h"
24 #include "src/gpu/graphite/UniquePaintParamsID.h"
25 
26 namespace {
27 
28 using namespace skgpu::graphite;
29 
compile(const RendererProvider * rendererProvider,ResourceProvider * resourceProvider,const KeyContext & keyContext,UniquePaintParamsID uniqueID,DrawTypeFlags drawTypes,SkSpan<RenderPassDesc> renderPassDescs,bool withPrimitiveBlender)30 void compile(const RendererProvider* rendererProvider,
31              ResourceProvider* resourceProvider,
32              const KeyContext& keyContext,
33              UniquePaintParamsID uniqueID,
34              DrawTypeFlags drawTypes,
35              SkSpan<RenderPassDesc> renderPassDescs,
36              bool withPrimitiveBlender) {
37     for (const Renderer* r : rendererProvider->renderers()) {
38         if (!(r->drawTypes() & drawTypes)) {
39             continue;
40         }
41 
42         if (r->emitsPrimitiveColor() != withPrimitiveBlender) {
43             // UniqueIDs are explicitly built either w/ or w/o primitiveBlending so must
44             // match what the Renderer requires
45             continue;
46         }
47 
48         for (auto&& s : r->steps()) {
49             SkASSERT(!s->performsShading() || s->emitsPrimitiveColor() == withPrimitiveBlender);
50 
51             UniquePaintParamsID paintID = s->performsShading() ? uniqueID
52                                                                : UniquePaintParamsID::InvalidID();
53             GraphicsPipelineDesc pipelineDesc(s, paintID);
54 
55             for (RenderPassDesc renderPassDesc : renderPassDescs) {
56                 auto pipeline = resourceProvider->findOrCreateGraphicsPipeline(
57                         keyContext.rtEffectDict(),
58                         pipelineDesc,
59                         renderPassDesc);
60                 if (!pipeline) {
61                     SKGPU_LOG_W("Failed to create GraphicsPipeline in precompile!");
62                     return;
63                 }
64             }
65         }
66     }
67 }
68 
69 } // anonymous namespace
70 
71 namespace skgpu::graphite {
72 
Precompile(Context * context,const PaintOptions & options,DrawTypeFlags drawTypes)73 void Precompile(Context* context, const PaintOptions& options, DrawTypeFlags drawTypes) {
74 
75     ShaderCodeDictionary* dict = context->priv().shaderCodeDictionary();
76     const Caps* caps = context->priv().caps();
77 
78     auto rtEffectDict = std::make_unique<RuntimeEffectDictionary>();
79 
80     SkColorInfo ci(kRGBA_8888_SkColorType, kPremul_SkAlphaType, nullptr);
81     KeyContext keyContext(dict, rtEffectDict.get(), ci);
82 
83     // TODO: we need iterate over a broader set of TextureInfos here. Perhaps, allow the client
84     // to pass in colorType, mipmapping and protection.
85     TextureInfo info = caps->getDefaultSampledTextureInfo(ci.colorType(),
86                                                           Mipmapped::kNo,
87                                                           Protected::kNo,
88                                                           Renderable::kYes);
89 
90     // Note: at least on Metal, the LoadOp, StoreOp and clearColor fields don't influence the
91     // actual RenderPassDescKey.
92     // TODO: if all of the Renderers associated w/ the requested drawTypes require MSAA we
93     // do not need to generate the combinations w/ the non-MSAA RenderPassDescs.
94     RenderPassDesc renderPassDescs[] = {
95         RenderPassDesc::Make(caps,
96                              info,
97                              LoadOp::kClear,
98                              StoreOp::kStore,
99                              DepthStencilFlags::kDepth,
100                              /* clearColor= */ { .0f, .0f, .0f, .0f },
101                              /* requiresMSAA= */ true),
102         RenderPassDesc::Make(caps,
103                              info,
104                              LoadOp::kClear,
105                              StoreOp::kStore,
106                              DepthStencilFlags::kDepthStencil,
107                              /* clearColor= */ { .0f, .0f, .0f, .0f },
108                              /* requiresMSAA= */ true),
109         RenderPassDesc::Make(caps,
110                              info,
111                              LoadOp::kClear,
112                              StoreOp::kStore,
113                              DepthStencilFlags::kDepth,
114                              /* clearColor= */ { .0f, .0f, .0f, .0f },
115                              /* requiresMSAA= */ false),
116         RenderPassDesc::Make(caps,
117                              info,
118                              LoadOp::kClear,
119                              StoreOp::kStore,
120                              DepthStencilFlags::kDepthStencil,
121                              /* clearColor= */ { .0f, .0f, .0f, .0f },
122                              /* requiresMSAA= */ false),
123     };
124 
125     options.priv().buildCombinations(
126         keyContext,
127         /* addPrimitiveBlender= */ false,
128          [&](UniquePaintParamsID uniqueID) {
129              compile(context->priv().rendererProvider(),
130                      context->priv().resourceProvider(),
131                      keyContext, uniqueID,
132                      static_cast<DrawTypeFlags>(drawTypes & ~DrawTypeFlags::kDrawVertices),
133                      renderPassDescs, /* withPrimitiveBlender= */ false);
134          });
135 
136     if (drawTypes & DrawTypeFlags::kDrawVertices) {
137         options.priv().buildCombinations(
138             keyContext,
139             /* addPrimitiveBlender= */ true,
140             [&](UniquePaintParamsID uniqueID) {
141                 compile(context->priv().rendererProvider(),
142                         context->priv().resourceProvider(),
143                         keyContext, uniqueID,
144                         DrawTypeFlags::kDrawVertices,
145                         renderPassDescs, /* withPrimitiveBlender= */ true);
146             });
147     }
148 }
149 
150 } // namespace skgpu::graphite
151