From f350571c13c694ff7b43250dbe08296244ab7c9f Mon Sep 17 00:00:00 2001 From: Bingus Date: Wed, 3 May 2023 11:56:10 -0700 Subject: [PATCH 1/2] Custom WGPU Shaders & Pipelines RFC --- text/23-custom-pipelines.md | 373 ++++++++++++++++++++++++++++++++++++ text/diagram.png | Bin 0 -> 80929 bytes text/silvia.jpeg | Bin 0 -> 37835 bytes 3 files changed, 373 insertions(+) create mode 100644 text/23-custom-pipelines.md create mode 100644 text/diagram.png create mode 100644 text/silvia.jpeg diff --git a/text/23-custom-pipelines.md b/text/23-custom-pipelines.md new file mode 100644 index 0000000..bb7923f --- /dev/null +++ b/text/23-custom-pipelines.md @@ -0,0 +1,373 @@ +# 🌈 Custom WGPU Shaders & Pipelines + +## πŸ“œ Summary + +This RFC aims to reach a consensus on the following: +1) Should we integrate custom WGPU shader & pipeline support into Iced? +2) If so, to what extent? And how? + +This RFC is similar to [RFC #19](https://github.com/iced-rs/rfcs/pull/19), but with a broader scope (for example, the +custom shader proposed in #19 could be built on top of this framework!). The idea is to allow users to use their +own WGPU pipelines & custom primitives to render their own content seamlessly alongside Iced's existing supported primitives. + +**Please note that this RFC is working off of the changes already present in the `advanced-text` branch!** + +## 🦾 Motivation + +Currently, the only way to use a custom shader with Iced is to do something like the WGPU +`integration` example, where you can render your own scene using Iced *independently* of the existing widget tree, +or create a custom `Renderer` and do everything yourself. You must either render your content before or after Iced +renders its user interface. This works in niche situations, for example a custom 3D scene with a 2d Iced overlay +rendered on top, but if you wish to adjust the shader used to fill, for example, a container that exists deep +within a widget tree, this is currently impossible without a fork or recreating the effect with potentially +very expensive CPU calculations on a `Canvas`. + +Adding custom WGPU shader & pipeline support to Iced will add extensibility, customizability, and modularity to the +existing rendering pipeline. I imagine a near future where we have repositories similar to `iced_aw`, where library +authors can provide their own pipeline integrations into Iced for all kinds of shaders, primitives, and even +post-processing effects! 🀯 + +Most GUI libraries out there allow some way of embedding the underlying graphics API calls alongside existing +widgets for further customizability, an example being querying a raw `WebGL` context from a HTML5 canvas and +doing what you will with it. I believe Iced would benefit immensely from this added functionality. + +The result of this RFC should be that there is a clear path for allowing "embeddable" WGPU pipelines in some fashion +to Iced, where library authors can create their own primitives & rendering pipelines which integrate seamlessly into +Iced's existing renderer & backend. + +## 🀠 Guide-level explanation + +### πŸ“š Concepts + +*Foreword:* Coming up with a strategy for adding custom pipeline support to Iced is not really about what, nor how, but +*when*. +At what +point in the frame presentation does the custom primitive get inserted into the primitive queue? Does it even get +inserted into the primitive queue at all? If it's not inserted, how do we know when to render it? If it is inserted, +what does a custom primitive actually mean? What *is* it? How do we reference the correct pipeline from the custom +primitive? If the custom primitive has its own primitive type, do we use codegen/generics and just take the generic +propagation L? Do we use reflection? Do we use trait objects & dynamic dispatching? Do we completely restructure +Iced's rendering pipeline to allow for multiple backends of the same type? If so, how do we allow for any arbitrary +amount of additive backends? Do we start getting down & dirty with macros to shave off a few additional pointer +hops? Could we do this with a minimal unsafe abstraction layer? Should we even do this at all? Why am I doing this? +*Why do I even exist?* + +![](silvia.jpeg) + +As you can see, this is a somewhat complex topic with a lot of tradeoffs between implementation strategies. Of +course, I would love if there was a better idea floating around out there that I haven't thought of! That being +said, **here are some of the concepts that you will need to understand before you can understand what this +RFC aims to address.** + +πŸ–Ό **Custom Pipelines** + +This is essentially just a regular ol' wgpu pipeline implementation, except one that isn't already integrated into +Iced! This can be as simple or complex as you want it to be. For example, in a prototype that I made to render a +simple triangle, this was as simple as this struct: + +```rust +pub struct CustomPipeline { + pipeline: wgpu::RenderPipeline, + vertices: wgpu::Buffer, +} +``` + +In Iced, `Primitive`s are mapped internally to the appropriate pipeline, though have no direct relationship to each +other (for instance, a `Pipeline` doesn't have a primitive type `P`). Each is chosen manually for what is +appropriate. There is currently also no abstraction for what a `Pipeline` actually is; by their nature they are all +somewhat unique from each other, with minor underlying similarities (for example, every render pipeline must at some +point allocate some data to a `wgpu::Buffer` & submit a `draw` command). + + +πŸ’  **Custom Primitives** + +What, exactly, pray tell, are we rendering? Ultimately this is some chunk of data that gets used by a custom +pipeline. This could take the form of data that's passed directly to the existing `Primitive` enum (like +current `Primitive`s are), or something as simple as a single pointer. + +One implementation might mean that a custom primitive could be defined within the existing `Primitive` enum as just a +pointer to some pipeline state that implements certain methods required for rendering. + +```rust +pub enum Primitive { + //..., + Custom { + id: u64, // a pipeline reference ID + pipeline_init: fn(device: &wgpu::Device, format: wgpu::TextureFormat) -> Box, + // where "Renderable" defines a set of methods necessary for drawing + } +} +``` + +Another implementation might define a custom primitive as a generic type that is unique to a `Renderer` or `Backend`. + +```rust +pub trait Backend { + //... +} +``` + +πŸ§… **Layers** + +In Iced, layering currently happens at the presentation level. Primitives are submitted to the `Renderer` in a +queue-like fashion, and are then grouped before being drawn back to front. This allows primitives that are meant to be +rendered together to be transformed together, somewhat like a scene. For example, when clipping primitives let's +say in a `Canvas`, this will create a new layer. Note that every layer added to the layer stack will incur +additional performance costs with pipeline switching & extra draw commands submitted to the GPU! + +When considering a layering approach for custom primitives, we must think about how they are processed. Should a +custom primitive be included in the existing `iced_wgpu::Layer` with some sort of ID matching? + +```rust +pub struct Layer<'a> { + //... + // some kind of reference to what can be rendered in this layer that + // we can match to a pipeline + custom: Vec, +} +``` + +Or perhaps we should enforce that all custom pipelines must group its supported primitives within its own layer? +This needs some considering, but could be implemented further down the line as an optimization. + +## 🎯 Implementation strategy + +I've gone through a few ~~hundred~~ dozen implementation strategies. I'll share a few here: + +### 🀾 Just throw a pointer at the `Renderer` + +You can view a small, very, *very* rough and unrefined prototype of this strategy [here](https://github.com/bungoboingo/iced/tree/custom-shader/pipeline-marker/examples/custom_shader/src). + +This example has a pointer-based approach, where the "state" of a pipeline & its associated primitive data is just +stored as a heap allocated pointer within the existing `iced_wgpu::Backend`. Within a custom widget's `draw`, +primitives are drawn like this: + +```rust +//... + renderer.draw_primitive(Primitive::Custom { + bounds, + pipeline: CustomPipeline { + id: self.id, + init: State::init, + }, + }) +``` + +Where `State::init` is a fn pointer with type signature: +```rust +pub init: fn(device: &wgpu::Device, format: wgpu::TextureFormat,) -> Box +``` + +`Renderable` refers to a trait which allows a custom pipeline to call `prepare()` (for preparing data for +rendering, similar to how we are doing it in every other pipeline we support in our existing `iced_wgpu::Backend`, e. +g. allocating & resizing wgpu buffers, writing uniform values, etc.). + +`Primitive::Custom` is then processed for inclusion in an `iced_wgpu::Layer`, where (if not already initialized) +it's initialization (`init` above) is performed & added to a lookup map in the `iced_wgpu::Backend`. Then, come +render time, if there are any `custom_primitives` within the `iced_wgpu::Layer`, we simply do a lookup for its +pipeline pointer & call `prepare()` and `render()` as needed. + +βœ… **Pros of this strategy:** + +- Simple to integrate into existing Iced infrastructure without major refactors. +- Performance is acceptable + +❌ **Cons of this strategy:** + +- Not flexible + - Even with preparing this very simple example I found myself needing to adjust the `Renderable` trait to give me + more and more data unique to that pipeline that I needed for that specific render pass to render a cube. +- Feels kinda hacky + - `Primitive::Custom` feels as though it doesn't really belong in the existing `iced_graphics::Primitive` enum, + but that's subjective! +- `prepare()` and `render()` calls must be dynamically dispatched every frame per-pipeline & thus cannot be inlined. + +Overall I'm pretty unhappy with this implementation strategy, and feel as though it's too narrow for creating a truly +flexible & modular system of adding custom shaders & pipelines to Iced. + +### 🎨 Custom Shader Widget + +Similar to how we currently have `Canvas` in Iced, this strategy would involve creating a custom widget which is +dependent on `wgpu` that has its own `Program` where a user can define how to render their own custom primitive. + +A custom shader widget might have a method that is defined like: + +```rust +pub trait Program { + type State: Default + 'static; + + fn render( + &self, + state: &Self::State, + device: &wgpu::Device, + encoder: &mut wgpu::CommandEncoder, + //... + ); +``` + +Or something similar, which, when implemented, would allow a user to define how to render their custom `State`. I +found that with this strategy, a `Primtive::Custom` wrapper of some kind was still needed, which ended up being +pretty similar to the previous strategy and just replacing `iced_graphics::Renderable` with +`iced_graphics::custom::Program`, so I did not finish a fully flushed out prototype. + +βœ… **Pros:** + +- Users who are already familiar with `Canvas` might find this type of widget familiar & intuitive to use. +- More in line with Iced's style + +And, like the previous strategy: +- Simple to integrate into existing Iced infrastructure without major refactors. +- Performance is acceptable, but worse than previous strategy + +❌ **Cons:** +- Same cons as the previous strategy; very little flexibility, users must shoehorn their pipeline code to fit into + this very specific trait `Program` provided by Iced. +- When I was prototyping this out, I found it nearly impossible to do this implementation without doing some kind of + reflection with `Program::State` in addition to the required dynamic dispatching. This could possibly not be a + real con as there might be a different, more performant way to do it! + +### πŸ”  Multiple Backend Support for Compositors + +I have no prototype to speak of this with strategy; it will involve a good amount of restructuring, possibly some +codegen for performance reasons, and some intermediate data structures added to the compositor. That being said, I +believe this is more along the lines of a "correct" solution for integrating custom shaders & pipelines into Iced as +it allows the most flexibility & feels the least hacky. + +This strategy involves adding support for multiple `Backend`s per `Compositor`. See the diagram below for a rough +outline of how it would work: + +![](diagram.png) + +Every `Backend` (probably should be renamed to something more appropriate, like `Pipelines` or `PipelineManager` or +something for clarity) would be responsible for its own primitive type that it can support. In the case of +`iced_wgpu::Backend`, this would be the `iced_graphics::Primitive` enum. The command encoder would be passed down +into every backend for recording before being submitted to the GPU. + +This would require a few new concepts added to the wgpu `Compositor`: + +πŸ’  **Primitive Queue** + +There must be a backend-aware queue which keeps track of the actual ordering of how primitives should be +rendered across all backends. I believe this could be implemented fairly easily either by having each `Backend` keep +track of its own queue and having some data structure delegate at the appropriate moment with some form of marker +indicating that we need to start rendering on another `Backend`. Some kind of order-tracking data structure is +essential for ensuring proper rendering order when there are multiple backends. + +Widgets would request that their custom primitives be added to this queue when calling `renderer.draw_primitive()`. + +πŸ‘¨β€πŸ’Ό **Backend "Manager"** + +This would essentially be responsible for initializing all the backends (lazily, perhaps!) & delegating the proper +primitives to the multiple `Backend`s for rendering. This would be initialized with the `Compositor` on application +start. + +βœ… **Pros:** +- Flexible, users can do whatever they want with their own custom `Backend`. +- Modular & additive; users can create a custom `Backend` library with their own primitives that it supports that + can be initialized with the `Compositor`. +- For users wanting to use a custom primitive from another library, or one they made, they would use it very + similarly to how you use currently supported `Primitive`s in Iced, which would feel intuitive. + +❌ **Cons:** +- Doing this strategy performantly without creating a bunch of trait objects might be challenging! At least just + from thinking about it for a few days I've not come up with that many ideas other than using a hefty amount of + codegen via generics or declarative macros. +- This would be quite a heavy refactor for the `iced_wgpu::Compositor`! +- This would (possibly?) preclude custom primitives being grouped together with other backend's primitives in + its own `Layer` for transformations, scaling, etc. which might be undesirable. + +### πŸ€” Other Ideas + +I've had several ~~thousand~~ other ideas that I thought I'd give a brief mention. I've dismissed most of these as +not being viable, but perhaps someone can think of a better way to implement them. + +1) Primitive Concatenation with `#[primitive]` attribute macro + +This idea would involve heavily ~~ab~~using proc macros to essentially "embed" Iced's primitives into a user's custom +primitive type, allowing them to set the primitive type of a `Renderer` at compile time, and include Iced's already +supported primitives, without needing dynamic dispatch. Library authors of custom primitives & pipelines could then +provide their own macro, which would be embedded into the `#[primitive]` attribute macro to keep concatenating +enums until you had a final `Primitive` type. This however feels like more of a hack than a real solution, at least +to me! + +2) Fck it, build script + +This idea would involve a hefty amount of codegen to generate both the final `Primitive` type similar to above, and +also the whole `Backend` with any custom pipelines embedded in it. This way a user has access to the exact same API +as currently offered in Iced when working with custom primitives. Also dismissed due to hackiness, but some sort of +build script might still be needed in the end (hopefully not to this extent!). + +## πŸ˜Άβ€πŸŒ«οΈ Drawbacks + +After prototyping out ideas for the last 2 weeks, I have come to the conclusion that whatever strategy we +decide, unless we do a hefty bit of codegen, will ultimately be less performant than just forking Iced & adding a +new pipeline/primitive directly to the existing WGPU backend. I'm of the opinion it's not a bad thing to fork a +library if you want to add something that others might not want, so perhaps that is the real solution. It's +certainly the simplest! + +You *can* also use custom shaders right now with Iced, albeit in a limited way, so perhaps further integration is +not needed. Perhaps we should look at a more composable way of creating a `Renderer` that can leverage already +implemented support from Iced's `Renderer`s instead, or something along those lines. + + +## 🧐 Rationale and alternatives + +I believe I've already addressed most of these pros & cons in the `Implementation` section above! I will say that the +implications of *not* doing this is that Iced would continue to be one of the few GUI libraries that does not offer +direct access to its rendering backend (e.g. the `wgpu::Device` and `wgpu::CommandEncoder`) or just the ability in +general to embed graphics-api-specific content in its existing widget tree. I believe that not allowing users to +leverage the GPU for more complex scenes alongside the ease of using Iced's built-in widgets and rendering pipelines +would be tragic! 😿 + + +## πŸ§‘β€πŸŽ¨ Prior art + +The most prevalent example of this feature that I can think of is being able to get a direct `WebGL` context from a +HTML5 `Canvas`, which allows users to render whatever they want (except things that use storage buffers! :P) on the +web. This has allowed all kinds of content for the web that we didn't have before, like complex 3D scenes, whole +games (RIP Flash), etc. that I think have made the web richer. Of course there is a performance implication of +allowing such raw access on a platform which some might say is unoptimized for such tasks, but that is not really a +consideration with Iced. + +A lot of other GUI frameworks allow use of custom shaders via OOP & inheritance (for example, by simply extending a +`Primitive` class or interface which defines how to draw itself). Obviously Iced's implementation will need to +differ since it is a functional library (although some form of trait object might be needed). Any game engine out there +allows custom shaders & entities, all submitted to one (or multiple) render queues. + +Android allows for "shaders" using their own shader language, AGSL, which functions similar to Iced's `Canvas`, but +also with GLSL and hooking directly into the GL context. They also use OOP & inheritance with a `GlSurfaceView` which +extends `View` (which is the base abstract class for all Android widget tree elements). This allows users to +interact with the (E)GL surface which provides a bounds that they can execute OpenGL commands within. + +The common thread amongst all of these implementations is that advanced users can access a raw handle to the +graphics backend and draw to a specific region that is integrated into the rest of the DOM or ECS or widget tree or +w/e to enable advanced drawing capabilities leveraging the GPU. I think the benefits of this type of flexible +integration are readily apparent! + +## πŸ˜΅β€πŸ’« Unresolved questions + +- What parts of the design do you expect to resolve through the RFC process before this gets merged? + +I would expect that this RFC resolves the overall direction of integrating flexible custom shader & pipeline support +into Iced. I'd like to discuss & settle on a game plan before committing real time to the final implementation. + +- What parts of the design do you expect to resolve through the implementation of this feature before stabilization? + +The exact implementation of the intermediary data structures (if needed!) for managing rendering order & backends, +small things that pop up during implementation that weren't considered. Once the general design is agreed upon I +think the implementation details can be iterated on in PRs or through discussion in this RFC/Discord. + +- What related issues do you consider out of scope for this RFC that could be addressed in the future independently of the solution that comes out of this RFC? + +I think any actual implementations of custom shaders would be built on-top of this RFC, possibly in a separate crate +within the Iced organization. + +## πŸ€– Future possibilities + +I think getting this design implemented correctly would open a huge number of doors for the Iced ecosystem. +Being able to write your own shaders and create a custom widget which any user can plug into their own application +and use seamlessly as part of Iced's widget tree is the ultimate form of customization. + +### If you made it to the end, congratulations! πŸ₯³ + +Now, let's discuss! \ No newline at end of file diff --git a/text/diagram.png b/text/diagram.png new file mode 100644 index 0000000000000000000000000000000000000000..ccc61b137d624f597f4e571afc06b864434ea85b GIT binary patch literal 80929 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 I*EkpcKNzngcmMzZ literal 0 HcmV?d00001 diff --git a/text/silvia.jpeg b/text/silvia.jpeg new file mode 100644 index 0000000000000000000000000000000000000000..5d398c5f64a70b5e4c1964194fcebe7fd8776073 GIT binary patch literal 37835 zcmb4}WmFx@wzd}*G`IwUyDkF3-QC>@?(Xgo+*!E027-YB?5A2Yu`hpL+Hv zW$EW9iC_hT~e;_}u|8o8V0S)ti zlxP4*$PZ2^NGKRc7)WU7Fo=&bfI5 zEjFwntMb(h#g875ZO3bzKqEGLN>P;rs{GlH!u#?s2m1$znD_^Zs@gv=#wMo!@HjcU zxcf?m@ zV1fAr^Px|0pZ*aX0^Gks_>YkO74knq`LF(dIDz=^01XWd`*ETo!Xu*of9vlG014{f z;zRprT#u(mDBsU8{0ged&pU%CUhlwE5e7MVI_jJBE31(nE^ANhjrKK%wcr@;y1iq+ z9`NhdJ&L@a%G>Kytp{wy<-r8Y&Dj3Z%FTOV2cx>K-Ap$ENO)i5Yw`)3rTwqkR>uKD zkDeKl9%(|x%EOkcrzkg+PNQ9}>9xq!7bp%ZD^L8}+iSXoGksVe;af)rbOUz&W;a5E zGtcu4XPy}!o*JH)$~+ogamM8EgE#l*7VUc-*jxe=0{t|1->HJzMLy0Nvnr4CCFw=? zDc4&$_}9ow$Y=h;7+c?!u*CW)e)EghzB%^l@->CCCRIJg)7Nzyp1*(v@0NyBAMT!x z%iK=K20iOpeP+e|4tD%==LR>)6>Sk7OZ(!RO-r1}g?&Dn`Xh1fzG3!{PKMpI7>|#uF&zW?hFs zN!!7bad9m+^_fvFTgtDnWq)+`H0?YM&wJvsi{oh{V8QZbpZodUtxLZG|`4^yeBhSj~ zw$4L!(%JrGTNH+|zJ6xS(>G1uZnoU+S8g@$>-C%;&B3RC@&=oItDkUxL9YA7sZ)JQ z&+$}H^KQ4A?=K*l%TD1YCY!(bG25l)_t;4%)+wQic%J9xnD3IyZPp804%5j)ri!zE z2EuzQsPUzSYMe{N`|S??-uOm0tYmb16rm{^jP=lB(X06E!sQCiB=Q@Zl0Wqp*Lm_N zpUPAFaml}LT{ruCwY~4C zy}s+HvhulwmNPD;Pvg(!);)yTv_Tqb@ufFWj>tWT19c~lk z*G{$D$kpWwj_SEXZw?|I4;-(BSl&Z|EdGoIZSc^fzR2Cp9bRwj{78biYWE^xTAwG1 zQWssX^M=QKYwkYyS)a7#y5=kQrp9*bn%CI_=b_}n+EZ64YzYbjc>4am<<_q7^>W42 z+YZ03t#YVjwttv_M<30pv!VYni%94N1!K+gRi`QYUWY&N7*uqN;#JEIbJT9?kvO-w#t!~| zsJ*u0aWQ(n+<`x_(0UA(vV%GEWxHkXtlja^k1UBl@C|?Rl6g5g^z3Am>e^`cI_lDn z&G6Wmex@C(xy`P1H1W{51ll@HKX#g-*mdUZ#aAy094o`w5OIT0Z;aaEEX6LPdUb({G+ADQ_qTE_a== z;tQTuSPj!o$0d;*ye4#NPhH5NHooG=XJ3_+ot?nECY$o7SKMAoofl&3c3FRbx+Pq@ zspC}-nP6YNwM(icvWbJe*6OLe6CCd)?a>zkgutv-`HAA|2Xh{1($?5vitie-ssOhI(yMt zx4+En8E+Kff+Ew1#!y`I0eo`^|na4pUyp3pH__Q!F4+90`z!F*Ld?G!)CoVti@u>~zph3;}) zl3u-7m#4~6RkF*EK6iSJIiOJ7*UAY(}G> zq1B^l9df*{fU2H|yhAMjn0AGsfzu}4=k2=_&gk6g@o6gfHD1Am^(*!iQjb7ONs=4N zM6r!i&xsGL)db=`Z+622hU3ZU6fbhY`krV*GR}%S%Ysi&9gk0!peV9ifZy0tML(xB76%k~(nFBr?$D3tCu1v0nxisOUs6ZpVRhjT6KOl*35yRSnBC#t@I~ z#!y0a!@VZXt{aooZ9ky9-=h z@uPJal%g*@xb{iZeh${cgj(nOcP%Y!Yy@&*^*o8|dvCht?Y1C^JxEzM7 zTII}?Ua?1eRZUGcN_)wpj}!+@Z!$FkVnpnfmft*D_(_@%5FT=Vcwd4y6=K>Vj<6#t zK4EYawc-+@C?DydP-TNY>mz;rY>0lJl4Gm1iefa#?Ta+w8g$D=>|@ma6m*2s8fp8r zWJCZbmz#wcpyf!R%w>xU_3z!`GWXDj!f#ioYaj4v+~LsKZ9!LTsB zt&IJg2W^96rzjHUrd$USgLm1Bl9c~^f(l}&yl6QkAE`UD>@hjW&KarJ zQ(}hTDH*?w>Kmg9^*7uuzAnI1bSPBy1uN2lePP0+M9Dc%qD<@mZJRO4G# z6;`NK|F+^>H{*63M^I=XCgO=Y`+lRcUGXa_9~Jgv(hB$SYXAWQsTNtgMrt7~r85(< zx)M?plb@OpXM1j7gcZIuNzkfYG3G@lY+Hy)J{+Z$7a`d~BhV#(&6|+@Xe>Q4LIOM{ zgJ#G5HW&W zsG6cEH#0QQTZfHhfz%Z?Kh^f6!n68!mP=flyf=*7-wFrAi6v$71olbvC1OOpmPDwd zg;O!?8;kU*`_Kdc-{N}p!%0+DS-f0UznX5{pQkBCj=4DHi%!zib;aq}{A`TS?N!l} z?y$Y-7?)s#uw*piSersH6-|h!N|~NPmbD{2VExrom4lZL*rucSp0m!RA6}I&qg{O2RzBHi zuQ6<_I9hxHODxYT_0V86D!Q@VR&9kc%S4wf79~7Ea!Ys!PGJimHpQ=C#WI)7tLTi( zvU}!am0QQ+kvAhKleF}rA645z$1WX?V5uCwj)J$TJ|ux}NZ(o7NcO28%;0u@$p>x^ zs7VQ(-w3#EigPtdf1$^4^7Er82_e<)e8X*`vR-SHp0{gj&VF%PR&>trDfem-Z~mjJ zdHGE{5=&2C)aq4llZh_nWN;EOdjIQqhRwWsijp`p;l28$ef7n`4h2l@O3Xg4_G+f` zl-7D(QiVU%XJJKblW%WGqSa2tn>C_~3=;QVCzvj&ko7Fo^K4+r2ht3`xx=4}NcQojr2cA(!W;HOCrK^6c zg-j>YaNFFyZ*g=>3OTn7caXGb1$GiQF^dp4v2lZ?#P)v;*UW+*Bvz{~-7LtHy(;(l z2-fpfF~hNp*u&_Xu%_4!KgS%9{#rNeTs@B?X^l5T)?w1q9YFWiH7*_OY0@hm)wJ2d zUZO)q^z*6z)&5;un-OMKw98R4o1FAZZ^A;WF0Gf#2txF{!%sW4s$ou!u?|t}qmB%R zPG2(k6&v)9+0k96Q%SsYjuGFiW{TpIn}t=q)ivmaHCr_{(o1(0(ET_439P}5kd>*% z3vAkN;xyOrY&6Wp53bFt_p8UYhs*bf=Sx0aYYP|bH!bwlh8D-J4#mnQ9io>RaZ=vm z+mcI+VT)OPj%(gD^a^P;Hs|MaT%2WEwhBL$N8e)yMc4RFZOkL8k15AIXp%5XX^>ze z1JUqj1w!(rwMaSCc~brY2J+StJ2uGr7ExE*LIlUI8KRc%73|cs{WlF|J9;91S@&jS zlGe&Q!2E8`*i2`eSlQAz=XS~HYH!dzSZb@VgRoEnnm%(^70+fgun7Xxv zVWIH`SID5AQ50F<8MwU>SZj=)ba_<*b_RJBUpv*wvkuP2_2oG_+mZ~&>0;pbinmMf zuJj!hB(s6v<82ye+(C{jKlqe}XGs!!iM29xY=b-fOj+b*!% zf`29&sa*b_E;4@G`Mxj!o2JP0C9ju|V zI$p@YBumkoJ!xxmVb?CyY`g~I-K%>KUncI{w3Fa0dnp=f8~mBz+O2A4ne^3p2tz;o zTx^%`&<+y4eqEMtpmANi^~@_tjoad3eQ;L7P;_95S@ltBQbe|K#4^JGY_3&%zz~>U zEfuxutUf32ScYT6+WuWAX*dkpEAZ^HvUtTdI_FzpNyF`@)k}4x%{6l0%&t+{#gprA zE5y<^(6lma?M10awvEde3?Z-T<~j~0EfLWD%B+7@CVxbb)BXk6zB4szk3r_G zTpXtV1(>d~y)_xHkgeGQ*|-r)Z5s)S6x>ZkyyAq+tF?%J7ReBjl9!#KGI(iKNH)HE zzV#x~jo=8@FAt5WF?z-{dU-N83J4e|;x6!@aj%cTxmI{ER01I*6Hr_-dTR$5F2jKn znS50K8!M}viovVUR(ew-1IM4eGD-zQ%nEHn6KIlZ*2?UH!ekrHIBsmD=%S@f3N zj_y5m7Y}21&j~%ZwQl?YYP~R|j2{!d>krll?y(>dULSg1Z+zbd8jZ^+b^uR&{)9F<+)pOx<#hKqpDRju@H(*)Y6Hk>oTRr2sDa`jxj zW@zo|-o0VjhLn>TjH@_OXfuGday82@=%U*PO)jiq!RiZi@*PKPbyNhmHx z{sOdJ`xodWBsYMEF;D7l=y0U1eZ5K(lv8&2=DxSkk|4JRX$s~M$}NVP!UK_x8#LtO z?R_dRbFk4!dg&Vw(-5wpbHhI&{vQ6V+d?hTo z-17u8=?*mM1wl1tbR)h&umaZ34kuPApeiRc@9{&2g)pKoQav^{gZKqylQW^Kg5<}D~ z-yKB5#*c^Sik^=ja_t~t4J_fdwO;%tF=6taWLlSVo;b23%sG)^rH;uF=8nq^(jYsw z_P08eybw&;@jUngGm81;Vbm5q2a>+e17mCSb~FaRt6%-Ztw|78ZGQb;#xSoIiJ>7+ zS$Dt>EkB^?E}RBD4CA;Uxk^J|OWFS+L4lrL2%JUN$qflv*lS|;C|&dBDP5n6+%E~L zdl10h9VQsE&tANCdqZEN5m{5L*2$!15;wBXbAee6{83BFqGXwMn&@6>{`%FiB9hTq zUuQu|(?CK}28SKEvSb_8pERScw)1?`>&1C)yVc&vB+yUu87@#oXOo0Y$!-=E@=B>z zMVYo#6&FGn?dSZrPYiTYD_VsD6lm0`(3HWm%ITBe@ww@x)X4*!r}KN$;gwsZ5*eDG@wo6!Q%pp+ z+q~L1p~D%ZRNR(+jQGqxqDj|nuL?WLX0iSJbqOopW?P$BS;KhBe117yiD#X zjSW^Wu5joyAaAQC4+=+H7o^7fnBjf8ZYra4ZPAu0NB1uXknWL3$D0hNQRW5uh`>tR znJY@`)Qw{Mmyqg>2TQwA6da?AH&)q!?Ip5_kCZOzvE2?PZ=R>Mv#L)t3d1%ITrmJZ zU}0h7Y8dmV_8`Ig_Ct|1`VF84MBI7QawCiHLgji5{bJKA zM3rdPNVsFDVks1uP2;SbE*-$kS#+bKwId?rK^D*a!nRc=QQw9F4^?WvvZmA0$lFJd zy6fcP#5!smV6d_=Wqw|5b1Brg$JyAxeaeYWF0`9y(Jqx(-;L20J-L8^d-fE+vC{t+ zAa%ayoARq_@&@yurRftqWWG$goHT-<0gxQnRv+GkxN+Z5f01FhKD(P>N!{j!#n6XG z_Vu|XFQu(98V;}1s zwfb}By4oyTnv{&Q(QmP2C$=2cY$Lpq=Z{0*$uAnGEJ2%pWF(r(Wk5J=jXmmZj*0ka zYlXrH>DI*B(R9%-vlUZ_=Kb|Tm@{aS*OYP55sTU$_g{zCn4}`LMGX4{%_9)kCkYZT z9Ei=x%Mhi~5fd`2!zhM7JC#Yrt9qa>in2*Ofquf1D0K%08q=&kP;||d!#AxOeT`aN zCUR+RRKK=Jt@BSDZgRtM8~qyWEnm5EtSB+btC1gR@>riiFuhuQSw#L zSSAP1&d|(ZWOJ<#xAXUdq%~zEL;kw9?~7?IEu`*xJx23RG%yx(R-z~Ncs3POD0OlG z*;1=4v>&jxDeGVf%x!TdW>gjl6X=UFaDpVPm#W1G_`_ca)GK4ew+Ur1wq52r7@lpGw4*(4F$|Ded*U(3^CSvw@8hIo@XOb8xV& zD39buElKmOR1kWE+Y>^`!}dT^yY6wH&LjdC1u$(JrkZ%eZ7JMX?zvVVpZN< zwoUJpR`pq@wq=!CzGJ?6Z=FWnHGe_Du!szcf@ol?DJNY`cieP`P8!ON)ESYLJH57P zg%~kF0Xif~XirI_h2lg@u;`7hY22VW$TL80a^Z_>>#xv#_C?Ev#BY(rqAV_zteU(C`ElDaJsI+S+6jsNeMCYW2*xU?CHBBh8(rV0L{jy~4^N@}j zvSB=)5SUgzU0g7eg?!3jb3fpCmQ0~}ViiPk@q-BquT|vs)~o@~-LNmU8D~k%Qzs#r z_F(;c{{2#1bzy7$i3&)TgKh<(#N>soH56r~Jm)$nY|`(U>u;FtLLjLL={#kiRKmK1)EzVCR$*Z->A| zZ>V!Iy3UqTAR1yppVl>gQ8mX*8I|W5n1wrYFkAr)t9wi3A8J!w$lrFY?O`^h5T!3< zNHw2NZz%|=!ptU5S0RQH_o^CZ{**?cOiNO1MlgTP@n9%&Q+y)v(;$#QS1XAq9LSe2 zU|AA`cB#zDfs=rpj^!oOv9Vd@S)TwpFHys)!NQOm-6ncGqR*by5ynk|N3)Swrq8e8 zMBi(bRyvP_i>g`vu{WB{2CtZc#0O#}v6N~Yk$#{{Y7lh8Gb9)MbV!Q-byi3HmsEe$ z@W)glKl{eP!O2SLmC=y?zOl)&O0^Uu5 zL{VvLNn#maNRAj3;j^Wnb4TfrZVWwlbYwxRAoSKiO?hM8v5ww{n~0x69XnA6JivN% zT%jhu6o)VWp;&mmKy5MeG2azd7CbiZ{3Z_zJ z9@AWpSqUA+a~w?M*-D4j!_nOInF5`==Esg$Kq_PeiH5@4x&?j+xrAr*zO9>NNxMa( zh#GTJuw*5gNEs4!_N;7I+J$XQOiVM)rv&oA2*clnOV_u=WR=q_i{+|>vMTicTDidu zBAF&3aB3rV1h$w`=K_ik-0lZ;Gwu}Pm_=2V1~l<1@IsPF#h5JQ6zGM9*17O0&?I>x z<$V0{2owke7@zVqO(-CY%Lf%@8!glZ%T_9YJE%$Z{zu#jtmJ6uzR^PAG%!_UX?!u; zWSIiy3(+#I%tZeNc0cyI@Iws6JQ@cNyfLjdJKjMp^!ug2`||N<60f zLjMHs=E>B?fyxHWpisxQoi-sJE5CyyS zl$V{``?;s!=#rZEruVz@fx}CNf&J-u9 z@`--eODqf}b4(;`BIMudd)+_vto+SCPGgbfX%&XO*(&4I?L@sg@0~47ix1166iV+Y z6?2Tk!OTPKB=Oj+Vv?f5|EELc>Y|e5#8V3phNH{@QQ!P4YBPfMO|PJ+FY?8!t9xfP zf!iU1dL38MF+(PGZS48W5{OFfM~20*eSg;6RUaQxUD?&)Qv%W^R7=ywP?MaMaymx7G z3M<3?G+xQ1k{Y}R_})KTtf1cE63H;q!0Mz7SmkYLF9?C>q|i;v;7@pi)Tz_45R}X!>Uiil`sbKTzD+V7L{HrPE+dWl!b62i85C52 zdLZZBunl6YAhm!2Ws%Bl4Y4Er=KQ@GJUOeeDmwBrVF+zL#^xurr^j1;KY*}+5m{2Z zC6pT|I2cMpag4ld%cvMJ)DqiEF$Ln&h!>U;?w}IPowJ&g4)wtQ-2vz62UHlEYy|TP z4srV$Dl$V``P|R_%BL8C2-ZFN}7jP~hy%<(Lk1g4Lz+mJ)4 zC7S4I>VMrNu?5DAEhcOvjX;ova=D;wcaVO*hqjXZ%#!sf%04OTl=RwScy6z z7vA{j7WY~DxRIR1nt%J<$2K#5h(U=&6cj}w6^vs3kqI*NUGf$PdtV$%K{=%S_-{H1 zNt4sPq@jI(u| z3ZaPm)sePr(CoWc6I7yh=W8d>ffVbW(tYNiVX1^^_L%u_oqO?&@EeNxfpVorq#G5b zo5=W4?(!-_w4aM%@L_>=6DPi6%<;jTzEBj~drT9i^*N!;hDyuT_{loI66a!@yS7C# z%`QAAf12Vqb6M={h{oTUv2OyA8p9pNIPD1@a1O$5;97k;3jph}Z$U2=DZWD+Up%G@ zdZB>2yM6kn%+ZoPj9r>C7Y2;#l;31KG$DZkFScI@7850h!{hn@q+>jPKEg;)!)^*q zcg_H$n~8_SxMoAU6vdY@e}eWFaYiZrRAJ(@uLgjh{&z~b`(xJiJqK}&p>c&1l0wT*&|PW0nq?O;UZPN9s$eS8m}`0GBJYlo@5Z+BmDQsx_W zKWuK#iE@-Defr>1u(M~mkX5k!tEr~S^c2_q26OO&(Sf-hHm#FxKvO+scYTMvJ_ zd0ECUJ%v{wX&B}~L=;r^1O+4o`_O>aG$I@!8ji1R1*+INtqdBO_CrZ^2=K)zSdYRv z<&jFpGV(bo`et4QhZyenj2Uk6+=7Tfd!GD<7e7mY!c-+gCVeDYF5=dD5ju4Y1z#5g z&}6;|coKgniBV)ks*3Wg+6%g6VHW9HnOtq7Luth!W9X>@=S^$Q~T` zQ?CedM^i`p;8P#P6{+qhID`0k0|trCDeV+2VUmo8O2(*mxOh@;bOJ>wsdpDnKZ9^6 z4*o=%5ZF}6U=$J~Y4%22;3^r1l_q(UeF3`(ksKo*+fNj4RKATM>ygIEU+^#=cQ4 zX3ev-UEA+tWOfT=@!ufj)!t&U1Y zfQf=yBfM;1s9=)wrv|KL^j1W5?Y#^rA}~6UWpSYyxN@g<>p!&WEB#Y-t5=Gi2F zMxj#ar@8emRSLMiLC!Xd+gLIN2`g4#s@^E7`fZq$GSU zE1z+D2N9R1GP;k-C|jvV!}|-B6n;gAI+H^-H257Qa*&Apj!0g7fTuPO)30sBnSf8$ zA_xS@Gko(IP0HhhD78g(zn}!rQ{_@}$3(IdFZH@i_MmA0uGBScNo-nf?3bk5E)llw zu?FMbPALG#XQJPI;^Ix{--&EIH*$4`nt09!swmQm%Qw%HC2Gt+R(||dnB|pBrz(+* z-c3@(CwQH&7hJTPE=9yZHWE$XeIwmnD3!AaCA$ZO9arQY+N5>BAtrSdxS z6q|vrTSX&*=j}tl=57qH_;%Jg_2)~=S~Zpn$KAd7pIvs#{SXzZvxO0c1}@(6Xx+|* z2I?x&9}JRPFfMQMpnclzrICq-?)XWOFbbkk*o>CYW1UIGe41(%E75jQ6KUF#luB80 zF_eH?OGSt3WN7s9L?!CE7ybFEFE;u3{qHNshvJywEV4v1Kk{BnOjJvblB5DT{Dpd=( zq=ra1EW#7Zh-0Szz2p2h3@wzNq%sxXo6kP$nm%FTEnYc-4>EMGRa$mosyp+A!LRu6 z9VE)RrujMdj~$cnvZTp08h-(zW8?A%2LY6rXeTlRY~YdU-Yjt;;nO*#jz_&rBX`C zMOD0Kc}sG0jd?YrDI@br{>+fvB84V>k1u!#c_CXy33J~PKV#6J?@4ygBa28c2u2Th z>d-16`^jodNDx|hD@OPO2l!30vL|~m6cP-*lWrXB@!1)V6>i@Brl?)TzTF6voQ8sO! z|3&Z6mig{ez4u;DzB*CR@uvtO_v8L7>A9fkkI02sB1@}CTng}EL{efKohK9f#gj?p zv~TALC&0WWerx0$9jiO%#CuE<3$hcRANJJ}Xz6Fmf5D#{Py6W6iSoEMBHr7;9~AE( z4tAtFn(xdRi1lb0;IIAi-bByzSuFuVtz8#LlJ943NgzvmAJy>SwD8D{sO_VGGok)x zwxT&884z$P)LW^TbOh~Cie*HWd*kt=N`DqMa)736rp6|df`q80B(>!Ct?P~+hA64{ z>fUYu!n1~>Sf}_%H7=IsiQuBY;l+$C7_ao|IdK1@m24xT67K@X9m`)f-D|2AH$V)ZvVeah0k`~70Q zR?8;?+JtD!WW(MW;&k#wQJ+p(M0i{Zt{kqELZC>AJo9<={a-+lZtHJM^VNr8ETo)9 zAD!ueawX>{o-iEP`>wKuMVGC=fbiwAkD8X@#WWY)KSp~BHuuBE!32!FNG-@|Ywl>3 z7xb_q3EPwF)+9v;!VvKXA%4oO<5(IA@7^DIPETksET1P5Yq>yH&f=3aTv?K|D0{?7 zQ&p*wMpURGf}M{OX4V2zdwjPIzEcl+*i{)0QuT&?MzL&>zl0Q$?-5^dd$HK+%)9sN zYwMJYR9fnrZWh~1992g}NqiVVMGcM+i4{1etVuJV3GTY z;(p~Qrz|IlZm}QkC}~+FmikBmT-1);NOJKWTFc@et#P2L!5R4JH>U!--2V%uzB>O_ z3xegoOlj0q7c;Rh2wjjAhr!cf=SIC}=2qxRVavUlLU)i_%W9S@ataCbB0b;97)c8@ zu&CUedKvWq0Fr@;Q}4`=w8v* z%=!(JJl8)zwHs@okmHrqvnzs=7wbP7rDhs+Bm5}>;UDmeervy^j1&vYi*Uo*bgpH5 z7C+=cOPEO23|>woJ3AuR70OQ^t=AkClYM;eaDEFsK9#N^ve>Cxgmw%DY<}8$pfyHe zk|aOmUZCQI?f)n)gQfV1+ zLWrSDrX9=@i49oHQzFVm$RO&p5P2a;jX+sdGZ^|KcZA?_cm#f&5m01J1#nRU zBo}<`qe{e}FV#mHKDYI@qL8V2G^wk~I?r$LG06OQ@oZ17cvx>bI=CfD_G2rZ&(^7Z zG3OCJz#_nlewEM~3{U2ge2)x~l&V+9;^JAP?v5Nu%a>RX0U_Bhh>;T_b1)-l4Y)4` z?L0*$atdPB9S`-%_e1(H@!WV+rqeD%atw zj~NE;5$dWhUs#snN+|Tx&h?nA96EdAT!1)E$l?>|3X;9XQpqWG)e7q=u8vxb*n`n4 zRN*uglKV;8#fOZEvb=O|KDP9zmB^{9md^*Rx<0}{gG?i<+tE)wEfdlFKwg|yS?Xux z{{x4X7v6Qi?B@99#uHl-%S1x`kA~9F$57JxMugYefjQ%fGnUOi@gh9kF00}L6{Avu zTIBr9GD0#y4^3Nxu9+}jB?-H1D)|?{3#%=&!#}Gdeb?7QRoIVKEbBmFMv&&7#|bYH6*D#xMHe zQ|_VsoO&>r=~sV#ZhJ%#3nUCtMXp)5!2%yfw8!zczP`EaNbd=s*9hJ>=c!|oBXk1& z5)0-5PxJTguW4T$A*dq$0-BF$rVe`syMA9e6oe}U4Z0^1Kel|%)akS+&%92$LqL1% z)Tx)L6&KahcU@{A-7UbK0ZRrva*?VG^FtnwQWF+-8V_;#BCRs!XUAqi zAIB3WpZFNYG7eY6Tzl^)sydV;zSFnX9CYWXyyETaV)69ddU)g2u&W}5kFb>d%8B#d zbJ3LWOgsoW!CzwAqooT}LCM(~^-dDimn(b!R5Q-Z_>Dhejp$0{bia&<($+}f*%6b! z?o%|RCOYdo?3nm0+9SUe<}<7k*n7ZNP`|&ExA=(}B@x-nIH3^6i)x2<0l~R~Yx+|X zyp%(NVBgM35mv=~>j<%gb4(qPzp2-NBAH6AAN*sBaR{x7rWc>+T?u|eNp}m}>lV$b z`c0G{Y{AFI?a~_Y3QYGru1@Q9DKOYYF3E)WWWE@hhK_+*&$-Z7?T3^()S%+r$0l@2~l3rOs9152oBC+e?XD5N}lcxuGh1l(ZLX2Ru z71+phM2Q8Nx}}}r^mvrLzW|p7+Ol`G>T*_+QSpMN;M4SS9k=V)b#SRSKKgUumq+R@ z_6nt+Gc-tBt+7HgH}0!ZMSRvHZZjqE-qogl*p@e3B*A$+M92fQvX%?@I_NG8pG2`1 ziinlFR>cF|JGdFIFZ&wdV5GoEvL4eY`}lgOVyJ|bVja{c30_nRw7J*NitvlsHN~uS zcN|432AHM06$@r(F5N^KXmrbQs9@vSnxF)x1AJ*NT8h&fC*?8@^f~@#t)bJI_!m0m zt;g0Br*M8FIWEJK9E)j?y8P%DA#vn+Q}ix7|Hn=du|x@uXB73(?R{}ud3-3S#wdn6 z0(ruPyR8M~%@Q><5(VhFLe)2f-}-&wo)j)mipQT}%jn6s7R)E! zD%vkHNhPcAjV~U{DS5u?Ys&w@Gn@>jtt8c~f8?vD@ni1IjiL|)r+6ur?=U4NFdnIb_tK#D5pul)y zhY*oGK>E@0hwPt~EWDu(zt1-F#lS|4@dRVwd;6$7wO^6(WojsmB<{$=N^}!ZP5AGr zYK3?#%s6Zx6}FaI3>MuYl@meq1WvekBj{Q_e`cCH17-y#S@w3H&vT=r*sz)~i^nl; zFrW+EA`KCg0wOGRyWjO+gVvdfI4LAycTT0avR8OUc18ySVwPdW`PTBl&4EF$CGu<) zsvj!?CVuS|Vb;ROGxK*9GYh)#k6lHHsWq{%(_EU3@hZ9yuUbu?f2lJVN8Wdm?ey24 z;GDZ*R)2Q+E7R@Z`6Q zeTbT#XA(H%Khr<)wTp}p_3e4bDe)fb?I^!+ArR^ccu%gw`wQ?D&%1L|^j#D9 z3kdX^F=X+w^wCjyk8?sSbSUCCx-Yxu`<3iHdwevVWNt5hSC5sRSfRJykm->w6-(hQ zKCoJZBX;mLBDQcRfe0EWB41L{GRiq5PlDe{5{JZS5A0k-!0`#rlk31i9h68A!(c9t zj+nYZeaDN~-wIn}gD7bgx=UMTd_?;Ugz-VaW>Nq``Z9`FNWmV^=c^>+Dev{D!xn6> zvee?2U~y74aP>EkDjxahv+{7z@a09m_+4B5G%o2ro_(sgPZ}?|=^%ntE||Hhz_S&Q77fcEMJ0L+53a?RRq?>y5<)srlf>Rpxcw2`C@A17Nid< zO+&!LyuvcSGPg3y5WHh()Cvy3L{{CPkfw$c?`-d0l_&P}XTo&=gI+X7p`Vv$#J5a@ z@*B83Z^VTFEp;&zoQe``OfP4oNZsUmqx1;l21^(pyyAG`GO@x}X<3#k>3ho~KkWrD zZIvKf9kuT?X{-tj5%Xhfa;H|gxHUShe4Jmi{?>Dx`10xz8MAjY*9=w(!pY9qXjk_v zNQi(VOsG=zcvVaQuYtrcLUQ3fqJ>|S@t2>0?H3?FQ1fGK3^9-(lV`pOfB`&lm7T~{ zT55`R2F-u8$}+ub3Xg5MzT&)7g=e+r2ILh{dkjcl!BY~2{?Wu?Bjd| zo}h!z4o)IDnwb0uAN#D(3spSYgFSdjJ;XAlk2QVB8^YnnhP! znNWn@iLV%_Z-*0}G(6PLyvuqEVJCRLe4#h$6Q2lIdE~JuHDg&iI0?K~(nVPddl7%c zH^w3{Ax=2OA}2xyep42u%nv)biM!*Y=N)iD>P!T+G?x^YCVdi1ysh=^gZ_o9H>LZ$=QaUq- z&Bgv;8qlbJ%O;P(G!+^3ppsc@H_f& zl-K0O9d&puHE^p=b9EM!j2xg7N`FK_sPFw+kGMr)pAG#@?7>@NVWa6>MC{`dqpVzE z3Sjra*%nr;ABEGgY>cQh4xbWY^&=~ScH;bSSU3|W70SqlzvYBkiv$*h>LS*lAI0#0 z)+LKJ_C+bp=g+RGwv62ig-)Y8(4Xm#JJJLz$zMGzR2v;Uds%IUZPNGWnDFR&6-$7X zWQ7rlM0r_jel>l}5hH7M&)yl|*f8$fcUUSGR3Z;0^2s+WR^HFdzh7*+li-R}eds*lbiwwwQ-r1Wym%(t)YQ5- z<7W*P5zi?PKK{Kv_Q1NXnVT1YE$!K9s$pcm=u5a-l1Lh%0JY3kV&ZpItvp=DoG9CR z;Y<5~bcx1oqn^)>69$ix3r8EsyH%%NRLT?^#kkroOUkp8(#5aJE>e<(sY81=HXTYu zhsq3!rG4`F%-2q6k;KyuzAm_P+qao1^Bon_hQ<9~aEjFlYG!7oEbM-D zy)XPyk+fs*bVnhEPtCoqBBTrqJ<&VZ-mg@y431u%YYKMh{6kkLH=gt)?13XQGyAuYe96q~!nQIVW~4vYL{<4C`0Gj>E!_43W|3dU zwD5P~K{&81x};Dc5uVf&7A|}KaPS>?r&!J0%B<%TeV6EQQd?WQsQtt8PWe<<4e;ft z0aMwf{P2JtW~ueF=7R$R=aq2nyVt()AW>$`MZjx%VY_?7=WL;mI4An0X7Gly zg%J^pnI}zo#7qTeX4OsQM>$|JxvztvOii$=UXPf#0gdS5v)eN$q2KpjRFiNj`5Rz>Rq-RIp~ zN$ALTz9H8V_5}3~Zzf%m^gR|?l;nSj3I z8D}P0W>fH8W<4kj|+#orC>L+8Aq#{OX?R zpF*VuVvDRS9AjX%zEf6SBjZf%+(Yu)ucZspJvVKEdh?NRPt?k--|T(DFi9ti=r+QE z#XBD1%{%s9!5*ezaZ=OEw3KIp&!oW>IN%dDtrg7dP2EI=Gp3QgNkjF1gQwNPiL`=4 z$BDc5rL{9>f#qp;QlJ;?U~BtVcu%ZO4rgTAouDDRB;J5Y5n?p6+VqpTIht@lXicG} ziT$%w^mX_HRV`Jc_PsT@x;J>~@MW88d$aIc?kk9_aUb&K;fu30-GZ}^t9CI=Ql}A( z5Ab*#1Pk zgRf)d&EAWDer0+3(#U9c2x#;V5NWL7my_K2tun08SNExbk&7B5Rhj-(x=QiAw21hb zL7JW9M8RBZMCEHt?Z|HdvzG3+n-s(^8Vr2Q3kAMS_kn#>@l)8qs$^Y!{Zke_v2Hv-xF`Z2u+?Yd)R#|A461J z;NF9olQSR209;};f#8{v?qJNCskY;nWmR-t3rNxA-5aN zy#PRR!UNom;wZ2_*jdB@`<-PMS3AxhYqBj>7jol-I)ajs3c>Bn>>b#z7`bkQ=i*6N z_j6U9!cCdRSaGD`-?7ALNA5cEw*MZNVBrN|3ZCoLrmlq?gI{QCi{9TFHYS$=d}N!2 z3+7gi((#{UgRyX!fdiq7^>oji8zLZ!0+!dClvXCkBJ8mgoWj4%0wiO2EXiaWF$pkr zLo{T&kADQa5_sB>vfrLgV%d)T0X>>6X3_*zhUGYj_XjrgTu-Na4H-0YbBLR%NXqZ1 z!TI7WT`;b}wOCnXnJ58#Z~B^EWr3zWf=ASPIL+qMc~mPGK72wPsChPna9*SXvzwMp z;KOtnBMGUqn??p4@VtNe*lT9A(l4)B0e5sf*%J*>gotwniR!??^eHQy+OMN9f6%(0UaQIC8*bhF8S5-?9jACPy3(=n_R>O|88DYja|zx-B`QN^Lsx`SXRS9DV$o2nmsn#5JumZMU%2MQA0OO# z1#c?<`dP`elP+~Aq?3Yp1y#==OX#YbdLA!~xuoY*q8B1Y zUV()ldhz3=v8w2`*w&tEChrj)Lklj;!iWkow_ymB%hN)tzkwQH5foqpCrl_mV?LdsWJF@eBxp-ICrsmGVNNRBZ>z^o+Gx@u zKJ9}^MTVy#s3edd4R-6$5AT8ahQwnID(u}JiCQkvJPld1uzoRl=`lal6tt{cm!1$d zG-5RgCr^2mBt~9FwB52mgIUVWo5N64S~f0(eS=|;9|dJK2aP#FSkIO9pi8^Tl|lfy zT`QqZE=pF^XcmR8aVP?UAEA%e>ydsIDGteGzN`D4m6>B3j&|Fa?QSgY-T@A)ez`P% zfEWsR+oc%JZFsN$T-T<2rcF?fn)2#9e|1!gX5jH$Uh`VPiuQ#f4FQxbG&kh(azSTq zf28f49U<$nl8KX$CrpJsfunCa-ULfhi6_?62GIqRCHOW!RA%(k1QRttfFDlU6Suq6 z^xba}=lOI_C3wlmz_LKkJYXv~q}LcVzkxA1eYr6)aZj&?`pm$4 zpu+g`E#Ok-Ty)4&`nr+6q%nL z{dN^m_xN*?q54iHRn}-x!MT-nJ9Vp>Ey5|ty(Q+=t$Vkg7O2|ZWKlw(x{i^{A>`@$=f1tQG=2moc%`0H6ns#MKRyFGNw?G+ z39dzZhkYY7c(hY)4WU%m5a)`yIsy_QTfbqFYEm&1{Bb-s;=n01kt<1zKuJnV?h#F4z9&CCsqU z$BG6gNRaw88q6kLI_UgVee79G7Fi+9be00n@eg5|)=6<^sIwWzPPgrcC?Zl(tgxj0 z{s9EJRcSAM7~vAV4<&tF{R$)JGASK)Dl4Gm!r;x{#U!%JI_(-WhxeWLNi~rY6fpCa z&#|at?8Rpw=xK>|4ONEf*H;7c^67s=T8TrS%m^NLO~bHa{KL35*%~O6qtDlYH~#xU z-cJQISh!7D+EIwwVL}ZZI7xNq@e+D_#7Pl%d@dTbpm?E3AcrnHyCw~``thPA`CA9& zI1dZDF6@7R39fJ7m6fA7KIv=Vj(R0AL-ajydV^%+z7+S~sD1j6Ap~LW=fxq~Nmvuz=dJrY&`MFav#C#JVD4-)@5 zMg-&7RlO>_{qi;8o%eU+^&j-X3(=&L%+8k+UOwC?3r|aFRJY&*Wos0s_;&gWGtns9 z358>@IyZ0O zOW>mTF9{yHxNin11l3A-NyBp|(@O**vKaYMw1BmVZhONm3n-Puut}F%ZLMibVNs;! zz+L02lm7?F>PJa7ZC_V9u5BJvuvf~{o0y!OtonHaLZO;TffBiXh9Gfg`h4%H^emwL za=wK??bjc5OfG%qe1CRhdDt3=gP4`09$7y#R7Vnok1gy3)U{&eGJh3U9gLc*EJXUO z@mN4J8*?^G1;k>ceG`?F10*C`K~tJHyVdkj@3}1+ z&tZo(Y;$|%Oibkdf)l$uAfMEyH^JY66^|cP#Xj@N6sSbM6-PaCJvAWhTPacuwTLjX z!jq;TUsawCs{7xk|6F67^<^MllnwcLH3MQ8vDbXbVBmS$>nFeTSEs#>TX44%;nAw? zYjQL}DbzNN&sK13-@PoF{SQz`9O31Y@ z={8Z%eK=E$jS851XlAs@$Nob0qYOv01$roI&pq7x*HFoe%}IvkQQe*t_n~vY>i9o@ z;pBsWKDz|$4}V76Lv+;a%Pd8f7DUb|-P7sfmIDZ-;iI%wmfL5BFZ`!IoSpf~-Y4sC z-B7^8e`&vYU;hyy;yrdx*t?Mfq~8}AXIU%o!>ddQ#Mr(@IWUh#?}jQ8rrfsrp6i;R za056*iK6=Drud&-&g3#0KhB4z*hW;uHos^mXhSuj4dXOIdbSh(u8fy=4M^wW+)ESm zOS5KHTG;wqY@R6!X2j5Bb*JD{TzYBa&_delDq;_kiJ>FzP2F;LmcF;NC`r|8skzvh zMZN{Nl&qN{S^n!mVKK~nPrnTqRg`P7mhj(S4M;y>wpKO`NEH7A3>%q0VEo}S1<~R18Vsqty;K*&P zHS|Y)LLyHV*8z28t(h}{O>LyLf7JXY_10Rd#$3DOw#nBK>)Hc{p|$K3w3LI>g3I4~ zvVTW{;_&Otlv&qo@(7{F%+fN@D&`>sv_XcHDJp;X$Bm_??qGy9Oko{yp`*gGtBA0% zDmYZTC4^Z1mHP7I>z2DO1KWs7RW?3n`Zc-U^mJ#gxCyCUNi@IrKL80~_B*s>p1wk| zPwW9@A-{p3hM5*$GsfKcTj=Pi$B&617vno*#I>&Q>35tGoTR`PIS$llNDUE#+?L3& zI(Qm08`;15;Edooziw4X46GJ=j=GMo;x-Qg8ITy0raJ!vfYs*~@(3euaR=*c=K0FO z-VW+zWg5rcLA=R;-7v2#e_y-xbmyjD0j=aHse^j#^{)`>r4!84scFV)31BiJ0_O2b zpA}m4?@??E^oAAk*2i4?+;Rj}45;1Cft=R-KNiW3{0a%-La1YZ+efe5z%OsXfP(DExq8I;U5(ClWwHwvzlr^5eP-PK z21Yp-1X}lVU`R+Dg3*UIKpLSNrhQ&@+sWBJV!qo+TrfLyO$xDRbj-jE*sT`XmIO|C z3#SFu z_JHA2R#a@lO&-c%BNVoSPC1ss0G+M38$)pl`9?>f(5_!sX>#oNycypv~E9W}C~{*@ z)u%D>#Ge&xJZ>zBZ+YppbFz|FcWbgpr15*cao0Rq$3vv$175e;rDoBf91{xfN)b5) z$Dw49y{r0Ta4Da#p@(r>LnIphTe;tFSEQ%!5U$VuxGahk3T5j}37X{gzPC3fzHdy+ zC~Gc$(?e1U51Bk1n_SxLLcJ*7RXi$hjF(!?l5BhifIWaGs-C$yEM5{zEhHAI7Zwa3 z*L7hTAm?aJIvXIu6)NUm@(5H4lBo zzO}utel<9Uw=wdb<=U`lu`R?cNd1)5OtD;~pv&JU>o)F&!u+D;Pu%7h_8Z9M9yqre zJhBL7>KItwMKp8YhaHNM>K%2yRi^THMrZ8kY<6M0$K{SQmrb}J$n?kCTmATJ8eW-| za@!(e9*~}jK-(DY0ub#D@I=jpq!_{+wcBXVD44J!v+G28jpUOC~d#uK!mYx`d|aO+fI0o(Q@@4$BW|m+gD)24}S*4EDtLA+=8es2L_|z#wt0O_1fEWRVlR zm=SX}C}cS00_Q49FmKSYwu(@GdY)_hG@E)mR@yjK&D&lP``B8BLdL%fVcci`P>q~O zmhOov4Vl2Iv|L1`c<+P{^Ar82<4 z8Ve$vYlNQ%POOB5^=NnGR+?8~+g%k!$-lQH@0*1@9y3u?3GV!m zaJQ;p)JEm0an?Q`=M{D%bzU+HZufH9CG#(v9~Q{j18{#uQlVcdgt}l8rUR$erQ3la zz_-Ye*v4p~-oTc`#cdsI@B${eP9gX#9wQe`VE{`r)m|vtSw+3z6f0=7r}VbP87P_F z$td+;L_GfTj*A>--n>j3qWnkqbP`Hh8w zNAQaif252K=Rz-$zyfIf(1?*2`b$Tx%mwt7h`6UC{CBQo9hGfC?PKJ;!Fsr9NZSU2 zUAC_$pcDhWS!dIJYFL-wh$to(r$7(h-VEd=o>&BryBa{rSDW8_?@_ko`N>iKneH(0 zy~}7HX^sL$?%KuY6{FE2L1|>IDfisv0FL8z`AraNnL?wsd~?c3>d04QOh9=B?RRA6 zpBtZ6b@^4A3NL>#JI#IzscLWtbe}l8ljpLLP^d=gBLv2Zj=ReehwM1h~QVnG1y4%TR&S{Su zmlv2t(tS=luF{)XmFR_qWR{eVnTG;h zKMdb?V$7DuC4v~kxt?gv%$-wRylR&Zw^l}@{fgdqC_g@7_D2qK{z~4FeJyE1RvKcn zEA6_ym_w=_!@KpS?=yO2Hxm&H924}C-aPH+FK|-0IZQ|?@u7*1TCTh@AZ_ot zRLAcS>ThdQL~CmhlI!)eaZm@7$+U2Pe)M4pw+t&reCTl8F{rABe)GBeaNnqEp`~?k zf_EQ3O#Femk6=3vF^&2v6JZ7!C1uTH)=dT zAly31GV4DkT^LBN-Utba-N+H$lQ3BT-NlTrAD7K~rG7}`sH54nJLy$&M$^G=KbHZS zW6s%XGsS9oafYGn{K%36iC!+gUpL=kLoaiqCi=p5*nA+)zPB~mbLj5GQ^8k0_x}KA z{O@!-D32>WISIIDb63)l3AUWr0u_$)dzbu5umjAkh#*`!eSfDsB?wx2GqgGYkl<* z@?Yid4L9oxqjw88#4lvwh3HP)-1Ga9Q53FHqS|%67es2zfhqCNkfqZbHD3=sQE|~c zz9*wT?9X0sH#JG2V!HfHY|6<0^huhqO(=AMYfh_rm^SuyYKR*>HWvzraScaf*RFL` zzwv#|Kfr}BcH(|dXtgZgjkehKYDqKLCv?B7$%agy`pWLVQDR|qO;%mwPmfMB$%gnh z5)kAkE+O&IvMW*4@$V(Y8#@j0H&&KU|AB&j3*|ky%~B6w-#rwoY-HTv-vme~?l`GY zSP!h2wuiKZv6KbyzEFh!Uno5hEJpbsAYfu*q^d@LWzj;z+VEgGC00{nuhy(4IGq!I zz$V0CSCH}$G}Zj@4dvMh;ecgwL7LR1`tnm`8J_9Oo@z)IwN8c=S+kHUIXpb0O3eJa zHWP4{sgUZKa;sfq?1f^5`k!*Yf(!{2k9rirG(Vd%W(0D-`BdOj<43TAE{5X~O zLZ`w$NPY`LEN-U$R)AU{$T~hd1aDkPer0ah7LhenskTy20Mp&%>@@{xdj9-rv@zHA z8Rbhb#;Ea;`4xdx(7pWX8`~bv(|>>h5#$Zk+y9Vk@xsgRMht*B=j>$c+D;KHw_%(h ztcqjjhSX=m=zoBeE&`LUSc93Q2GXxOemoSD{ZfCU&Q0`RmqbR5FTP|=$V*Ho+E(7M z-tngQK+*4@kHy~-MMr|pLZtsk=Mw*~a{f{O7{H1X1uv1S=EPPJ%)9v0PW71T`DlQ) zXV2>En{C+4E9VKXci}1FSs$P&I-6%tdzi{&J>sP;*PV&Ao!-Y} zK4^^M?<+V#hG)|)-P?#p)`t}T^wyQf_{`#)Q{Mc(WiZ>oc(9tZ>$hjNyVMY{Wv*Lm zv!xO}wPs$ujf6^{%YV|pe&gQWNy8rFO)sxF=$J%{jg7-6^Y*SsuYz$pZ=j_v4TJg}{#a1~!B21K>bpNEErmJSZdqRH$ ziI(i0Ogu@7Ybn2d4g(GHW#5I()mD*&xUb0U-ho*Pd+vIAvAN|o-PwMDOmMe&YnXT` zJ}~1a*)3`&y%p%4wljc8^-uB!myE&OtIN(|3c@`$zQWy!Gq$_>^CbbL!wFUaS-GkE z^vuJ|5#mf(Rk-qws~10-apBv;)VsU*jTyHhZ7I?rlu}LfCkdOoTffX0Dit-AH5>tsm=X!4Ecz zoXA+qH|Mcs80en@!MFPJsasiwvg$k%j~&Jmxj#F)HUH7#F_wLObr&>)s9^LucNx*R zhI%u6N?uh>RJ3&p0*WYGkhNYc6R=gCWr`4yuJw)GCiX!R|NLL0J<$sK?IU1qZj-S;`lVP^gXJsFFDf>knNgLc{BFC##||| zD*1MnyZrDXjQFX|8hcO;)_Ls%<@Keq#mH_kCLKFAoi^SV~mY3CTLp7G&%f`N->*Wgor}+!*@aC zK0Q_C%mv5sU3msyV;S%Q<~)y z0_HPbxYC%(rJu5^-)^^C=rCS=ukbye&izE)j}$w~-LY-l5L_T$7c)2Y=VRs6*)35= zzXGr}r5NOf)gyL~<%ZQG??_L4Z2;V_Mkq9PaiY zAg|T7D(hi;pL2{#;9|Tk3}=M6uX)q zQ`xde$MNhd``>GH%Kt!NXx06dk!&l@F#jZi;Qn}sXKahAS?{)Nhr{Hw>56DZ5s=Rp z3(7=$M0X6zZ{-g z(|JucAB%#c$pP;)%g%|5pb@q@Xn-qp0FR$NPS0?D;gJ zD`VUwHe;;nM@UbKMBo!1ywsTU-W*>-=FCG7Y^r!>70+Dp;c@K7U_^@CLJ zg4;S+gO-BdD-kabidA>KK?jE=jC~KQVRTj26V`hATALNZuAOa48YZ5;v6jgQdJ)z7 z&iZu2DI??dVtyw>&Nj~jzmT;qzKa%+;c&3t>OzGJS8ghk_zP}|1f;1;1Re7I+y^5; zKXsBw!xw;r@5#5bNTr4SyLa=JlBX$J`FD+@g`5 zzZvHzE(P;sFp(J5b&IiHvtBV33itgcTcX-o9$XDVP{;;c;w}E@OA;U*TCgBt z!$y8V)5IaYF5D_O{SZCP%6IMugsHIjBPBn3+I}L8PGY>R8u{opCQxC&B2bm4@FO)h zC$D8S)tp3ZtaQP%5zNT2Q<;82U`jbUbEDT&j|F=C34E980t6uu9`#zh11Un4SsdI( z!gRpDR~BUqX(tWA$_9FbvQ919HG$2r<8c!X1@GAz zr$P$5feloNq`Q;TqZs#wvYgu3jN9_e^37=WvVQY@N&2{BZ}J8br^`TL?wbXpO`=YW zbhH|*a@%4oLNSU7ztDiY)Ct7^DCeos)J;VelxETnVYX!Nf3E2cr*G;I&f$|Fp@l3a zG4h}zE=}>SFU3CJ58qfwcl*D0lmBc&W*0_4#}xK0!k3EgMMdx5Vq0XtK9+LK?nGcU zt)W21XQ7Bd@m8aA*%_5dOvLT?r$w2K95o}@5XDp_5Xe5`!bpq|(YezZJ$uk;(}(2F zEWV*mKL|-~fEca)r3)*kw}AaD4~(*O7Y(+n4s&D1`>QF9-dF{AnP*@tq*GpPi@?wg z>z=B#^K-22lyn@bRS3&QjS#*pk^gP2Zw0EvS7r@`rm&7EWlp0s@L=TXY&QD)?hHI) ze}w#rydP_USEf!#Vw}+51p1HuJWvp0@hLax$uRf>egV5(fLmaqNb@C*E!ga*eBO~5KyDzy{GVS3Uh?4lTxKq*YV;^N9&VFxLa zB0jtd(bOPj3PwTikzep^uBW9Mvhy?UWo3}1sYapnoQo*XBuF@NGVM(86wGYb zO%Y;V_Ya7iYxW4xO5*3SM6AUyk@TMOxABel`j^oBq=sLEOqdJ&IT+4((o9Df?z)a~ zQ!P-?e^RRfY>jRv3aI29FLGpwpNvZD!o&eQRwmru9pW zfCr82p0k*M(1GPnd2Rbd9H|MlX~#X#-(NieVeFUwMjMAp+$n?M2EXq=FA4u=V z!-Dx&e^IzB%w;Knt%p1s=rMZiY&S+jY(md4zrC#7>EX59rLJY#*vLG$x&-W-8ztS@ zG7S$p>fPSjT(!|-5zCysm|<0%)J^+Kj}@|M=ALI^he29mOyvjN$XQ{|(2uMXwROU-zmd@O&+`=UIwV9KMoph63$ALKF z_qUfgB|-di1sHCOC$YR$0=C9srNP3bgPv3J`=mtsdA*PYE&_9+B-ooYk_585M9_qx zjssTw*j8;{)dYw9YTDHY8LXsYPPUxLUn2;gA4lx4TO;Gv?6!nIFeJvcfq~e zCN@xNUI(A0KcKPq5=;JaVL3HSYLS{EI~M{Yb!_C;&bAKe+rD)zU!CCi84+Z25K>4= zIm@&_jGNp%*yy{P+FlBbYOTJ@<*LrfM)iIz0G3sJ-V1UkuPiad?9~>I!nY5NS1HB* zAp$0a@?!i{$@~W}xca6ngIY*5G8_vMrWkc_s*?FLfw!yNGqgaj_!-qfkBKU_rVopO zxVGSpL5WJ%3URtB>EESD3WG3uhz1zdr3alM3lVG&S^N|bP7hHie6O8H234%0b6dj> z@xtC|pupNHsS$7-<5d3#uu~<4jQAp};R23tF9yfRK&7r6A+@KCgE0J2(3uzMEzMg0 z2#q zk$Yj*putvhExnL4&XFd-%g?z+)iD-%CBmG#jum99(aga1(iDJ(tlZBay23_cyj2^= z<6w$Jp+Re#R{$n23dO6aiIMd>e>YV0&%?qGlqwAC*<|(&lKmV@MeF>6Go5RgUPY|jZutZt;uJa>2icP9;mSkREJ16qalS0t6>`J z<~U@#AU|7ZAjWbN6!p)WTAsUX#Vvx+@N=6pI_{RLjj*LvE1B%646;euFtPQ%_KOv1H;z(BSH6H4a z%=EA_5_K`hnw2pWua6yMDWrJd0l0J0YemMGC`PnyqczHe1#5#UtT8DH8FXuiHBGD^ zx%vv0jK6_UpjjYDU_g9_BcO|sEzGsCLowzAGTk?xCRe7QdRN(O&zOGET#3r~hblCw zNxhk@L!meU$9-lU3=DXC(^!qN*RLDk%G`}1ZV$HSf*9g5s;?{(aLOB9lL-Z}JIk_; z?4w+LS+!yc!PH+vCGz0x;235N;{K8l!Iyuj{^_m4Nci6!(yx(!MQ>qqN|q3n=yO|G zua(ePKLKlF)^-$i(Uf*OQQ|u<5G$QgkJ?z@hUZt@Jz<2xHEdc>MqB8@J#viOu*54T zfS&Sg&H9g9JCl<3l*>2p)NUqTgs6r(I6% zb7RYzd~y`;J+Ex24#`gA*jlQY%=RG0Zz&WNaVunNfg4xcIXd#8!Aa}F&M*0jd@Udi zbdW?=RWALizA~ksg1I2y<8SLiAhLQt25*!^kNTZ%Heh+t{)16^6`jeFsp)q3ZC#RV zj7t6hWwILLQFnwIb8?xI0$C4pLqW&u2i6L&YUY1WQK|qW45JiWIeCVgVwA8trIsGr1WU=DX+{k znL(IVo|J)j_$-x-`ffa(ZBJ!EitKxx2UXc+I*0QtsYKbet*bW;mV8TRpZ?I0$uCQW1`BB0O#z-WqI)iB~jHx(6WdYJC@aInPYt`P4S4eLa`{zT*lXh z4t2Kryq9nOm<;Rqo9P{?WVfiPdO84?^kXd2 zpVkM(JIf;t7;c66!HvZ7MLfG%Ea%@;`e)}5_%4*xuGpZFw_g)9u)!{~(>(u;vl}09 zlan&;rLBs=h|-I9iJD_{lU>4B)P80j45psNd}u;*2;z{A4Q7_AT_&S#v?P;OJ^eIj zXZts8o32^!!){o=G&;0i!potsjj2<$@~~7tukbKAxg-5t9=L4l`_+1v`&^rXE{8en z1LZ(Usc+74hih6kft}9w=p-d=`(lmt2#L#Wokf_Oa^4>2{#I4A_Zqc^Xjw$8w!eRA z40gn+Jlrd4Y9$u2H4}gJwt{$;^#pC&tUw(LCwoMgc#EFkK z3s%<;@y%Bxj|-$j$$JLs{LqIQCbTwxx&^eOp#gd)ed}&;&SrnP)L33PVyEf8Nu)>X zO|31{T;~2tttcx1qjY3u=slwrevYlKRiUuei6*pdD=~~Mf{g+Bgx(~Nf}idDdZU%{6?mpEuf!ecm2u<2yM81FTl^G7%Nuq#wbQoMo5=u;yj!8i(cB+PPYxC`_fOqZZS% z5E6jghdAoKj$(*bXIh>Qk(l0I&7Gi>y8h6`tc+G*NXFw%s+FQ={I$`VlRJ!rIbR(H z`|OzHi~4ozfdU6xT%w^%6f~NpfGcH+LP4K7Vd4nH(Bqoha4J1Z895zwlc;}aE#&ep z1IaTW43Z2n4SM*OD8rnzXvM9(-$o|G)m6O&1Hb1nAnPlhuHlmE=DFok}6Zc}SiQP4xG<*VBwI))WP?z~j!jq>{Eh zf~z`WqI=42=^R!HudMD{;E3#g|7gT$sFKU%GLG$*7szh(NhR>(0`_G4IkGB8@gi@c zbWz1xP@LdPSBMPBB+Fdkd-I6ptC*fhfeZQ9^Mr?A-I)09LZ=p{6PO}k7&b)AyQV6` zJ_r3lPFKvLCd2o70;pOdOn;Y)!jy=GKxoJ6am?pJ4C`(TSsx9On5|F-wI;Hw8{0WcF7?HCRva)sCg2qGYhriqnNXDL6Xom?>}T z;-bZfM>nkM>^XK1F>L_7rOaJ_LNbW|n0^jCac9Q-&3M)Z4m4V@03IW<`1B#*}fUIZQ`J0SRto(2% zxzJu5URHXhgTif@0I4zu{qU!y%u5wL<}^AuGF|_YlTD9tZhhV5Oi+O%`INro4>2p# zMMc7`2Ns;^^u<*v*UJ2w{m;I34~o4e7ITBmg}pNk2`l^j)h1&Hv2@sQ5CeSEEXDqb zqZ2@r`~6%`HsW$9*kF2yusil?minQTgLF+ZLY$_;iTcLBCg+6Qb_q%2^YxisXPd_{ zjz)G*Q@iOCma|nY(3^{1woi#_ih)(*lLoX z10w|mCr6*|tM8F6B}$OsO~+F4w2;6qaS-lZ#<-rb9*piME|msCym$Ns(_{g}(wi`q zwf|IO@#1CB^JlledRd4MhdEf7aTR`SLA?F@1`IrNhaO+Ge5v84w}M;eB2jE6$O(BMvt`zXv`gtdz(j^&65!M|{Sp zXsAesFO8YW{)<)q6^KiSM`*N;CIeLU$*|`L)pkLD;-kM>*?dHG`&*@f!jA&w(5@qj zl?!@><%8FAamdu~-KWo|#^}h*sz_GWD9}((gCZM6z%37Yk=sO}ks4Z+2z@41V^J9E zR~+HAdgm!Cm>L?-t15wBaNtnZGbCbbuTdhN>^>m@h{txzVx zgC5}m459@`Y-B!2FFYH^|I{wMG-5&(09SM-zjC0(FZcwq2u$J_^n31paDT`DT}jaCob7pOxt+oyLMm1iO5}ZXI821tqYnC3$V5Qk zBurI+Wleo&Oz5E-4eQ}up9y1`ny)f8VmAJ{6i)Ql z*RteBPM}1YSVS3It%V=hs7uVkK+FCdOfDhhXs9E`3{lWyUfQQWmr0am4jE^|JhvNW z{EvvP+Ce3ri!JpFklRC&0GCZSG^$1+KO=xt^L&jA3-Zl~cHGM>VE4yf_@8z@ZDIc~ z_>eJ6T+Fk}fAsGS#_w}3h+#VlCy2teh(4`NyHcK=U$`TmkjcJQ8r()II9ALzhTY^s+0eUQC0<|C2sg<8}C?}ym!FJg13;Pfyvp^mdKV9{>$;as) z3XjsT!kCe?KvVKNMlO(-^Ec6TrP9)=sLUmn->?5r9viWPUn?skPw#r@)U`(;*eD5Siot2Sth-Wz{tiaUZ%jK-M5P3E9xEIHZU^tlWw%xstH(9-CL zBNua>Q_exGYzup%YBb1Fcvw_M%C?$bu*-hnnXikp7Zk+(>;D9#5nJvCQpX%t)3=Ya`6&KjQ z$+jX?)fGn`X`L5tOXa){ApO~tn(m_sPu*LCMbYsVRV+#KBC23mnMV~~MCJI}d(~=i ziBu^gjCd;Fp*~CIsf0F=BN@!LUvf$IQ%E|HU0d{a zTu8yQ7a_o%dD{R7SOq>4tI0k_tR7eO2X+H;At#;&0=CRS!8tvP3dn1sU&tZdVnLIx zxP3~FhgkOcq-G39-Nm-uSQIo_w@E;LVupW?H!5`#1cysCx<1k!toA%~=3eyDYT z^UtZOO5q9FUSPMpK5it8BZSgqT^TT4LD`CmE`|{y(`?iNfC&+gt2gW=hRloHAt%K+ z`)udW444;Um z(WqfUb242~9`pI70xXYL( zP*do9+|61;94zrd$BB5a$jWKSp2kmBc5~YXr>E}9bP@sc zT9KL&-Yh@#uR%pXiN<}XSf9mmo~Ht_zXw;I9U3U-YO)9ER|{FsnkHEn9l2-8B$Nba zgp0G<5wS`bh>{Xuy1=LKjIn`JlqcjUjw{N^7`ao#4?d_nl*zA_`MCh!%{UbHfbZo> zlo_ycgc0{egkZY?{hE=9kaYUIKR|;6-C(3}4C_#g;ZdLNtP$f{d&*5jozwi-KmqG^ zcK+%tr{LhcnG7;^AB#I^kmb^`%Nb>cocM$ikGk9*nbPM@e&|sw%WOVw_pzPA{{V(q zz}`+XqvWpnnM^)j8tezj4S;xP>0m>S4OE~bmnidQW4L;-(IrG0cd5_9ln_cF zVbd}v@>S>t4lpCV$L@%hAlbs77}3mQG6X&bPYs&@+pV8M`EQW~AgUlyWe;F^tY*V5 zE;Z1L35oA7P6=rb>XFAshPNB)CBQH_EdJ@Wi$Hfwar|TPXC>f0Ev0ZrE@GEV*IpuY zK3QDwz+q6a0rL9v6u>rnC=l>W`?0}DFpIcrB4S1YC!VXTG0MqD2^cTTT#HMOzfJi( z-{d&0fFa6diohVe`?1rG+aw}KHXEb$NNWqHs#dWuom#@5%0u>>I3zNv5q>yfpW>SA zOOL_}H}Q3z&1_-xiJ#vp(OEDAOu11$?w(XQkx9e(qHr=1C&!y0o#h<*Y4#36D3YJN z3gCg@Vw^G)KHC#%i{ody=;xEqKU2Wyj4{txtH9KbE0$IFb;&jP_AR z8b|^m7AY~AOsXtY<-4)$R43{@6{us z4B%{!-5z}?4P+%$yj(^&4G>)L@nFLV5mpFHAmQ_8B!*zey4O>YpgWE$GbPumP)Q~m zCG>f}QnPL2;W1w5GMs>F1WfRaP?C)(!y2TZs6b6Yn}Pk<^Hh#ZpW3vg`DCk!$E5!1 zig=L8NkRF`p%h|llayxE36aaym3bRAqW4G6DX}*JO4c6`Ad!K{n(2TBjKM#;34&nI zoUfe691ahT4`i`#3(HMv-uVKtPX>C*rZS zk%`nlL3T|{4joUVYI!LXBuIGoP7qU%GdngoRtWCxIt7-Dhr1HsBTnkWDb33}-I5Q< zcnUI(O-L`5OnxjJe*_=98U@@B$P^Mms5pIct_iV~D4$D|P~=}MA2g#W4*QGKNI{M! z&6?@hS<*wJYuuy2T<3+jA&QOw@xv6z_qy_s(-|Vb5MPQd9$>FdF33;fuuvpIaqv?? z$rvGE&uQhV`x?h)r-GISjF@6g4TvPl5 zUUk5~U`O*rJ3ueRR?iM~P=63q-6B`+H7aUA21u|BM0!g@4r7XLjU{6Tb~R>!oDpW= z2S+z>6EM&>t&to&R)IeSYRQ1}Sa{tW9)2%~qPY)2^wXsw8(=sBl3WpdMN@a%PcPIyK*&Qumm2H-E{ZG)~kW|oinw*;4k2#NxU-%U}%7V@l=Ww zz#iH&YC@6%3FE~xIm&ti`ZRk#Dy-@T3Z2<1fW3loKo8lgdxFC`O2~fig%nVJE`i3F zA>i!#rKSP&=xX$Qhls1wATD{lxe8@8V{l0Lvrb3^{{WyDB=}DqVI{CSs zu)zMB3+RCUlwyTT$(Qs{;MOq-6F_PsIQBhMO4KAmb|f}??p0CuQ8?WvjH{POX)X_@ zECZp11%*_5WUc}*7>|lN3@3-0>?r)!B(hv@Gtj9~Q!D-t7BBvRll5b>QuAE;Cz@;u z-Xuy#<_Wt{p!@#-Cb-~C!_PKa`Dyn3S9i^qsY{+BqV$>|NipoOiO-+js+X(3gqugEU-<}ZBf(*ghb>|`tpmXQUn3vPyyuG}5d~h&L@~lPTR|iM zoQtW6vQ;&nCGk8|25!-dBk>^qtLcd(2yr(|NZdS!%?oc-Nv^SFu`cVjSuac`8^;~5h-l?}L zh)bmrB`#)Lcl@gYjRl9JXs`B$4ls>&4?m;P|VyeGJda`a(^@%)`{g> zLL znjeZWJn~Ej;iV+2?<^qxZtpS{WXOS$LoH0CFdOKb%*U-e!(qfiZ~p)S;Gvyf-XXcZ zYy)v;Dpb8P;Wr>uk;z6gAtR=u&QN)~WU3aUm5?~KLXtc;h=2-dCvz{|N$LPu9@>!~ zldYXN>@@jlFjL%7X*;AJsxujavZ1fyp-F;qj;!xPyJFgZG^YoO%wqYW4tmX%%VQW8 zLyW4P6IZV5oF;3jE=a^Z1laKT@N)d~LU?Hao--;2fDAJCf87ib!DgQzKSx6z4krEO&rW0DDXU(LB6Yt@vq7v zN}@4G7&uQBOIFTsGtrfPia0~BLMz>1gIEq?v4+h9N?=@+P^|I^#%q|^1GRgh0Qoa# zCMPCV9mU&aAqpbKw^2wFtfv4bBp7)3su1tZaa_ELe->_~L&|sV`(BQ$iCw6tLOvv_ z!$piaU)fJ54=vdWd#rwUT5C}=!XT%`wiaXN@YxSd2)Z1_K2OPcuaK>3=UgZ{QhlWl z&CDeO9Gs(xhVBA5txI8LDFQgDUIb7`F@uUt?stx}>c;FY471TRyz>K)MNODD6Tv6L zUXvWjjd=*c%UU4s{v*&RuKm^iRTFkK_HEG)~YDnf(`>x z%uUhsO&nD=)eIiuOU+~-yAF=;t+Wi`q)|V*qzUR`8}7Ks0CWV0r5UATLP|yinMjlmwU9(gr1j@3 z#2=a*7FRRqyB1pnB_S#KU2jQ2lEI)LA(nhIP(#EC#;kjRQ?9ZbaEMU8%HBN7MmE=6xnX!S?{Ujr7Z5H7)1 z{;7V1&W{?EtOE1QxAF>lh%xv=zS3DmnMdWRK*~seDx}2l#LN*E6w;TXj2ct`CYfWH zq8M2i+2G5+ho5V~J;#lqCkqySTvnj&D2SF{Rnb73F)FxoShCzK&V&~bBuq7-U5u*2 z87cax3yb2T8vGR@T``WXqZ!LJTNI85F0QG(DW;f_CpI)RR)P)Bs`D~gWXKsKECV4g z%^`* Date: Fri, 5 May 2023 08:56:25 -0700 Subject: [PATCH 2/2] Moved each design into it's on file for clarity; Expanded more on the custom widget design & API, finished a rough prototype; Made it more clear what the final API exposed to the user would be in each design case --- text/23-custom-pipelines.md | 213 ++++++++-------------------- text/designs/23-01-pointer.md | 168 ++++++++++++++++++++++ text/designs/23-02-widget.md | 92 ++++++++++++ text/designs/23-03-multi-backend.md | 110 ++++++++++++++ 4 files changed, 431 insertions(+), 152 deletions(-) create mode 100644 text/designs/23-01-pointer.md create mode 100644 text/designs/23-02-widget.md create mode 100644 text/designs/23-03-multi-backend.md diff --git a/text/23-custom-pipelines.md b/text/23-custom-pipelines.md index bb7923f..7e10d42 100644 --- a/text/23-custom-pipelines.md +++ b/text/23-custom-pipelines.md @@ -55,124 +55,55 @@ hops? Could we do this with a minimal unsafe abstraction layer? Should we even d ![](silvia.jpeg) As you can see, this is a somewhat complex topic with a lot of tradeoffs between implementation strategies. Of -course, I would love if there was a better idea floating around out there that I haven't thought of! That being -said, **here are some of the concepts that you will need to understand before you can understand what this -RFC aims to address.** +course, I would love if there was a better idea floating around out there that I haven't thought of! That being said, +here are a few different designs & their concepts that would need to be introduced to Iced. I've broken them into +their own markdown files for an easier time reading! -πŸ–Ό **Custom Pipelines** +1) [Custom Primitive Pointer Design](designs/23-01-pointer.md) +2) [Custom Shader Widget Design](designs/23-02-widget.md) +3) [Multi-Backend Design](designs/23-03-multi-backend.md) -This is essentially just a regular ol' wgpu pipeline implementation, except one that isn't already integrated into -Iced! This can be as simple or complex as you want it to be. For example, in a prototype that I made to render a -simple triangle, this was as simple as this struct: - -```rust -pub struct CustomPipeline { - pipeline: wgpu::RenderPipeline, - vertices: wgpu::Buffer, -} -``` - -In Iced, `Primitive`s are mapped internally to the appropriate pipeline, though have no direct relationship to each -other (for instance, a `Pipeline` doesn't have a primitive type `P`). Each is chosen manually for what is -appropriate. There is currently also no abstraction for what a `Pipeline` actually is; by their nature they are all -somewhat unique from each other, with minor underlying similarities (for example, every render pipeline must at some -point allocate some data to a `wgpu::Buffer` & submit a `draw` command). +All of these designs must be flagged under `wgpu`, unless we wanted to do some kind of fallback for tiny-skia which +I don't think is viable. What would we fall back to for the software renderer if a user tries to render a 3D object, +which tiny-skia does not support? Blue screen? :P +Overall, I'm the most happy with design #3 and think that it offers the most flexibility for advanced users to +truly render anything they want. -πŸ’  **Custom Primitives** -What, exactly, pray tell, are we rendering? Ultimately this is some chunk of data that gets used by a custom -pipeline. This could take the form of data that's passed directly to the existing `Primitive` enum (like -current `Primitive`s are), or something as simple as a single pointer. - -One implementation might mean that a custom primitive could be defined within the existing `Primitive` enum as just a -pointer to some pipeline state that implements certain methods required for rendering. - -```rust -pub enum Primitive { - //..., - Custom { - id: u64, // a pipeline reference ID - pipeline_init: fn(device: &wgpu::Device, format: wgpu::TextureFormat) -> Box, - // where "Renderable" defines a set of methods necessary for drawing - } -} -``` - -Another implementation might define a custom primitive as a generic type that is unique to a `Renderer` or `Backend`. +## 🎯 Implementation strategy -```rust -pub trait Backend { - //... -} -``` +### πŸ™Œ #1: Custom Primitive Pointer Design -πŸ§… **Layers** +Behind the scenes, this would require very little changes to Iced! -In Iced, layering currently happens at the presentation level. Primitives are submitted to the `Renderer` in a -queue-like fashion, and are then grouped before being drawn back to front. This allows primitives that are meant to be -rendered together to be transformed together, somewhat like a scene. For example, when clipping primitives let's -say in a `Canvas`, this will create a new layer. Note that every layer added to the layer stack will incur -additional performance costs with pipeline switching & extra draw commands submitted to the GPU! +A `Primitive::Custom` variant would need to be added to the existing `iced_graphics::Primitive` enum, in order to +have a way to pass a pipeline pointer to the `Renderer` and indicate its proper order in the primitive stack. -When considering a layering approach for custom primitives, we must think about how they are processed. Should a -custom primitive be included in the existing `iced_wgpu::Layer` with some sort of ID matching? +We would also need to add a new field to an `iced_wgpu::Layer`, something along the lines of: ```rust pub struct Layer<'a> { - //... - // some kind of reference to what can be rendered in this layer that - // we can match to a pipeline - custom: Vec, + //... + custom: Vec, } ``` -Or perhaps we should enforce that all custom pipelines must group its supported primitives within its own layer? -This needs some considering, but could be implemented further down the line as an optimization. - -## 🎯 Implementation strategy - -I've gone through a few ~~hundred~~ dozen implementation strategies. I'll share a few here: - -### 🀾 Just throw a pointer at the `Renderer` - -You can view a small, very, *very* rough and unrefined prototype of this strategy [here](https://github.com/bungoboingo/iced/tree/custom-shader/pipeline-marker/examples/custom_shader/src). - -This example has a pointer-based approach, where the "state" of a pipeline & its associated primitive data is just -stored as a heap allocated pointer within the existing `iced_wgpu::Backend`. Within a custom widget's `draw`, -primitives are drawn like this: - -```rust -//... - renderer.draw_primitive(Primitive::Custom { - bounds, - pipeline: CustomPipeline { - id: self.id, - init: State::init, - }, - }) -``` - -Where `State::init` is a fn pointer with type signature: -```rust -pub init: fn(device: &wgpu::Device, format: wgpu::TextureFormat,) -> Box -``` +To indicate which pipelines are grouped within this layer. Or perhaps we could require that all custom pipelines are +on separate layers, though that has performance implications. -`Renderable` refers to a trait which allows a custom pipeline to call `prepare()` (for preparing data for -rendering, similar to how we are doing it in every other pipeline we support in our existing `iced_wgpu::Backend`, e. -g. allocating & resizing wgpu buffers, writing uniform values, etc.). +We would also need a way to cache & perform lookups for trait objects which implement `Renderable`; in my prototype +I've simply used a `HashMap` inside of the `iced_wgpu::Backend`. -`Primitive::Custom` is then processed for inclusion in an `iced_wgpu::Layer`, where (if not already initialized) -it's initialization (`init` above) is performed & added to a lookup map in the `iced_wgpu::Backend`. Then, come -render time, if there are any `custom_primitives` within the `iced_wgpu::Layer`, we simply do a lookup for its -pipeline pointer & call `prepare()` and `render()` as needed. +Then, when rendering during frame presentation, we simply perform a lookup for the `PipelineId`s contains within the +`Layer`, and perform their `prepare()` and `render()` methods. Done! -βœ… **Pros of this strategy:** +βœ… **Pros of this design:** - Simple to integrate into existing Iced infrastructure without major refactors. - Performance is acceptable -❌ **Cons of this strategy:** +❌ **Cons of this design:** - Not flexible - Even with preparing this very simple example I found myself needing to adjust the `Renderable` trait to give me @@ -185,30 +116,19 @@ pipeline pointer & call `prepare()` and `render()` as needed. Overall I'm pretty unhappy with this implementation strategy, and feel as though it's too narrow for creating a truly flexible & modular system of adding custom shaders & pipelines to Iced. -### 🎨 Custom Shader Widget +### 🎨 #2: Custom Shader Widget -Similar to how we currently have `Canvas` in Iced, this strategy would involve creating a custom widget which is -dependent on `wgpu` that has its own `Program` where a user can define how to render their own custom primitive. +The internals for this custom shader widget are very similar to the previous strategy; the main difference is that +internally, *we* would create the custom primitive which holds the pointer to the pipeline data, not the user. The +other difference is that the `Program` trait is merged with the `Renderable` trait, and that we create the widget +implementation for the user, no custom widget required. -A custom shader widget might have a method that is defined like: +Other concepts must be added, like the concept of `Time` in a render pass. In my prototype, I've implemented it at +the `wgpu::Backend` level, but in its final form we would need to shift it up to the `Compositor` level, I believe. +It's exposed to the user as a simple `Duration`, which is calculated from the difference between when the +`iced_wgpu::Backend` is initialized up until that frame. -```rust -pub trait Program { - type State: Default + 'static; - - fn render( - &self, - state: &Self::State, - device: &wgpu::Device, - encoder: &mut wgpu::CommandEncoder, - //... - ); -``` - -Or something similar, which, when implemented, would allow a user to define how to render their custom `State`. I -found that with this strategy, a `Primtive::Custom` wrapper of some kind was still needed, which ended up being -pretty similar to the previous strategy and just replacing `iced_graphics::Renderable` with -`iced_graphics::custom::Program`, so I did not finish a fully flushed out prototype. +There may be other information needed in the `Program` trait which is discovered as the implementation evolves. βœ… **Pros:** @@ -217,64 +137,52 @@ pretty similar to the previous strategy and just replacing `iced_graphics::Rende And, like the previous strategy: - Simple to integrate into existing Iced infrastructure without major refactors. -- Performance is acceptable, but worse than previous strategy +- Performance is acceptable ❌ **Cons:** - Same cons as the previous strategy; very little flexibility, users must shoehorn their pipeline code to fit into - this very specific trait `Program` provided by Iced. -- When I was prototyping this out, I found it nearly impossible to do this implementation without doing some kind of - reflection with `Program::State` in addition to the required dynamic dispatching. This could possibly not be a - real con as there might be a different, more performant way to do it! + this very specific trait `Program` provided by Iced. ### πŸ”  Multiple Backend Support for Compositors -I have no prototype to speak of this with strategy; it will involve a good amount of restructuring, possibly some -codegen for performance reasons, and some intermediate data structures added to the compositor. That being said, I -believe this is more along the lines of a "correct" solution for integrating custom shaders & pipelines into Iced as -it allows the most flexibility & feels the least hacky. - -This strategy involves adding support for multiple `Backend`s per `Compositor`. See the diagram below for a rough -outline of how it would work: - -![](diagram.png) - -Every `Backend` (probably should be renamed to something more appropriate, like `Pipelines` or `PipelineManager` or -something for clarity) would be responsible for its own primitive type that it can support. In the case of -`iced_wgpu::Backend`, this would be the `iced_graphics::Primitive` enum. The command encoder would be passed down -into every backend for recording before being submitted to the GPU. - -This would require a few new concepts added to the wgpu `Compositor`: +Internally, this design is the most complex and requires the most changes to Iced, but I don't think it's so wildly +complex that it would be hard to maintain! This design would require a few new concepts added to the wgpu `Compositor`: πŸ’  **Primitive Queue** -There must be a backend-aware queue which keeps track of the actual ordering of how primitives should be -rendered across all backends. I believe this could be implemented fairly easily either by having each `Backend` keep -track of its own queue and having some data structure delegate at the appropriate moment with some form of marker -indicating that we need to start rendering on another `Backend`. Some kind of order-tracking data structure is +There must be a backend-aware queue which keeps track of the actual ordering of how primitives should be +rendered across all backends. I believe this could be implemented fairly easily either by having each `Backend` keep +track of its own queue and having some data structure delegate at the appropriate moment with some form of marker +indicating that we need to start rendering on another `Backend`. Some kind of order-tracking data structure is essential for ensuring proper rendering order when there are multiple backends. Widgets would request that their custom primitives be added to this queue when calling `renderer.draw_primitive()`. πŸ‘¨β€πŸ’Ό **Backend "Manager"** -This would essentially be responsible for initializing all the backends (lazily, perhaps!) & delegating the proper -primitives to the multiple `Backend`s for rendering. This would be initialized with the `Compositor` on application +This would essentially be responsible for initializing all the backends (lazily, perhaps!) & delegating the proper +primitives to the multiple `Backend`s for rendering. This would be initialized with the `Compositor` on application start. +πŸ‘¨β€πŸ’» **Declarative backends!() macro** + +This would be initialized in `Application::run()` as a parameter, or could be exposed somewhere else potentially +(perhaps as an associated type of `Application`?). I haven't super thoroughly thought it through, but my initial +idea is to have it return a `backend::Manager` from its `TokenStream` which would be moved into the `Compositor`. + βœ… **Pros:** - Flexible, users can do whatever they want with their own custom `Backend`. - Modular & additive; users can create a custom `Backend` library with their own primitives that it supports that can be initialized with the `Compositor`. -- For users wanting to use a custom primitive from another library, or one they made, they would use it very - similarly to how you use currently supported `Primitive`s in Iced, which would feel intuitive. +- For users wanting to use a custom primitive from another library, or one they made, they would use it exactly how + you use currently supported `Primitive`s in Iced, which would feel intuitive. ❌ **Cons:** -- Doing this strategy performantly without creating a bunch of trait objects might be challenging! At least just - from thinking about it for a few days I've not come up with that many ideas other than using a hefty amount of - codegen via generics or declarative macros. +- Would involve a hefty amount of codegen to do performantly - This would be quite a heavy refactor for the `iced_wgpu::Compositor`! -- This would (possibly?) preclude custom primitives being grouped together with other backend's primitives in - its own `Layer` for transformations, scaling, etc. which might be undesirable. +- This design would preclude custom primitives being clipped together with other backend's primitives in + its own `Layer` for transformations, scaling, etc. which might be undesirable. There might be a way to implement + this within the `backend::Manager`, however! ### πŸ€” Other Ideas @@ -370,4 +278,5 @@ and use seamlessly as part of Iced's widget tree is the ultimate form of customi ### If you made it to the end, congratulations! πŸ₯³ -Now, let's discuss! \ No newline at end of file +Now, let's discuss! + diff --git a/text/designs/23-01-pointer.md b/text/designs/23-01-pointer.md new file mode 100644 index 0000000..11e6bcd --- /dev/null +++ b/text/designs/23-01-pointer.md @@ -0,0 +1,168 @@ +# πŸ™Œ #1: Custom Primitive Pointer Design + +You can view a small, very, *very* rough and unrefined prototype of this design [here](https://github.com/bungoboingo/iced/tree/custom-shader/pipeline-marker/examples/custom_shader/src). + +The design of this implementation focuses on providing a fn pointer which both initializes the state of a custom +pipeline, and returns a pointer to that state so the backend can cache & reuse. We would need to expose a type of +trait which has methods necessary for rendering, something along the lines of: + +```rust +pub trait Renderable { + fn prepare( + &mut self, + _device: &wgpu::Device, + _queue: &wgpu::Queue, + _encoder: &mut wgpu::CommandEncoder, + _scale_factor: f32, + _transformation: Transformation, + _time: Duration, //used for shader animations, calculated every frame + ); + + fn render( + &self, + encoder: &mut wgpu::CommandEncoder, + _device: &wgpu::Device, + _target: &wgpu::TextureView, + _clear_color: Option, + _scale_factor: f32, + _target_size: Size, + // final implementation may contain more information + ); +} +``` +And have the ability to initialize a pipeline & retrieve a pointer to it's state: + +```rust +pub init: fn( + device: &wgpu::Device, + format: wgpu::TextureFormat, +) -> Box; +``` + +Which would need to be stored in a `Primitive`, e.g. `Primitive::Custom`, which could be used by a user like this: + +```rust + renderer.draw_primitive(Primitive::Custom { + bounds, + pipeline: CustomPipeline { + id: self.id, // a pipeline identifier so we can look up the data pointer + init: State::init, // an initialization fn pointer which returns a pointer to the pipeline data + }, + }) +``` + +This would be the entirety of the API exposed to a user of Iced. The rest of the implementation details would be +handled internally by the wgpu `Backend`. + +For example, a typical implementation from a user in this "hands off" scenario might look something like this: + +```rust +pub struct Pipeline { + pipeline: wgpu::RenderPipeline, + vertices: wgpu::Buffer, + indices: wgpu::Buffer, + // ... +} + +impl Pipeline { + // We must provide a way for the Renderer to initialize this pipeline since it needs to hold a + // pointer to this `State` + fn init( + device: &wgpu::Device, + format: wgpu::TextureFormat, + target_size: Size, + ) -> Box { + let vertices = device.create_buffer(&wgpu::BufferDescriptor { + label: Some("cubes vertex buffer"), + size: std::mem::size_of::<[Vertex3D; 8]>() as u64, + usage: wgpu::BufferUsages::VERTEX | wgpu::BufferUsages::COPY_DST, + mapped_at_creation: false, + }); + + //... rest of the wgpu pipeline initialization omitted for brevity! + + Box::new(Self { + pipeline, + vertices, + indices, + }) + } +} + +/// Implement the "renderable" trait for this `State` struct +impl Renderable for Pipeline { + fn prepare( + &mut self, + _device: &wgpu::Device, + _queue: &wgpu::Queue, + _encoder: &mut wgpu::CommandEncoder, + _scale_factor: f32, + _transformation: Transformation, + _time: Duration, + ) { + // Allocate what data you want to render + let mut cube = Cube::new(); + queue.write_buffer(&self.vertices, 0, bytemuck::bytes_of(&cube)); + } + + fn render( + &self, + encoder: &mut wgpu::CommandEncoder, + _device: &wgpu::Device, + _target: &wgpu::TextureView, + _clear_color: Option, + _scale_factor: f32, + _target_size: Size, + ) { + let mut render_pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor { + /// omitted for brevity + }); + + render_pass.set_pipeline(&self.pipeline); + // issues command to the render_pass + } +} + +/// Include the custom "primitive" into a custom widget +struct Cubes { + height: Length, + width: Length, + id: u64, // a pipeline identifier +} + +impl Widget> for Cubes { + // ... + + fn draw( + &self, + _state: &Tree, + renderer: &mut iced_graphics::Renderer, + _theme: &T, + _style: &Style, + layout: Layout<'_>, + _cursor_position: Point, + _viewport: &Rectangle, + ) { + ///.. + /// now pass the pointer to the renderer along with a unique pipeline ID for caching & lookup + renderer.draw_primitive(Primitive::Custom { + bounds, + pipeline: CustomPipeline { + id: self.id, + init: Pipeline::init, + }, + }) + } +} +``` + +```rust +/// In your application code.. +fn view(&self) -> Element<'_, Self::Message, Renderer> { + Cubes::new() // Initiate your custom widget which draws a custom primitive + .width(Length::Fill) + .height(Length::Fill) + .id(0) // set a pipeline ID so we can store a pointer to a specific "renderable" state + .into() +} +``` \ No newline at end of file diff --git a/text/designs/23-02-widget.md b/text/designs/23-02-widget.md new file mode 100644 index 0000000..3e850c2 --- /dev/null +++ b/text/designs/23-02-widget.md @@ -0,0 +1,92 @@ +# 🎨 #2: Custom Shader Widget + +You can view a rough prototype of this strategy here: [here](https://github.com/bungoboingo/iced/tree/custom-shader/widget/examples/custom_shader/src) + +Similar to how we currently have `Canvas` in Iced, this design would involve exposing a new built-in widget which is +dependent on `wgpu` that has its own `Program` where a user can define how to render their own data. + +A custom shader widget might have a `Program` trait similar to a `canvas::Program`, but with methods from the +`Renderable` trait from strategy #1. + +```rust +pub trait Program { + fn update( + &mut self, + _event: Event, + _bounds: Rectangle, + _cursor: Cursor, + _device: &wgpu::Device, + _queue: &wgpu::Queue, + _encoder: &mut wgpu::CommandEncoder, + _scale_factor: f32, + _transformation: Transformation, + _time: Duration, + ) -> (event::Status, Option); + + fn render( + &self, + _encoder: &mut wgpu::CommandEncoder, + _device: &wgpu::Device, + _target: &wgpu::TextureView, + _clear_color: Option, + _scale_factor: f32, + _target_size: Size, + ) -> RenderStatus; + + fn mouse_interaction( + &self, + _state: &Self::State, + _bounds: Rectangle, + _cursor: Cursor, + ) -> mouse::Interaction { + mouse::Interaction::default() + } + + //possibly some more needed methods +} +``` + +Similar to `Canvas`, but without a `draw()` method; instead there is a `render()` method which returns a new enum, +`RenderStatus` (name TBD). Might need to change the name `Program`, as `Shader::Program` is an overloaded term! + +Users would return either `RenderStatus::Done` or `RenderStatus::Redraw` to indicate their render operation either +can wait to be redrawn until the next application update, or must be redrawn immediately. This is the case when a +shader has an animation. + +New to Iced & a parameter of the `update()` method is the concept of `time`. This is simply a duration of time that +has passed since the start of the application. This can be used to animate shaders (see my prototype above for an +example!). + +We will probably also end up using an associated `State` type similar to `Canvas` for handling internal state mutation. + +A user will create a new custom shader widget using the `Shader` widget implementation in `iced_graphics`. + +```rust +pub struct Shader { + width: Length, + height: Length, + init: fn( + device: &wgpu::Device, + format: wgpu::TextureFormat, + target_size: Size, + ) -> Box, + id: u64, //unique pipeline ID + //properties subject to change! +} +``` + +This provides the `Program` pointer, similar to the "custom primitive pointer design" I've listed in the previous file. +Users will simply implement the `Program` trait for their own data structure & pass the initializer to the `Shader` +widget. + +```rust + fn view(&self) -> Element<'_, Self::Message, Renderer> { + Shader::new(Pipeline::init, 0) + .width(Length::Fill) + .height(Length::Fill) + .into() + } +``` + +Where `Pipeline::init` creates the pipeline code for wgpu. This is about all that is exposed to a user of the +library! The rest is internal implementation details. diff --git a/text/designs/23-03-multi-backend.md b/text/designs/23-03-multi-backend.md new file mode 100644 index 0000000..b92d026 --- /dev/null +++ b/text/designs/23-03-multi-backend.md @@ -0,0 +1,110 @@ +# πŸ”  Multiple Backend Support for Compositors + +I have no prototype to speak of this with strategy; it will involve a good amount of restructuring, possibly some +codegen for performance reasons, and some intermediate data structures added to the compositor. That being said, I +believe this is more along the lines of a "correct" solution for integrating custom shaders & pipelines into Iced as +it allows the most flexibility & feels the least hacky. + +This strategy involves adding support for multiple `Backend`s per `Compositor`. See the diagram below for a rough +outline of how it would work: + +![](diagram.png) + +A user or library author would be responsible for creating their own `Backend` data structure that handles +all primitives of a certain type. + +```rust +struct CustomBackend { + // pipelines that the user has created! + pipeline_3d: Pipeline3D, + //... +} + +impl Backend for CustomBackend { + type Primitive = CustomPrimitive; + type Layer = CustomLayer; +} + +pub enum CustomPrimitive { + Sphere(Sphere), + Cube(Cube), + //... +} + +struct CustomLayer { + pub spheres: Vec, + pub cubes: Vec, + //... +} +``` +This `CustomBackend` would need to implement a certain trait type, here named `Backend`, which could be defined +something like this: + +```rust +pub trait Backend { + type Primitive; + type Layer; + + fn present( + &mut self, + device: &wgpu::Device, + queue: &wgpu::Queue, + encoder: &mut wgpu::CommandEncoder, + clear_color: Option, + format: wgpu::TextureFormat, + frame: &wgpu::TextureView, + primitives: &[Self::Primitive], + viewport: &Viewport, + ); + + fn prepare( + &mut self, + device: &wgpu::Device, + queue: &wgpu::Queue, + encoder: &mut wgpu::CommandEncoder, + scale_factor: f32, + transformation: Transformation, + layers: &[Self::Layer<'_>], + ); + + fn render( + &mut self, + device: &wgpu::Device, + encoder: &mut wgpu::CommandEncoder, + target: &wgpu::TextureView, + clear_color: Option, + scale_factor: f32, + target_size: Size, + layers: &[Self::Layer<'_>], + ); + + // other methods might be needed! +} +``` + +Users would include this send this backend to the Compositor in some way, either at runtime (box'd, dyn'd) with a +`Command`, or I was thinking of a more performant solution involving codegen, either a build script or with a +declarative macro, something like: + +```rust +Application::run( + iced::Settings::default(), + //.. other backends provided by library authors could be added in this declarative macro! + backends!(Iced, CustomBackend, OtherBacked,), +) +``` + +From a user's perspective, that's it! Just including the backend would map it internally to a custom primitive type, +and then they would be able to draw a custom primitive same as any other Iced primitive. + +```rust +//... +renderer.draw_primitive( + CustomPrimitive::Sphere(Sphere { + u_sections: 16, + v_sections: 16, + radius: 4.0, + }) +) +``` +