how to draw many rects fast?

245 views
Skip to first unread message

Ruan Beihong

unread,
May 18, 2023, 10:34:43 AM5/18/23
to skia-discuss
We are using skia built into WASM for 2D rendering.
Currently we need skia to draw many rects (say 1000 per SkSurface) each with a different transforming matrix and a little argument variation with a same SkRuntimeEffect. We find skia calls a lot of glUniformMatrix3fv. Is it normal? Why can't we batch that transform matrix?

code is something like:
auto surface = SkSurface::makeRenderTarget(...);
auto canvas = surface.getCanavas();
auto rect = SkRect::MakeXY(256, 256);
for (auto i = 0; i < 1000; i++) {
   SkPaint p;
   auto shader = runtime_effect.makeShader();
   p.setShader(shader);
   SkAutoCanvasRestore restore(canvas, true);
   canvas->concat(some_unique_transform);
   canvas->drawRect(rect, p);
}
//run other shader that samples the surface...

Ruan Beihong

unread,
May 18, 2023, 10:45:13 AM5/18/23
to skia-discuss
Screenshot 2023-05-18 at 22.41.31.png

K. Moon

unread,
May 18, 2023, 1:29:56 PM5/18/23
to skia-d...@googlegroups.com
I don't know if this would make any difference, but is there a reason to have the SkPaint configuration inside of the loop, rather than outside of it?

--
You received this message because you are subscribed to the Google Groups "skia-discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email to skia-discuss...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/skia-discuss/6b228911-d1aa-44e8-9e10-c71c3b3b3d1fn%40googlegroups.com.

Jim Van Verth

unread,
May 18, 2023, 1:56:10 PM5/18/23
to skia-d...@googlegroups.com
I don't think moving the SkPaint out of the loop would have much of an effect on this, though it's more efficient to create that shader once.

What happens if you concat the matrix once, outside the loop? I believe it's seeing that the matrix stack has changed so it invalidates the uniform.



--

Jim Van Verth |
 Software Engineer | Google.com

Jim Van Verth

unread,
May 18, 2023, 2:22:34 PM5/18/23
to skia-d...@googlegroups.com
My colleague has pointed out that you said that each rect has a different transform. Is that correct?

Ruan Beihong

unread,
May 18, 2023, 2:51:38 PM5/18/23
to skia-discuss
True. Each rect has a different transform. Each rect also drawn with a shader that share the same SKSL and has only one uniform modified.

Ruan Beihong

unread,
May 18, 2023, 3:06:58 PM5/18/23
to skia-discuss
Because we need to change a uniform value in shader parameter and build a SkShader for each rect.
We've try to remove the shader for each rect. There's still a lot of call (glUniform2fv). It seems batching it not working as I'd expected.

Ruan Beihong

unread,
May 18, 2023, 3:07:01 PM5/18/23
to skia-discuss
Thanks for your attention. We'd like to know:
- What prevent skia from batching all parameter for drawing.
- Any suggestions to provide a packed parameters to SKSL instead of passing them in uniform one by one?
- We've plan to try run the shader once to generate some temporary texture and then sample them using DrawAtlas. Should be faster since we pack the tranform in advance. Not very sure it will cover our use-case though.

craste...@gmail.com

unread,
May 18, 2023, 7:01:21 PM5/18/23
to skia-discuss
Out of curiousity,
What do the uniforms contain?  
Why is the shader different for each rect?
Are the rectangles filled with separate raster images?

Ruan Beihong

unread,
May 19, 2023, 4:52:22 AM5/19/23
to skia-discuss
 It's used to change the opacity of each rect. It seems that skia will not batching those call if SkPaint has different SkShader binded.

After some trial and error, we finally reach a very low CPU side overhead as we expected, by using DrawAtlas.

Brian Osman

unread,
May 19, 2023, 8:58:48 AM5/19/23
to skia-d...@googlegroups.com
Glad to know that (DrawAtlas is a pretty handy API for these kinds of operations). If the only shader difference is in alpha, you could also try setting the SkPaint's alpha. (If your SkPaint has a shader, the paint alpha is still used to modulate the final shader output, so that you can easily do these kinds of transparency/fade-out effects). Depending on various factors, Skia *might* batch rectangles if that's the only difference. (I don't remember exactly, though...)

Jim Van Verth

unread,
May 19, 2023, 11:13:27 AM5/19/23
to skia-d...@googlegroups.com
DrawAtlas does the batching (if I understand correctly) that you're thinking of, in that it stores the transforms as vertex attributes so it can use one draw to render all of them (but it's restricted to non-perspective transforms with uniform scale). DrawRect may or may not batch, as Brian described. In particular I don't recall if we pre-transform the rects to device space, which would allow them to batch with different transforms (assuming the same shader, filters, etc). In the new GPU renderer that we're in the process of creating, we store uniforms for multiple draws in one large storage buffer. So that kind of switching on uniform binding should be reduced considerably.

Reply all
Reply to author
Forward
0 new messages