// ============================================================================= // llimphi-hybrid :: la tercera técnica de rasterización // ----------------------------------------------------------------------------- // Llimphi tiene ya dos rasterizadores y ninguno sirve en el teléfono: // // llimphi-raster vello sobre wgpu — COMPUTE SHADERS. El camino de siempre. // llimphi-cpu vello_cpu — sin GPU del todo. El camino de wawa bare-metal. // // Este es el tercero, y nació de una medición, no de un gusto. El diagnóstico // de `02_ruway/llimphi/android/DIAGNOSTICO.md` probó, cambiando UNA variable // por vez sobre el mismo Redmi Note 13 Pro (Mali-G57 MC2, driver // `libGLES_mali.so v1.r54p1-09bet0`): // // rasterizador backend resultado // ninguno (clear) Vulkan anda · 176 MB GL // vello (compute) Vulkan DEVICE LOST al primer frame · 437 MB GL // vello (compute) GLES SIGABRT en «Vello shader init» // vello_hybrid Vulkan SIGSEGV en cmpbe_v2_compile_multiple_shaders // vello_hybrid GLES ✅ 119 fps · 0,0% negro · 205 MB GL // // O sea: el compilador de shaders de ese driver no digiere el compute de vello // por NINGÚN camino, y sólo digiere los pipelines de render de vello_hybrid por // GLES. Una sola celda de esa matriz llega a la pantalla, y ésta es la pieza // que la usa. // // ## Lo que este crate NO reinventa // // La mitad difícil ya estaba escrita. `vello::Scene` es un buffer CODIFICADO y // `vello_hybrid::Scene` es imperativa y con estado — la misma brecha que // `llimphi-cpu` cerró para vello_cpu, con la misma forma de solución. Así que // acá se reusa su [`Escena`](llimphi_cpu::Escena) grabadora tal cual, y lo // único propio es el reproductor. // // Que se pueda reusar no es suerte: `vello_cpu::RenderContext` y // `vello_hybrid::Scene` son la MISMA API, método por método —`set_paint`, // `set_transform`, `fill_path`, `push_layer` con la misma firma de cinco // `Option`—, porque las dos son fachadas del mismo `vello_common`. De ahí que // este pintor sea casi renglón por renglón el de `llimphi-cpu`. // // ## Las dos cosas que sí cambian, y por qué // // **Las imágenes.** vello_cpu muestrea un `Pixmap` en RAM; hybrid quiere la // imagen ya subida a un atlas de texturas y referida por `ImageId` (los propios // autores marcan el pixmap como fuera de alcance en `scene.rs`). Eso parte el // trabajo en dos pasadas —subir, después reproducir—, porque subir necesita // `device`/`queue`/`encoder` y reproducir no. Ver [`Pintor::pintar`]. // // **La máscara de luminancia.** vello_hybrid directamente no soporta máscaras // —`unimplemented!()` en `scene.rs:921`—, así que hay que rodearla. El rodeo // resulta exacto: la máscara siempre nace de una FORMA, y la luminancia de una // forma blanca sobre negro es idéntica a la cobertura de un recorte por esa // misma forma. Ver [`Pintor::pintar`] y el comentario del método. // // ## Lo que falta cubrir // // El texto (`Orden::Glifos`) está implementado pero **sin test**: probarlo // headless exigiría una fuente, y el puente que produce esas órdenes vive en // `llimphi-text`. Se verifica de punta a punta en el teléfono (F2), que es // donde de todos modos hay que mirarlo. Las otras seis órdenes sí tienen test // con conteo exacto de píxeles contra GPU real. // ============================================================================= mod pintor; #[cfg(test)] mod pruebas; pub use pintor::{limites_seguros, Pintor, RenderError}; // Se reexporta el sustrato por el mismo motivo que lo hace `llimphi-cpu`: para // que quien use este crate no declare `vello_hybrid` ni `wgpu` por su cuenta y // termine con DOS versiones y un «expected Device, found Device». Acá el riesgo // vale aunque hoy el workspace entero comparta wgpu 29: un consumidor que // declare `wgpu` suelto puede derivar de esa versión sin que nadie lo note. pub use vello_hybrid; pub use wgpu; // Y la grabadora, para que el consumidor no tenga que saber que vive en otro // crate: desde afuera, grabar y reproducir son una sola pieza. pub use llimphi_cpu::{escena, Escena, Forma, Glifo, Orden};