• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2023 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/AtlasProvider.h"
9 
10 #include "include/gpu/graphite/Recorder.h"
11 #include "src/gpu/graphite/ClipAtlasManager.h"
12 #include "src/gpu/graphite/ComputePathAtlas.h"
13 #include "src/gpu/graphite/DrawContext.h"
14 #include "src/gpu/graphite/Log.h"
15 #include "src/gpu/graphite/RasterPathAtlas.h"
16 #include "src/gpu/graphite/RecorderPriv.h"
17 #include "src/gpu/graphite/RendererProvider.h"
18 #include "src/gpu/graphite/TextureProxy.h"
19 #include "src/gpu/graphite/text/TextAtlasManager.h"
20 
21 namespace skgpu::graphite {
22 
QueryPathAtlasSupport(const Caps * caps)23 AtlasProvider::PathAtlasFlagsBitMask AtlasProvider::QueryPathAtlasSupport(const Caps* caps) {
24     // The raster-backend path atlas is always supported.
25     PathAtlasFlagsBitMask flags = PathAtlasFlags::kRaster;
26     if (RendererProvider::IsVelloRendererSupported(caps)) {
27         flags |= PathAtlasFlags::kCompute;
28     }
29     return flags;
30 }
31 
AtlasProvider(Recorder * recorder)32 AtlasProvider::AtlasProvider(Recorder* recorder)
33         : fTextAtlasManager(std::make_unique<TextAtlasManager>(recorder))
34         , fRasterPathAtlas(std::make_unique<RasterPathAtlas>(recorder))
35         , fClipAtlasManager(std::make_unique<ClipAtlasManager>(recorder))
36         , fPathAtlasFlags(QueryPathAtlasSupport(recorder->priv().caps())) {}
37 
createComputePathAtlas(Recorder * recorder) const38 std::unique_ptr<ComputePathAtlas> AtlasProvider::createComputePathAtlas(Recorder* recorder) const {
39     if (this->isAvailable(PathAtlasFlags::kCompute)) {
40         return ComputePathAtlas::CreateDefault(recorder);
41     }
42     return nullptr;
43 }
44 
getRasterPathAtlas() const45 RasterPathAtlas* AtlasProvider::getRasterPathAtlas() const {
46     return fRasterPathAtlas.get();
47 }
48 
getClipAtlasManager() const49 ClipAtlasManager* AtlasProvider::getClipAtlasManager() const {
50     return fClipAtlasManager.get();
51 }
52 
getAtlasTexture(Recorder * recorder,uint16_t width,uint16_t height,SkColorType colorType,uint16_t identifier,bool requireStorageUsage)53 sk_sp<TextureProxy> AtlasProvider::getAtlasTexture(Recorder* recorder,
54                                                    uint16_t width,
55                                                    uint16_t height,
56                                                    SkColorType colorType,
57                                                    uint16_t identifier,
58                                                    bool requireStorageUsage) {
59     uint64_t key = static_cast<uint64_t>(width)  << 48 |
60                    static_cast<uint64_t>(height) << 32 |
61                    static_cast<uint64_t>(colorType) << 16 |
62                    static_cast<uint64_t>(identifier);
63     auto iter = fTexturePool.find(key);
64     if (iter != fTexturePool.end()) {
65         return iter->second;
66     }
67 
68     // We currently only make the distinction between a storage texture (written by a
69     // compute pass) and a plain sampleable texture (written via upload) that won't be
70     // used as a render attachment.
71     const Caps* caps = recorder->priv().caps();
72     auto textureInfo = requireStorageUsage
73             ? caps->getDefaultStorageTextureInfo(colorType)
74             : caps->getDefaultSampledTextureInfo(colorType,
75                                                  Mipmapped::kNo,
76                                                  recorder->priv().isProtected(),
77                                                  Renderable::kNo);
78     sk_sp<TextureProxy> proxy = TextureProxy::Make(caps,
79                                                    recorder->priv().resourceProvider(),
80                                                    SkISize::Make((int32_t) width, (int32_t) height),
81                                                    textureInfo,
82                                                    "AtlasProviderTexture",
83                                                    Budgeted::kYes);
84     if (!proxy) {
85         return nullptr;
86     }
87 
88     fTexturePool[key] = proxy;
89     return proxy;
90 }
91 
freeGpuResources()92 void AtlasProvider::freeGpuResources() {
93     // Clear out any pages not in use or needed for any pending work on the Recorder.
94     // In the event this is called right after a snap(), all pages would be eligible
95     // for cleanup anyways.
96     fTextAtlasManager->freeGpuResources();
97     if (fRasterPathAtlas) {
98         fRasterPathAtlas->freeGpuResources();
99     }
100     if (fClipAtlasManager) {
101         fClipAtlasManager->freeGpuResources();
102     }
103     // Release any textures held directly by the provider. These textures are used by transient
104     // ComputePathAtlases that are reset every time a DrawContext snaps a DrawTask so there is no
105     // need to reset those atlases explicitly here. Since the AtlasProvider gives out refs to the
106     // TextureProxies in the pool, it should be safe to clear the pool in the middle of Recording.
107     // Draws that use the previous TextureProxies will have refs on them.
108     fTexturePool.clear();
109 }
110 
recordUploads(DrawContext * dc)111 void AtlasProvider::recordUploads(DrawContext* dc) {
112     if (!fTextAtlasManager->recordUploads(dc)) {
113         SKGPU_LOG_E("TextAtlasManager uploads have failed -- may see invalid results.");
114     }
115 
116     if (fRasterPathAtlas) {
117         fRasterPathAtlas->recordUploads(dc);
118     }
119     if (fClipAtlasManager) {
120         fClipAtlasManager->recordUploads(dc);
121     }
122 }
123 
compact()124 void AtlasProvider::compact() {
125     fTextAtlasManager->compact();
126     if (fRasterPathAtlas) {
127         fRasterPathAtlas->compact();
128     }
129     if (fClipAtlasManager) {
130         fClipAtlasManager->compact();
131     }
132 }
133 
invalidateAtlases()134 void AtlasProvider::invalidateAtlases() {
135     // We must also evict atlases on a failure. The failed tasks can include uploads that the
136     // atlas was depending on for its caches. Failing to prepare means they will never run so
137     // future "successful" Recorder snaps would otherwise reference atlas pages that had stale
138     // contents.
139     fTextAtlasManager->evictAtlases();
140     if (fRasterPathAtlas) {
141         fRasterPathAtlas->evictAtlases();
142     }
143     if (fClipAtlasManager) {
144         fClipAtlasManager->evictAtlases();
145     }
146 }
147 
148 }  // namespace skgpu::graphite
149