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 "include/gpu/graphite/precompile/Precompile.h"
13 #include "src/gpu/graphite/Caps.h"
14 #include "src/gpu/graphite/ContextPriv.h"
15 #include "src/gpu/graphite/ContextUtils.h"
16 #include "src/gpu/graphite/GraphicsPipeline.h"
17 #include "src/gpu/graphite/GraphicsPipelineDesc.h"
18 #include "src/gpu/graphite/KeyContext.h"
19 #include "src/gpu/graphite/Log.h"
20 #include "src/gpu/graphite/PrecompileInternal.h"
21 #include "src/gpu/graphite/RenderPassDesc.h"
22 #include "src/gpu/graphite/Renderer.h"
23 #include "src/gpu/graphite/RendererProvider.h"
24 #include "src/gpu/graphite/ResourceProvider.h"
25 #include "src/gpu/graphite/RuntimeEffectDictionary.h"
26 #include "src/gpu/graphite/UniquePaintParamsID.h"
27 #include "src/gpu/graphite/precompile/PaintOptionsPriv.h"
28
29 namespace {
30
31 using namespace skgpu::graphite;
32
compile(const RendererProvider * rendererProvider,ResourceProvider * resourceProvider,const KeyContext & keyContext,UniquePaintParamsID uniqueID,DrawTypeFlags drawTypes,SkSpan<const RenderPassDesc> renderPassDescs,bool withPrimitiveBlender,Coverage coverage)33 void compile(const RendererProvider* rendererProvider,
34 ResourceProvider* resourceProvider,
35 const KeyContext& keyContext,
36 UniquePaintParamsID uniqueID,
37 DrawTypeFlags drawTypes,
38 SkSpan<const RenderPassDesc> renderPassDescs,
39 bool withPrimitiveBlender,
40 Coverage coverage) {
41 for (const Renderer* r : rendererProvider->renderers()) {
42 if (!(r->drawTypes() & drawTypes)) {
43 continue;
44 }
45
46 if (r->emitsPrimitiveColor() != withPrimitiveBlender) {
47 // UniqueIDs are explicitly built either w/ or w/o primitiveBlending so must
48 // match what the Renderer requires
49 continue;
50 }
51
52 if (r->coverage() != coverage) {
53 // For now, UniqueIDs are explicitly built with a specific type of coverage so must
54 // match what the Renderer requires
55 continue;
56 }
57
58 for (auto&& s : r->steps()) {
59 SkASSERT(!s->performsShading() || s->emitsPrimitiveColor() == withPrimitiveBlender);
60
61 UniquePaintParamsID paintID = s->performsShading() ? uniqueID
62 : UniquePaintParamsID::InvalidID();
63 GraphicsPipelineDesc pipelineDesc(s, paintID);
64
65 for (const RenderPassDesc& renderPassDesc : renderPassDescs) {
66 sk_sp<GraphicsPipeline> pipeline = resourceProvider->findOrCreateGraphicsPipeline(
67 keyContext.rtEffectDict(),
68 pipelineDesc,
69 renderPassDesc);
70 if (!pipeline) {
71 SKGPU_LOG_W("Failed to create GraphicsPipeline in precompile!");
72 return;
73 }
74 }
75 }
76 }
77 }
78
79 } // anonymous namespace
80
81 namespace skgpu::graphite {
82
Precompile(Context * context,RuntimeEffectDictionary * rteDict,const GraphicsPipelineDesc & pipelineDesc,const RenderPassDesc & renderPassDesc)83 bool Precompile(Context* context,
84 RuntimeEffectDictionary* rteDict,
85 const GraphicsPipelineDesc& pipelineDesc,
86 const RenderPassDesc& renderPassDesc) {
87 ResourceProvider* resourceProvider = context->priv().resourceProvider();
88
89 sk_sp<GraphicsPipeline> pipeline = resourceProvider->findOrCreateGraphicsPipeline(
90 rteDict,
91 pipelineDesc,
92 renderPassDesc);
93 if (!pipeline) {
94 SKGPU_LOG_W("Failed to create GraphicsPipeline in precompile!");
95 return false;
96 }
97
98 return true;
99 }
100
Precompile(Context * context,const PaintOptions & options,DrawTypeFlags drawTypes)101 void Precompile(Context* context, const PaintOptions& options, DrawTypeFlags drawTypes) {
102
103 ShaderCodeDictionary* dict = context->priv().shaderCodeDictionary();
104 const Caps* caps = context->priv().caps();
105
106 auto rtEffectDict = std::make_unique<RuntimeEffectDictionary>();
107
108 SkColorInfo ci(kRGBA_8888_SkColorType, kPremul_SkAlphaType, nullptr);
109 KeyContext keyContext(
110 caps, dict, rtEffectDict.get(), ci, /* dstTexture= */ nullptr, /* dstOffset= */ {0, 0});
111
112 for (Coverage coverage : { Coverage::kNone, Coverage::kSingleChannel, Coverage::kLCD }) {
113 PrecompileCombinations(
114 context, options, keyContext,
115 static_cast<DrawTypeFlags>(drawTypes & ~DrawTypeFlags::kDrawVertices),
116 /* withPrimitiveBlender= */ false,
117 coverage);
118 }
119
120 if (drawTypes & DrawTypeFlags::kDrawVertices) {
121 for (Coverage coverage: { Coverage::kNone, Coverage::kSingleChannel, Coverage::kLCD }) {
122 // drawVertices w/ colors use a primitiveBlender while those w/o don't
123 for (bool withPrimitiveBlender : { true, false }) {
124 PrecompileCombinations(context, options, keyContext,
125 DrawTypeFlags::kDrawVertices,
126 withPrimitiveBlender,
127 coverage);
128 }
129 }
130 }
131 }
132
PrecompileCombinations(Context * context,const PaintOptions & options,const KeyContext & keyContext,DrawTypeFlags drawTypes,bool withPrimitiveBlender,Coverage coverage)133 void PrecompileCombinations(Context* context,
134 const PaintOptions& options,
135 const KeyContext& keyContext,
136 DrawTypeFlags drawTypes,
137 bool withPrimitiveBlender,
138 Coverage coverage) {
139 const Caps* caps = keyContext.caps();
140 // Since the precompilation path's uniforms aren't used and don't change the key,
141 // the exact layout doesn't matter
142 PipelineDataGatherer gatherer(caps, Layout::kMetal);
143
144 SkColorType destCT = keyContext.dstColorInfo().colorType();
145 // TODO: we need iterate over a broader set of TextureInfos here. Perhaps, allow the client
146 // to pass in colorType, mipmapping and protection.
147 TextureInfo info = caps->getDefaultSampledTextureInfo(destCT,
148 Mipmapped::kNo,
149 Protected::kNo,
150 Renderable::kYes);
151
152 Swizzle writeSwizzle = caps->getWriteSwizzle(destCT, info);
153 // Note: at least on Metal, the LoadOp, StoreOp and clearColor fields don't influence the
154 // actual RenderPassDescKey.
155 // TODO: if all of the Renderers associated w/ the requested drawTypes require MSAA we
156 // do not need to generate the combinations w/ the non-MSAA RenderPassDescs.
157 const RenderPassDesc renderPassDescs[] = {
158 RenderPassDesc::Make(caps,
159 info,
160 LoadOp::kClear,
161 StoreOp::kStore,
162 DepthStencilFlags::kDepth,
163 /* clearColor= */ { .0f, .0f, .0f, .0f },
164 /* requiresMSAA= */ true,
165 writeSwizzle),
166 RenderPassDesc::Make(caps,
167 info,
168 LoadOp::kClear,
169 StoreOp::kStore,
170 DepthStencilFlags::kDepthStencil,
171 /* clearColor= */ { .0f, .0f, .0f, .0f },
172 /* requiresMSAA= */ true,
173 writeSwizzle),
174 RenderPassDesc::Make(caps,
175 info,
176 LoadOp::kClear,
177 StoreOp::kStore,
178 DepthStencilFlags::kDepth,
179 /* clearColor= */ { .0f, .0f, .0f, .0f },
180 /* requiresMSAA= */ false,
181 writeSwizzle),
182 RenderPassDesc::Make(caps,
183 info,
184 LoadOp::kClear,
185 StoreOp::kStore,
186 DepthStencilFlags::kDepthStencil,
187 /* clearColor= */ { .0f, .0f, .0f, .0f },
188 /* requiresMSAA= */ false,
189 writeSwizzle),
190 };
191
192 options.priv().buildCombinations(
193 keyContext,
194 &gatherer,
195 drawTypes,
196 withPrimitiveBlender,
197 coverage,
198 [context, &keyContext, &renderPassDescs](UniquePaintParamsID uniqueID,
199 DrawTypeFlags drawTypes,
200 bool withPrimitiveBlender,
201 Coverage coverage) {
202 compile(context->priv().rendererProvider(),
203 context->priv().resourceProvider(),
204 keyContext,
205 uniqueID,
206 drawTypes,
207 renderPassDescs,
208 withPrimitiveBlender,
209 coverage);
210 });
211 }
212
213 } // namespace skgpu::graphite
214