Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
Recorder.h
Go to the documentation of this file.
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#ifndef skgpu_graphite_Recorder_DEFINED
9#define skgpu_graphite_Recorder_DEFINED
10
12#include "include/core/SkSize.h"
17
18#include <chrono>
19
20struct AHardwareBuffer;
21class SkCanvas;
22struct SkImageInfo;
23class SkPixmap;
25
26namespace skgpu {
27class RefCntedCallback;
28class TokenTracker;
29}
30
31namespace sktext::gpu {
32class StrikeCache;
34}
35
36namespace skgpu::graphite {
37
38class AtlasProvider;
39class BackendTexture;
40class Caps;
41class Context;
42class Device;
43class DrawBufferManager;
44class GlobalCache;
45class ImageProvider;
46class ProxyCache;
47class RecorderPriv;
49class RuntimeEffectDictionary;
50class SharedContext;
51class Task;
52class TaskList;
53class TextureDataBlock;
54class TextureInfo;
55class UniformDataBlock;
56class UploadBufferManager;
57
58template<typename T> class PipelineDataCache;
61
62struct SK_API RecorderOptions final {
66
68
69 static constexpr size_t kDefaultRecorderBudget = 256 * (1 << 20);
70 // What is the budget for GPU resources allocated and held by this Recorder.
71 size_t fGpuBudgetInBytes = kDefaultRecorderBudget;
72};
73
74class SK_API Recorder final {
75public:
76 Recorder(const Recorder&) = delete;
77 Recorder(Recorder&&) = delete;
78 Recorder& operator=(const Recorder&) = delete;
80
81 ~Recorder();
82
83 BackendApi backend() const;
84
85 std::unique_ptr<Recording> snap();
86
87 ImageProvider* clientImageProvider() { return fClientImageProvider.get(); }
88 const ImageProvider* clientImageProvider() const { return fClientImageProvider.get(); }
89
90 /**
91 * Creates a new backend gpu texture matching the dimensions and TextureInfo. If an invalid
92 * TextureInfo or a TextureInfo Skia can't support is passed in, this will return an invalid
93 * BackendTexture. Thus the client should check isValid on the returned BackendTexture to know
94 * if it succeeded or not.
95 *
96 * If this does return a valid BackendTexture, the caller is required to use
97 * Recorder::deleteBackendTexture or Context::deleteBackendTexture to delete the texture. It is
98 * safe to use the Context that created this Recorder or any other Recorder created from the
99 * same Context to call deleteBackendTexture.
100 */
101 BackendTexture createBackendTexture(SkISize dimensions, const TextureInfo&);
102
103#ifdef SK_BUILD_FOR_ANDROID
104 BackendTexture createBackendTexture(AHardwareBuffer*,
105 bool isRenderable,
106 bool isProtectedContent,
107 SkISize dimensions,
108 bool fromAndroidWindow = false) const;
109#endif
110
111 /**
112 * If possible, updates a backend texture with the provided pixmap data. The client
113 * should check the return value to see if the update was successful. The client is required
114 * to insert a Recording into the Context and call `submit` to send the upload work to the gpu.
115 * The backend texture must be compatible with the provided pixmap(s). Compatible, in this case,
116 * means that the backend format is compatible with the base pixmap's colortype. The src data
117 * can be deleted when this call returns.
118 * If the backend texture is mip mapped, the data for all the mipmap levels must be provided.
119 * In the mipmapped case all the colortypes of the provided pixmaps must be the same.
120 * Additionally, all the miplevels must be sized correctly (please see
121 * SkMipmap::ComputeLevelSize and ComputeLevelCount).
122 * Note: the pixmap's alphatypes and colorspaces are ignored.
123 * For the Vulkan backend after a successful update the layout of the created VkImage will be:
124 * VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
125 */
126 bool updateBackendTexture(const BackendTexture&,
127 const SkPixmap srcData[],
128 int numLevels);
129
130 /**
131 * If possible, updates a compressed backend texture filled with the provided raw data. The
132 * client should check the return value to see if the update was successful. The client is
133 * required to insert a Recording into the Context and call `submit` to send the upload work to
134 * the gpu.
135 * If the backend texture is mip mapped, the data for all the mipmap levels must be provided.
136 * Additionally, all the miplevels must be sized correctly (please see
137 * SkMipMap::ComputeLevelSize and ComputeLevelCount).
138 * For the Vulkan backend after a successful update the layout of the created VkImage will be:
139 * VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
140 */
141 bool updateCompressedBackendTexture(const BackendTexture&,
142 const void* data,
143 size_t dataSize);
144
145 /**
146 * Called to delete the passed in BackendTexture. This should only be called if the
147 * BackendTexture was created by calling Recorder::createBackendTexture on a Recorder that is
148 * associated with the same Context. If the BackendTexture is not valid or does not match the
149 * BackendApi of the Recorder then nothing happens.
150 *
151 * Otherwise this will delete/release the backend object that is wrapped in the BackendTexture.
152 * The BackendTexture will be reset to an invalid state and should not be used again.
153 */
154 void deleteBackendTexture(const BackendTexture&);
155
156 // Adds a proc that will be moved to the Recording upon snap, subsequently attached to the
157 // CommandBuffer when the Recording is added, and called when that CommandBuffer is submitted
158 // and finishes. If the Recorder or Recording is deleted before the proc is added to the
159 // CommandBuffer, it will be called with result Failure.
160 void addFinishInfo(const InsertFinishInfo&);
161
162 // Returns a canvas that will record to a proxy surface, which must be instantiated on replay.
163 // This can only be called once per Recording; subsequent calls will return null until a
164 // Recording is snapped. Additionally, the returned SkCanvas is only valid until the next
165 // Recording snap, at which point it is deleted.
166 SkCanvas* makeDeferredCanvas(const SkImageInfo&, const TextureInfo&);
167
168 /**
169 * Frees GPU resources created and held by the Recorder. Can be called to reduce GPU memory
170 * pressure. Any resources that are still in use (e.g. being used by work submitted to the GPU)
171 * will not be deleted by this call. If the caller wants to make sure all resources are freed,
172 * then they should first make sure to submit and wait on any outstanding work.
173 */
174 void freeGpuResources();
175
176 /**
177 * Purge GPU resources on the Recorder that haven't been used in the past 'msNotUsed'
178 * milliseconds or are otherwise marked for deletion, regardless of whether the context is under
179 * budget.
180 */
181 void performDeferredCleanup(std::chrono::milliseconds msNotUsed);
182
183 /**
184 * Returns the number of bytes of the Recorder's gpu memory cache budget that are currently in
185 * use.
186 */
187 size_t currentBudgetedBytes() const;
188
189 /**
190 * Returns the size of Recorder's gpu memory cache budget in bytes.
191 */
192 size_t maxBudgetedBytes() const;
193
194 /**
195 * Enumerates all cached GPU resources owned by the Recorder and dumps their memory to
196 * traceMemoryDump.
197 */
198 void dumpMemoryStatistics(SkTraceMemoryDump* traceMemoryDump) const;
199
200 // Provides access to functions that aren't part of the public API.
202 const RecorderPriv priv() const; // NOLINT(readability-const-return-type)
203
204private:
205 friend class Context; // For ctor
206 friend class Device; // For registering and deregistering Devices;
207 friend class RecorderPriv; // for ctor and hidden methods
208
210
211 SingleOwner* singleOwner() const { return &fSingleOwner; }
212
213 // We keep track of all Devices that are connected to a Recorder. This allows the client to
214 // safely delete an SkSurface or a Recorder in any order. If the client deletes the Recorder
215 // we need to notify all Devices that the Recorder is no longer valid. If we delete the
216 // SkSurface/Device first we will flush all the Device's into the Recorder before deregistering
217 // it from the Recorder.
218 //
219 // We take a ref on the Device so that ~Device() does not have to deregister the recorder
220 // (which can happen on any thread if the Device outlives the Surface via an Image view).
221 // Recorder::flushTrackedDevices() cleans up uniquely held and immutable Devices on the recorder
222 // thread so this extra ref is not significantly increasing the Device lifetime.
223 //
224 // Note: We could probably get by with only registering Devices directly connected to
225 // SkSurfaces. All other one off Devices will be created in a controlled scope where the
226 // Recorder should still be valid by the time they need to flush their work when the Device is
227 // deleted. We would have to make sure we safely handle cases where a client calls saveLayer
228 // then either deletes the SkSurface or Recorder before calling restore. For simplicity we just
229 // register every device for now, but if we see extra overhead in pushing back the extra
230 // pointers, we can look into only registering SkSurface Devices.
231 void registerDevice(sk_sp<Device>);
232 void deregisterDevice(const Device*);
233
234 sk_sp<SharedContext> fSharedContext;
235 std::unique_ptr<ResourceProvider> fResourceProvider;
236 std::unique_ptr<RuntimeEffectDictionary> fRuntimeEffectDict;
237
238 // NOTE: These are stored by pointer to allow them to be forward declared.
239 std::unique_ptr<TaskList> fRootTaskList;
240 std::unique_ptr<UniformDataCache> fUniformDataCache;
241 std::unique_ptr<TextureDataCache> fTextureDataCache;
242 std::unique_ptr<DrawBufferManager> fDrawBufferManager;
243 std::unique_ptr<UploadBufferManager> fUploadBufferManager;
244
245 // Iterating over tracked devices in flushTrackedDevices() needs to be re-entrant and support
246 // additions to fTrackedDevices if registerDevice() is triggered by a temporary device during
247 // flushing. Removals are handled by setting elements to null; final clean up is handled at the
248 // end of the initial call to flushTrackedDevices().
249 skia_private::TArray<sk_sp<Device>> fTrackedDevices;
250 int fFlushingDevicesIndex = -1;
251
252 uint32_t fUniqueID; // Needed for MessageBox handling for text
253 uint32_t fNextRecordingID = 1;
254 std::unique_ptr<AtlasProvider> fAtlasProvider;
255 std::unique_ptr<TokenTracker> fTokenTracker;
256 std::unique_ptr<sktext::gpu::StrikeCache> fStrikeCache;
257 std::unique_ptr<sktext::gpu::TextBlobRedrawCoordinator> fTextBlobCache;
258 sk_sp<ImageProvider> fClientImageProvider;
259
260 // In debug builds we guard against improper thread handling
261 // This guard is passed to the ResourceCache.
262 // TODO: Should we also pass this to Device, DrawContext, and similar classes?
263 mutable SingleOwner fSingleOwner;
264
265 sk_sp<Device> fTargetProxyDevice;
266 std::unique_ptr<SkCanvas> fTargetProxyCanvas;
267 std::unique_ptr<Recording::LazyProxyData> fTargetProxyData;
268
270
271#if defined(GRAPHITE_TEST_UTILS)
272 // For testing use only -- the Context used to create this Recorder
273 Context* fContext = nullptr;
274#endif
275};
276
277} // namespace skgpu::graphite
278
279#endif // skgpu_graphite_Recorder_DEFINED
const char * backend
struct AHardwareBuffer AHardwareBuffer
#define SK_API
Definition SkAPI.h:35
const Context & fContext
Recorder(Recorder &&)=delete
Recorder & operator=(Recorder &&)=delete
const ImageProvider * clientImageProvider() const
Definition Recorder.h:88
ImageProvider * clientImageProvider()
Definition Recorder.h:87
Recorder(const Recorder &)=delete
Recorder & operator=(const Recorder &)=delete
FlPixelBufferTexturePrivate * priv
BackendApi
Definition GpuTypes.h:22
Definition DM.cpp:1161
RecorderOptions(const RecorderOptions &)
sk_sp< ImageProvider > fImageProvider
Definition Recorder.h:67
skgpu::graphite::Recorder Recorder