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

#include <VelloRenderer.h>

Classes

struct  RenderParams
 

Public Member Functions

 VelloRenderer (const Caps *)
 
 ~VelloRenderer ()
 
std::unique_ptr< DispatchGrouprenderScene (const RenderParams &, const VelloScene &, sk_sp< TextureProxy > target, Recorder *) const
 

Detailed Description

Definition at line 77 of file VelloRenderer.h.

Constructor & Destructor Documentation

◆ VelloRenderer()

skgpu::graphite::VelloRenderer::VelloRenderer ( const Caps caps)
explicit

Definition at line 248 of file VelloRenderer.cpp.

248 {
250 fFineArea = std::make_unique<VelloFineAreaAlpha8Step>();
251 fFineMsaa16 = std::make_unique<VelloFineMsaa16Alpha8Step>();
252 fFineMsaa8 = std::make_unique<VelloFineMsaa8Alpha8Step>();
253 } else {
254 fFineArea = std::make_unique<VelloFineAreaStep>();
255 fFineMsaa16 = std::make_unique<VelloFineMsaa16Step>();
256 fFineMsaa8 = std::make_unique<VelloFineMsaa8Step>();
257 }
258}
@ kAlpha_8_SkColorType
pixel with alpha in 8-bit byte
Definition: SkColorType.h:21
SkColorType ComputeShaderCoverageMaskTargetFormat(const Caps *caps)

◆ ~VelloRenderer()

skgpu::graphite::VelloRenderer::~VelloRenderer ( )
default

Member Function Documentation

◆ renderScene()

std::unique_ptr< DispatchGroup > skgpu::graphite::VelloRenderer::renderScene ( const RenderParams params,
const VelloScene scene,
sk_sp< TextureProxy target,
Recorder recorder 
) const

Definition at line 262 of file VelloRenderer.cpp.

265 {
266 TRACE_EVENT0("skia.gpu", TRACE_FUNC);
268
269 if (scene.fEncoding->is_empty()) {
270 return nullptr;
271 }
272
273 if (params.fWidth == 0 || params.fHeight == 0) {
274 return nullptr;
275 }
276
277 // TODO: validate that the pixel format matches the pipeline layout.
278 // Clamp the draw region to the target texture dimensions.
279 const SkISize dims = target->dimensions();
280 if (dims.isEmpty() || dims.fWidth < 0 || dims.fHeight < 0) {
281 SKGPU_LOG_W("VelloRenderer: cannot render to an empty target");
282 return nullptr;
283 }
284
285 SkASSERT(scene.fLayers == 0); // Begin/end clips must be matched.
286 auto config = scene.fEncoding->prepare_render(
287 std::min(params.fWidth, static_cast<uint32_t>(dims.fWidth)),
288 std::min(params.fHeight, static_cast<uint32_t>(dims.fHeight)),
289 to_vello_color(params.fBaseColor));
290 auto dispatchInfo = config->workgroup_counts();
291 auto bufferSizes = config->buffer_sizes();
292
294
295 // In total there are 25 resources that are used across the full pipeline stages. The sizes of
296 // these resources depend on the encoded scene. We allocate all of them and assign them
297 // directly to the builder here instead of delegating the logic to the ComputeSteps.
298 DrawBufferManager* bufMgr = recorder->priv().drawBufferManager();
299
300 size_t uboSize = config->config_uniform_buffer_size();
301 auto [uboPtr, configBuf] = bufMgr->getUniformPointer(uboSize);
302 if (!uboPtr || !config->write_config_uniform_buffer(to_slice(uboPtr, uboSize))) {
303 return nullptr;
304 }
305
306 size_t sceneSize = config->scene_buffer_size();
307 auto [scenePtr, sceneBuf] = bufMgr->getStoragePointer(sceneSize);
308 if (!scenePtr || !config->write_scene_buffer(to_slice(scenePtr, sceneSize))) {
309 return nullptr;
310 }
311
312 // TODO(b/285189802): The default sizes for the bump buffers (~97MB) exceed Graphite's resource
313 // budget if multiple passes are necessary per frame (250MB, see ResouceCache.h). We apply a
314 // crude size reduction here which seems to be enough for a 4k x 4k atlas render for the GMs
315 // that we have tested. The numbers below are able to render GM_longpathdash with CPU-side
316 // stroke expansion.
317 //
318 // We need to come up with a better approach to accurately predict the sizes for these buffers
319 // based on the scene encoding and our resource budget. It should be possible to build a
320 // conservative estimate using the total number of path verbs, some heuristic based on the verb
321 // and the path's transform, and the total number of tiles.
322 //
323 // The following numbers amount to ~48MB
324 const size_t lines_size = bufferSizes.lines;
325 const size_t bin_data_size = bufferSizes.bin_data;
326 const size_t tiles_size = bufferSizes.tiles;
327 const size_t segments_size = bufferSizes.segments;
328 const size_t seg_counts_size = bufferSizes.seg_counts;
329 const size_t ptcl_size = bufferSizes.ptcl;
330
331 // See the comments in VelloComputeSteps.h for an explanation of the logic here.
332
333 builder.assignSharedBuffer({configBuf, uboSize}, kVelloSlot_ConfigUniform);
334 builder.assignSharedBuffer({sceneBuf, sceneSize}, kVelloSlot_Scene);
335
336 // Buffers get cleared ahead of the entire DispatchGroup. Allocate the bump buffer early to
337 // avoid a potentially recycled (and prematurely cleared) scratch buffer.
338 ScratchBuffer bump = bufMgr->getScratchStorage(bufferSizes.bump_alloc);
339 builder.assignSharedBuffer(new_scratch_slice(bump), kVelloSlot_BumpAlloc, ClearBuffer::kYes);
340
341 // path_reduce
342 ScratchBuffer tagmonoids = bufMgr->getScratchStorage(bufferSizes.path_monoids);
343 {
344 // This can be immediately returned after input processing.
345 ScratchBuffer pathtagReduceOutput = bufMgr->getScratchStorage(bufferSizes.path_reduced);
346 builder.assignSharedBuffer(new_scratch_slice(pathtagReduceOutput),
348 builder.assignSharedBuffer(new_scratch_slice(tagmonoids), kVelloSlot_TagMonoid);
349 builder.appendStep(&fPathtagReduce, to_wg_size(dispatchInfo.path_reduce));
350
351 // If the input is too large to be fully processed by a single workgroup then a second
352 // reduce step and two scan steps are necessary. Otherwise one reduce+scan pair is
353 // sufficient.
354 //
355 // In either case, the result is `tagmonoids`.
356 if (dispatchInfo.use_large_path_scan) {
357 ScratchBuffer reduced2 = bufMgr->getScratchStorage(bufferSizes.path_reduced2);
358 ScratchBuffer reducedScan = bufMgr->getScratchStorage(bufferSizes.path_reduced_scan);
359
360 builder.assignSharedBuffer(new_scratch_slice(reduced2),
362 builder.assignSharedBuffer(new_scratch_slice(reducedScan),
364
365 builder.appendStep(&fPathtagReduce2, to_wg_size(dispatchInfo.path_reduce2));
366 builder.appendStep(&fPathtagScan1, to_wg_size(dispatchInfo.path_scan1));
367 builder.appendStep(&fPathtagScanLarge, to_wg_size(dispatchInfo.path_scan));
368 } else {
369 builder.appendStep(&fPathtagScanSmall, to_wg_size(dispatchInfo.path_scan));
370 }
371 }
372
373 // bbox_clear
374 ScratchBuffer pathBboxes = bufMgr->getScratchStorage(bufferSizes.path_bboxes);
375 builder.assignSharedBuffer(new_scratch_slice(pathBboxes), kVelloSlot_PathBBoxes);
376 builder.appendStep(&fBboxClear, to_wg_size(dispatchInfo.bbox_clear));
377
378 // flatten
379 ScratchBuffer lines = bufMgr->getScratchStorage(lines_size);
380 builder.assignSharedBuffer(new_scratch_slice(lines), kVelloSlot_Lines);
381 builder.appendStep(&fFlatten, to_wg_size(dispatchInfo.flatten));
382
383 tagmonoids.returnToPool();
384
385 // draw_reduce
386 ScratchBuffer drawReduced = bufMgr->getScratchStorage(bufferSizes.draw_reduced);
387 builder.assignSharedBuffer(new_scratch_slice(drawReduced), kVelloSlot_DrawReduceOutput);
388 builder.appendStep(&fDrawReduce, to_wg_size(dispatchInfo.draw_reduce));
389
390 // draw_leaf
391 ScratchBuffer drawMonoids = bufMgr->getScratchStorage(bufferSizes.draw_monoids);
392 ScratchBuffer binData = bufMgr->getScratchStorage(bin_data_size);
393 // A clip input buffer must still get bound even if the encoding doesn't contain any clips
394 ScratchBuffer clipInput = bufMgr->getScratchStorage(bufferSizes.clip_inps);
395 builder.assignSharedBuffer(new_scratch_slice(drawMonoids), kVelloSlot_DrawMonoid);
396 builder.assignSharedBuffer(new_scratch_slice(binData), kVelloSlot_InfoBinData);
397 builder.assignSharedBuffer(new_scratch_slice(clipInput), kVelloSlot_ClipInput);
398 builder.appendStep(&fDrawLeaf, to_wg_size(dispatchInfo.draw_leaf));
399
400 drawReduced.returnToPool();
401
402 // clip_reduce, clip_leaf
403 // The clip bbox buffer is always an input to the binning stage, even when the encoding doesn't
404 // contain any clips
405 ScratchBuffer clipBboxes = bufMgr->getScratchStorage(bufferSizes.clip_bboxes);
406 builder.assignSharedBuffer(new_scratch_slice(clipBboxes), kVelloSlot_ClipBBoxes);
407 WorkgroupSize clipReduceWgCount = to_wg_size(dispatchInfo.clip_reduce);
408 WorkgroupSize clipLeafWgCount = to_wg_size(dispatchInfo.clip_leaf);
409 bool doClipReduce = clipReduceWgCount.scalarSize() > 0u;
410 bool doClipLeaf = clipLeafWgCount.scalarSize() > 0u;
411 if (doClipReduce || doClipLeaf) {
412 ScratchBuffer clipBic = bufMgr->getScratchStorage(bufferSizes.clip_bics);
413 ScratchBuffer clipEls = bufMgr->getScratchStorage(bufferSizes.clip_els);
414 builder.assignSharedBuffer(new_scratch_slice(clipBic), kVelloSlot_ClipBicyclic);
415 builder.assignSharedBuffer(new_scratch_slice(clipEls), kVelloSlot_ClipElement);
416 if (doClipReduce) {
417 builder.appendStep(&fClipReduce, clipReduceWgCount);
418 }
419 if (doClipLeaf) {
420 builder.appendStep(&fClipLeaf, clipLeafWgCount);
421 }
422 }
423
424 clipInput.returnToPool();
425
426 // binning
427 ScratchBuffer drawBboxes = bufMgr->getScratchStorage(bufferSizes.draw_bboxes);
428 ScratchBuffer binHeaders = bufMgr->getScratchStorage(bufferSizes.bin_headers);
429 builder.assignSharedBuffer(new_scratch_slice(drawBboxes), kVelloSlot_DrawBBoxes);
430 builder.assignSharedBuffer(new_scratch_slice(binHeaders), kVelloSlot_BinHeader);
431 builder.appendStep(&fBinning, to_wg_size(dispatchInfo.binning));
432
433 pathBboxes.returnToPool();
434 clipBboxes.returnToPool();
435
436 // tile_alloc
437 ScratchBuffer paths = bufMgr->getScratchStorage(bufferSizes.paths);
438 ScratchBuffer tiles = bufMgr->getScratchStorage(tiles_size);
439 builder.assignSharedBuffer(new_scratch_slice(paths), kVelloSlot_Path);
440 builder.assignSharedBuffer(new_scratch_slice(tiles), kVelloSlot_Tile);
441 builder.appendStep(&fTileAlloc, to_wg_size(dispatchInfo.tile_alloc));
442
443 drawBboxes.returnToPool();
444
445 // path_count_setup
446 auto indirectCountBuffer = new_indirect_slice(bufMgr, bufferSizes.indirect_count);
447 builder.assignSharedBuffer(indirectCountBuffer, kVelloSlot_IndirectCount);
448 builder.appendStep(&fPathCountSetup, to_wg_size(dispatchInfo.path_count_setup));
449
450 // Rasterization stage scratch buffers.
451 ScratchBuffer seg_counts = bufMgr->getScratchStorage(seg_counts_size);
452 ScratchBuffer segments = bufMgr->getScratchStorage(segments_size);
453 ScratchBuffer ptcl = bufMgr->getScratchStorage(ptcl_size);
454
455 // path_count
456 builder.assignSharedBuffer(new_scratch_slice(seg_counts), kVelloSlot_SegmentCounts);
457 builder.appendStepIndirect(&fPathCount, indirectCountBuffer);
458
459 // backdrop
460 builder.appendStep(&fBackdrop, to_wg_size(dispatchInfo.backdrop));
461
462 // coarse
463 builder.assignSharedBuffer(new_scratch_slice(ptcl), kVelloSlot_PTCL);
464 builder.appendStep(&fCoarse, to_wg_size(dispatchInfo.coarse));
465
466 // path_tiling_setup
467 builder.appendStep(&fPathTilingSetup, to_wg_size(dispatchInfo.path_tiling_setup));
468
469 // path_tiling
470 builder.assignSharedBuffer(new_scratch_slice(segments), kVelloSlot_Segments);
471 builder.appendStepIndirect(&fPathTiling, indirectCountBuffer);
472
473 // fine
474 builder.assignSharedTexture(std::move(target), kVelloSlot_OutputImage);
475 const ComputeStep* fineVariant = nullptr;
476 switch (params.fAaConfig) {
478 fineVariant = fFineArea.get();
479 break;
481 fineVariant = fFineMsaa16.get();
482 break;
484 fineVariant = fFineMsaa8.get();
485 break;
486 }
487 SkASSERT(fineVariant != nullptr);
488 builder.appendStep(fineVariant, to_wg_size(dispatchInfo.fine));
489
490 return builder.finalize();
491}
#define SKGPU_LOG_W(fmt,...)
Definition: Log.h:40
#define SkASSERT(cond)
Definition: SkAssert.h:116
static bool ComputeStep(const SkPoint &a, const SkPoint &b, SkScalar radius, SkPoint *step)
#define TRACE_FUNC
Definition: SkTraceEvent.h:30
std::pair< void *, BindBufferInfo > getUniformPointer(size_t requiredBytes)
DrawBufferManager * drawBufferManager()
Definition: RecorderPriv.h:58
const EmbeddedViewParams * params
uint32_t * target
static float min(float r, float g, float b)
Definition: hsl.cpp:48
DlVertices::Builder Builder
constexpr int kVelloSlot_DrawBBoxes
constexpr int kVelloSlot_Lines
constexpr int kVelloSlot_LargePathtagScanFirstPassOutput
constexpr int kVelloSlot_BinHeader
constexpr int kVelloSlot_SegmentCounts
constexpr int kVelloSlot_ClipBicyclic
constexpr int kVelloSlot_Scene
constexpr int kVelloSlot_ConfigUniform
constexpr int kVelloSlot_ClipInput
constexpr int kVelloSlot_IndirectCount
constexpr int kVelloSlot_DrawReduceOutput
constexpr int kVelloSlot_LargePathtagReduceSecondPassOutput
constexpr int kVelloSlot_TagMonoid
constexpr int kVelloSlot_Segments
constexpr int kVelloSlot_InfoBinData
constexpr int kVelloSlot_ClipElement
constexpr int kVelloSlot_PathBBoxes
constexpr int kVelloSlot_Path
constexpr int kVelloSlot_OutputImage
constexpr int kVelloSlot_Tile
constexpr int kVelloSlot_PathtagReduceOutput
constexpr int kVelloSlot_PTCL
constexpr int kVelloSlot_ClipBBoxes
constexpr int kVelloSlot_DrawMonoid
constexpr int kVelloSlot_BumpAlloc
constexpr struct @263 tiles[]
Definition: SkSize.h:16
bool isEmpty() const
Definition: SkSize.h:31
int32_t fHeight
Definition: SkSize.h:18
int32_t fWidth
Definition: SkSize.h:17
#define TRACE_EVENT0(category_group, name)
Definition: trace_event.h:131

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