xref: /aosp_15_r20/external/skia/src/gpu/graphite/ScratchResourceManager.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1 /*
2  * Copyright 2024 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/ScratchResourceManager.h"
9 
10 #include "src/gpu/graphite/Resource.h"
11 #include "src/gpu/graphite/ResourceProvider.h"
12 #include "src/gpu/graphite/Texture.h"
13 #include "src/gpu/graphite/TextureProxy.h"
14 
15 namespace skgpu::graphite {
16 
ScratchResourceManager(ResourceProvider * resourceProvider,std::unique_ptr<ProxyReadCountMap> proxyCounts)17 ScratchResourceManager::ScratchResourceManager(ResourceProvider* resourceProvider,
18                                                std::unique_ptr<ProxyReadCountMap> proxyCounts)
19         : fResourceProvider(resourceProvider)
20         , fProxyReadCounts(std::move(proxyCounts)) {
21     SkASSERT(resourceProvider);
22     SkASSERT(fProxyReadCounts);
23 }
24 
25 ScratchResourceManager::~ScratchResourceManager() = default;
26 
getScratchTexture(SkISize dimensions,const TextureInfo & info,std::string_view label)27 sk_sp<Texture> ScratchResourceManager::getScratchTexture(SkISize dimensions,
28                                                          const TextureInfo& info,
29                                                          std::string_view label) {
30     for (ScratchTexture& st : fScratchTextures) {
31         if (st.fAvailable &&
32             st.fTexture->dimensions() == dimensions &&
33             st.fTexture->textureInfo() == info) {
34             // An exact match, reuse it.
35             st.fAvailable = false;
36             return st.fTexture;
37         }
38     }
39 
40     // No texture was available so go out to the resource provider, which will hopefully find a
41     // cached resource that was freed up from a previous recording (or create a new one, if not).
42     // TODO(b/339496039): Always start with a fixed label like "ScratchTexture" and then concatenate
43     // the proxy label that's passed in onto the texture's label, including when reusing a texture.
44     sk_sp<Texture> newScratchTexture = fResourceProvider->findOrCreateScratchTexture(
45             dimensions, info, std::move(label), Budgeted::kYes);
46     if (newScratchTexture) {
47         fScratchTextures.push_back({newScratchTexture, /*fAvailable=*/false});
48     }
49     return newScratchTexture;
50 }
51 
returnTexture(sk_sp<Texture> texture)52 void ScratchResourceManager::returnTexture(sk_sp<Texture> texture) {
53     for (ScratchTexture& st : fScratchTextures) {
54         if (st.fTexture.get() == texture.get()) {
55             SkASSERT(!st.fAvailable);
56             st.fAvailable = true;
57             return;
58         }
59     }
60     // Trying to return a resource that didn't come from getScratchTexture().
61     SkASSERT(false);
62 }
63 
pushScope()64 void ScratchResourceManager::pushScope() {
65     // Push a null pointer to mark the beginning of the list of listeners in the next depth
66     fListenerStack.push_back(nullptr);
67 }
68 
popScope()69 void ScratchResourceManager::popScope() {
70     // Must have at least the null element to start the scope being popped
71     SkASSERT(!fListenerStack.empty());
72 
73     // TODO: Assert that the current sublist is empty (i.e. the back element is a null pointer) but
74     // for now skip over them and leave them un-invoked to keep the unconsumed scratch resources
75     // out of the pool so they remain valid in later recordings.
76     int n = 0;
77     while (fListenerStack.fromBack(n)) {
78         n++;
79     }
80     SkASSERT(n < fListenerStack.size() && fListenerStack.fromBack(n) == nullptr);
81     // Remove all non-null listeners after the most recent null entry AND the null entry
82     fListenerStack.pop_back_n(n + 1);
83 }
84 
notifyResourcesConsumed()85 void ScratchResourceManager::notifyResourcesConsumed() {
86     // Should only be called inside a scope
87     SkASSERT(!fListenerStack.empty());
88 
89     int n = 0;
90     while (PendingUseListener* listener = fListenerStack.fromBack(n)) {
91         listener->onUseCompleted(this);
92         n++;
93     }
94     SkASSERT(n < fListenerStack.size() && fListenerStack.fromBack(n) == nullptr);
95     // Remove all non-null listeners that were just invoked, but do not remove the null entry that
96     // marks the start of this scope boundary.
97     if (n > 0) {
98         fListenerStack.pop_back_n(n);
99     }
100 }
101 
markResourceInUse(PendingUseListener * listener)102 void ScratchResourceManager::markResourceInUse(PendingUseListener* listener) {
103     // Should only be called inside a scope
104     SkASSERT(!fListenerStack.empty());
105     fListenerStack.push_back(listener);
106 }
107 
108 }  // namespace skgpu::graphite
109