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