Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
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 75 of file VelloRenderer.h.

Constructor & Destructor Documentation

◆ VelloRenderer()

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

Definition at line 244 of file VelloRenderer.cpp.

244 {
246 fFineArea = std::make_unique<VelloFineAreaAlpha8Step>();
247 fFineMsaa16 = std::make_unique<VelloFineMsaa16Alpha8Step>();
248 fFineMsaa8 = std::make_unique<VelloFineMsaa8Alpha8Step>();
249 } else {
250 fFineArea = std::make_unique<VelloFineAreaStep>();
251 fFineMsaa16 = std::make_unique<VelloFineMsaa16Step>();
252 fFineMsaa8 = std::make_unique<VelloFineMsaa8Step>();
253 }
254}
@ 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 258 of file VelloRenderer.cpp.

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

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