Flutter Engine
The Flutter Engine
Public Member Functions | Friends | List of all members
skgpu::graphite::Recorder Class Referencefinal

#include <Recorder.h>

Public Member Functions

 Recorder (const Recorder &)=delete
 
 Recorder (Recorder &&)=delete
 
Recorderoperator= (const Recorder &)=delete
 
Recorderoperator= (Recorder &&)=delete
 
 ~Recorder ()
 
BackendApi backend () const
 
std::unique_ptr< Recordingsnap ()
 
ImageProviderclientImageProvider ()
 
const ImageProviderclientImageProvider () const
 
BackendTexture createBackendTexture (SkISize dimensions, const TextureInfo &)
 
bool updateBackendTexture (const BackendTexture &, const SkPixmap srcData[], int numLevels)
 
bool updateCompressedBackendTexture (const BackendTexture &, const void *data, size_t dataSize)
 
void deleteBackendTexture (const BackendTexture &)
 
void addFinishInfo (const InsertFinishInfo &)
 
SkCanvasmakeDeferredCanvas (const SkImageInfo &, const TextureInfo &)
 
void freeGpuResources ()
 
void performDeferredCleanup (std::chrono::milliseconds msNotUsed)
 
size_t currentBudgetedBytes () const
 
size_t maxBudgetedBytes () const
 
void dumpMemoryStatistics (SkTraceMemoryDump *traceMemoryDump) const
 
RecorderPriv priv ()
 
const RecorderPriv priv () const
 

Friends

class Context
 
class Device
 
class RecorderPriv
 

Detailed Description

Definition at line 75 of file Recorder.h.

Constructor & Destructor Documentation

◆ Recorder() [1/2]

skgpu::graphite::Recorder::Recorder ( const Recorder )
delete

◆ Recorder() [2/2]

skgpu::graphite::Recorder::Recorder ( Recorder &&  )
delete

◆ ~Recorder()

skgpu::graphite::Recorder::~Recorder ( )

Definition at line 134 of file Recorder.cpp.

134 {
136 // Any finished procs that haven't been passed to a Recording fail
137 for (int i = 0; i < fFinishedProcs.size(); ++i) {
138 fFinishedProcs[i]->setFailureResult();
139 }
140
141 for (auto& device : fTrackedDevices) {
142 // deregisterDevice() may have left an entry as null previously.
143 if (device) {
144 device->abandonRecorder();
145 }
146 }
147#if defined(GRAPHITE_TEST_UTILS)
148 if (fContext) {
149 fContext->priv().deregisterRecorder(this);
150 }
151#endif
152
153 // TODO: needed?
154 fStrikeCache->freeAll();
155}
#define ASSERT_SINGLE_OWNER
Definition: Recorder.cpp:57
const Context & fContext
VkDevice device
Definition: main.cc:53

Member Function Documentation

◆ addFinishInfo()

void skgpu::graphite::Recorder::addFinishInfo ( const InsertFinishInfo info)

Definition at line 432 of file Recorder.cpp.

432 {
433 if (info.fFinishedProc) {
435 RefCntedCallback::Make(info.fFinishedProc, info.fFinishedContext);
436 fFinishedProcs.push_back(std::move(callback));
437 }
438}
static void info(const char *fmt,...) SK_PRINTF_LIKE(1
Definition: DM.cpp:213
static sk_sp< RefCntedCallback > Make(Callback proc, Context ctx)
FlKeyEvent uint64_t FlKeyResponderAsyncCallback callback

◆ backend()

BackendApi skgpu::graphite::Recorder::backend ( ) const

Definition at line 157 of file Recorder.cpp.

157{ return fSharedContext->backend(); }

◆ clientImageProvider() [1/2]

ImageProvider * skgpu::graphite::Recorder::clientImageProvider ( )
inline

Definition at line 88 of file Recorder.h.

88{ return fClientImageProvider.get(); }

◆ clientImageProvider() [2/2]

const ImageProvider * skgpu::graphite::Recorder::clientImageProvider ( ) const
inline

Definition at line 89 of file Recorder.h.

89{ return fClientImageProvider.get(); }

◆ createBackendTexture()

BackendTexture skgpu::graphite::Recorder::createBackendTexture ( SkISize  dimensions,
const TextureInfo info 
)

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.

Definition at line 284 of file Recorder.cpp.

284 {
286
287 if (!info.isValid() || info.backend() != this->backend()) {
288 return {};
289 }
290 return fResourceProvider->createBackendTexture(dimensions, info);
291}
BackendTexture createBackendTexture(SkISize dimensions, const TextureInfo &)

◆ currentBudgetedBytes()

size_t skgpu::graphite::Recorder::currentBudgetedBytes ( ) const

Returns the number of bytes of the Recorder's gpu memory cache budget that are currently in use.

Definition at line 463 of file Recorder.cpp.

463 {
465 return fResourceProvider->getResourceCacheCurrentBudgetedBytes();
466}
size_t getResourceCacheCurrentBudgetedBytes() const

◆ deleteBackendTexture()

void skgpu::graphite::Recorder::deleteBackendTexture ( const BackendTexture texture)

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.

Definition at line 423 of file Recorder.cpp.

423 {
425
426 if (!texture.isValid() || texture.backend() != this->backend()) {
427 return;
428 }
429 fResourceProvider->deleteBackendTexture(texture);
430}
void deleteBackendTexture(const BackendTexture &)
FlTexture * texture

◆ dumpMemoryStatistics()

void skgpu::graphite::Recorder::dumpMemoryStatistics ( SkTraceMemoryDump traceMemoryDump) const

Enumerates all cached GPU resources owned by the Recorder and dumps their memory to traceMemoryDump.

Definition at line 473 of file Recorder.cpp.

473 {
475 fResourceProvider->dumpMemoryStatistics(traceMemoryDump);
476 // TODO: What is the graphite equivalent for the text blob cache and how do we print out its
477 // used bytes here (see Ganesh implementation).
478}
void dumpMemoryStatistics(SkTraceMemoryDump *traceMemoryDump) const

◆ freeGpuResources()

void skgpu::graphite::Recorder::freeGpuResources ( )

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.

Definition at line 440 of file Recorder.cpp.

440 {
442
443 // We don't want to free the Uniform/TextureDataCaches or the Draw/UploadBufferManagers since
444 // all their resources need to be held on to until a Recording is snapped. And once snapped, all
445 // their held resources are released. The StrikeCache and TextBlobCache don't hold onto any Gpu
446 // resources.
447
448 // The AtlasProvider gives out refs to TextureProxies so it should be safe to clear its pool
449 // in the middle of Recording since those using the previous TextureProxies will have refs on
450 // them.
451 fAtlasProvider->clearTexturePool();
452
453 fResourceProvider->freeGpuResources();
454}

◆ makeDeferredCanvas()

SkCanvas * skgpu::graphite::Recorder::makeDeferredCanvas ( const SkImageInfo imageInfo,
const TextureInfo textureInfo 
)

Definition at line 235 of file Recorder.cpp.

236 {
237 // Mipmaps can't reasonably be kept valid on a deferred surface with no actual texture.
238 if (textureInfo.mipmapped() == Mipmapped::kYes) {
239 SKGPU_LOG_W("Requested a deferred canvas with mipmapping; this is not supported");
240 return nullptr;
241 }
242
243 if (fTargetProxyCanvas) {
244 // Require snapping before requesting another canvas.
245 SKGPU_LOG_W("Requested a new deferred canvas before snapping the previous one");
246 return nullptr;
247 }
248
249 fTargetProxyData = std::make_unique<Recording::LazyProxyData>(textureInfo);
250 // Use kLoad for the initial load op since the purpose of a deferred canvas is to draw on top
251 // of an existing, late-bound texture.
252 fTargetProxyDevice = Device::Make(this,
253 fTargetProxyData->refLazyProxy(),
254 imageInfo.dimensions(),
255 imageInfo.colorInfo(),
256 {},
258 fTargetProxyCanvas = std::make_unique<SkCanvas>(fTargetProxyDevice);
259 return fTargetProxyCanvas.get();
260}
#define SKGPU_LOG_W(fmt,...)
Definition: Log.h:40
static sk_sp< Device > Make(Recorder *recorder, sk_sp< TextureProxy >, SkISize deviceSize, const SkColorInfo &, const SkSurfaceProps &, LoadOp initialLoadOp, bool registerWithRecorder=true)
Definition: Device.cpp:276
const SkColorInfo & colorInfo() const
Definition: SkImageInfo.h:404
SkISize dimensions() const
Definition: SkImageInfo.h:421

◆ maxBudgetedBytes()

size_t skgpu::graphite::Recorder::maxBudgetedBytes ( ) const

Returns the size of Recorder's gpu memory cache budget in bytes.

Definition at line 468 of file Recorder.cpp.

468 {
470 return fResourceProvider->getResourceCacheLimit();
471}

◆ operator=() [1/2]

Recorder & skgpu::graphite::Recorder::operator= ( const Recorder )
delete

◆ operator=() [2/2]

Recorder & skgpu::graphite::Recorder::operator= ( Recorder &&  )
delete

◆ performDeferredCleanup()

void skgpu::graphite::Recorder::performDeferredCleanup ( std::chrono::milliseconds  msNotUsed)

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.

Definition at line 456 of file Recorder.cpp.

456 {
458
459 auto purgeTime = skgpu::StdSteadyClock::now() - msNotUsed;
460 fResourceProvider->purgeResourcesNotUsedSince(purgeTime);
461}
void purgeResourcesNotUsedSince(StdSteadyClock::time_point purgeTime)

◆ priv() [1/2]

RecorderPriv skgpu::graphite::Recorder::priv ( )
inline

Definition at line 106 of file RecorderPriv.h.

106 {
107 return RecorderPriv(this);
108}
friend class RecorderPriv
Definition: Recorder.h:208

◆ priv() [2/2]

const RecorderPriv skgpu::graphite::Recorder::priv ( ) const
inline

Definition at line 110 of file RecorderPriv.h.

110 { // NOLINT(readability-const-return-type)
111 return RecorderPriv(const_cast<Recorder*>(this));
112}

◆ snap()

std::unique_ptr< Recording > skgpu::graphite::Recorder::snap ( )

Definition at line 159 of file Recorder.cpp.

159 {
160 TRACE_EVENT0("skia.gpu", TRACE_FUNC);
162 this->priv().flushTrackedDevices();
163
164 std::unordered_set<sk_sp<TextureProxy>, Recording::ProxyHash> nonVolatileLazyProxies;
165 std::unordered_set<sk_sp<TextureProxy>, Recording::ProxyHash> volatileLazyProxies;
166 fTextureDataCache->foreach([&](const TextureDataBlock* block) {
167 for (int j = 0; j < block->numTextures(); ++j) {
168 const TextureDataBlock::SampledTexture& tex = block->texture(j);
169
170 if (tex.first->isLazy()) {
171 if (tex.first->isVolatile()) {
172 volatileLazyProxies.insert(tex.first);
173 } else {
174 nonVolatileLazyProxies.insert(tex.first);
175 }
176 }
177 }
178 });
179
180 std::unique_ptr<Recording::LazyProxyData> targetProxyData;
181 if (fTargetProxyData) {
182 targetProxyData = std::move(fTargetProxyData);
183 fTargetProxyDevice.reset();
184 fTargetProxyCanvas.reset();
185 }
186
187 // The scratch resources only need to be tracked until prepareResources() is finished, so
188 // Recorder doesn't hold a persistent manager and it can be deleted when snap() returns.
189 ScratchResourceManager scratchManager{fResourceProvider, std::move(fProxyReadCounts)};
190 fProxyReadCounts = std::make_unique<ProxyReadCountMap>();
191
192 // In both the "task failed" case and the "everything is discarded" case, there's no work that
193 // needs to be done in insertRecording(). However, we use nullptr as a failure signal, so
194 // kDiscard will return a non-null Recording that has no tasks in it.
195 if (fDrawBufferManager->hasMappingFailed() ||
196 fRootTaskList->prepareResources(fResourceProvider,
197 &scratchManager,
198 fRuntimeEffectDict.get()) == Task::Status::kFail) {
199 // Leaving 'fTrackedDevices' alone since they were flushed earlier and could still be
200 // attached to extant SkSurfaces.
201 fDrawBufferManager = std::make_unique<DrawBufferManager>(fResourceProvider,
202 fSharedContext->caps(),
203 fUploadBufferManager.get());
204 fTextureDataCache = std::make_unique<TextureDataCache>();
205 fUniformDataCache = std::make_unique<UniformDataCache>();
206 fRootTaskList->reset();
207 fRuntimeEffectDict->reset();
208 return nullptr;
209 }
210
211 std::unique_ptr<Recording> recording(new Recording(fNextRecordingID++,
212 fUniqueID,
213 std::move(nonVolatileLazyProxies),
214 std::move(volatileLazyProxies),
215 std::move(targetProxyData),
216 std::move(fFinishedProcs)));
217
218 // Allow the buffer managers to add any collected tasks for data transfer or initialization
219 // before moving the root task list to the Recording.
220 fDrawBufferManager->transferToRecording(recording.get());
221 fUploadBufferManager->transferToRecording(recording.get());
222 recording->priv().addTasks(std::move(*fRootTaskList));
223
224 SkASSERT(!fRootTaskList->hasTasks());
225 fRuntimeEffectDict->reset();
226 fTextureDataCache = std::make_unique<TextureDataCache>();
227 fUniformDataCache = std::make_unique<UniformDataCache>();
228 if (!this->priv().caps()->requireOrderedRecordings()) {
229 fAtlasProvider->textAtlasManager()->evictAtlases();
230 }
231
232 return recording;
233}
#define SkASSERT(cond)
Definition: SkAssert.h:116
#define TRACE_FUNC
Definition: SkTraceEvent.h:30
std::pair< sk_sp< TextureProxy >, SamplerDesc > SampledTexture
Definition: PipelineData.h:57
#define TRACE_EVENT0(category_group, name)
Definition: trace_event.h:131

◆ updateBackendTexture()

bool skgpu::graphite::Recorder::updateBackendTexture ( const BackendTexture backendTex,
const SkPixmap  srcData[],
int  numLevels 
)

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. 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

Definition at line 314 of file Recorder.cpp.

316 {
318
319 if (!backendTex.isValid() || backendTex.backend() != this->backend()) {
320 return false;
321 }
322
323 if (!srcData || numLevels <= 0) {
324 return false;
325 }
326
327 // If the texture has MIP levels then we require that the full set is overwritten.
328 int numExpectedLevels = 1;
329 if (backendTex.info().mipmapped() == Mipmapped::kYes) {
330 numExpectedLevels = SkMipmap::ComputeLevelCount(backendTex.dimensions().width(),
331 backendTex.dimensions().height()) + 1;
332 }
333 if (numLevels != numExpectedLevels) {
334 return false;
335 }
336
337 SkColorType ct = srcData[0].colorType();
338
339 if (!this->priv().caps()->areColorTypeAndTextureInfoCompatible(ct, backendTex.info())) {
340 return false;
341 }
342
344 if (!texture) {
345 return false;
346 }
347
349
350 std::vector<MipLevel> mipLevels;
351 mipLevels.resize(numLevels);
352
353 for (int i = 0; i < numLevels; ++i) {
354 SkASSERT(srcData[i].addr());
355 SkASSERT(srcData[i].info().colorInfo() == srcData[0].info().colorInfo());
356
357 mipLevels[i].fPixels = srcData[i].addr();
358 mipLevels[i].fRowBytes = srcData[i].rowBytes();
359 }
360
361 // Src and dst colorInfo are the same
362 const SkColorInfo& colorInfo = srcData[0].info().colorInfo();
363 // Add UploadTask to Recorder
364 UploadInstance upload = UploadInstance::Make(this,
365 std::move(proxy),
366 colorInfo, colorInfo,
367 mipLevels,
368 SkIRect::MakeSize(backendTex.dimensions()),
369 std::make_unique<ImageUploadContext>());
370 if (!upload.isValid()) {
371 SKGPU_LOG_E("Recorder::updateBackendTexture: Could not create UploadInstance");
372 return false;
373 }
374 sk_sp<Task> uploadTask = UploadTask::Make(std::move(upload));
375
376 // Need to flush any pending work in case it depends on this texture
377 this->priv().flushTrackedDevices();
378
379 this->priv().add(std::move(uploadTask));
380
381 return true;
382}
#define SKGPU_LOG_E(fmt,...)
Definition: Log.h:38
SkColorType
Definition: SkColorType.h:19
static int ComputeLevelCount(int baseWidth, int baseHeight)
Definition: SkMipmap.cpp:134
size_t rowBytes() const
Definition: SkPixmap.h:145
SkColorType colorType() const
Definition: SkPixmap.h:173
const SkImageInfo & info() const
Definition: SkPixmap.h:135
const void * addr() const
Definition: SkPixmap.h:153
ResourceProvider * resourceProvider()
Definition: RecorderPriv.h:33
void add(sk_sp< Task >)
Definition: Recorder.cpp:485
sk_sp< Texture > createWrappedTexture(const BackendTexture &, std::string_view label)
static sk_sp< TextureProxy > Wrap(sk_sp< Texture >)
static UploadInstance Make(Recorder *, sk_sp< TextureProxy > targetProxy, const SkColorInfo &srcColorInfo, const SkColorInfo &dstColorInfo, SkSpan< const MipLevel > levels, const SkIRect &dstRect, std::unique_ptr< ConditionalUploadContext >)
Definition: UploadTask.cpp:91
static sk_sp< UploadTask > Make(UploadList *)
Definition: UploadTask.cpp:425
Definition: upload.py:1
static constexpr SkIRect MakeSize(const SkISize &size)
Definition: SkRect.h:66

◆ updateCompressedBackendTexture()

bool skgpu::graphite::Recorder::updateCompressedBackendTexture ( const BackendTexture backendTex,
const void *  data,
size_t  dataSize 
)

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. 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

Definition at line 384 of file Recorder.cpp.

386 {
388
389 if (!backendTex.isValid() || backendTex.backend() != this->backend()) {
390 return false;
391 }
392
393 if (!data) {
394 return false;
395 }
396
398 if (!texture) {
399 return false;
400 }
401
403
404 // Add UploadTask to Recorder
405 UploadInstance upload = UploadInstance::MakeCompressed(this,
406 std::move(proxy),
407 data,
408 dataSize);
409 if (!upload.isValid()) {
410 SKGPU_LOG_E("Recorder::updateBackendTexture: Could not create UploadInstance");
411 return false;
412 }
413 sk_sp<Task> uploadTask = UploadTask::Make(std::move(upload));
414
415 // Need to flush any pending work in case it depends on this texture
416 this->priv().flushTrackedDevices();
417
418 this->priv().add(std::move(uploadTask));
419
420 return true;
421}
static UploadInstance MakeCompressed(Recorder *, sk_sp< TextureProxy > targetProxy, const void *data, size_t dataSize)
Definition: UploadTask.cpp:235
std::shared_ptr< const fml::Mapping > data
Definition: texture_gles.cc:63

Friends And Related Function Documentation

◆ Context

friend class Context
friend

Definition at line 206 of file Recorder.h.

◆ Device

friend class Device
friend

Definition at line 207 of file Recorder.h.

◆ RecorderPriv

friend class RecorderPriv
friend

Definition at line 208 of file Recorder.h.


The documentation for this class was generated from the following files: