Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
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 74 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 124 of file Recorder.cpp.

124 {
126 // Any finished procs that haven't been passed to a Recording fail
127 for (int i = 0; i < fFinishedProcs.size(); ++i) {
128 fFinishedProcs[i]->setFailureResult();
129 }
130
131 for (auto& device : fTrackedDevices) {
132 // deregisterDevice() may have left an entry as null previously.
133 if (device) {
134 device->abandonRecorder();
135 }
136 }
137#if defined(GRAPHITE_TEST_UTILS)
138 if (fContext) {
139 fContext->priv().deregisterRecorder(this);
140 }
141#endif
142
143 // TODO: needed?
144 fStrikeCache->freeAll();
145}
const Context & fContext
VkDevice device
Definition main.cc:53
#define ASSERT_SINGLE_OWNER
Definition Device.cpp:120

Member Function Documentation

◆ addFinishInfo()

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

Definition at line 429 of file Recorder.cpp.

429 {
430 if (info.fFinishedProc) {
432 RefCntedCallback::Make(info.fFinishedProc, info.fFinishedContext);
433 fFinishedProcs.push_back(std::move(callback));
434 }
435}
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 147 of file Recorder.cpp.

147{ return fSharedContext->backend(); }

◆ clientImageProvider() [1/2]

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

Definition at line 87 of file Recorder.h.

87{ return fClientImageProvider.get(); }

◆ clientImageProvider() [2/2]

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

Definition at line 88 of file Recorder.h.

88{ 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 281 of file Recorder.cpp.

281 {
283
284 if (!info.isValid() || info.backend() != this->backend()) {
285 return {};
286 }
287 return fResourceProvider->createBackendTexture(dimensions, info);
288}

◆ 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 460 of file Recorder.cpp.

460 {
462 return fResourceProvider->getResourceCacheCurrentBudgetedBytes();
463}

◆ 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 420 of file Recorder.cpp.

420 {
422
423 if (!texture.isValid() || texture.backend() != this->backend()) {
424 return;
425 }
426 fResourceProvider->deleteBackendTexture(texture);
427}
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 470 of file Recorder.cpp.

470 {
472 fResourceProvider->dumpMemoryStatistics(traceMemoryDump);
473 // TODO: What is the graphite equivalent for the text blob cache and how do we print out its
474 // used bytes here (see Ganesh implementation).
475}

◆ 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 437 of file Recorder.cpp.

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

◆ makeDeferredCanvas()

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

Definition at line 219 of file Recorder.cpp.

220 {
221 // Mipmaps can't reasonably be kept valid on a deferred surface with no actual texture.
222 if (textureInfo.mipmapped() == Mipmapped::kYes) {
223 SKGPU_LOG_W("Requested a deferred canvas with mipmapping; this is not supported");
224 return nullptr;
225 }
226
227 if (fTargetProxyCanvas) {
228 // Require snapping before requesting another canvas.
229 SKGPU_LOG_W("Requested a new deferred canvas before snapping the previous one");
230 return nullptr;
231 }
232
233 fTargetProxyData = std::make_unique<Recording::LazyProxyData>(textureInfo);
234 // Use kLoad for the initial load op since the purpose of a deferred canvas is to draw on top
235 // of an existing, late-bound texture.
236 fTargetProxyDevice = Device::Make(this,
237 fTargetProxyData->refLazyProxy(),
238 imageInfo.dimensions(),
239 imageInfo.colorInfo(),
240 {},
242 fTargetProxyCanvas = std::make_unique<SkCanvas>(fTargetProxyDevice);
243 return fTargetProxyCanvas.get();
244}
#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:268
const SkColorInfo & colorInfo() const
SkISize dimensions() const

◆ maxBudgetedBytes()

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

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

Definition at line 465 of file Recorder.cpp.

465 {
467 return fResourceProvider->getResourceCacheLimit();
468}

◆ 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 453 of file Recorder.cpp.

453 {
455
456 auto purgeTime = skgpu::StdSteadyClock::now() - msNotUsed;
457 fResourceProvider->purgeResourcesNotUsedSince(purgeTime);
458}

◆ priv() [1/2]

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

Definition at line 102 of file RecorderPriv.h.

102 {
103 return RecorderPriv(this);
104}
friend class RecorderPriv
Definition Recorder.h:207

◆ priv() [2/2]

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

Definition at line 106 of file RecorderPriv.h.

106 { // NOLINT(readability-const-return-type)
107 return RecorderPriv(const_cast<Recorder*>(this));
108}

◆ snap()

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

Definition at line 149 of file Recorder.cpp.

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

◆ 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 311 of file Recorder.cpp.

313 {
315
316 if (!backendTex.isValid() || backendTex.backend() != this->backend()) {
317 return false;
318 }
319
320 if (!srcData || numLevels <= 0) {
321 return false;
322 }
323
324 // If the texture has MIP levels then we require that the full set is overwritten.
325 int numExpectedLevels = 1;
326 if (backendTex.info().mipmapped() == Mipmapped::kYes) {
327 numExpectedLevels = SkMipmap::ComputeLevelCount(backendTex.dimensions().width(),
328 backendTex.dimensions().height()) + 1;
329 }
330 if (numLevels != numExpectedLevels) {
331 return false;
332 }
333
334 SkColorType ct = srcData[0].colorType();
335
336 if (!this->priv().caps()->areColorTypeAndTextureInfoCompatible(ct, backendTex.info())) {
337 return false;
338 }
339
341 if (!texture) {
342 return false;
343 }
344
346
347 std::vector<MipLevel> mipLevels;
348 mipLevels.resize(numLevels);
349
350 for (int i = 0; i < numLevels; ++i) {
351 SkASSERT(srcData[i].addr());
352 SkASSERT(srcData[i].info().colorInfo() == srcData[0].info().colorInfo());
353
354 mipLevels[i].fPixels = srcData[i].addr();
355 mipLevels[i].fRowBytes = srcData[i].rowBytes();
356 }
357
358 // Src and dst colorInfo are the same
359 const SkColorInfo& colorInfo = srcData[0].info().colorInfo();
360 // Add UploadTask to Recorder
361 UploadInstance upload = UploadInstance::Make(this,
362 std::move(proxy),
363 colorInfo, colorInfo,
364 mipLevels,
365 SkIRect::MakeSize(backendTex.dimensions()),
366 std::make_unique<ImageUploadContext>());
367 if (!upload.isValid()) {
368 SKGPU_LOG_E("Recorder::updateBackendTexture: Could not create UploadInstance");
369 return false;
370 }
371 sk_sp<Task> uploadTask = UploadTask::Make(std::move(upload));
372
373 // Need to flush any pending work in case it depends on this texture
374 this->priv().flushTrackedDevices();
375
376 this->priv().add(std::move(uploadTask));
377
378 return true;
379}
#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()
void add(sk_sp< Task >)
Definition Recorder.cpp:477
virtual sk_sp< Texture > createWrappedTexture(const BackendTexture &)=0
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 >)
static sk_sp< UploadTask > Make(UploadList *)
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 381 of file Recorder.cpp.

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

Friends And Related Symbol Documentation

◆ Context

friend class Context
friend

Definition at line 205 of file Recorder.h.

◆ Device

friend class Device
friend

Definition at line 206 of file Recorder.h.

◆ RecorderPriv

friend class RecorderPriv
friend

Definition at line 207 of file Recorder.h.


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