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/gpu/graphite/CommandBuffer.h"
11 #include "src/gpu/graphite/ContextPriv.h"
12 #include "src/gpu/graphite/Log.h"
13 #include "src/gpu/graphite/RecordingPriv.h"
14 #include "src/gpu/graphite/Resource.h"
15 #include "src/gpu/graphite/ResourceProvider.h"
16 #include "src/gpu/graphite/Surface_Graphite.h"
17 #include "src/gpu/graphite/TaskGraph.h"
18 #include "src/gpu/graphite/Texture.h"
19 #include "src/gpu/graphite/TextureProxy.h"
20
21 #include <unordered_set>
22
23 namespace skgpu::graphite {
24
Recording(std::unique_ptr<TaskGraph> graph,std::unordered_set<sk_sp<TextureProxy>,ProxyHash> && nonVolatileLazyProxies,std::unordered_set<sk_sp<TextureProxy>,ProxyHash> && volatileLazyProxies,std::unique_ptr<LazyProxyData> targetProxyData)25 Recording::Recording(std::unique_ptr<TaskGraph> graph,
26 std::unordered_set<sk_sp<TextureProxy>, ProxyHash>&& nonVolatileLazyProxies,
27 std::unordered_set<sk_sp<TextureProxy>, ProxyHash>&& volatileLazyProxies,
28 std::unique_ptr<LazyProxyData> targetProxyData)
29 : fGraph(std::move(graph))
30 , fNonVolatileLazyProxies(std::move(nonVolatileLazyProxies))
31 , fVolatileLazyProxies(std::move(volatileLazyProxies))
32 , fTargetProxyData(std::move(targetProxyData)) {}
33
~Recording()34 Recording::~Recording() {}
35
36 #if GRAPHITE_TEST_UTILS
isTargetProxyInstantiated() const37 bool Recording::isTargetProxyInstantiated() const {
38 return fTargetProxyData->lazyProxy()->isInstantiated();
39 }
40 #endif
41
42 ////////////////////////////////////////////////////////////////////////////////
hasNonVolatileLazyProxies() const43 bool RecordingPriv::hasNonVolatileLazyProxies() const {
44 return !fRecording->fNonVolatileLazyProxies.empty();
45 }
46
instantiateNonVolatileLazyProxies(ResourceProvider * resourceProvider)47 bool RecordingPriv::instantiateNonVolatileLazyProxies(ResourceProvider* resourceProvider) {
48 SkASSERT(this->hasNonVolatileLazyProxies());
49
50 for (auto proxy : fRecording->fNonVolatileLazyProxies) {
51 if (!proxy->lazyInstantiate(resourceProvider)) {
52 return false;
53 }
54 }
55
56 // Note: once all the lazy proxies have been instantiated, that's it - there are no more
57 // chances to instantiate.
58 fRecording->fNonVolatileLazyProxies.clear();
59 return true;
60 }
61
hasVolatileLazyProxies() const62 bool RecordingPriv::hasVolatileLazyProxies() const {
63 return !fRecording->fVolatileLazyProxies.empty();
64 }
65
instantiateVolatileLazyProxies(ResourceProvider * resourceProvider)66 bool RecordingPriv::instantiateVolatileLazyProxies(ResourceProvider* resourceProvider) {
67 SkASSERT(this->hasVolatileLazyProxies());
68
69 for (auto proxy : fRecording->fVolatileLazyProxies) {
70 if (!proxy->lazyInstantiate(resourceProvider)) {
71 return false;
72 }
73 }
74
75 return true;
76 }
77
deinstantiateVolatileLazyProxies()78 void RecordingPriv::deinstantiateVolatileLazyProxies() {
79 if (!this->hasVolatileLazyProxies()) {
80 return;
81 }
82
83 for (auto proxy : fRecording->fVolatileLazyProxies) {
84 SkASSERT(proxy->isVolatile());
85 proxy->deinstantiate();
86 }
87 }
88
89 #if GRAPHITE_TEST_UTILS
numVolatilePromiseImages() const90 int RecordingPriv::numVolatilePromiseImages() const {
91 return fRecording->fVolatileLazyProxies.size();
92 }
93
numNonVolatilePromiseImages() const94 int RecordingPriv::numNonVolatilePromiseImages() const {
95 return fRecording->fNonVolatileLazyProxies.size();
96 }
97
hasTasks() const98 bool RecordingPriv::hasTasks() const { return fRecording->fGraph->hasTasks(); }
99 #endif
100
addCommands(Context * context,CommandBuffer * commandBuffer,Surface * replaySurface,SkIVector replayTranslation)101 bool RecordingPriv::addCommands(Context* context,
102 CommandBuffer* commandBuffer,
103 Surface* replaySurface,
104 SkIVector replayTranslation) {
105 AutoDeinstantiateTextureProxy autoDeinstantiateTargetProxy(
106 fRecording->fTargetProxyData ? fRecording->fTargetProxyData->lazyProxy() : nullptr);
107
108 const Texture* replayTarget = nullptr;
109 SkASSERT(SkToBool(fRecording->fTargetProxyData) == SkToBool(replaySurface));
110 ResourceProvider* resourceProvider = context->priv().resourceProvider();
111 if (fRecording->fTargetProxyData) {
112 if (!replaySurface) {
113 SKGPU_LOG_E("No surface provided to instantiate target texture proxy.");
114 return false;
115 }
116 TextureProxy* surfaceTexture = replaySurface->backingTextureProxy();
117 if (!surfaceTexture->instantiate(resourceProvider)) {
118 SKGPU_LOG_E("Could not instantiate target texture proxy.");
119 return false;
120 }
121 if (!fRecording->fTargetProxyData->lazyInstantiate(resourceProvider,
122 surfaceTexture->refTexture())) {
123 SKGPU_LOG_E("Could not instantiate deferred texture proxy.");
124 return false;
125 }
126 replayTarget = surfaceTexture->texture();
127 }
128
129 if (!fRecording->fGraph->addCommands(
130 context, commandBuffer, {replayTarget, replayTranslation})) {
131 return false;
132 }
133 for (size_t i = 0; i < fRecording->fExtraResourceRefs.size(); ++i) {
134 commandBuffer->trackResource(fRecording->fExtraResourceRefs[i]);
135 }
136 return true;
137 }
138
addResourceRef(sk_sp<Resource> resource)139 void RecordingPriv::addResourceRef(sk_sp<Resource> resource) {
140 fRecording->fExtraResourceRefs.push_back(std::move(resource));
141 }
142
addTask(sk_sp<Task> task)143 void RecordingPriv::addTask(sk_sp<Task> task) {
144 fRecording->fGraph->prepend(std::move(task));
145 }
146
LazyProxyData(const TextureInfo & textureInfo)147 Recording::LazyProxyData::LazyProxyData(const TextureInfo& textureInfo) {
148 fTargetProxy = TextureProxy::MakeFullyLazy(
149 textureInfo, skgpu::Budgeted::kNo, Volatile::kYes, [this](ResourceProvider*) {
150 SkASSERT(SkToBool(fTarget));
151 return std::move(fTarget);
152 });
153 }
154
lazyProxy()155 TextureProxy* Recording::LazyProxyData::lazyProxy() { return fTargetProxy.get(); }
156
refLazyProxy()157 sk_sp<TextureProxy> Recording::LazyProxyData::refLazyProxy() { return fTargetProxy; }
158
lazyInstantiate(ResourceProvider * resourceProvider,sk_sp<Texture> texture)159 bool Recording::LazyProxyData::lazyInstantiate(ResourceProvider* resourceProvider,
160 sk_sp<Texture> texture) {
161 fTarget = std::move(texture);
162 return fTargetProxy->lazyInstantiate(resourceProvider);
163 }
164
165 } // namespace skgpu::graphite
166