Flutter Engine
The Flutter Engine
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
ResourceProvider.cpp
Go to the documentation of this file.
1/*
2 * Copyright 2021 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
9
31
32namespace skgpu::graphite {
33
34// This is only used when tracing is enabled at compile time.
35[[maybe_unused]] static std::string to_str(const SharedContext* ctx,
36 const GraphicsPipelineDesc& gpDesc,
37 const RenderPassDesc& rpDesc) {
38 const ShaderCodeDictionary* dict = ctx->shaderCodeDictionary();
39 const RenderStep* step = ctx->rendererProvider()->lookup(gpDesc.renderStepID());
40 return GetPipelineLabel(dict, rpDesc, step, gpDesc.paintParamsID());
41}
42
44 SingleOwner* singleOwner,
45 uint32_t recorderID,
46 size_t resourceBudget)
47 : fSharedContext(sharedContext)
48 , fResourceCache(ResourceCache::Make(singleOwner, recorderID, resourceBudget)) {}
49
51 fResourceCache->shutdown();
52}
53
55 const RuntimeEffectDictionary* runtimeDict,
56 const GraphicsPipelineDesc& pipelineDesc,
57 const RenderPassDesc& renderPassDesc) {
58 auto globalCache = fSharedContext->globalCache();
59 UniqueKey pipelineKey = fSharedContext->caps()->makeGraphicsPipelineKey(pipelineDesc,
60 renderPassDesc);
61 sk_sp<GraphicsPipeline> pipeline = globalCache->findGraphicsPipeline(pipelineKey);
62 if (!pipeline) {
63 // Haven't encountered this pipeline, so create a new one. Since pipelines are shared
64 // across Recorders, we could theoretically create equivalent pipelines on different
65 // threads. If this happens, GlobalCache returns the first-through-gate pipeline and we
66 // discard the redundant pipeline. While this is wasted effort in the rare event of a race,
67 // it allows pipeline creation to be performed without locking the global cache.
68 // NOTE: The parameters to TRACE_EVENT are only evaluated inside an if-block when the
69 // category is enabled.
70 TRACE_EVENT1("skia.shaders", "createGraphicsPipeline", "desc",
71 TRACE_STR_COPY(to_str(fSharedContext, pipelineDesc, renderPassDesc).c_str()));
72 pipeline = this->createGraphicsPipeline(runtimeDict, pipelineDesc, renderPassDesc);
73 if (pipeline) {
74 // TODO: Should we store a null pipeline if we failed to create one so that subsequent
75 // usage immediately sees that the pipeline cannot be created, vs. retrying every time?
76 pipeline = globalCache->addGraphicsPipeline(pipelineKey, std::move(pipeline));
77 }
78 }
79 return pipeline;
80}
81
83 const ComputePipelineDesc& pipelineDesc) {
84 auto globalCache = fSharedContext->globalCache();
85 UniqueKey pipelineKey = fSharedContext->caps()->makeComputePipelineKey(pipelineDesc);
86 sk_sp<ComputePipeline> pipeline = globalCache->findComputePipeline(pipelineKey);
87 if (!pipeline) {
88 pipeline = this->createComputePipeline(pipelineDesc);
89 if (pipeline) {
90 pipeline = globalCache->addComputePipeline(pipelineKey, std::move(pipeline));
91 }
92 }
93 return pipeline;
94}
95
96////////////////////////////////////////////////////////////////////////////////////////////////
97
99 const TextureInfo& info,
100 std::string_view label,
101 skgpu::Budgeted budgeted) {
102 SkASSERT(info.isValid());
103
105
107 // Scratch textures are not shareable
108 fSharedContext->caps()->buildKeyForTexture(dimensions, info, kType, Shareable::kNo, &key);
109
110 return this->findOrCreateTextureWithKey(dimensions,
111 info,
112 key,
113 std::move(label),
114 budgeted);
115}
116
118 const TextureInfo& info) {
119 SkASSERT(info.isValid());
120
122
124 // We always make depth and stencil attachments shareable. Between any render pass the values
125 // are reset. Thus it is safe to be used by multiple different render passes without worry of
126 // stomping on each other's data.
128
129 return this->findOrCreateTextureWithKey(dimensions,
130 info,
131 key,
132 "DepthStencilAttachment",
134}
135
137 const TextureInfo& info) {
138 SkASSERT(info.isValid());
139
141
143 // We always make discardable msaa attachments shareable. Between any render pass we discard
144 // the values of the MSAA texture. Thus it is safe to be used by multiple different render
145 // passes without worry of stomping on each other's data. It is the callings code's
146 // responsibility to populate the discardable MSAA texture with data at the start of the
147 // render pass.
149
150 return this->findOrCreateTextureWithKey(dimensions,
151 info,
152 key,
153 "DiscardableMSAAAttachment",
155}
156
157sk_sp<Texture> ResourceProvider::findOrCreateTextureWithKey(SkISize dimensions,
158 const TextureInfo& info,
160 std::string_view label,
161 skgpu::Budgeted budgeted) {
162 // If the resource is shareable it should be budgeted since it shouldn't be backing any client
163 // owned object.
164 SkASSERT(key.shareable() == Shareable::kNo || budgeted == skgpu::Budgeted::kYes);
165
166 if (Resource* resource = fResourceCache->findAndRefResource(key, budgeted)) {
167 resource->setLabel(std::move(label));
168 return sk_sp<Texture>(static_cast<Texture*>(resource));
169 }
170
171 auto tex = this->createTexture(dimensions, info, budgeted);
172 if (!tex) {
173 return nullptr;
174 }
175
176 tex->setKey(key);
177 tex->setLabel(std::move(label));
178 fResourceCache->insertResource(tex.get());
179
180 return tex;
181}
182
184 std::string_view label) {
185 sk_sp<Texture> texture = this->onCreateWrappedTexture(backendTexture);
186 if (texture) {
187 texture->setLabel(std::move(label));
188 }
189 return texture;
190}
191
194
195 if (Resource* resource = fResourceCache->findAndRefResource(key, skgpu::Budgeted::kYes)) {
196 return sk_sp<Sampler>(static_cast<Sampler*>(resource));
197 }
198
199 sk_sp<Sampler> sampler = this->createSampler(samplerDesc);
200 if (!sampler) {
201 return nullptr;
202 }
203
204 sampler->setKey(key);
205 fResourceCache->insertResource(sampler.get());
206 return sampler;
207}
208
211 AccessPattern accessPattern,
212 std::string_view label) {
214
216 {
217 // For the key we need ((sizeof(size_t) + (sizeof(uint32_t) - 1)) / (sizeof(uint32_t))
218 // uint32_t's for the size and one uint32_t for the rest.
219 static_assert(sizeof(uint32_t) == 4);
220 static const int kSizeKeyNum32DataCnt = (sizeof(size_t) + 3) / 4;
221 static const int kKeyNum32DataCnt = kSizeKeyNum32DataCnt + 1;
222
223 SkASSERT(static_cast<uint32_t>(type) < (1u << 4));
224 SkASSERT(static_cast<uint32_t>(accessPattern) < (1u << 1));
225
226 GraphiteResourceKey::Builder builder(&key, kType, kKeyNum32DataCnt, Shareable::kNo);
227 builder[0] = (static_cast<uint32_t>(type) << 0) |
228 (static_cast<uint32_t>(accessPattern) << 4);
229 size_t szKey = size;
230 for (int i = 0; i < kSizeKeyNum32DataCnt; ++i) {
231 builder[i + 1] = (uint32_t) szKey;
232
233 // If size_t is 4 bytes, we cannot do a shift of 32 or else we get a warning/error that
234 // shift amount is >= width of the type.
235 if constexpr(kSizeKeyNum32DataCnt > 1) {
236 szKey = szKey >> 32;
237 }
238 }
239 }
240
242 if (Resource* resource = fResourceCache->findAndRefResource(key, budgeted)) {
243 resource->setLabel(std::move(label));
244 return sk_sp<Buffer>(static_cast<Buffer*>(resource));
245 }
246 auto buffer = this->createBuffer(size, type, accessPattern);
247 if (!buffer) {
248 return nullptr;
249 }
250
251 buffer->setKey(key);
252 buffer->setLabel(std::move(label));
253 fResourceCache->insertResource(buffer.get());
254 return buffer;
255}
256
257namespace {
258bool dimensions_are_valid(const int maxTextureSize, const SkISize& dimensions) {
259 if (dimensions.isEmpty() ||
260 dimensions.width() > maxTextureSize ||
261 dimensions.height() > maxTextureSize) {
262 SKGPU_LOG_W("Call to createBackendTexture has requested dimensions (%d, %d) larger than the"
263 " supported gpu max texture size: %d. Or the dimensions are empty.",
264 dimensions.fWidth, dimensions.fHeight, maxTextureSize);
265 return false;
266 }
267 return true;
268}
269}
270
272 if (!dimensions_are_valid(fSharedContext->caps()->maxTextureSize(), dimensions)) {
273 return {};
274 }
275 return this->onCreateBackendTexture(dimensions, info);
276}
277
278#ifdef SK_BUILD_FOR_ANDROID
280 bool isRenderable,
281 bool isProtectedContent,
282 SkISize dimensions,
283 bool fromAndroidWindow) const {
284 if (!dimensions_are_valid(fSharedContext->caps()->maxTextureSize(), dimensions)) {
285 return {};
286 }
287 return this->onCreateBackendTexture(hardwareBuffer,
288 isRenderable,
289 isProtectedContent,
290 dimensions,
291 fromAndroidWindow);
292}
293
295 bool isRenderable,
296 bool isProtectedContent,
297 SkISize dimensions,
298 bool fromAndroidWindow) const {
299 return {};
300}
301#endif
302
304 this->onDeleteBackendTexture(texture);
305}
306
308 // TODO: Are there Resources that are ref'd by the ResourceProvider or its subclasses that need
309 // be released? If we ever find that we're holding things directly on the ResourceProviders we
310 // call down into the subclasses to allow them to release things.
311
312 fResourceCache->purgeResources();
313}
314
315void ResourceProvider::purgeResourcesNotUsedSince(StdSteadyClock::time_point purgeTime) {
316 fResourceCache->purgeResourcesNotUsedSince(purgeTime);
317}
318
319} // namespace skgpu::graphite
static int step(int x, SkScalar min, SkScalar max)
Definition: BlurTest.cpp:215
static void info(const char *fmt,...) SK_PRINTF_LIKE(1
Definition: DM.cpp:213
struct AHardwareBuffer AHardwareBuffer
#define SKGPU_LOG_W(fmt,...)
Definition: Log.h:40
#define SkASSERT(cond)
Definition: SkAssert.h:116
static SkString resource(SkPDFResourceType type, int index)
#define TRACE_STR_COPY(str)
Definition: SkTraceEvent.h:63
GLenum type
T * get() const
Definition: SkRefCnt.h:303
virtual GraphiteResourceKey makeSamplerKey(const SamplerDesc &samplerDesc) const
Definition: Caps.cpp:73
virtual UniqueKey makeGraphicsPipelineKey(const GraphicsPipelineDesc &, const RenderPassDesc &) const =0
virtual UniqueKey makeComputePipelineKey(const ComputePipelineDesc &) const =0
virtual void buildKeyForTexture(SkISize dimensions, const TextureInfo &, ResourceType, Shareable, GraphiteResourceKey *) const =0
int maxTextureSize() const
Definition: Caps.h:141
UniquePaintParamsID paintParamsID() const
const RenderStep * lookup(uint32_t uniqueID) const
sk_sp< GraphicsPipeline > findOrCreateGraphicsPipeline(const RuntimeEffectDictionary *, const GraphicsPipelineDesc &, const RenderPassDesc &)
sk_sp< Texture > findOrCreateDiscardableMSAAAttachment(SkISize dimensions, const TextureInfo &)
sk_sp< ComputePipeline > findOrCreateComputePipeline(const ComputePipelineDesc &)
virtual sk_sp< Sampler > createSampler(const SamplerDesc &)=0
void purgeResourcesNotUsedSince(StdSteadyClock::time_point purgeTime)
virtual sk_sp< Buffer > createBuffer(size_t size, BufferType type, AccessPattern)=0
sk_sp< Texture > createWrappedTexture(const BackendTexture &, std::string_view label)
virtual sk_sp< Texture > onCreateWrappedTexture(const BackendTexture &)=0
sk_sp< Texture > findOrCreateScratchTexture(SkISize, const TextureInfo &, std::string_view label, skgpu::Budgeted)
virtual BackendTexture onCreateBackendTexture(SkISize dimensions, const TextureInfo &)=0
ResourceProvider(SharedContext *sharedContext, SingleOwner *singleOwner, uint32_t recorderID, size_t resourceBudget)
sk_sp< Sampler > findOrCreateCompatibleSampler(const SamplerDesc &)
BackendTexture createBackendTexture(SkISize dimensions, const TextureInfo &)
sk_sp< Texture > findOrCreateDepthStencilAttachment(SkISize dimensions, const TextureInfo &)
void deleteBackendTexture(const BackendTexture &)
virtual sk_sp< GraphicsPipeline > createGraphicsPipeline(const RuntimeEffectDictionary *, const GraphicsPipelineDesc &, const RenderPassDesc &)=0
virtual void onDeleteBackendTexture(const BackendTexture &)=0
virtual sk_sp< Texture > createTexture(SkISize, const TextureInfo &, skgpu::Budgeted)=0
sk_sp< Buffer > findOrCreateBuffer(size_t size, BufferType type, AccessPattern, std::string_view label)
sk_sp< ResourceCache > fResourceCache
virtual sk_sp< ComputePipeline > createComputePipeline(const ComputePipelineDesc &)=0
const Caps * caps() const
Definition: SharedContext.h:39
ShaderCodeDictionary * shaderCodeDictionary()
Definition: SharedContext.h:49
const RendererProvider * rendererProvider() const
Definition: SharedContext.h:47
FlTexture * texture
SK_API sk_sp< SkDocument > Make(SkWStream *dst, const SkSerialProcs *=nullptr, std::function< void(const SkPicture *)> onEndPage=nullptr)
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir Path to the cache directory This is different from the persistent_cache_path in embedder which is used for Skia shader cache icu native lib Path to the library file that exports the ICU data vm service The hostname IP address on which the Dart VM Service should be served If not defaults to or::depending on whether ipv6 is specified vm service A custom Dart VM Service port The default is to pick a randomly available open port disable vm Disable the Dart VM Service The Dart VM Service is never available in release mode disable vm service Disable mDNS Dart VM Service publication Bind to the IPv6 localhost address for the Dart VM Service Ignored if vm service host is set endless trace buffer
Definition: switches.h:126
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
Definition: switches.h:259
static std::string to_str(const SharedContext *ctx, const GraphicsPipelineDesc &gpDesc, const RenderPassDesc &rpDesc)
uint32_t ResourceType
std::string GetPipelineLabel(const ShaderCodeDictionary *dict, const RenderPassDesc &renderPassDesc, const RenderStep *renderStep, UniquePaintParamsID paintID)
Budgeted
Definition: GpuTypes.h:35
Definition: SkSize.h:16
bool isEmpty() const
Definition: SkSize.h:31
int32_t fHeight
Definition: SkSize.h:18
int32_t fWidth
Definition: SkSize.h:17
constexpr int32_t width() const
Definition: SkSize.h:36
constexpr int32_t height() const
Definition: SkSize.h:37
#define TRACE_EVENT1(category_group, name, arg1_name, arg1_val)
Definition: trace_event.h:141