Out of Process Rasterization
enne@
What is OOP-R?
Previous GPU raster pipeline:
paint (SkPicture) → raster task → raster (Skia) → gles2 command buffer → gl
Current OOP raster pipeline:
paint (paint ops) → raster task → raster command buffer → raster (Skia) → gl
Why OOP-R?
Top Level Goal: use Vulkan instead of OpenGL (for performance / stability)
Problem: command buffer has OpenGL baked in
Solution: create a new command buffer interface and serialization format, run raster (Skia) in the gpu process
Bonus goals: OpenGL is chatty; serializing paint data structures is faster
Data Structures
Why?
Mappings from analogous Skia classes:
PaintCanvas subclasses:
SkiaPaintCanvas is PaintCanvas -> SkCanvas
RecordPaintCanvas is PaintCanvas -> PaintRecord
PaintOpBuffer / PaintRecord dissection
class CC_PAINT_EXPORT PaintOp {
public:
uint32_t type : 8;
uint32_t skip : 24; // size of this serialized op
};
PaintOps = heterogenous types serialized in a flat buffer, e.g.:
enum class PaintOpType : uint8_t {
Annotate,
ClipPath,
ClipRect,
ClipRRect,
Concat,
CustomData,
DrawColor,
DrawDRRect,
DrawImage,
DrawImageRect,
DrawIRect,
DrawLine,
DrawOval,
DrawPath,
DrawRecord,
DrawRect,
DrawRRect,
DrawSkottie,
DrawTextBlob,
Noop,
Restore,
Rotate,
Save,
SaveLayer,
SaveLayerAlpha,
Scale,
SetMatrix,
Translate,
};
SaveOp
DrawRectOp
DrawColorOp
RestoreOp
&c &c &c
Serialization Overview
command buffer
transfer buffer
mapped memory
GPURasterBufferProvider
RI::BeginRasterCHROMIUM(mailbox, etc)
RI::RasterCHROMIUM(record, settings)
Grab all transfer buffer space
POBSerializer::Serialize(paint record)
SerializePreamble()
for each op in record:
serialize op into transfer buffer
if it doesn’t fit:
SendSerializedData()
Allocate/wait until tb space available
Shrink transfer buffer to space used
SendSerializedData()
RI::EndRasterCHROMIUM()
rough call stack / psuedocode
BeginRC
RC
RC
Create�TCEntry
RC
RC
EndRC
(serialized ops)
image
data
glyph
data
Command Buffer Changes
GL Command Buffer:
GLES2Interface + GLES2Implementation
GLES2Decoder(Impl)
Raster Command Buffer:
RasterInterface + RasterImplementation
RasterInterface + RasterImplementationGLES
RasterDecoder(Impl)
Transfer Cache Overview
Coordinates caching of data between the renderer and gpu.
Entries don’t depend on other entries.
Types: images, paint shaders, raw memory
Depends on discardable gpu memory system via gpu::(Client|Service)DiscardableManager. (Note: not the same as base::DiscardableMemoryAllocator!)
Create/Lock/Unlock commands in command buffer, issued by client but processed on service side.
Lock on client side and unlock on service side access shared memory, so no need for ipc to check availability.
GPU side can purge unlocked items freely so long as the client locks before using.
Image Serialization Details
Transfer cache used for all image types:�pre-decoded, at raster, lazy, non-lazy
ServiceImageTransferCacheEntry handles uploading, software vs hardware images, color space conversion
Serializing an image is just serializing its transfer cache id
(Client|Server)PaintCache
Questions:
Implementation Details:
Typeface and Glyph Serialization
Renderer Side
While serializing, draw all PaintOps into a SkTextBlobCacheDiffCanvas to find blobs.
SkStrikeServer + ClientFontManager find new typefaces and strikes, lock any strikes needed using discardable handles.
Prior to a RasterCHROMIUM command, serialize new typefaces and strikes into mapped memory.
GPU Side
When receiving a RasterCHROMIUM command, add all new typefaces and strikes to the SkStrikeClient + ServiceFontManager.
When rastering to a Ganesh-backed SkCanvas, look up any glyphs needed from the SkStrikeClient.
Unexpected
Hurdles
Follow-up Work