xref: /aosp_15_r20/external/skia/src/gpu/graphite/GlobalCache.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
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/GlobalCache.h"
9 
10 #include "src/gpu/graphite/ComputePipeline.h"
11 #include "src/gpu/graphite/ContextUtils.h"
12 #include "src/gpu/graphite/GraphicsPipeline.h"
13 #include "src/gpu/graphite/Resource.h"
14 
15 namespace skgpu::graphite {
16 
GlobalCache()17 GlobalCache::GlobalCache()
18         : fGraphicsPipelineCache(256)  // TODO: find a good value for these limits
19         , fComputePipelineCache(256) {}
20 
~GlobalCache()21 GlobalCache::~GlobalCache() {
22     // These should have been cleared out earlier by deleteResources().
23     SkDEBUGCODE(SkAutoSpinlock lock{ fSpinLock });
24     SkASSERT(fGraphicsPipelineCache.count() == 0);
25     SkASSERT(fComputePipelineCache.count() == 0);
26     SkASSERT(fStaticResource.empty());
27 }
28 
deleteResources()29 void GlobalCache::deleteResources() {
30     SkAutoSpinlock lock{ fSpinLock };
31 
32     fGraphicsPipelineCache.reset();
33     fComputePipelineCache.reset();
34     fStaticResource.clear();
35 }
36 
findGraphicsPipeline(const UniqueKey & key)37 sk_sp<GraphicsPipeline> GlobalCache::findGraphicsPipeline(const UniqueKey& key) {
38     SkAutoSpinlock lock{fSpinLock};
39 
40     sk_sp<GraphicsPipeline>* entry = fGraphicsPipelineCache.find(key);
41 #if defined(GPU_TEST_UTILS)
42     if (entry) { ++fStats.fGraphicsCacheHits; } else { ++fStats.fGraphicsCacheMisses; }
43 #endif
44     return entry ? *entry : nullptr;
45 }
46 
47 #if SK_HISTOGRAMS_ENABLED
48 // These values are persisted to logs. Entries should not be renumbered and
49 // numeric values should never be reused.
50 //
51 // LINT.IfChange(PipelineCreationRace)
52 enum class PipelineCreationRace {
53     // The <First>Over<Second> enum names mean the first type of compilation won a compilation race
54     // over the second type of compilation and ended up in the cache.
55     kNormalOverNormal                 = 0, // can happen w/ multiple Recorders on different threads
56     kNormalOverPrecompilation         = 1,
57     kPrecompilationOverNormal         = 2,
58     kPrecompilationOverPrecompilation = 3, // can happen with multiple threaded precompilation calls
59 
60     kMaxValue = kPrecompilationOverPrecompilation,
61 };
62 // LINT.ThenChange(//tools/metrics/histograms/enums.xml:SkiaPipelineCreationRace)
63 
64 [[maybe_unused]] static constexpr int kPipelineCreationRaceCount =
65         static_cast<int>(PipelineCreationRace::kMaxValue) + 1;
66 #endif // SK_HISTOGRAMS_ENABLED
67 
addGraphicsPipeline(const UniqueKey & key,sk_sp<GraphicsPipeline> pipeline)68 sk_sp<GraphicsPipeline> GlobalCache::addGraphicsPipeline(const UniqueKey& key,
69                                                          sk_sp<GraphicsPipeline> pipeline) {
70     SkAutoSpinlock lock{fSpinLock};
71 
72     sk_sp<GraphicsPipeline>* entry = fGraphicsPipelineCache.find(key);
73     if (!entry) {
74         // No equivalent pipeline was stored in the cache between a previous call to
75         // findGraphicsPipeline() that returned null (triggering the pipeline creation) and this
76         // later adding to the cache.
77 #if defined(GPU_TEST_UTILS)
78         ++fStats.fGraphicsCacheAdditions;
79 #endif
80         entry = fGraphicsPipelineCache.insert(key, std::move(pipeline));
81     } else {
82 #if defined(GPU_TEST_UTILS)
83         // else there was a race creating the same pipeline and this thread lost, so return
84         // the winner
85         ++fStats.fGraphicsRaces;
86 #endif
87 #if SK_HISTOGRAMS_ENABLED
88         [[maybe_unused]] int race = (*entry)->fromPrecompile() * 2 + pipeline->fromPrecompile();
89         SK_HISTOGRAM_ENUMERATION("Graphite.PipelineCreationRace",
90                                  race,
91                                  kPipelineCreationRaceCount);
92 #endif
93     }
94     return *entry;
95 }
96 
97 #if defined(GPU_TEST_UTILS)
numGraphicsPipelines() const98 int GlobalCache::numGraphicsPipelines() const {
99     SkAutoSpinlock lock{fSpinLock};
100 
101     return fGraphicsPipelineCache.count();
102 }
103 
resetGraphicsPipelines()104 void GlobalCache::resetGraphicsPipelines() {
105     SkAutoSpinlock lock{fSpinLock};
106 
107     fGraphicsPipelineCache.reset();
108 }
109 
forEachGraphicsPipeline(const std::function<void (const UniqueKey &,const GraphicsPipeline *)> & fn)110 void GlobalCache::forEachGraphicsPipeline(
111         const std::function<void(const UniqueKey&, const GraphicsPipeline*)>& fn) {
112     SkAutoSpinlock lock{fSpinLock};
113 
114     fGraphicsPipelineCache.foreach([&](const UniqueKey* k, const sk_sp<GraphicsPipeline>* v) {
115         fn(*k, v->get());
116     });
117 }
118 
getStats() const119 GlobalCache::PipelineStats GlobalCache::getStats() const {
120     SkAutoSpinlock lock{fSpinLock};
121 
122     return fStats;
123 }
124 #endif // defined(GPU_TEST_UTILS)
125 
findComputePipeline(const UniqueKey & key)126 sk_sp<ComputePipeline> GlobalCache::findComputePipeline(const UniqueKey& key) {
127     SkAutoSpinlock lock{fSpinLock};
128     sk_sp<ComputePipeline>* entry = fComputePipelineCache.find(key);
129     return entry ? *entry : nullptr;
130 }
131 
addComputePipeline(const UniqueKey & key,sk_sp<ComputePipeline> pipeline)132 sk_sp<ComputePipeline> GlobalCache::addComputePipeline(const UniqueKey& key,
133                                                        sk_sp<ComputePipeline> pipeline) {
134     SkAutoSpinlock lock{fSpinLock};
135     sk_sp<ComputePipeline>* entry = fComputePipelineCache.find(key);
136     if (!entry) {
137         entry = fComputePipelineCache.insert(key, std::move(pipeline));
138     }
139     return *entry;
140 }
141 
addStaticResource(sk_sp<Resource> resource)142 void GlobalCache::addStaticResource(sk_sp<Resource> resource) {
143     SkAutoSpinlock lock{fSpinLock};
144     fStaticResource.push_back(std::move(resource));
145 }
146 
147 } // namespace skgpu::graphite
148