• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
8 #include "include/gpu/graphite/Recording.h"
9 
10 #include "src/core/SkChecksum.h"
11 #include "src/gpu/RefCntedCallback.h"
12 #include "src/gpu/graphite/CommandBuffer.h"
13 #include "src/gpu/graphite/ContextPriv.h"
14 #include "src/gpu/graphite/Log.h"
15 #include "src/gpu/graphite/RecordingPriv.h"
16 #include "src/gpu/graphite/Resource.h"
17 #include "src/gpu/graphite/ResourceProvider.h"
18 #include "src/gpu/graphite/Surface_Graphite.h"
19 #include "src/gpu/graphite/Texture.h"
20 #include "src/gpu/graphite/TextureProxy.h"
21 #include "src/gpu/graphite/task/TaskList.h"
22 
23 #include <unordered_set>
24 
25 using namespace skia_private;
26 
27 namespace skgpu::graphite {
28 
Recording(uint32_t uniqueID,uint32_t recorderID,std::unordered_set<sk_sp<TextureProxy>,ProxyHash> && nonVolatileLazyProxies,std::unordered_set<sk_sp<TextureProxy>,ProxyHash> && volatileLazyProxies,std::unique_ptr<LazyProxyData> targetProxyData,TArray<sk_sp<RefCntedCallback>> && finishedProcs)29 Recording::Recording(uint32_t uniqueID,
30                      uint32_t recorderID,
31                      std::unordered_set<sk_sp<TextureProxy>, ProxyHash>&& nonVolatileLazyProxies,
32                      std::unordered_set<sk_sp<TextureProxy>, ProxyHash>&& volatileLazyProxies,
33                      std::unique_ptr<LazyProxyData> targetProxyData,
34                      TArray<sk_sp<RefCntedCallback>>&& finishedProcs)
35         : fUniqueID(uniqueID)
36         , fRecorderID(recorderID)
37         , fRootTaskList(new TaskList)
38         , fNonVolatileLazyProxies(std::move(nonVolatileLazyProxies))
39         , fVolatileLazyProxies(std::move(volatileLazyProxies))
40         , fTargetProxyData(std::move(targetProxyData))
41         , fFinishedProcs(std::move(finishedProcs)) {}
42 
~Recording()43 Recording::~Recording() {
44     // Any finished procs that haven't been passed to a CommandBuffer fail
45     this->priv().setFailureResultForFinishedProcs();
46 }
47 
operator ()(const sk_sp<TextureProxy> & proxy) const48 std::size_t Recording::ProxyHash::operator()(const sk_sp<TextureProxy> &proxy) const {
49     return SkGoodHash()(proxy.get());
50 }
51 
LazyProxyData(const TextureInfo & textureInfo)52 Recording::LazyProxyData::LazyProxyData(const TextureInfo& textureInfo) {
53     fTargetProxy = TextureProxy::MakeFullyLazy(
54             textureInfo, skgpu::Budgeted::kNo, Volatile::kYes, [this](ResourceProvider*) {
55                 SkASSERT(SkToBool(fTarget));
56                 return std::move(fTarget);
57             });
58 }
59 
lazyProxy()60 TextureProxy* Recording::LazyProxyData::lazyProxy() { return fTargetProxy.get(); }
61 
refLazyProxy()62 sk_sp<TextureProxy> Recording::LazyProxyData::refLazyProxy() { return fTargetProxy; }
63 
lazyInstantiate(ResourceProvider * resourceProvider,sk_sp<Texture> texture)64 bool Recording::LazyProxyData::lazyInstantiate(ResourceProvider* resourceProvider,
65                                                sk_sp<Texture> texture) {
66     fTarget = std::move(texture);
67     return fTargetProxy->lazyInstantiate(resourceProvider);
68 }
69 
70 ////////////////////////////////////////////////////////////////////////////////
hasNonVolatileLazyProxies() const71 bool RecordingPriv::hasNonVolatileLazyProxies() const {
72     return !fRecording->fNonVolatileLazyProxies.empty();
73 }
74 
instantiateNonVolatileLazyProxies(ResourceProvider * resourceProvider)75 bool RecordingPriv::instantiateNonVolatileLazyProxies(ResourceProvider* resourceProvider) {
76     SkASSERT(this->hasNonVolatileLazyProxies());
77 
78     for (const auto& proxy : fRecording->fNonVolatileLazyProxies) {
79         if (!proxy->lazyInstantiate(resourceProvider)) {
80             return false;
81         }
82     }
83 
84     // Note: once all the lazy proxies have been instantiated, that's it - there are no more
85     // chances to instantiate.
86     fRecording->fNonVolatileLazyProxies.clear();
87     return true;
88 }
89 
hasVolatileLazyProxies() const90 bool RecordingPriv::hasVolatileLazyProxies() const {
91     return !fRecording->fVolatileLazyProxies.empty();
92 }
93 
instantiateVolatileLazyProxies(ResourceProvider * resourceProvider)94 bool RecordingPriv::instantiateVolatileLazyProxies(ResourceProvider* resourceProvider) {
95     SkASSERT(this->hasVolatileLazyProxies());
96 
97     for (const auto& proxy : fRecording->fVolatileLazyProxies) {
98         if (!proxy->lazyInstantiate(resourceProvider)) {
99             return false;
100         }
101     }
102 
103     return true;
104 }
105 
deinstantiateVolatileLazyProxies()106 void RecordingPriv::deinstantiateVolatileLazyProxies() {
107     if (!this->hasVolatileLazyProxies()) {
108         return;
109     }
110 
111     for (const auto& proxy : fRecording->fVolatileLazyProxies) {
112         SkASSERT(proxy->isVolatile());
113         proxy->deinstantiate();
114     }
115 }
116 
setFailureResultForFinishedProcs()117 void RecordingPriv::setFailureResultForFinishedProcs() {
118     for (int i = 0; i < fRecording->fFinishedProcs.size(); ++i) {
119         fRecording->fFinishedProcs[i]->setFailureResult();
120     }
121     fRecording->fFinishedProcs.clear();
122 }
123 
addCommands(Context * context,CommandBuffer * commandBuffer,Surface * targetSurface,SkIVector targetTranslation)124 bool RecordingPriv::addCommands(Context* context,
125                                 CommandBuffer* commandBuffer,
126                                 Surface* targetSurface,
127                                 SkIVector targetTranslation) {
128     AutoDeinstantiateTextureProxy autoDeinstantiateTargetProxy(
129             fRecording->fTargetProxyData ? fRecording->fTargetProxyData->lazyProxy() : nullptr);
130 
131     const Texture* replayTarget = nullptr;
132     ResourceProvider* resourceProvider = context->priv().resourceProvider();
133     SkASSERT(!SkToBool(fRecording->fTargetProxyData) || SkToBool(targetSurface));
134     if (fRecording->fTargetProxyData) {
135         if (!targetSurface) {
136             SKGPU_LOG_E("No surface provided to instantiate target texture proxy.");
137             return false;
138         }
139         TextureProxy* surfaceTexture = targetSurface->backingTextureProxy();
140         if (!surfaceTexture->instantiate(resourceProvider)) {
141             SKGPU_LOG_E("Could not instantiate target texture proxy.");
142             return false;
143         }
144         if (!fRecording->fTargetProxyData->lazyInstantiate(resourceProvider,
145                                                            surfaceTexture->refTexture())) {
146             SKGPU_LOG_E("Could not instantiate deferred texture proxy.");
147             return false;
148         }
149         replayTarget = surfaceTexture->texture();
150     }
151 
152     for (size_t i = 0; i < fRecording->fExtraResourceRefs.size(); ++i) {
153         commandBuffer->trackResource(fRecording->fExtraResourceRefs[i]);
154     }
155 
156     // There's no need to differentiate kSuccess and kDiscard at the root list level; if every task
157     // is discarded, the Recording will automatically be a no-op on replay while still correctly
158     // notifying any finish procs the client may have added.
159     if (fRecording->fRootTaskList->addCommands(
160                 context, commandBuffer, {replayTarget, targetTranslation}) == Task::Status::kFail) {
161         return false;
162     }
163     for (int i = 0; i < fRecording->fFinishedProcs.size(); ++i) {
164         commandBuffer->addFinishedProc(std::move(fRecording->fFinishedProcs[i]));
165     }
166     fRecording->fFinishedProcs.clear();
167 
168     return true;
169 }
170 
addResourceRef(sk_sp<Resource> resource)171 void RecordingPriv::addResourceRef(sk_sp<Resource> resource) {
172     fRecording->fExtraResourceRefs.push_back(std::move(resource));
173 }
174 
addTask(sk_sp<Task> task)175 void RecordingPriv::addTask(sk_sp<Task> task) {
176     fRecording->fRootTaskList->add(std::move(task));
177 }
178 
addTasks(TaskList && tasks)179 void RecordingPriv::addTasks(TaskList&& tasks) {
180     fRecording->fRootTaskList->add(std::move(tasks));
181 }
182 
183 #if defined(GRAPHITE_TEST_UTILS)
isTargetProxyInstantiated() const184 bool RecordingPriv::isTargetProxyInstantiated() const {
185     return fRecording->fTargetProxyData->lazyProxy()->isInstantiated();
186 }
187 
numVolatilePromiseImages() const188 int RecordingPriv::numVolatilePromiseImages() const {
189     return fRecording->fVolatileLazyProxies.size();
190 }
191 
numNonVolatilePromiseImages() const192 int RecordingPriv::numNonVolatilePromiseImages() const {
193     return fRecording->fNonVolatileLazyProxies.size();
194 }
195 
hasTasks() const196 bool RecordingPriv::hasTasks() const {
197     return fRecording->fRootTaskList->hasTasks();
198 }
199 #endif
200 
201 } // namespace skgpu::graphite
202