A trilha nativa do eQuantic.UI
Seu C# desenha cada pixel.
O Photon é um renderizador de GPU feito do zero para os mesmos componentes que servem suas páginas web. Metal na Apple, Vulkan no resto, direto no drawable. Sem camada Skia. Sem WebView. Um backend de referência em CPU decide o que é correto, e a GPU precisa concordar.
4 plataformasmacOS, iOS, Android, Windows
±1 LSBGPU contra a referência em CPU
91imagens golden comitadas
0pacotes de terceiros
PhotonDesktop
$ dotnet run --project samples/PhotonDesktop[photon] backend: Metal (BGRA8_sRGB)[photon] text: CoreText · icons: CoreGraphics[photon] render scale 2.0, layout in dp
uma janela de verdade, apresentando frames da GPU
$ dotnet run -- --Photon:ScreenshotPath out.png# one settled frame, headless, same metrics
POR QUE UM RENDERIZADOR PRÓPRIOUma UI pede poucas primitivas,não uma biblioteca 2D genérica.Encapsular o Skia significaria herdar uma biblioteca gráfica inteira para desenhar retângulos arredondados e texto. Ser dono da camada significa que a matemática é nossa, e testável até o pixel.
Previsível, por construçãoOs shaders são compilados offline de uma única fonte Slang para artefatos Metal e SPIR-V comitados, e o registro de pipelines é fixo. Nada compila um shader enquanto seu usuário espera, e os caches de pipeline sobrevivem entre execuções. Esse engasgo tem causa conhecida, e esta é a cura.
Uma superfície mínima e honestaLimpar, preencher e contornar um retângulo com raio por canto, um gradiente de duas paradas, uma textura, um clip, uma camada, um transform pré-calculado. Interfaces são feitas disso. A display list é plana e sem heap, então um frame é um buffer de registros e não um grafo de objetos.
Um único modelo normativoUm único arquivo de matemática de distância com sinal é a especificação. O rasterizador de CPU e todo fragment shader de GPU implementam exatamente essas fórmulas, então "qual está certo" nunca vira debate entre plataformas.
Previsível, por construçãoOs shaders são compilados offline de uma única fonte Slang para artefatos Metal e SPIR-V comitados, e o registro de pipelines é fixo. Nada compila um shader enquanto seu usuário espera, e os caches de pipeline sobrevivem entre execuções. Esse engasgo tem causa conhecida, e esta é a cura.
Uma superfície mínima e honestaLimpar, preencher e contornar um retângulo com raio por canto, um gradiente de duas paradas, uma textura, um clip, uma camada, um transform pré-calculado. Interfaces são feitas disso. A display list é plana e sem heap, então um frame é um buffer de registros e não um grafo de objetos.
Um único modelo normativoUm único arquivo de matemática de distância com sinal é a especificação. O rasterizador de CPU e todo fragment shader de GPU implementam exatamente essas fórmulas, então "qual está certo" nunca vira debate entre plataformas.
Previsível, por construçãoOs shaders são compilados offline de uma única fonte Slang para artefatos Metal e SPIR-V comitados, e o registro de pipelines é fixo. Nada compila um shader enquanto seu usuário espera, e os caches de pipeline sobrevivem entre execuções. Esse engasgo tem causa conhecida, e esta é a cura.
Uma superfície mínima e honestaLimpar, preencher e contornar um retângulo com raio por canto, um gradiente de duas paradas, uma textura, um clip, uma camada, um transform pré-calculado. Interfaces são feitas disso. A display list é plana e sem heap, então um frame é um buffer de registros e não um grafo de objetos.
Um único modelo normativoUm único arquivo de matemática de distância com sinal é a especificação. O rasterizador de CPU e todo fragment shader de GPU implementam exatamente essas fórmulas, então "qual está certo" nunca vira debate entre plataformas.
O PIPELINEDa expressão C# ao frame na GPUA árvore é reexpandida a partir de uma raiz retida a cada frame, e é por isso também que o hot reload funciona: um corpo de método modificado simplesmente passa a valer no próximo.
01
Seus componentes
O mesmo vocabulário write-once que o alvo web renderiza. Build(ComponentContext) é puro e baseado em tokens.
02
Layout, em C#
Nosso próprio motor de flex, com o navegador como juiz: fill herda a indeterminação, shrink para num piso de min-content, limites fazem o filho se medir de novo.
03
Uma display list
O realizador transforma a árvore pós-layout em comandos de desenho planos. O builder é reaproveitado entre frames, então, em regime estável, nada mais é alocado.
04
Um backend a apresenta
Uma interface, três implementações. As de GPU codificam direto no drawable da própria janela; a de CPU é o gabarito contra o qual elas são medidas.
IRenderBackend
Reference
NORMATIVO
Um rasterizador escalar em CPU. Nunca é distribuído num app, e é ele que fixa cada imagem golden.
Metal
macOS e iOS, codificando num drawable de CAMetalLayer.
Vulkan
Android, e Windows sempre que um driver expõe uma superfície.
Os dois backends de GPU rodam o mesmo loop de codificação sobre uma única RHI, então uma plataforma nova é uma swapchain e uma janela, não um renderizador novo.
PLATAFORMASQuatro janelas reais, sem wrappers por baixoCada shell fala com o SO por bindings finos e tipados que nós escrevemos: sem framework de interop, sem shims em C, sem pacotes de terceiros. Texto, ícones e imagens vêm dos frameworks da própria plataforma, porque um sistema que já tem um motor de texto é quem deve medir o texto.
PLATAFORMA
BACKEND
TEXTO & IMAGENS
A JANELA
macOS
Metal
CoreText · ImageIO
NSWindow sobre uma CAMetalLayer, raster retina com layout em dp, mouse, rolagem e teclado do SO
iOS
Metal
CoreText · ImageIO
Os mesmos serviços da Apple que no macOS, escritos uma vez; só a janela e o loop de eventos mudam
Android
Vulkan
Serviços de texto da plataforma
O app fornece uma factory em vez de um Main; os frames são apresentados no callback de vsync da plataforma
Windows
NOVO
Vulkan, ou Reference
DirectWrite · Direct2D · WIC
Uma janela Win32 de verdade, com DPI por monitor e modo escuro que segue o sistema. Sem driver Vulkan, recorre ao rasterizador de referência e continua desenhando
PLATAFORMA
BACKEND
TEXTO & IMAGENS
A JANELA
macOS
Metal
CoreText · ImageIO
NSWindow sobre uma CAMetalLayer, raster retina com layout em dp, mouse, rolagem e teclado do SO
iOS
Metal
CoreText · ImageIO
Os mesmos serviços da Apple que no macOS, escritos uma vez; só a janela e o loop de eventos mudam
Android
Vulkan
Serviços de texto da plataforma
O app fornece uma factory em vez de um Main; os frames são apresentados no callback de vsync da plataforma
Windows
NOVO
Vulkan, ou Reference
DirectWrite · Direct2D · WIC
Uma janela Win32 de verdade, com DPI por monitor e modo escuro que segue o sistema. Sem driver Vulkan, recorre ao rasterizador de referência e continua desenhando
Esse fallback é o motivo de o backend normativo não ser só uma fixture de teste. Uma máquina virtual ou sessão de Área de Trabalho Remota costuma não ter driver Vulkan, e o app ainda abre uma janela e renderiza corretamente, só que na CPU.
PARIDADE"Na minha máquina parece certo" não é uma mediçãoCada cena renderiza por um backend, os pixels são lidos de volta e comparados com um PNG comitado. A referência em CPU fixa essas imagens; os backends de GPU rodam o mesmo catálogo para provar que concordam. Um desvio de mais de um ou dois bits é um bug com nome, não um detalhe de plataforma.
91 imagens golden no repositório: pares de componentes em claro e escuro, estados de sheet no meio do arrasto, gradientes, anéis de foco, cobertura de texturas.
Um codec PNG sem dependências, então o harness não tem nada para instalar, e uma falha grava um diff amplificado que você pode examinar.
Uma única fonte de shader em Slang, transliterando a matemática do C#, compilada offline nos artefatos que as duas GPUs consomem. Você nunca roda uma toolchain de shaders.
A MESMA CENA, TRÊS RASTERIZADORES
Reference
Metal
Vulkan
diff vs golden ... 0 px above tolerancegpu ↔ cpu ........ within ±1 LSB
Uma ilustração do contrato, não uma captura de tela do harness. O catálogo real fica no repositório e roda no CI.
PERFORMANCEAs promessas vêm com números, e uma catracaMedidos numa cena tipo dashboard, vinte e quatro cartões e uma faixa de animação em loop, num Mac série M. Os tetos ficam fixados com folga acima deles, então uma regressão quebra o build em vez de ser notada seis meses depois.
0.23 msrealize, medianap95 0.32 ms, para um orçamento de 8.33 ms
67.5 KBalocados por frameregime estável, com reciclagem de frames ligada
146comandos de desenhopara a cena inteira do dashboard
2 Hzum cursor piscandoframes agendados, não um loop de render contínuo
0.23 msrealize, medianap95 0.32 ms, para um orçamento de 8.33 ms
67.5 KBalocados por frameregime estável, com reciclagem de frames ligada
146comandos de desenhopara a cena inteira do dashboard
2 Hzum cursor piscandoframes agendados, não um loop de render contínuo
0.23 msrealize, medianap95 0.32 ms, para um orçamento de 8.33 ms
67.5 KBalocados por frameregime estável, com reciclagem de frames ligada
146comandos de desenhopara a cena inteira do dashboard
2 Hzum cursor piscandoframes agendados, não um loop de render contínuo
0.23 msrealize, medianap95 0.32 ms, para um orçamento de 8.33 ms
67.5 KBalocados por frameregime estável, com reciclagem de frames ligada
146comandos de desenhopara a cena inteira do dashboard
2 Hzum cursor piscandoframes agendados, não um loop de render contínuo
Um caminho é identidade, cacheado entre frames
O builder da lista mantém sua capacidade
Frames substituídos alimentam um pool de nós
O QUE É REAL HOJEUm motor que desenha os próprios pixels te deve tudoO sistema operacional enxerga uma única view opaca, então nada vem de graça. Cada item aqui teve que ser construído em vez de herdado.
Texto de verdade, não um atlas de texturas
Um único motor mede e rasteriza, então as quebras de linha concordam por construção. Os bitmaps são dimensionados pela caixa de tinta da linha, e é por isso que uma descendente profunda nunca é cortada.
Ícones e imagens
Um parser de caminhos SVG em C# puro alimenta o rasterizador da plataforma, e as fotografias agora são decodificadas pelos próprios serviços de imagem do sistema na Apple e no Windows.
Entrada que a plataforma respeita
Uma única ordem de foco, teclas mortas e composição CJK renderizadas inline no cursor de texto, gestos por caminho com tolerância de toque, cursores e área de transferência.
Uma árvore de semântica
Ordem de leitura derivada do layout realizado, incluindo conteúdo rolado para fora da tela, conduzindo o VoiceOver no macOS. Um gate impede que ela se afaste do percurso do teclado.
Hot reload, estado intacto
Rode com dotnet watch run, edite o corpo de um Build, salve. Três cliques no contador sobrevivem, porque o estado vive num store indexado por caminho.
Movimento, rolagem e overlays
Movimento em loop, transições de valor, entrada e saída de presença, cabeçalhos fixos, arrastar-para-dispensar com deslize e menus ancorados em limites reais.
Texto de verdade, não um atlas de texturas
Um único motor mede e rasteriza, então as quebras de linha concordam por construção. Os bitmaps são dimensionados pela caixa de tinta da linha, e é por isso que uma descendente profunda nunca é cortada.
Ícones e imagens
Um parser de caminhos SVG em C# puro alimenta o rasterizador da plataforma, e as fotografias agora são decodificadas pelos próprios serviços de imagem do sistema na Apple e no Windows.
Entrada que a plataforma respeita
Uma única ordem de foco, teclas mortas e composição CJK renderizadas inline no cursor de texto, gestos por caminho com tolerância de toque, cursores e área de transferência.
Uma árvore de semântica
Ordem de leitura derivada do layout realizado, incluindo conteúdo rolado para fora da tela, conduzindo o VoiceOver no macOS. Um gate impede que ela se afaste do percurso do teclado.
Hot reload, estado intacto
Rode com dotnet watch run, edite o corpo de um Build, salve. Três cliques no contador sobrevivem, porque o estado vive num store indexado por caminho.
Movimento, rolagem e overlays
Movimento em loop, transições de valor, entrada e saída de presença, cabeçalhos fixos, arrastar-para-dispensar com deslize e menus ancorados em limites reais.
Texto de verdade, não um atlas de texturas
Um único motor mede e rasteriza, então as quebras de linha concordam por construção. Os bitmaps são dimensionados pela caixa de tinta da linha, e é por isso que uma descendente profunda nunca é cortada.
Ícones e imagens
Um parser de caminhos SVG em C# puro alimenta o rasterizador da plataforma, e as fotografias agora são decodificadas pelos próprios serviços de imagem do sistema na Apple e no Windows.
Entrada que a plataforma respeita
Uma única ordem de foco, teclas mortas e composição CJK renderizadas inline no cursor de texto, gestos por caminho com tolerância de toque, cursores e área de transferência.
Uma árvore de semântica
Ordem de leitura derivada do layout realizado, incluindo conteúdo rolado para fora da tela, conduzindo o VoiceOver no macOS. Um gate impede que ela se afaste do percurso do teclado.
Hot reload, estado intacto
Rode com dotnet watch run, edite o corpo de um Build, salve. Três cliques no contador sobrevivem, porque o estado vive num store indexado por caminho.
Movimento, rolagem e overlays
Movimento em loop, transições de valor, entrada e saída de presença, cabeçalhos fixos, arrastar-para-dispensar com deslize e menus ancorados em limites reais.
Onde fica a cerca. A ponte de acessibilidade já funciona no macOS; iOS e Android consomem a mesma árvore e ainda não estão ligados. Superfícies de código confirmam uma composição, mas não renderizam o trecho marcado inline. Preferimos apontar isso a deixar você descobrir.
COMECEJanela na GPU em três comandos
O pré-requisito é o SDK do .NET. O Photon não precisa de SDK gráfico, de toolchain de shaders nem de etapa de build nativo, porque os shaders já vêm compilados e os bindings são C# puro.
$ dotnet new install eQuantic.UI.Templates$ dotnet new equantic-native -n MyNativeApp$ cd MyNativeApp && dotnet run→ uma janela de verdade na GPU. Troque o template por equantic-app e os mesmos componentes passam a servir uma página web.
0.2.0-preview.62
preview de desenvolvimento no NuGet, licença MIT
eQuantic.UIeQuantic.UI
Photon
A trilha nativa de GPU do eQuantic.UI. Metal e Vulkan, conferidos contra uma referência em CPU.MIT © eQuantic.