File: Recorder.h

package info (click to toggle)
webkit2gtk 2.48.5-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 429,764 kB
  • sloc: cpp: 3,697,587; javascript: 194,444; ansic: 169,997; python: 46,499; asm: 19,295; ruby: 18,528; perl: 16,602; xml: 4,650; yacc: 2,360; sh: 2,098; java: 1,993; lex: 1,327; pascal: 366; makefile: 298
file content (309 lines) | stat: -rw-r--r-- 13,575 bytes parent folder | download | duplicates (11)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
/*
 * Copyright 2021 Google LLC
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#ifndef skgpu_graphite_Recorder_DEFINED
#define skgpu_graphite_Recorder_DEFINED

#include "include/core/SkRefCnt.h"
#include "include/core/SkSize.h"
#include "include/gpu/graphite/GraphiteTypes.h"
#include "include/gpu/graphite/Recording.h"
#include "include/private/base/SingleOwner.h"
#include "include/private/base/SkTArray.h"

#include <chrono>

struct AHardwareBuffer;
class SkCanvas;
struct SkImageInfo;
class SkPixmap;
class SkTraceMemoryDump;

namespace skgpu {
class RefCntedCallback;
class TokenTracker;
}

namespace sktext::gpu {
class StrikeCache;
class TextBlobRedrawCoordinator;
}

namespace skgpu::graphite {

class AtlasProvider;
class BackendTexture;
class Caps;
class Context;
class Device;
class DrawBufferManager;
class GlobalCache;
class ImageProvider;
class ProxyCache;
class ProxyReadCountMap;
class RecorderPriv;
class ResourceProvider;
class RuntimeEffectDictionary;
class SharedContext;
class Task;
class TaskList;
class TextureDataBlock;
class TextureInfo;
class UniformDataBlock;
class UploadBufferManager;
class UploadList;

template<typename T> class PipelineDataCache;
using TextureDataCache = PipelineDataCache<TextureDataBlock>;

struct SK_API RecorderOptions final {
    RecorderOptions();
    RecorderOptions(const RecorderOptions&);
    ~RecorderOptions();

    sk_sp<ImageProvider> fImageProvider;

    static constexpr size_t kDefaultRecorderBudget = 256 * (1 << 20);
    // What is the budget for GPU resources allocated and held by this Recorder.
    size_t fGpuBudgetInBytes = kDefaultRecorderBudget;
};

class SK_API Recorder final {
public:
    Recorder(const Recorder&) = delete;
    Recorder(Recorder&&) = delete;
    Recorder& operator=(const Recorder&) = delete;
    Recorder& operator=(Recorder&&) = delete;

    ~Recorder();

    BackendApi backend() const;

    std::unique_ptr<Recording> snap();

    ImageProvider* clientImageProvider() { return fClientImageProvider.get(); }
    const ImageProvider* clientImageProvider() const { return fClientImageProvider.get(); }

    /**
     * Gets the maximum supported texture size.
     */
    int maxTextureSize() const;

    /**
     * Creates a new backend gpu texture matching the dimensions and TextureInfo. If an invalid
     * TextureInfo or a TextureInfo Skia can't support is passed in, this will return an invalid
     * BackendTexture. Thus the client should check isValid on the returned BackendTexture to know
     * if it succeeded or not.
     *
     * If this does return a valid BackendTexture, the caller is required to use
     * Recorder::deleteBackendTexture or Context::deleteBackendTexture to delete the texture. It is
     * safe to use the Context that created this Recorder or any other Recorder created from the
     * same Context to call deleteBackendTexture.
     */
    BackendTexture createBackendTexture(SkISize dimensions, const TextureInfo&);

#ifdef SK_BUILD_FOR_ANDROID
    BackendTexture createBackendTexture(AHardwareBuffer*,
                                        bool isRenderable,
                                        bool isProtectedContent,
                                        SkISize dimensions,
                                        bool fromAndroidWindow = false) const;
#endif

    /**
     * If possible, updates a backend texture with the provided pixmap data. The client
     * should check the return value to see if the update was successful. The client is required
     * to insert a Recording into the Context and call `submit` to send the upload work to the gpu.
     * The backend texture must be compatible with the provided pixmap(s). Compatible, in this case,
     * means that the backend format is compatible with the base pixmap's colortype. The src data
     * can be deleted when this call returns. When the BackendTexture is safe to be destroyed by the
     * client, Skia will call the passed in GpuFinishedProc. The BackendTexture should not be
     * destroyed before that.
     * If the backend texture is mip mapped, the data for all the mipmap levels must be provided.
     * In the mipmapped case all the colortypes of the provided pixmaps must be the same.
     * Additionally, all the miplevels must be sized correctly (please see
     * SkMipmap::ComputeLevelSize and ComputeLevelCount).
     * Note: the pixmap's alphatypes and colorspaces are ignored.
     * For the Vulkan backend after a successful update the layout of the created VkImage will be:
     *      VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
     */
    bool updateBackendTexture(const BackendTexture&,
                              const SkPixmap srcData[],
                              int numLevels,
                              GpuFinishedProc = nullptr,
                              GpuFinishedContext = nullptr);

    /**
     * If possible, updates a compressed backend texture filled with the provided raw data. The
     * client should check the return value to see if the update was successful. The client is
     * required to insert a Recording into the Context and call `submit` to send the upload work to
     * the gpu. When the BackendTexture is safe to be destroyed by the client, Skia will call the
     * passed in GpuFinishedProc. The BackendTexture should not be destroyed before that.
     * If the backend texture is mip mapped, the data for all the mipmap levels must be provided.
     * Additionally, all the miplevels must be sized correctly (please see
     * SkMipMap::ComputeLevelSize and ComputeLevelCount).
     * For the Vulkan backend after a successful update the layout of the created VkImage will be:
     *      VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
     */
    bool updateCompressedBackendTexture(const BackendTexture&,
                                        const void* data,
                                        size_t dataSize,
                                        GpuFinishedProc = nullptr,
                                        GpuFinishedContext = nullptr);

    /**
     * Called to delete the passed in BackendTexture. This should only be called if the
     * BackendTexture was created by calling Recorder::createBackendTexture on a Recorder that is
     * associated with the same Context. If the BackendTexture is not valid or does not match the
     * BackendApi of the Recorder then nothing happens.
     *
     * Otherwise this will delete/release the backend object that is wrapped in the BackendTexture.
     * The BackendTexture will be reset to an invalid state and should not be used again.
     */
    void deleteBackendTexture(const BackendTexture&);

    // Adds a proc that will be moved to the Recording upon snap, subsequently attached to the
    // CommandBuffer when the Recording is added, and called when that CommandBuffer is submitted
    // and finishes. If the Recorder or Recording is deleted before the proc is added to the
    // CommandBuffer, it will be called with result Failure.
    void addFinishInfo(const InsertFinishInfo&);

    // Returns a canvas that will record to a proxy surface, which must be instantiated on replay.
    // This can only be called once per Recording; subsequent calls will return null until a
    // Recording is snapped. Additionally, the returned SkCanvas is only valid until the next
    // Recording snap, at which point it is deleted.
    SkCanvas* makeDeferredCanvas(const SkImageInfo&, const TextureInfo&);

    /**
     * Frees GPU resources created and held by the Recorder. Can be called to reduce GPU memory
     * pressure. Any resources that are still in use (e.g. being used by work submitted to the GPU)
     * will not be deleted by this call. If the caller wants to make sure all resources are freed,
     * then they should first make sure to submit and wait on any outstanding work.
     */
    void freeGpuResources();

    /**
     * Purge GPU resources on the Recorder that haven't been used in the past 'msNotUsed'
     * milliseconds or are otherwise marked for deletion, regardless of whether the context is under
     * budget.
     */
    void performDeferredCleanup(std::chrono::milliseconds msNotUsed);

    /**
     * Returns the number of bytes of the Recorder's gpu memory cache budget that are currently in
     * use.
     */
    size_t currentBudgetedBytes() const;

    /**
     * Returns the number of bytes of the Recorder's resource cache that are currently purgeable.
     */
    size_t currentPurgeableBytes() const;

    /**
     * Returns the size of Recorder's gpu memory cache budget in bytes.
     */
    size_t maxBudgetedBytes() const;

    /**
     * Sets the size of Recorders's gpu memory cache budget in bytes. If the new budget is lower
     * than the current budget, the cache will try to free resources to get under the new budget.
     */
    void setMaxBudgetedBytes(size_t bytes);

    /**
     * Enumerates all cached GPU resources owned by the Recorder and dumps their memory to
     * traceMemoryDump.
     */
    void dumpMemoryStatistics(SkTraceMemoryDump* traceMemoryDump) const;

    // Provides access to functions that aren't part of the public API.
    RecorderPriv priv();
    const RecorderPriv priv() const;  // NOLINT(readability-const-return-type)

private:
    friend class Context; // For ctor
    friend class Device; // For registering and deregistering Devices;
    friend class RecorderPriv; // for ctor and hidden methods

    // If Context is non-null, the Recorder will use the Context's resource provider
    // instead of creating its own.
    Recorder(sk_sp<SharedContext>, const RecorderOptions&, const Context*);

    SingleOwner* singleOwner() const { return &fSingleOwner; }

    // We keep track of all Devices that are connected to a Recorder. This allows the client to
    // safely delete an SkSurface or a Recorder in any order. If the client deletes the Recorder
    // we need to notify all Devices that the Recorder is no longer valid. If we delete the
    // SkSurface/Device first we will flush all the Device's into the Recorder before deregistering
    // it from the Recorder.
    //
    // We take a ref on the Device so that ~Device() does not have to deregister the recorder
    // (which can happen on any thread if the Device outlives the Surface via an Image view).
    // Recorder::flushTrackedDevices() cleans up uniquely held and immutable Devices on the recorder
    // thread so this extra ref is not significantly increasing the Device lifetime.
    //
    // Note: We could probably get by with only registering Devices directly connected to
    // SkSurfaces. All other one off Devices will be created in a controlled scope where the
    // Recorder should still be valid by the time they need to flush their work when the Device is
    // deleted. We would have to make sure we safely handle cases where a client calls saveLayer
    // then either deletes the SkSurface or Recorder before calling restore. For simplicity we just
    // register every device for now, but if we see extra overhead in pushing back the extra
    // pointers, we can look into only registering SkSurface Devices.
    void registerDevice(sk_sp<Device>);
    void deregisterDevice(const Device*);

    sk_sp<SharedContext> fSharedContext;
    ResourceProvider* fResourceProvider; // May point to the Context's resource provider
    std::unique_ptr<ResourceProvider> fOwnedResourceProvider; // May be null
    std::unique_ptr<RuntimeEffectDictionary> fRuntimeEffectDict;

    // NOTE: These are stored by pointer to allow them to be forward declared.
    std::unique_ptr<TaskList> fRootTaskList;
    // Aggregated one-time uploads that preceed all tasks in the root task list.
    std::unique_ptr<UploadList> fRootUploads;

    std::unique_ptr<TextureDataCache> fTextureDataCache;
    std::unique_ptr<DrawBufferManager> fDrawBufferManager;
    std::unique_ptr<UploadBufferManager> fUploadBufferManager;
    std::unique_ptr<ProxyReadCountMap> fProxyReadCounts;

    // Iterating over tracked devices in flushTrackedDevices() needs to be re-entrant and support
    // additions to fTrackedDevices if registerDevice() is triggered by a temporary device during
    // flushing. Removals are handled by setting elements to null; final clean up is handled at the
    // end of the initial call to flushTrackedDevices().
    skia_private::TArray<sk_sp<Device>> fTrackedDevices;
    int fFlushingDevicesIndex = -1;

    uint32_t fUniqueID;  // Needed for MessageBox handling for text
    uint32_t fNextRecordingID = 1;
    std::unique_ptr<AtlasProvider> fAtlasProvider;
    std::unique_ptr<TokenTracker> fTokenTracker;
    std::unique_ptr<sktext::gpu::StrikeCache> fStrikeCache;
    std::unique_ptr<sktext::gpu::TextBlobRedrawCoordinator> fTextBlobCache;
    sk_sp<ImageProvider> fClientImageProvider;

    // In debug builds we guard against improper thread handling
    // This guard is passed to the ResourceCache.
    // TODO: Should we also pass this to Device, DrawContext, and similar classes?
    mutable SingleOwner fSingleOwner;

    sk_sp<Device> fTargetProxyDevice;
    std::unique_ptr<SkCanvas> fTargetProxyCanvas;
    std::unique_ptr<Recording::LazyProxyData> fTargetProxyData;

    skia_private::TArray<sk_sp<RefCntedCallback>> fFinishedProcs;

#if defined(GPU_TEST_UTILS)
    // For testing use only -- the Context used to create this Recorder
    Context* fContext = nullptr;
#endif
};

} // namespace skgpu::graphite

#endif // skgpu_graphite_Recorder_DEFINED