--- id: DEC-0019 ticket: perf-host-desktop-frame-pacing-and-presentation title: Decision - [PERF] Host Desktop Frame Pacing and Presentation status: accepted created: 2026-04-20 accepted: 2026-04-20 agenda: AGD-0009 plans: [PLN-0036] tags: [perf, host, desktop, frame-pacing, presentation, debug] --- # Status Accepted. This decision is now normatively locked and is ready to drive planning and execution. ## Contexto O host desktop atual usa `ControlFlow::Poll`, pede redraw continuamente e reapresenta o framebuffer mesmo quando a maquina nao publicou um novo frame logico. Esse comportamento conflita com o modelo temporal de `docs/specs/runtime/01-time-model-and-cycles.md`, onde a maquina opera em frames logicos de 60 Hz, e com o contrato de portabilidade e isolamento de debug em `docs/specs/runtime/10-debug-inspection-and-profiling.md` e `docs/specs/runtime/11-portability-and-cross-platform-execution.md`, onde apresentacao e overlay pertencem ao host, mas nao devem redefinir a semantica logica da maquina. O problema a ser fechado aqui nao eh o desenho final do backend grafico. O problema eh definir quando o host desktop tem permissao para acordar, converter e apresentar pixels sem transformar a shell desktop em um loop de polling agressivo. ## Decisao O host desktop SHALL adotar pacing orientado por frame logico publicado e por eventos externos relevantes, e MUST NOT manter redraw continuo por padrao. Normas desta decisao: 1. Gatilho canonico de redraw - O host MUST considerar um novo frame logico publicado como gatilho principal de apresentacao. - O host MAY solicitar redraw adicional quando houver evento externo relevante que altere apenas a superficie host-owned, incluindo resize da janela, expose/invalidate da janela, toggle de overlay, atualizacao visivel do debugger ou mudanca de estado local da shell. - O host MUST NOT solicitar redraw continuo apenas para "ver se existe frame novo". 2. Politica do event loop - O host desktop MUST sair de `ControlFlow::Poll` como politica padrao. - O event loop SHOULD operar em modo de espera dirigida por deadline ou evento, usando `WaitUntil` para o proximo slice logico quando houver trabalho temporal agendado e `Wait` quando nao houver deadline imediato. - `Poll` MAY existir apenas em modo explicitamente opt-in de profiling/diagnostico host-owned e MUST NOT ser o comportamento normal de execucao. 3. Conversao de framebuffer - A conversao RGB565 -> RGBA8 permanece full-frame nesta fase. - Essa conversao MUST acontecer apenas quando houver novo frame logico publicado ou quando um evento host-owned exigir recomposicao/apresentacao da superficie visivel. - Dirty-region conversion e offload para shader/GPU ficam explicitamente fora do contrato desta decisao e poderao ser avaliados em discussao separada se o full-frame on-demand ainda for insuficiente. 4. Modo ocioso, pausa e debug - Quando a VM estiver pausada, em breakpoint, esperando `start`, ou sem cart carregado, o host MUST preservar o ultimo frame visivel valido e MUST NOT ficar redesenhando continuamente. - Nesses estados, redraw adicional so pode ocorrer por evento host-owned relevante, como overlay/debug data visivel, resize/expose ou transicao explicita de estado. - Buffers logicos da maquina MUST NOT ser trocados durante pausa apenas para sustentar HUD host-owned. 5. Sinal de "novo frame disponivel" - O runtime/host boundary MUST ter um ponto canonico de observacao do "frame pronto", alinhado ao momento em que o frame logico e publicado para apresentacao. - A implementacao inicial MAY usar um sinal explicito, contador monotonicamente crescente, dirty flag ou observacao do ponto de swap/publicacao, desde que a semantica seja unica e nao ambigua. - Essa decisao MUST NOT introduzir uma ABI guest-visible nova. O sinal pertence ao boundary interno runtime-host e as superficies host-owned de inspecao. ## Rationale `Poll` com redraw continuo mascara custo de apresentacao, consome CPU sem beneficio visual e reduz a utilidade do desktop como referencia de comportamento energetico razoavel. Ao mesmo tempo, a shell desktop nao deve ser tratada como uma plataforma "ultra-conservadora" a ponto de perder ergonomia de debug. Por isso a decisao nao proibe redraw extra; ela apenas restringe redraw extra a eventos com causa concreta e visivel. Manter a conversao full-frame por enquanto evita reabrir a arquitetura de renderizacao durante um trabalho cujo alvo principal eh pacing. O ganho imediato vem de parar de converter e apresentar quando nada mudou. Se isso nao bastar, dirty regions ou shader path podem ser discutidos depois com evidencias. Separar "frame logico publicado" de "overlay host-owned mudou" preserva o contrato de portabilidade: o host pode mostrar mais informacao tecnica sem forcar a VM a produzir frames adicionais nem adulterar o framebuffer logico. ## Invariantes / Contrato - A maquina continua definindo frames logicos em 60 Hz; o host nao redefine esse relogio. - O host apresenta o ultimo frame logico publicado; ele nao inventa frames intermediarios. - Overlay e debugger sao host-owned e MAY compor sobre uma superficie de apresentacao host-only. - Overlay/debug MUST NOT exigir redraw continuo quando seu conteudo estiver estavel. - Conversao/presentacao do framebuffer MUST ser dirigida por mudanca observavel, nao por polling agressivo. - O boundary runtime-host MUST expor um criterio unico para detectar publicacao de frame logico. - Esta decisao nao promove dirty regions nem GPU offload a contrato normativo. - Esta decisao nao altera semantica guest-visible de `DRAW`, buffers logicos, ciclos, ou telemetria de certificacao. ## Alternativas Descartadas ### Manter `Poll` permanente no desktop Descartado porque esconde custo real de apresentacao, desperdiça CPU e cria uma shell cuja estabilidade aparente depende de trabalho inutil. ### Redraw orientado apenas por vsync fisico Descartado como contrato canonico porque o modelo PROMETEU e dirigido por frame logico e a portabilidade nao depende de sincronizar a semantica da maquina a uma frequencia fisica do host. ### Reabrir o problema com dirty regions ou shader path como pre-condicao Descartado nesta etapa porque mistura otimizacao secundaria com o contrato principal de pacing. O problema imediato pode e deve ser resolvido sem nova arquitetura de render backend. ## Impactos ### Spec - `docs/specs/runtime/10-debug-inspection-and-profiling.md` deve refletir que a apresentacao host-owned observa frame publicado e nao requer redraw continuo para HUD/overlay estavel. - `docs/specs/runtime/11-portability-and-cross-platform-execution.md` deve explicitar que a superficie host de apresentacao pode recompor overlay por evento relevante, sem transformar isso em polling permanente. ### Runtime - O runtime pode precisar expor ou estabilizar um ponto interno de publicacao de frame pronto para o host desktop consumir de forma canonica. - Nenhuma nova ABI guest-visible deve ser criada por este trabalho. ### Host Desktop - O loop winit deve migrar de `Poll` para espera dirigida por deadline/evento. - `request_redraw()` deixa de ser incondicional no ciclo de idle. - A apresentacao passa a depender de novo frame logico ou evento host-owned relevante. ### Firmware - Sem mudanca de semantica guest-visible. - Estados de pausa/breakpoint continuam impedindo avanco de tempo logico e swap de buffers logicos. ### Tooling - Overlay/debugger continuam host-owned, mas precisam declarar quando realmente invalidam a superficie visivel. - Profiling host-only pode manter um modo opt-in de polling agressivo, separado do comportamento normal. ## Referencias - [AGD-0009]() - [docs/specs/runtime/01-time-model-and-cycles.md](/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/docs/specs/runtime/01-time-model-and-cycles.md) - [docs/specs/runtime/10-debug-inspection-and-profiling.md](/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/docs/specs/runtime/10-debug-inspection-and-profiling.md) - [docs/specs/runtime/11-portability-and-cross-platform-execution.md](/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/docs/specs/runtime/11-portability-and-cross-platform-execution.md) - [runner.rs](/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/crates/host/prometeu-host-desktop-winit/src/runner.rs:252) ## Propagacao Necessaria - Escrever um `PLN` para implementar a mudanca no host desktop. - Atualizar as specs normativas citadas para refletir este contrato. - Ajustar o host desktop para consumir um gatilho canonico de frame publicado. - Adicionar testes para: - ausencia de redraw continuo sem frame novo; - redraw em evento host-owned relevante; - preservacao do ultimo frame em pausa/breakpoint/no-cart; - modo opt-in de polling apenas quando explicitamente habilitado. ## Revision Log - 2026-04-20: Initial draft from AGD-0009. - 2026-04-20: Accepted and linked to PLN-0036.