14 KiB
| id | ticket | title | status | created | resolved | decision | tags | |||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| AGD-0043 | real-render-worker-establishment | Real Render Worker Establishment | open | 2026-06-06 |
|
Contexto
DEC-0031 definiu o contrato arquitetural da fronteira VM/render. AGD-0042 preparou a fronteira host/hardware/render para que Hardware deixe de ser um objeto concreto atravessando o worker e passe a ser contrato/facades implementadas pelo host.
Esta agenda discute a implementacao do worker real propriamente dito, assumindo que a preparacao da fronteira ja foi resolvida antes da execucao.
Estado Atual Depois da AGD-0042
A preparacao de fronteira foi executada pelos planos PLN-0098 a PLN-0109:
HardwareBridgefoi removido do codigo e deixou de ser contrato publico;RuntimePlatformpassou a ser a fronteira runtime-facing para render, input, audio, assets e telemetry;RenderSubmissionSinkaceita submissao owned;Game2DFrameComposersepara fechamento logico de frame do backend de render;- syscalls
gfx2d.*egfxui.*bufferizam comandos e nao desenham imediatamente viaGfx; - firmware, Hub, runtime e host desktop passam por servicos de plataforma;
- testes de runtime/firmware usam
TestPlatformcomo fixture local; - specs de GFX/portabilidade documentam que o worker/render consumer nao deve depender de
&mut Hardware,&mut Gfx,FrameComposervivo ou estado mutavel da VM.
O estado atual ainda nao tem worker real. O LocalRenderWorker continua sendo o caminho local/cooperativo que consome RenderSubmission no mesmo processo. O proximo passo desta agenda e decidir onde vive o controller do worker real, qual handoff thread-safe ele usa, e qual backend renderizavel ele owns ou recebe.
Problema
O LocalRenderWorker atual e cooperativo/local. Ele prova o roteamento de policy, mas nao prova:
- thread/core real;
- ownership do backend renderizavel;
- present loop;
- stop token para current work;
- bounded shutdown/join;
- stale epoch durante rasterizacao;
- erro tipado de render/present;
- repeat real do ultimo frame valido;
- ausencia de bloqueio da VM sob atraso do render.
Pontos Criticos
1. Ownership e lifecycle do worker
Precisamos decidir quem cria, inicia, para e reinicia o worker: runtime controller, host/HAL, ou ambos em contrato dividido.
2. Handoff real
O single-slot latest-wins ja existe como abstracao local. O worker real precisa de uma implementacao thread-safe, sem fila crescente e sem bloquear a VM.
3. Backend renderizavel
O worker deve owns um backend minimo ou receber capability host-owned. Esse backend deve consumir RenderSubmission, resolver recursos read-only e produzir/presentar frame sem &mut Hardware.
4. Present cadence
Precisamos decidir se o worker roda a 60Hz, se o host event loop dirige present, ou se ha uma autoridade separada de display cadence. Repeated present deve virar comportamento real, nao apenas hook.
5. Shutdown/current work
Quando houver uma submission em rasterizacao, shutdown e owner transition precisam impedir present obsoleto e terminar em tempo bounded.
6. Error model
Precisamos trocar o modelo infalivel/panic containment por erro tipado para render/present/worker failure.
7. Testes de concorrencia
Precisamos provar o contrato sem depender de janela nativa nem sleeps frageis.
Opcoes
Opcao A - Worker thread no runtime com backend mockavel
Abordagem: runtime cria um worker thread generico que recebe um backend implementando trait testavel.
Pros:
- testes de contrato mais diretos;
- menor dependencia do host desktop.
Contras:
- runtime passa a owns detalhes de thread;
- precisa cuidado para nao absorver politica de host/window.
Manutenibilidade: boa se o backend for limpo; ruim se virar acoplamento de host dentro do runtime.
Opcao B - Worker thread no host desktop primeiro
Abordagem: implementar o primeiro worker no host winit/pixels e adaptar o runtime a submit/policy.
Pros:
- valida o caso real visual;
- encaixa com surface/present/winit.
Contras:
- mais dificil testar sem janela;
- risco de contrato ficar host-specific;
- portabilidade fica menos comprovada.
Manutenibilidade: boa para desktop, menos boa para hardware proprio.
Opcao C - Worker controller runtime + backend host/HAL
Abordagem: criar um controller de worker que implementa handoff, stop token, epoch check e telemetry; o backend concreto vem de host/HAL e pode ser mockado em testes.
Pros:
- separa contrato de backend;
- testavel sem janela;
- mapeia para thread desktop, outro core ou fallback;
- preserva
RenderManagercomo coordenador.
Contras:
- desenho inicial mais exigente;
- depende da preparacao da
AGD-0042.
Manutenibilidade: melhor opcao se queremos worker real sem amarrar a winit.
Sugestao / Recomendacao
Recomendo a Opcao C - Worker controller runtime + backend host/HAL.
O primeiro worker real deveria:
- consumir um handoff thread-safe single-slot;
- ter stop token e shutdown bounded;
- checar ownership/epoch antes de present;
- expor erros tipados;
- repetir o ultimo frame valido em cadence definida;
- sincronizar telemetry sem alterar semantica da VM;
- ter backend fake/mocked para testes de concorrencia.
O host desktop pode ser a primeira integracao concreta, mas nao deve ser o unico lugar onde o contrato e testado.
Perguntas em Aberto
1. Onde vive o worker controller?
Pergunta: O worker controller vive em prometeu-system, prometeu-hal, prometeu-drivers, ou host?
Sugestao: colocar o controller contratual em prometeu-system, proximo de RenderManager, e manter traits pequenas em prometeu-hal quando forem superficie compartilhada. prometeu-drivers deve continuar oferecendo implementacoes locais/testaveis; host desktop deve integrar o controller, nao definir o contrato.
Motivo: o RenderManager ja owns policy de AppMode, ownership/epoch, latest-wins e telemetry. Se o controller nascer apenas no host, a semantica de worker vira desktop-specific e fica mais dificil provar o contrato sem janela nativa.
2. Qual handoff thread-safe usar?
Pergunta: O handoff thread-safe sera Mutex<Option<...>>, canal bounded, atomic slot, ou estrutura propria?
Sugestao: comecar com uma estrutura propria simples baseada em Mutex<Option<RenderSubmission>> + Condvar, encapsulada como single-slot latest-wins. O produtor substitui a pending submission sem bloquear em rasterizacao; o consumidor espera por nova submission ou shutdown.
Motivo: canal bounded tende a preservar historico ou bloquear produtor se nao for usado com cuidado. Um slot explicito modela diretamente a regra ja aceita: nao existe fila crescente, a ultima submissao completa vence.
3. Como modelar current work, shutdown e stale owner?
Pergunta: Como modelar current work para shutdown e stale owner?
Sugestao: separar pending de in_flight. Ao tomar uma submission, o worker carimba in_flight localmente, renderiza, e checa ownership/epoch contra um snapshot atomico ou handle compartilhado antes de present. Shutdown sinaliza stop, acorda o worker e faz join bounded; se houver trabalho em andamento, ele pode terminar rasterizacao, mas nao pode apresentar se o owner/epoch estiver obsoleto ou o stop ja exigir descarte. O timeout deve ser configuravel; como default inicial, usar 250ms, que e longo o bastante para evitar falso positivo em desktop comum e curto o bastante para detectar worker preso sem travar encerramento.
Motivo: isso evita que shutdown dependa de cancelar mid-raster em codigo que talvez nao seja cancelavel, mas ainda impede present obsoleto.
4. Quem chama present?
Pergunta: Quem chama present: worker, host event loop, ou display cadence service?
Sugestao: no primeiro corte, o worker deve produzir/publish uma superficie pronta como buffer RGBA8888 owned, por exemplo OwnedRgba8888Frame, definido em prometeu-hal. O host event loop continua sendo autoridade de apresentacao da janela nativa. O "repeat ultimo frame valido" deve repetir o ultimo buffer publicado, nao recompor nem exigir que o worker conheca a API nativa de janela/swap.
Motivo: RGBA8888 ja e o formato logico canonico nas specs. Um frame owned com FrameId, ownership/epoch, largura, altura, stride_pixels e pixels RGBA8888 em Vec<u32> deixa o contrato testavel sem janela e evita acoplamento a winit/pixels, SDL, swapchain ou textura nativa. Colocar o swap real dentro do worker pode funcionar em alguns hosts e quebrar portabilidade. O contrato importante e que a VM nao bloqueie e que o host tenha uma superficie publicada coerente.
5. Como o worker recebe recursos read-only?
Pergunta: Como o worker recebe recursos read-only preparados na AGD-0042?
Sugestao: o primeiro backend deve receber RenderSubmission owned e uma interface compacta de acesso read-only aos banks por id. Banks sao read-only por definicao durante o consumo de render; o worker resolve recursos por ids estaveis, sem copiar bank, sem snapshot de bank e sem depender de Arc como requisito do contrato.
Motivo: AGD-0042 eliminou o bridge monolitico exatamente para impedir que o worker dependa do hardware inteiro. A proxima decisao precisa declarar quais recursos sao lidos pelo render backend e como sua estabilidade e garantida durante uma submissao em voo. A estabilidade vem da regra de leitura: o worker ve banks por id via interface read-only, enquanto instalacao/mutacao de bank permanece fora do consumo renderizavel em voo.
6. Qual erro tipado minimo?
Pergunta: Qual erro tipado minimo precisamos no primeiro worker?
Sugestao: introduzir um erro pequeno, por exemplo RenderWorkerError, cobrindo pelo menos: backend unavailable, render failed, present/publish failed, shutdown timeout, stale submission discarded. Panics continuam sendo capturados como falha interna, mas nao devem ser o modelo operacional normal.
Motivo: LocalRenderWorker hoje prova policy, mas nao diferencia falhas reais de render/present. O worker real precisa reportar falhas sem contaminar a VM com detalhes de host.
7. Como provar que a VM nao bloqueia?
Pergunta: Como provar que a VM nao bloqueia quando o worker atrasa?
Sugestao: criar testes deterministas com backend fake controlado por barreiras/condvars, nao sleeps. O teste deve segurar o worker em rasterizacao, produzir frames adicionais no runtime, verificar substituicao latest-wins/drop telemetry, e provar que o tick da VM retorna sem esperar o consumo terminar.
Motivo: sleeps tornam teste de concorrencia fragil. Barreiras permitem provar especificamente a propriedade desejada: produtor nao bloqueia em raster/present lento.
8. Qual primeiro backend real?
Pergunta: Qual sera o primeiro backend real: desktop Gfx/pixels, framebuffer local, ou fake backend?
Sugestao: implementar primeiro um backend fake/mocked para contrato e um backend local framebuffer para integracao sem janela. A integracao desktop vem em seguida como consumidor concreto, usando a mesma trait. Ao final desta agenda, o worker deve estar funcionando completamente no caminho host real; a divisao em planos serve para controlar risco, nao para reduzir o alvo final.
Motivo: se o primeiro backend for desktop/winit, o contrato corre risco de nascer acoplado a detalhes de janela. Se o primeiro for fake/local, a semantica do worker fica testavel antes da integracao visual. Ainda assim, a agenda so deve ser considerada concluida quando a integracao host real tambem estiver operando sobre o worker.
Criterio para Encerrar
Esta agenda pode virar decision quando tivermos:
- local/camada do worker controller;
- estrutura thread-safe de handoff;
- trait/backend de render/present;
- present cadence/repeat;
- shutdown/current work;
- error model;
- test matrix de concorrencia;
- escopo do primeiro worker real.
Discussion
- 2026-06-06: Agenda criada dentro da
DSC-0042para separar worker real da preparacao de fronteira discutida emAGD-0042. - 2026-06-15: Apos a conclusao dos planos
PLN-0098aPLN-0109, a direcao da agenda foi alinhada em torno da Opcao C: controller emprometeu-system, handoff single-slot thread-safe, backend fake/local primeiro, e publicacao de frame owned RGBA8888 antes da integracao desktop concreta. - 2026-06-15: Perguntas restantes alinhadas:
OwnedRgba8888Framedeve viver emprometeu-halcom pixelsVec<u32>RGBA8888; banks sao acessados por interface compacta read-only via ids, sem copia/snapshot/Arccomo contrato; shutdown deve ter timeout configuravel com default inicial sugerido de250ms; a agenda pode virar varios plans, mas so fecha quando o worker funcionar no host real.
Resolution
Direcao proposta para decisao:
RenderManagercontinua como autoridade de policy, ownership/epoch, latest-wins e telemetry;- o worker controller contratual deve viver em
prometeu-system; - traits compartilhadas minimas podem viver em
prometeu-hal; - o handoff real deve ser single-slot latest-wins com sincronizacao explicita, inicialmente
Mutex<Option<RenderSubmission>> + Condvar; - o worker separa
pendingdein_flighte checa stop/ownership/epoch antes de publicar; - shutdown deve ser bounded e configuravel; default inicial sugerido:
250ms; - o worker publica um
OwnedRgba8888Frameemprometeu-hal, contendo frame id, owner/epoch, dimensoes,stride_pixelse pixels RGBA8888 owned emVec<u32>; - o worker acessa banks por ids estaveis atraves de uma interface compacta read-only; nao copia banks, nao depende de snapshots de bank e nao usa
Arccomo parte obrigatoria do contrato; - o host event loop faz o upload/present nativo a partir do ultimo frame publicado;
- o primeiro backend deve ser fake/local para provar contrato e concorrencia sem janela;
- a integracao desktop concreta vem depois, usando a mesma trait/backend contract;
- a agenda pode ser executada em varios plans, mas o criterio final e ter o worker funcionando completamente no host real;
- testes devem usar barreiras/condvars para provar ausencia de bloqueio da VM, latest-wins, stale discard, shutdown bounded e telemetry.