VM and Render Parallel Execution Boundary
This commit is contained in:
parent
df0d7949c8
commit
26e038e195
@ -1,7 +1,8 @@
|
||||
{"type":"meta","next_id":{"DSC":42,"AGD":42,"DEC":32,"PLN":98,"LSN":48,"CLSN":1}}
|
||||
{"type":"meta","next_id":{"DSC":43,"AGD":43,"DEC":32,"PLN":98,"LSN":49,"CLSN":1}}
|
||||
{"type":"discussion","id":"DSC-0039","status":"abandoned","ticket":"render-pipeline-family-and-future-3d","title":"Render Pipeline Family and Future 3D","created_at":"2026-06-04","updated_at":"2026-06-04","tags":["gfx","renderer","runtime","architecture","pipeline"],"agendas":[{"id":"AGD-0039","file":"AGD-0039-render-pipeline-family-and-future-3d.md","status":"abandoned","created_at":"2026-06-04","updated_at":"2026-06-04","_override_reason":"User explicitly chose to close this agenda without a new decision because DSC-0038 already established enough architecture for future extension, and 3D is intentionally deferred."}],"decisions":[],"plans":[],"lessons":[],"_override_reason":"User explicitly chose to close this agenda without a new decision because DSC-0038 already established enough architecture for future extension, and 3D is intentionally deferred."}
|
||||
{"type":"discussion","id":"DSC-0040","status":"in_progress","ticket":"vm-render-parallel-execution-boundary","title":"VM and Render Parallel Execution Boundary","created_at":"2026-06-04","updated_at":"2026-06-05","tags":["runtime","renderer","vm","concurrency","architecture","perf"],"agendas":[{"id":"AGD-0040","file":"AGD-0040-vm-and-render-parallel-execution-boundary.md","status":"accepted","created_at":"2026-06-04","updated_at":"2026-06-05"}],"decisions":[{"id":"DEC-0031","file":"DEC-0031-vm-and-render-parallel-execution-boundary.md","status":"accepted","created_at":"2026-06-05","updated_at":"2026-06-05","ref_agenda":"AGD-0040"}],"plans":[{"id":"PLN-0087","file":"PLN-0087-fix-game2d-packet-overlay-composition.md","status":"done","created_at":"2026-06-05","updated_at":"2026-06-05","ref_decisions":["DEC-0031"]},{"id":"PLN-0088","file":"PLN-0088-define-read-only-render-resource-boundary.md","status":"done","created_at":"2026-06-05","updated_at":"2026-06-05","ref_decisions":["DEC-0031"]},{"id":"PLN-0089","file":"PLN-0089-introduce-render-handoff-abstraction.md","status":"done","created_at":"2026-06-05","updated_at":"2026-06-05","ref_decisions":["DEC-0031"]},{"id":"PLN-0090","file":"PLN-0090-add-render-frame-pacing-contract.md","status":"done","created_at":"2026-06-05","updated_at":"2026-06-05","ref_decisions":["DEC-0031"]},{"id":"PLN-0091","file":"PLN-0091-implement-appmode-render-policy-matrix.md","status":"done","created_at":"2026-06-05","updated_at":"2026-06-05","ref_decisions":["DEC-0031"]},{"id":"PLN-0092","file":"PLN-0092-add-render-epoch-ownership-transitions.md","status":"done","created_at":"2026-06-05","updated_at":"2026-06-05","ref_decisions":["DEC-0031"]},{"id":"PLN-0093","file":"PLN-0093-add-render-telemetry-counters-and-events.md","status":"done","created_at":"2026-06-05","updated_at":"2026-06-05","ref_decisions":["DEC-0031"]},{"id":"PLN-0094","file":"PLN-0094-specify-async-render-boundary.md","status":"done","created_at":"2026-06-05","updated_at":"2026-06-05","ref_decisions":["DEC-0031"]},{"id":"PLN-0095","file":"PLN-0095-prototype-local-render-worker-capability.md","status":"done","created_at":"2026-06-05","updated_at":"2026-06-05","ref_decisions":["DEC-0031"]},{"id":"PLN-0096","file":"PLN-0096-define-render-shutdown-and-failure-handling.md","status":"done","created_at":"2026-06-05","updated_at":"2026-06-05","ref_decisions":["DEC-0031"]},{"id":"PLN-0097","file":"PLN-0097-add-async-render-integration-test-matrix.md","status":"done","created_at":"2026-06-05","updated_at":"2026-06-05","ref_decisions":["DEC-0031"]}],"lessons":[]}
|
||||
{"type":"discussion","id":"DSC-0040","status":"done","ticket":"vm-render-parallel-execution-boundary","title":"VM and Render Parallel Execution Boundary","created_at":"2026-06-04","updated_at":"2026-06-06","tags":["runtime","renderer","vm","concurrency","architecture","perf"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0048","file":"discussion/lessons/DSC-0040-vm-render-parallel-execution-boundary/LSN-0048-render-workers-need-a-closed-packet-contract.md","status":"done","created_at":"2026-06-06","updated_at":"2026-06-06"}]}
|
||||
{"type":"discussion","id":"DSC-0041","status":"open","ticket":"foreground-stack-game-pause-shell-vm-backed","title":"Foreground Stack, Game Pause, and VM-Backed Shell Coexistence","created_at":"2026-06-05","updated_at":"2026-06-05","tags":["runtime","os","lifecycle","shell","game","vm","foreground","architecture"],"agendas":[{"id":"AGD-0041","file":"AGD-0041-foreground-stack-game-pause-shell-vm-backed.md","status":"open","created_at":"2026-06-05","updated_at":"2026-06-05"}],"decisions":[],"plans":[],"lessons":[]}
|
||||
{"type":"discussion","id":"DSC-0042","status":"open","ticket":"real-render-worker-establishment","title":"Real Render Worker Establishment","created_at":"2026-06-06","updated_at":"2026-06-06","tags":["runtime","renderer","worker","concurrency","host","hal","architecture"],"agendas":[{"id":"AGD-0042","file":"AGD-0042-real-render-worker-establishment.md","status":"open","created_at":"2026-06-06","updated_at":"2026-06-06"}],"decisions":[],"plans":[],"lessons":[]}
|
||||
{"type":"discussion","id":"DSC-0038","status":"done","ticket":"render-frame-packet-boundary","title":"Logical Render Pipelines and Command Packets","created_at":"2026-05-25","updated_at":"2026-06-04","tags":["gfx","renderer","runtime","frame-composer","architecture","ui","pipeline"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0047","file":"discussion/lessons/DSC-0038-render-frame-packet-boundary/LSN-0047-typed-render-submissions-preserve-domain-boundaries.md","status":"done","created_at":"2026-06-04","updated_at":"2026-06-04"}]}
|
||||
{"type":"discussion","id":"DSC-0035","status":"done","ticket":"task-owned-shell-windows","title":"Agenda - Task-Owned Shell Windows","created_at":"2026-05-15","updated_at":"2026-05-15","tags":["runtime","os","task","window-manager","shell","lifecycle"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0044","file":"discussion/lessons/DSC-0035-task-owned-shell-windows/LSN-0044-task-window-liveness-belongs-to-the-task.md","status":"done","created_at":"2026-05-15","updated_at":"2026-05-15"}]}
|
||||
{"type":"discussion","id":"DSC-0034","status":"done","ticket":"system-os-domain-facades","title":"Agenda - SystemOS Domain Facades","created_at":"2026-05-15","updated_at":"2026-05-15","tags":["runtime","os","services","api-surface","lifecycle","fs"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0043","file":"discussion/lessons/DSC-0034-system-os-domain-facades/LSN-0043-systemos-domain-facades.md","status":"done","created_at":"2026-05-15","updated_at":"2026-05-15"}]}
|
||||
|
||||
@ -0,0 +1,104 @@
|
||||
---
|
||||
id: LSN-0048
|
||||
ticket: vm-render-parallel-execution-boundary
|
||||
title: Render Workers Need a Closed Packet Contract
|
||||
created: 2026-06-06
|
||||
tags: [runtime, renderer, vm, concurrency, handoff, telemetry]
|
||||
---
|
||||
|
||||
## Context
|
||||
|
||||
`DSC-0040` took the runtime from a local "close and immediately render" model toward an architecture that can later support a real render worker, separate thread, separate core, or host-provided renderer.
|
||||
|
||||
The important result was not a real worker thread. The result was the contract a real worker must obey: the VM/logical side produces closed render submissions; the render side consumes those submissions without relying on live mutable VM, `Hardware`, `Gfx`, or `FrameComposer` state.
|
||||
|
||||
This work built on `DSC-0038`, where typed render submissions became the domain boundary. `DSC-0040` made that boundary operational by adding ownership, pacing, handoff, AppMode policy, shutdown semantics, and telemetry.
|
||||
|
||||
## Key Decisions
|
||||
|
||||
### Game Frames Are Closed Submissions
|
||||
|
||||
**What:** `RenderSubmissionPacket::Game2D` is the render consumer's complete frame description. The consumer must compose scene/layers/sprites first and then apply `gfx2d` primitives as the final overlay.
|
||||
|
||||
**Why:** A worker cannot safely reconstruct a frame from live runtime state. If an active-scene path bypasses the packet and calls a live `FrameComposer` path, the packet is no longer a true handoff boundary.
|
||||
|
||||
**Trade-offs:** Keeping packets small means heavy resources are referenced by stable IDs rather than copied per frame. That requires disciplined resource lifetime and read-only access APIs.
|
||||
|
||||
### Handoff Is Single-Slot Latest-Wins
|
||||
|
||||
**What:** The producer writes one pending submission. A newer submission replaces an older unconsumed one, and the replacement is telemetry.
|
||||
|
||||
**Why:** Render queues should not accumulate stale game frames. Latest-wins bounds memory, latency, and stale presentation risk.
|
||||
|
||||
**Trade-offs:** The system does not guarantee that every produced frame is consumed or presented. VM semantics must not depend on present acknowledgement.
|
||||
|
||||
### Frame Pacing Is Not Render ACK
|
||||
|
||||
**What:** Game logical frames are paced by a frame scheduler, not by render completion. `FRAME_SYNC` remains the logical frame boundary.
|
||||
|
||||
**Why:** Letting the worker decide when the VM may advance mixes display/raster completion with logical simulation authority. The VM should not run freely, but it also should not wait for a specific render ACK.
|
||||
|
||||
**Trade-offs:** A delayed render consumer repeats the last valid frame, while logical frames remain sequential. Overruns are diagnostics and telemetry, not hidden catch-up simulation.
|
||||
|
||||
### AppMode Owns Render Policy
|
||||
|
||||
**What:** Game workloads are frame-paced and worker-capable with local fallback. Shell/System UI remains lifecycle-driven and local/synchronous by default.
|
||||
|
||||
**Why:** A Shell app has a different lifecycle from a game loop. Treating Shell as just another game renderer would force unnecessary frame pacing and worker semantics into UI flows.
|
||||
|
||||
**Trade-offs:** The packet boundary is shared, but execution policy differs by AppMode. Future Shell worker support should be a separate decision, not an accidental inheritance from Game.
|
||||
|
||||
### Epoch Guards Presentation
|
||||
|
||||
**What:** Submissions carry render ownership. Foreground visual-owner changes update the active render epoch, and stale submissions are discarded before present.
|
||||
|
||||
**Why:** A worker may finish old work after the visible owner has changed. Without an epoch check, old Game, Shell, splash, or crash frames can be presented after they are no longer valid.
|
||||
|
||||
**Trade-offs:** Epoch protects correctness, but it does not solve foreground stack policy. Game pause/resume and VM-backed Shell coexistence belong to lifecycle/SystemOS discussions.
|
||||
|
||||
## Patterns and Algorithms
|
||||
|
||||
The durable pattern is:
|
||||
|
||||
```text
|
||||
logical core / VM
|
||||
-> close typed RenderSubmission
|
||||
-> publish to single pending slot
|
||||
-> render consumer takes owned submission
|
||||
-> validate ownership/epoch
|
||||
-> rasterize from packet + read-only resources
|
||||
-> present or repeat last valid frame
|
||||
-> report telemetry
|
||||
```
|
||||
|
||||
The render manager is a coordinator, not a renderer. It owns policy, frame IDs, handoff, ownership, shutdown state, and telemetry. Concrete raster/present capability belongs to a render surface, backend, host, HAL, or future worker implementation.
|
||||
|
||||
The current `LocalRenderWorker` is intentionally a prototype. It proves the same policy path can select a worker-capable consumer, but it does not prove thread ownership, bounded join, stop token behavior for in-flight work, or a real 60Hz present loop.
|
||||
|
||||
## Pitfalls
|
||||
|
||||
### Treating overlay commands as background setup
|
||||
|
||||
Once `gfx2d` is a final overlay, `gfx2d.clear` in a scene-backed game frame clears over the composed scene and sprites. That is a cartridge/framework discipline issue: scene-backed games should not use final overlay clear as world background initialization.
|
||||
|
||||
### Consulting live composer state during packet consumption
|
||||
|
||||
The active-scene consumer must not decide from live `FrameComposer` state whether a packet has a scene. It must read `packet.composer.bound_scene`. Otherwise the worker boundary silently depends on mutable state that may already belong to a different logical frame.
|
||||
|
||||
### Counting telemetry without behavior
|
||||
|
||||
Counters such as repeated presents and shutdown discards are useful only if later worker work connects them to real display cadence and real in-flight cancellation. The local implementation establishes the surface; a real worker still needs behavior behind it.
|
||||
|
||||
### Assuming read-only banks solve viewport cache
|
||||
|
||||
Read-only glyph and scene bank access is only part of the worker boundary. The viewport cache and resolver path still need a concrete read-only or ownership model before a real threaded worker can rasterize without live `FrameComposer`.
|
||||
|
||||
## Takeaways
|
||||
|
||||
- A render worker is first a contract problem, then a threading problem.
|
||||
- Closed packets must be complete enough to render without live VM/runtime state.
|
||||
- Latest-wins handoff keeps render latency bounded and makes dropped frames observable.
|
||||
- Game pacing belongs to the frame scheduler; render completion is telemetry, not VM semantics.
|
||||
- Shell UI can share the packet concept without inheriting the Game frame loop.
|
||||
- Epoch checks are the guardrail that prevents obsolete visual owners from presenting stale work.
|
||||
- The real worker should be introduced as a separate discussion and plan, using this contract rather than reopening it.
|
||||
@ -1,729 +0,0 @@
|
||||
---
|
||||
id: AGD-0040
|
||||
ticket: vm-render-parallel-execution-boundary
|
||||
title: VM and Render Parallel Execution Boundary
|
||||
status: accepted
|
||||
created: 2026-06-04
|
||||
resolved:
|
||||
decision:
|
||||
tags: [runtime, renderer, vm, concurrency, architecture, perf]
|
||||
---
|
||||
|
||||
# Agenda - VM and Render Parallel Execution Boundary
|
||||
|
||||
## Contexto
|
||||
|
||||
`DSC-0038` estabeleceu `RenderSubmission` como snapshot fechado. A lesson `LSN-0047` registra explicitamente que uma submissao fechada e o primitivo util para concorrencia futura, mesmo que o v1 ainda consuma tudo de forma sincrona.
|
||||
|
||||
No codigo atual, `RenderManager` guarda apenas `latest_complete_submission`, fecha frames no fluxo da VM/runtime e publica para uma `RenderSurface` via chamada direta. Isso e correto para o v1, mas ainda nao decide como mover rasterizacao/publicacao para outra thread ou core.
|
||||
|
||||
A demanda aqui e separar a VM continuando em um core/thread de execucao logica enquanto o pipeline grafico consome submissions fechadas em outro worker/core, sem acesso mutavel vivo a VM, `Hardware` ou `Gfx`.
|
||||
|
||||
## Problema
|
||||
|
||||
Prometeu ainda nao tem contrato operacional para paralelismo VM/render.
|
||||
|
||||
A fronteira de dados ja aponta a direcao, mas faltam decisoes sobre:
|
||||
|
||||
- quem cria e possui a fila ou slot de submissao;
|
||||
- se a politica `latest complete submission wins` basta quando ha worker real;
|
||||
- como lidar com frame pacing, backpressure e queda de frames;
|
||||
- quais recursos podem ser compartilhados read-only;
|
||||
- como manter determinismo da VM;
|
||||
- como representar isso em desktop host, handheld proprio e testes;
|
||||
- se o render worker e parte do runtime, do host, da HAL ou apenas uma abstracao futura.
|
||||
|
||||
## Pontos Criticos
|
||||
|
||||
### 1. A VM nao pode depender do consumidor de render
|
||||
|
||||
A VM deve produzir estado/comandos e avançar segundo seu proprio budget. O render worker pode atrasar, pular frames ou publicar a ultima submissao completa, mas nao deve exigir acesso mutavel ao estado vivo da VM para rasterizar.
|
||||
|
||||
### 2. Snapshot fechado nao e automaticamente thread-safe
|
||||
|
||||
`RenderSubmission` owned ajuda, mas qualquer referencia indireta a assets, scene cache, bancos de glyphs ou surfaces precisa ter politica clara: copia, handle estavel, Arc/read-only, snapshot de recurso, ou acesso mediado.
|
||||
|
||||
### 3. `latest complete submission wins` precisa virar protocolo
|
||||
|
||||
Como principio, nao queremos fila infinita. Mas uma implementacao com worker precisa decidir se usa single-slot atomico, double/triple buffering, canal bounded, sequence numbers, acknowledgements ou outro mecanismo.
|
||||
|
||||
### 4. Frame pacing muda quando render sai do fluxo principal
|
||||
|
||||
Hoje tick, fechamento de frame, consumo e host presentation estao acoplados. Com worker separado, a VM pode produzir mais rapido que o render ou o render pode apresentar em cadencia diferente. Isso precisa de uma regra de tempo.
|
||||
|
||||
### 5. Desktop thread nao e automaticamente modelo de handheld core
|
||||
|
||||
No host desktop, a implementacao natural pode ser uma thread. No hardware proprio, pode ser outro core, DMA, coprocessador, scanout ou rotina cooperativa. A decisao deve separar contrato runtime de implementacao host.
|
||||
|
||||
## Opcoes
|
||||
|
||||
### Opcao A - Manter consumo sincrono, apenas preservar contrato de snapshot
|
||||
|
||||
**Abordagem:**
|
||||
|
||||
Nao criar worker agora. Consolidar somente as invariantes: submissions owned/fechadas, sem acesso mutavel vivo durante consumo, e testes que impedem regressao para immediate rendering.
|
||||
|
||||
**Pro:**
|
||||
|
||||
- menor risco;
|
||||
- evita concorrencia prematura;
|
||||
- mantem foco em estabilizar o novo renderer;
|
||||
- ainda prepara a arquitetura.
|
||||
|
||||
**Con:**
|
||||
|
||||
- nao reduz latencia/custo no curto prazo;
|
||||
- pode adiar decisoes dificeis sobre recursos compartilhados;
|
||||
- o codigo pode voltar a assumir consumo sincrono se nao houver guardrails.
|
||||
|
||||
**Maintainability:**
|
||||
|
||||
Alta como etapa intermediaria, mas incompleta para a demanda de core/thread separado.
|
||||
|
||||
### Opcao B - Render worker com slot bounded `latest-complete`
|
||||
|
||||
**Abordagem:**
|
||||
|
||||
Criar um worker de render que consome um slot/canal bounded de `RenderSubmission`. O produtor substitui a submissao pendente quando uma mais nova fica pronta; o consumidor sempre pega a ultima completa disponivel.
|
||||
|
||||
**Pro:**
|
||||
|
||||
- implementa a politica ja aceita;
|
||||
- evita fila infinita;
|
||||
- desacopla VM e rasterizacao;
|
||||
- aproxima desktop e hardware proprio por contrato de single/latest slot.
|
||||
|
||||
**Con:**
|
||||
|
||||
- exige `Send`/ownership/read-only real nos dados;
|
||||
- precisa regra de shutdown, erro e sincronizacao;
|
||||
- pode mascarar frames descartados sem telemetria adequada.
|
||||
|
||||
**Maintainability:**
|
||||
|
||||
Boa se o protocolo for pequeno e testavel.
|
||||
|
||||
### Opcao C - Fila bounded com N submissions
|
||||
|
||||
**Abordagem:**
|
||||
|
||||
Usar canal bounded com 2 ou 3 submissions para suavizar picos e permitir que o render trabalhe atrasado.
|
||||
|
||||
**Pro:**
|
||||
|
||||
- simples em desktop;
|
||||
- reduz bloqueios imediatos;
|
||||
- permite medicao de atraso.
|
||||
|
||||
**Con:**
|
||||
|
||||
- contradiz parcialmente latest-wins se N crescer;
|
||||
- aumenta memoria e latencia;
|
||||
- pode apresentar frames velhos;
|
||||
- menos adequado para handheld com memoria restrita.
|
||||
|
||||
**Maintainability:**
|
||||
|
||||
Media. Pode ser util como implementacao, mas precisa de regra forte para descarte.
|
||||
|
||||
### Opcao D - Render thread como detalhe exclusivo do host desktop
|
||||
|
||||
**Abordagem:**
|
||||
|
||||
Mover rasterizacao/publicacao para thread do host, sem mudar contrato runtime/HAL.
|
||||
|
||||
**Pro:**
|
||||
|
||||
- melhora desktop sem mexer no console;
|
||||
- menor impacto no runtime;
|
||||
- facilita experimentos.
|
||||
|
||||
**Con:**
|
||||
|
||||
- pode criar divergencia entre host e alvo real;
|
||||
- nao resolve contrato para hardware proprio;
|
||||
- risco de esconder dependencia mutavel por baixo do host.
|
||||
|
||||
**Maintainability:**
|
||||
|
||||
Media a baixa como solucao canonica. Boa apenas para experimento ou profiling.
|
||||
|
||||
## Sugestao / Recomendacao
|
||||
|
||||
A recomendacao inicial e uma decisao em duas fases:
|
||||
|
||||
1. Fechar agora as invariantes da Opcao A como contrato obrigatorio.
|
||||
2. Planejar a Opcao B como primeiro modelo real de worker quando a base estiver pronta.
|
||||
|
||||
O contrato desejado deve ser:
|
||||
|
||||
```text
|
||||
VM/runtime core
|
||||
builds domain buffers
|
||||
closes RenderSubmission snapshot
|
||||
publishes latest complete submission to bounded handoff
|
||||
|
||||
render worker/core
|
||||
takes latest complete submission
|
||||
consumes immutable packet/resource handles
|
||||
rasterizes/publishes through RenderSurface
|
||||
reports telemetry/backpressure
|
||||
```
|
||||
|
||||
O worker nao deve receber `&mut Hardware`, `&mut Gfx`, `&mut VirtualMachineRuntime` ou ponte que permita voltar ao estado vivo da VM.
|
||||
|
||||
## Perguntas Respondidas
|
||||
|
||||
- [x] O handoff deve ser single-slot latest-wins, canal bounded N=2, ou outro protocolo?
|
||||
- Resposta: single-slot latest-wins, sem bloquear VM/produtor.
|
||||
- [x] Quais tipos dentro de `RenderSubmission` precisam ser `Send + Sync` ou owned?
|
||||
- Resposta: submissions/packets cruzam a fronteira como dados owned pequenos; APIs read-only compartilhadas de bancos/cache precisam provar seguranca de compartilhamento antes do worker real.
|
||||
- [x] Como assets, scene cache e glyph banks cruzam a fronteira sem copia pesada?
|
||||
- Resposta: por IDs/handles estaveis e APIs read-only; bancos sao imutaveis por contrato, e o viewport cache pertence ao core logico.
|
||||
- [x] Quem e dono do worker: `RenderManager`, host desktop, SystemOS service ou HAL?
|
||||
- Resposta: `SystemOS`/lifecycle decide politica/AppMode; `RenderManager` coordena handoff, epoch, ownership e telemetry; host/HAL fornece capacidades e execucao concreta.
|
||||
- [x] O render worker pode bloquear a VM ou apenas descartar/substituir submissions?
|
||||
- Resposta: nao bloqueia a VM/produtor; descarta/substitui pending submissions conforme latest-wins.
|
||||
- [x] Como medir frames produzidos, consumidos, descartados e apresentados?
|
||||
- Resposta: counters e ultimos frame IDs separados para produced, replaced/dropped, consumed, presented, repeated, errors e stale epoch discards.
|
||||
- [x] Como shutdown, crash, mode transition e troca de cart interagem com worker?
|
||||
- Resposta: transicoes incrementam epoch/generation, invalidam pending/current obsoletos e impedem present de frames do owner anterior.
|
||||
- [x] Qual parte deve ser especificada agora e qual deve esperar implementacao real?
|
||||
- Resposta: especificar agora o contrato de packet fechado, handoff latest-wins, frame pacing, AppMode policy, epoch ownership e telemetry minima; implementacao concreta do worker/render backend fica para decision/plan posterior.
|
||||
|
||||
## Grandes Problemas Esperados
|
||||
|
||||
### Topico 1 - Game2DFramePacket como snapshot completo
|
||||
|
||||
**Status:** direcao respondida; execucao pendente.
|
||||
|
||||
**Pergunta de fechamento:** o consumidor de `RenderSubmissionPacket::Game2D` consegue compor o frame completo a partir do packet fechado, sem depender de caminho alternativo por estado vivo?
|
||||
|
||||
Hoje `Hardware::publish_render_submission` ignora parte do `Game2DFramePacket` quando ha scene ativa, porque chama `frame_composer.render_frame(&mut self.gfx)` em vez de consumir o packet completo. Isso quebra a premissa de que o worker pode receber um snapshot fechado e rasterizar sem estado vivo.
|
||||
|
||||
Antes de qualquer render worker, `Game2DFramePacket` precisa ser a fonte completa de composicao: scene/layers/sprites, `gfx2d` overlay e publicacao.
|
||||
|
||||
**Direcao atual:** nao ha debate arquitetural relevante restante para este topico. `gfx2d` deve ser overlay apos a composicao Game 2D, e o consumidor de `RenderSubmissionPacket::Game2D` deve aplicar a mesma ordem em frames com scene ativa e sem scene ativa. O que falta e corrigir o caminho atual que contorna o packet quando ha scene ativa e adicionar teste de regressao cobrindo scene ativa + primitive overlay.
|
||||
|
||||
### Topico 2 - Recursos pesados e fronteira read-only
|
||||
|
||||
**Status:** direcao respondida.
|
||||
|
||||
**Pergunta de fechamento:** como scene cache, glyph banks, memory banks, assets e recursos futuros cruzam a fronteira sem `&mut Hardware`, `&mut Gfx` ou `FrameComposer` vivo?
|
||||
|
||||
`RenderSubmission` e owned, mas a composicao real ainda depende de `FrameComposer`, scene cache, resolver, glyph banks, memory banks e `Gfx`. Um worker nao pode receber `&mut Hardware` nem consultar `FrameComposer` vivo. Precisamos decidir como recursos pesados entram no snapshot: handles estaveis, `Arc` read-only, snapshots pequenos, ou acesso mediado.
|
||||
|
||||
**O que falta discutir:** o ponto nao e copiar todos os recursos pesados para dentro do packet. Isso seria caro e provavelmente errado. O que falta e separar tres categorias:
|
||||
|
||||
- estado de frame que deve estar no packet fechado: camera, scene binding, sprites, HUD, primitives, copy/update requests ja calculados;
|
||||
- recursos residentes grandes que podem ser referenciados por handle/slot e lidos via `Arc`/read-only: glyph banks, scene banks, caches materializados;
|
||||
- estado mutavel de preparacao que deve ficar no core logico antes do handoff: resolver update, cache refresh, asset installation, bank residency changes.
|
||||
|
||||
**Direcao provavel:** o render worker deve receber um snapshot pequeno com comandos e handles estaveis, mais acesso read-only aos bancos/caches necessarios. A atualizacao de resolver/cache e a instalacao/troca de assets devem acontecer antes do handoff, no core logico ou em um servico proprietario, nunca durante rasterizacao no worker.
|
||||
|
||||
**Perguntas respondidas:**
|
||||
|
||||
- [x] O `Game2DFramePacket` deve carregar apenas `BoundScenePacket { bank_id }` ou tambem um snapshot/read handle do cache materializado?
|
||||
- Resposta: IDs somente. Os bancos sao imutaveis por definicao; o packet nao deve capturar handles pesados por frame.
|
||||
- [x] O cache de viewport pertence ao produtor logico, ao render worker, ou a um recurso compartilhado read-only apos refresh?
|
||||
- Resposta: o viewport cache pertence ao core logico. O render worker deve acessa-lo apenas por uma API de leitura.
|
||||
- [x] Uma troca de asset/bank pode invalidar recursos enquanto uma submission antiga ainda esta sendo rasterizada?
|
||||
- Resposta: a submission aponta por ID para o recurso. Se o recurso for trocado, a submission ainda pode executar e o resultado pode ficar confuso/diferente. Disciplina de troca de assets e responsabilidade do dev ou framework.
|
||||
- [x] O handoff deve capturar `Arc<GlyphBank>`/`Arc<SceneBank>` por frame para garantir liveness, ou apenas IDs de slot com regra de nao substituir enquanto houver frame em voo?
|
||||
- Resposta: somente IDs. Nao vamos garantir integridade do resultado por captura de recurso; disciplina de troca e responsabilidade do dev ou framework.
|
||||
- [x] Quais tipos precisam provar `Send + Sync` antes de qualquer worker real?
|
||||
- Esclarecimento: esta pergunta e tecnica. Em Rust, qualquer dado/API compartilhado entre threads precisa ser seguro para envio/leitura concorrente. Com a resposta "IDs somente" no packet, a exigencia sai do `Game2DFramePacket` pesado e recai principalmente sobre a API de leitura dos bancos/cache e sobre o protocolo de handoff.
|
||||
- Resposta: essa prova fica como criterio tecnico de implementacao do worker real; a decisao arquitetural e que a fronteira compartilhada deve ser owned ou read-only, sem `&mut Hardware`, `&mut Gfx`, `FrameComposer` vivo ou acesso mutavel a VM.
|
||||
|
||||
**Direcao respondida:** packet pequeno com IDs, bancos imutaveis por contrato, viewport cache pertencente ao core logico e acesso do worker por API read-only. O sistema nao deve tentar garantir integridade visual de submissions antigas contra troca disciplinarmente incorreta de assets/banks; essa disciplina pertence ao dev/framework.
|
||||
|
||||
### Topico 3 - Protocolo de handoff latest-wins
|
||||
|
||||
**Status:** direcao respondida.
|
||||
|
||||
**Pergunta de fechamento:** qual protocolo substitui o `Option<RenderSubmission>` local quando houver outro core/thread?
|
||||
|
||||
O `latest_complete_submission` atual e apenas um `Option<RenderSubmission>` dentro do runtime. Para outro core/thread, isso precisa virar protocolo: single-slot latest-wins, canal bounded, sequence numbers, descarte, acknowledgement e telemetria.
|
||||
|
||||
**O que falta discutir:** este topico define o contrato de handoff, nao a politica de frame pacing completa. Precisamos escolher como uma submission sai do core logico e chega ao render worker:
|
||||
|
||||
- single-slot latest-wins: produtor substitui a submission pendente por uma mais nova, e o worker consome a ultima disponivel;
|
||||
- canal bounded N=1/2: produtor tenta enviar, e o protocolo decide se descarta antigo, descarta novo ou bloqueia;
|
||||
- acknowledgement: worker informa qual `frame_id` consumiu/apresentou, ou o produtor apenas publica e esquece;
|
||||
- ownership: a submission e movida para o handoff ou clonada do `RenderManager`;
|
||||
- sequence numbers: `frame_id` basta ou precisamos de counters separados para produzido/consumido/apresentado;
|
||||
- escopo por pipeline: Game pode usar handoff; Shell pode publicar sincrono.
|
||||
|
||||
**Direcao provavel:** para o primeiro modelo real, preferir single-slot latest-wins, sem fila crescente e sem bloquear a VM. `RenderManager` deixa de ser apenas dono de `Option<RenderSubmission>` e passa a publicar uma submission fechada para um handoff pequeno. O worker pega a ultima submission disponivel; se uma submission antiga for substituida antes do consumo, isso conta como drop/substituicao mensuravel.
|
||||
|
||||
**Direcao aceita:** single-slot latest-wins, sem bloquear a VM/produtor.
|
||||
|
||||
**Perguntas respondidas:**
|
||||
|
||||
- [x] O slot guarda exatamente uma pending submission alem da currently rendering, ou apenas a ultima submission atomica disponivel?
|
||||
- Resposta: o handoff guarda uma pending submission owned. Se o worker ja pegou uma submission, ela esta fora do slot e em consumo. O slot representa apenas a proxima/latest pending.
|
||||
- [x] Quando o worker esta renderizando frame N e o core produz N+1 e N+2, N+1 deve ser descartado?
|
||||
- Resposta: sim. `N+2` substitui `N+1` se `N+1` ainda nao foi retirado pelo worker. Isso e counted como replaced/dropped-before-consume.
|
||||
- [x] O produtor precisa saber que uma submission foi consumida, ou so que foi substituida/publicada?
|
||||
- Resposta: o produtor nao espera acknowledgement para continuar. O worker deve reportar consumed/presented como telemetria assíncrona, mas isso nao bloqueia nem participa da progressao da VM.
|
||||
- Observacao: a preocupacao restante e a semantica do `tick`. Hoje VM e render estao dentro do mesmo tick sincrono. Com worker, o tick deve fechar/publicar a submission, mas nao esperar ACK de render. A relacao entre tick, present efetivo e telemetria fica para o Topico 4.
|
||||
- [x] `frame_id` e suficiente para telemetria, ou precisamos de contadores separados de produced/dropped/consumed/presented?
|
||||
- Resposta: `frame_id` e suficiente para ordenacao, mas nao para observabilidade. Precisamos de contadores separados: produced, replaced/dropped-before-consume, consumed, presented, render_errors/present_errors, e ultimos frame ids por etapa.
|
||||
- [x] Shell UI fica fora do protocolo worker por default, ou usa o mesmo handoff quando configurado?
|
||||
- Resposta: Shell UI fica fora por default e pode continuar sincrono/local. O mesmo protocolo pode ser reutilizado se uma configuracao futura quiser worker para Shell, mas a politica inicial e por pipeline/AppMode.
|
||||
|
||||
**Direcao respondida:** o protocolo base e single-slot latest-wins com ownership moved para o handoff, pending slot substituivel, worker consumindo owned submission, VM/produtor nunca bloqueado, ack apenas para telemetria e politica por pipeline.
|
||||
|
||||
Confirmacoes de 2026-06-04:
|
||||
|
||||
- ownership moved para o handoff: aceito;
|
||||
- produtor sem ACK bloqueante: aceito, com a preocupacao de definir a nova semantica de tick;
|
||||
- contadores separados: seguir com essa direcao;
|
||||
- Shell UI fora do worker por default: aceito.
|
||||
|
||||
### Topico 4 - Frame pacing e backpressure
|
||||
|
||||
**Status:** direcao respondida.
|
||||
|
||||
**Pergunta de fechamento:** a VM bloqueia, descarta, substitui ou apenas mede atraso quando o render worker esta atrasado?
|
||||
|
||||
Hoje tick, fechamento, raster e present acontecem no mesmo fluxo. Com worker separado, a VM pode produzir frames mais rapido que o render consome, ou o render pode apresentar em outra cadencia. Precisamos decidir se a VM bloqueia, descarta, substitui, ou apenas mede atraso.
|
||||
|
||||
**Direcao em discussao:** se o render real for para worker/core, o `present` passa a ser responsabilidade do worker/render surface e deve mirar a cadencia de display, inicialmente 60Hz. O worker nao consome uma fila crescente; ele consome a latest submission disponivel pelo protocolo single-slot e apresenta em sua cadencia.
|
||||
|
||||
O core logico/VM deixa de precisar reservar tempo de render dentro do mesmo tick sincrono, mas nao deve rodar livremente. O frame logico da VM e parte do modelo de tempo do jogo: animacoes, input, scripts e simulacao dependem dele. Portanto, a VM deve continuar paced por frame logico, mirando 1:1 com a cadencia do worker/display sempre que possivel.
|
||||
|
||||
Idealmente, ha relacao 1:1:
|
||||
|
||||
```text
|
||||
1 logical VM frame
|
||||
-> 1 RenderSubmission
|
||||
-> 1 presented worker frame
|
||||
```
|
||||
|
||||
Mas o contrato nao deve depender de sempre conseguir isso. A direcao revisada e:
|
||||
|
||||
- o worker/render surface e dono do `present` em 60Hz;
|
||||
- o worker apresenta o ultimo frame processado/disponivel;
|
||||
- quando o worker aceita/pega uma nova submission para apresentacao, isso avanca o frame counter visivel;
|
||||
- se a VM ainda nao disponibilizou uma nova submission, o worker mantem a ultima renderizacao e registra skip/no-new-frame;
|
||||
- a VM nao roda frames logicos ilimitados a frente do display; ela so deve iniciar novo frame logico quando a cadencia permitir produzir o proximo frame esperado;
|
||||
- se o worker ainda esta processando um frame anterior, a VM pode preparar/publicar o proximo frame logico dentro do limite 1:1, mas nao deve acumular multiplos frames logicos pendentes.
|
||||
|
||||
Isso muda a leitura do latest-wins: ele continua util para substituir uma pending submission que ainda nao foi pega pelo worker, mas nao deve virar autorizacao para a VM rodar muito a frente do display. O objetivo e desacoplar custo de raster/present, nao desacoplar o tempo logico do jogo da cadencia de frame.
|
||||
|
||||
Se o worker nao rasterizar dentro do budget de 60Hz, o sistema deve contar atraso/drop/skip em telemetria. A VM nao deve bloquear esperando ACK de render, mas deve respeitar o pace de frame logico definido pelo display/worker.
|
||||
|
||||
Refinamento importante:
|
||||
|
||||
A VM nao espera ACK de render/present de uma submission especifica, mas deve esperar a autorizacao de pace derivada do frame counter/display. Ou seja, o render worker nao confirma "terminei seu frame N, pode seguir"; em vez disso, o sistema avanca uma cadencia de frame e a VM so inicia o proximo logical frame quando essa cadencia permite. Isso evita que a VM rode livremente sem transformar present em bloqueio sincrono.
|
||||
|
||||
### Corner cases de frame pacing
|
||||
|
||||
1. Worker em 60Hz, VM pronta antes do proximo refresh.
|
||||
- A VM deve ficar aguardando o proximo frame pace para iniciar novo logical frame.
|
||||
- Nao deve produzir multiplas submissions futuras.
|
||||
|
||||
2. Worker apresenta refresh sem nova submission.
|
||||
- O worker repete/mantem a ultima renderizacao.
|
||||
- O sistema registra skip/no-new-frame.
|
||||
- O frame counter visivel pode avancar, mas a VM nao deve simular um novo logical frame retroativamente.
|
||||
|
||||
3. VM produz submission, worker ainda esta rasterizando frame anterior.
|
||||
- A submission nova fica no single-slot pending.
|
||||
- Se outra submission fosse produzida antes do worker pegar a pending, ela substituiria a pending; porem o pace da VM deve impedir esse acúmulo na pratica.
|
||||
|
||||
4. Worker pega pending submission para rasterizar.
|
||||
- A pending sai do slot e passa a pertencer ao worker.
|
||||
- A VM nao espera ACK dessa submission, mas so inicia novo logical frame quando o pace permitir.
|
||||
|
||||
5. Worker perde prazo de 16.67ms.
|
||||
- O sistema registra atraso/render-overrun.
|
||||
- A VM nao deve tentar compensar produzindo frames extras.
|
||||
- A proxima permissao de logical frame deve seguir a politica de pace, nao backlog.
|
||||
|
||||
6. VM demora mais que a janela esperada de logical frame.
|
||||
- O runtime nao deve encerrar o frame por budget como mecanismo normal.
|
||||
- `FRAME_SYNC` continua sendo o fim canonico do logical frame.
|
||||
- O sistema registra logical-frame-overrun para certificacao/watchdog/diagnostico.
|
||||
- O worker continua apresentando a ultima renderizacao.
|
||||
- Quando a VM finalmente publica a submission, ela representa o proximo logical frame sequencial, nao um frame pulado.
|
||||
|
||||
7. Mode transition Game/Shell enquanto ha pending ou currently-rendering submission.
|
||||
- A submission antiga nao deve ser apresentada depois que o modo mudou, a menos que a politica de transition permita explicitamente.
|
||||
- O handoff precisa carregar generation/mode epoch ou equivalente para invalidar frames obsoletos.
|
||||
|
||||
8. Cartridge/app troca enquanto worker tem frame antigo.
|
||||
- Submissions de app/cart anterior devem ser descartadas por generation/epoch.
|
||||
- O worker deve limpar ou substituir a surface conforme politica de lifecycle.
|
||||
|
||||
9. Crash/panic durante logical frame antes de publicar submission.
|
||||
- O worker segue apresentando ultimo frame valido ate receber crash/shell submission.
|
||||
- O crash path deve poder invalidar pending game frame.
|
||||
|
||||
10. Crash/panic no render worker.
|
||||
- Nao pode corromper determinismo da VM.
|
||||
- Deve virar telemetria/erro de render e possivelmente fallback para sync/local render ou crash surface.
|
||||
|
||||
11. Input sampling.
|
||||
- Input deve ser amostrado no inicio do logical frame autorizado pelo pace.
|
||||
- Se o worker repetir frame por falta de submission nova, nao deve haver novo input sampling/logical update correspondente.
|
||||
|
||||
12. Frame counter semantics.
|
||||
- Precisamos separar pelo menos logical_frame_id, produced_submission_frame_id e presented_frame_id.
|
||||
- O frame counter que autoriza a VM deve representar cadencia logica/display, nao ACK de uma submission especifica.
|
||||
|
||||
### Avaliacao de desenho
|
||||
|
||||
O desenho fica mais complexo se o render worker tambem virar a autoridade do frame counter que libera a VM. Isso mistura duas responsabilidades:
|
||||
|
||||
- cadencia logica do sistema;
|
||||
- consumo/rasterizacao/publicacao de submissions.
|
||||
|
||||
Uma alternativa mais limpa e introduzir uma autoridade de pace separada, por exemplo `FrameClock` ou scheduler de frame, que emite ticks de 60Hz. A VM e o render worker observam essa cadencia, mas nenhum dos dois e dono exclusivo dela.
|
||||
|
||||
Modelo preferido para reduzir complexidade:
|
||||
|
||||
```text
|
||||
FrameClock / frame scheduler
|
||||
emits 60Hz frame ticks
|
||||
|
||||
VM/core logico
|
||||
runs at most one logical frame per frame tick
|
||||
samples input on authorized logical frame
|
||||
publishes at most one latest submission
|
||||
|
||||
render worker/surface
|
||||
presents on display cadence
|
||||
consumes latest available submission
|
||||
repeats last rendered frame if no new submission exists
|
||||
```
|
||||
|
||||
Assim, a VM nao espera ACK do worker e tambem nao roda livremente. Ela espera o frame clock. O worker nao precisa "desbloquear" a VM; ele apenas consome e apresenta. Isso preserva 1:1 como alvo sem acoplar progresso logico a sucesso/falha de rasterizacao.
|
||||
|
||||
Conclusao provisoria: preferir `FrameClock`/scheduler como autoridade de cadencia, `RenderManager` como produtor de submissions, e render worker como consumidor/presenter. Evitar que o worker seja dono do frame counter canonico.
|
||||
|
||||
Refinamento sobre Shell/App lifecycle:
|
||||
|
||||
O `FrameClock`/scheduler nao deve impor um game loop ao Shell. O loop de um game e diferente do lifecycle de um app UI, e em Prometeu o game loop e entregue no hardware/runtime como parte do modelo de console. Shell/SystemOS deve ser tratado como lifecycle/event-driven: input, janelas, foco, app lifecycle e invalidacao visual determinam quando ha trabalho logico ou render novo.
|
||||
|
||||
Portanto, `FrameClock` deve autorizar cadencia de logical frame para pipelines de game, mas Shell UI nao deve necessariamente consumir um frame logico de VM a cada 60Hz. Para Shell:
|
||||
|
||||
```text
|
||||
SystemOS/Shell lifecycle events
|
||||
-> input/window/app updates when needed
|
||||
-> build ShellUiFramePacket on invalidation/event
|
||||
-> present/repeat last surface as needed
|
||||
```
|
||||
|
||||
Isso reforca que `FrameScheduler` nao e "scheduler da VM". Ele e uma fonte de cadencia para workloads que precisam de frame pacing, especialmente Game2D/Game3D. Shell/App lifecycle pode usar outro modelo, com render por invalidacao ou por eventos, ainda que o host/display continue apresentando em 60Hz.
|
||||
|
||||
Resposta sobre budget e frames lentos:
|
||||
|
||||
`FRAME_SYNC` e o fim canonico do logical frame. O budget antigo era um mecanismo grosseiro para pausar a VM e permitir que o tick continuasse; nesse desenho ele nao deve ser usado como forma normal de encerrar ou cortar um frame logico.
|
||||
|
||||
Budget passa a existir para certificacao, watchdog, diagnostico e deteccao de overrun. Se um logical frame demora mais que aproximadamente 16.67ms, nao pulamos logical frames da VM para alcançar o display. Frames logicos devem ser sequenciais. O resultado visivel e stutter/repeticao do ultimo frame pelo worker, nao time-skip semantico.
|
||||
|
||||
```text
|
||||
VM logical frame N demora demais
|
||||
-> worker repete ultimo frame disponivel
|
||||
-> runtime registra overrun
|
||||
-> VM continua ate FRAME_SYNC/trap/halt/watchdog fatal
|
||||
-> submission publicada e N, nao N+k
|
||||
```
|
||||
|
||||
**Perguntas respondidas:**
|
||||
|
||||
- [x] O worker deve repetir o ultimo frame quando nao houver submission nova no refresh de 60Hz?
|
||||
- Resposta: sim. O worker mantem a ultima renderizacao e registra skip/no-new-frame.
|
||||
- [x] A VM deve continuar limitada a um logical frame por tick de sistema, ou pode produzir multiplas submissions entre presents?
|
||||
- Resposta: a VM nao deve produzir multiplos frames logicos a frente do display. O alvo e 1 logical frame por frame worker/display, com no maximo uma pending submission pelo protocolo latest-wins.
|
||||
- [x] `FRAME_SYNC` continua sendo o limite canonico de logical frame mesmo sem present sincrono?
|
||||
- Resposta: sim. `FRAME_SYNC` continua delimitando logical frame da VM. O present deixa de ser sincrono, mas o frame logico continua paced.
|
||||
- [x] Qual budget permanece na VM: ciclos/instrucoes por logical frame, tempo real, ou ambos?
|
||||
- Resposta: `FRAME_SYNC` encerra o logical frame. Budget nao e mecanismo normal de tick/frame advance. Budget/ciclos/tempo real ficam para certificacao, watchdog, diagnostico e overrun policy.
|
||||
- [x] Como detectar game rodando rapido demais se o render worker esta desacoplado?
|
||||
- Resposta: o runtime nao permite que a VM rode livremente a frente do frame counter/worker. A telemetria deve contar produced, accepted/presented e skips para detectar desalinhamento.
|
||||
|
||||
### Topico 5 - Politica por pipeline/AppMode
|
||||
|
||||
**Status:** direcao respondida; detalhamento de lifecycle movido para `DSC-0041`.
|
||||
|
||||
**Pergunta de fechamento:** quais pipelines devem poder usar worker e quais podem continuar sincronos/localmente?
|
||||
|
||||
Shell UI pode continuar sincrona/local. O contrato comum deve ser packet fechado, mas a politica de execucao deve variar por pipeline. Forcar Shell UI para render worker pode aumentar complexidade sem ganho.
|
||||
|
||||
**O que precisamos acertar:** este topico define a matriz de politica por `AppMode`/pipeline. O sistema hoje tem `AppMode::Game` e `AppMode::Shell`, mas esses modos nao devem receber a mesma semantica de loop/render.
|
||||
|
||||
Direcao ja encaminhada:
|
||||
|
||||
- `Game2D` e futuro `Game3D` sao workloads frame-paced. Devem poder usar `FrameScheduler` e render worker.
|
||||
- `ShellUi` e Shell/SystemOS sao lifecycle/event-driven. Devem poder continuar sincronos/localmente e renderizar por invalidacao/evento.
|
||||
- O contrato comum continua sendo `RenderSubmission` fechado.
|
||||
- A politica de execucao do consumidor pode variar por pipeline/AppMode.
|
||||
|
||||
**Perguntas respondidas:**
|
||||
|
||||
- [x] `AppMode::Game` sempre usa `FrameScheduler`, mesmo se o game nao tiver render pesado?
|
||||
- Resposta: sim. Game e frame-paced por definicao. Futuramente `AppMode::Game` pode virar algo mais explicito como `AppMode::Game2D`, mas cada AppMode deve ter uma politica de render explicita.
|
||||
- [x] `AppMode::Game` deve usar render worker por default, ou isso deve ser capability/configuracao de host?
|
||||
- Resposta: Game usa render worker por default quando o host/runtime suporta, com fallback sincrono/local.
|
||||
- [x] `AppMode::Shell` deve ficar explicitamente fora do `FrameScheduler` logico de game?
|
||||
- Resposta: sim. Shell nao herda game loop.
|
||||
- [x] Shell UI deve publicar sincrono/local por default, com worker apenas opt-in?
|
||||
- Resposta: sim. Shell UI e sincrono/local por default; worker so como opt-in futuro.
|
||||
- [x] Apps VM-backed dentro do Shell seguem lifecycle de Shell ou podem declarar workload frame-paced proprio?
|
||||
- Resposta: seguem lifecycle de Shell, sem direito a declarar workload frame-paced proprio.
|
||||
- [x] Firmware screens como splash/crash seguem politica Shell/local ou politica propria?
|
||||
- Resposta: seguem politica Shell/local.
|
||||
- [x] A escolha de politica fica no `RenderManager`, no SystemOS/lifecycle, ou em uma camada de host/runtime configuration?
|
||||
- Resposta: SystemOS/lifecycle decide o perfil/AppMode; `RenderManager` executa a politica; host/runtime fornece capacidades e fallback.
|
||||
|
||||
**Direcao respondida:** cada AppMode deve ter politica explicita de render. Game atual e frame-paced e pode usar worker por default quando disponivel. Shell e lifecycle/event-driven e sincrono/local por default. Apps VM-backed dentro do Shell seguem lifecycle de Shell, sem opt-in para game pacing proprio.
|
||||
|
||||
### Topico 6 - Lifecycle, transitions e ownership da surface
|
||||
|
||||
**Status:** direcao respondida; detalhamento de lifecycle movido para `DSC-0041`.
|
||||
|
||||
**Pergunta de fechamento:** quem possui a surface/submission durante troca Game/Shell, crash, splash, troca de cart e shutdown?
|
||||
|
||||
Troca Game/Shell, crash screen, splash, troca de cart e shutdown precisam saber quem possui a surface e qual submission ainda pode ser publicada. O worker nao pode ficar publicando frame velho depois que o modo ou cartridge mudou.
|
||||
|
||||
**O que precisamos acertar:** quando existe worker/render assíncrono, podem existir submissions em tres estados:
|
||||
|
||||
- pending no single-slot;
|
||||
- currently-rendering no worker;
|
||||
- ultimo frame apresentado/mantido na surface.
|
||||
|
||||
Lifecycle precisa dizer o que acontece com cada um quando o sistema muda de dono visual.
|
||||
|
||||
**Direcao provavel:** toda submission deve carregar um contexto de ownership alem de `frame_id` e `app_mode`, por exemplo `render_epoch`/`generation`, `app_id` ou `surface_owner`. O `RenderManager`/SystemOS incrementa essa generation quando troca app, cart, modo ou crash state. O worker deve descartar pending/current frames cujo ownership nao combine com o epoch ativo antes de apresentar.
|
||||
|
||||
**Perguntas respondidas para o escopo desta agenda:**
|
||||
|
||||
- [x] Troca Game -> Shell invalida imediatamente pending/current Game submissions?
|
||||
- Resposta: sim. A troca de foreground visual owner incrementa epoch/generation e torna obsoletas as submissions do owner anterior.
|
||||
- [x] Troca Shell -> Game deve limpar surface ou pode manter ultimo Shell frame ate primeiro Game frame?
|
||||
- Resposta: pode manter a ultima surface apresentada ate a primeira submission valida do novo owner, desde que nenhum frame antigo seja apresentado novamente como nova submission. Limpar e uma politica visual opcional.
|
||||
- [x] Crash screen invalida pending/current Game frame antes de publicar crash Shell/local frame?
|
||||
- Resposta: sim. Crash troca o owner visual para a tela de erro/sistema e deve invalidar frames pendentes/correntes do Game.
|
||||
- [x] Splash/crash/hub usam uma surface compartilhada ou ownership proprio?
|
||||
- Resposta: podem usar a mesma surface fisica, mas precisam de ownership logico proprio via epoch/generation/surface owner.
|
||||
- [x] Troca de cartridge/app incrementa `render_epoch` mesmo se `AppMode` continuar igual?
|
||||
- Resposta: sim. `AppMode` nao e identidade suficiente; troca de app/cart precisa invalidar submissions antigas.
|
||||
- [x] Worker pode terminar raster de um frame obsoleto, mas deve checar epoch antes de present?
|
||||
- Resposta: sim. O worker pode desperdiçar trabalho ja iniciado, mas nao pode apresentar se o epoch/owner nao for mais atual.
|
||||
- [x] Quem incrementa epoch: SystemOS/lifecycle, `RenderManager`, host, ou todos via API central?
|
||||
- Resposta: `SystemOS`/lifecycle decide a transicao semantica; `RenderManager` deve oferecer a API central que incrementa/aplica epoch. Host nao decide ownership.
|
||||
- [x] Shutdown deve drenar worker, cancelar pending/current, ou apenas parar present?
|
||||
- Resposta: shutdown deve parar present, descartar pending, invalidar current por epoch/stop token e encerrar/joinar o worker de forma bounded. Nao deve drenar frames obsoletos para a tela.
|
||||
|
||||
**Levantamento de material existente:**
|
||||
|
||||
- `DSC-0031` / `LSN-0040` ja estabeleceu `AppMode` como discriminador de perfil. Game e Shell/System usam a mesma VM/transporte internamente, mas nao compartilham o mesmo perfil autoral. Game segue pipeline de jogo; Shell/System segue pipeline Runtime/Hub.
|
||||
- `DSC-0032` / `LSN-0041` ja estabeleceu `SystemOS` como autoridade semantica de lifecycle para task/process. Firmware nao deve coordenar manualmente task/process fora dessa fronteira.
|
||||
- `DSC-0035` / `LSN-0044` ja estabeleceu que Shell liveness depende da janela focada pertencer ao proprio task; perder a janela elegivel fecha o Shell task via lifecycle e volta ao Hub.
|
||||
- `DSC-0036` / `LSN-0045` ja estabeleceu o fluxo visual/lifecycle `Hub/Home -> Shell app -> task-owned window -> close -> lifecycle close -> Hub/Home`.
|
||||
- `DSC-0038` / `LSN-0047` ja estabeleceu que `RenderManager` coordena active app mode, submission closure, transitions, capabilities e publication flow, mas sem virar renderer.
|
||||
|
||||
**Estado atual de implementacao:**
|
||||
|
||||
- Firmware possui estados explicitos (`GameRunning`, `ShellRunning`, `AppCrashes`, splash/hub/load) e `change_state` executa `on_exit`/`on_enter` imediatamente para evitar frames vazios.
|
||||
- `LoadCartridgeStep` roteia `AppMode::Shell` para task/window Shell e `ShellRunning`; caso contrario cria task de game e entra em `GameRunning`.
|
||||
- `GameRunningStep` exige task foreground e executa `ctx.os.vm().tick(...)`.
|
||||
- `ShellRunningStep` exige task foreground e janela focada pertencente ao task; caso contrario fecha pelo lifecycle e volta ao Hub.
|
||||
- `RenderManager` atual tem `RenderTransitionState::Pending { from, to }`, mas isso e placeholder/no-op: nao ha epoch/generation, invalidacao de pending/current frames, nem ownership de surface.
|
||||
|
||||
**Gap para este topico:** as politicas de lifecycle Game/Shell existem, mas ainda nao foram propagadas para ownership visual assíncrono. Para `DSC-0040`, a direcao e suficiente: toda transicao de foreground visual owner passa por uma API central do `RenderManager`, incrementa epoch/generation, invalida pending/current do owner anterior e impede present de frames obsoletos.
|
||||
|
||||
### Caso principal - Home durante Game e retorno ao Game
|
||||
|
||||
Cenario esperado:
|
||||
|
||||
```text
|
||||
GameRunning
|
||||
-> usuario aperta Home
|
||||
-> Game e suspenso/pausado como task foreground
|
||||
-> Hub/Home assume Shell UI
|
||||
-> usuario navega/checa algo no Shell
|
||||
-> usuario retorna ao Game
|
||||
-> Game volta como foreground
|
||||
```
|
||||
|
||||
Mesmo sem transicoes suaves, esse ciclo precisa funcionar. O estado atual cobre partes do modelo, mas nao o ciclo completo:
|
||||
|
||||
- ja existe `GameRunningStep` para game fullscreen foreground;
|
||||
- ja existe `HubHomeStep` e `ShellRunningStep` para Hub/Shell lifecycle;
|
||||
- ja existe lifecycle authority em `SystemOS`;
|
||||
- ja existe Shell task/window liveness;
|
||||
- ainda nao ha evidencia de um fluxo Home durante `GameRunning` que suspenda o game, entre no Hub, e depois retorne ao mesmo game;
|
||||
- o `RenderManager` so possui `RenderTransitionState::Pending { from, to }` como placeholder; nao ha ownership/epoch para invalidar frames de Game enquanto o Hub assume a surface.
|
||||
|
||||
Politica provavel para esse caso:
|
||||
|
||||
- Home em Game nao fecha o game; suspende/pausa o game task/process.
|
||||
- Ao entrar no Hub, qualquer pending/current Game submission deve ser invalidada por epoch/generation antes de Shell/Hub assumir a surface.
|
||||
- Hub/Shell renderiza local/sincrono por politica Shell.
|
||||
- Retornar ao Game incrementa epoch novamente e retoma o game task/process.
|
||||
- O primeiro frame de retorno ao Game deve vir de uma nova Game submission; ate la a surface pode manter ultimo Hub frame ou limpar conforme politica visual.
|
||||
- Transicoes suaves ficam fora do escopo; o requisito minimo e ownership correto e ausencia de frame obsoleto apresentado apos troca de dono.
|
||||
|
||||
Questao de escopo levantada:
|
||||
|
||||
No ciclo `Game -> Shell -> Game`, pode existir um game pausado e um app Shell VM-backed aberto ao mesmo tempo. Isso cruza render ownership com lifecycle/process policy.
|
||||
|
||||
Direcao provisoria para esta agenda:
|
||||
|
||||
- somente um Game foreground/pausado por vez;
|
||||
- somente um Shell foreground aberto por vez no v1;
|
||||
- background execution fica fora deste contrato;
|
||||
- Shell VM-backed durante Game pausado deve seguir lifecycle de Shell e nao ganha politica frame-paced propria;
|
||||
- a VM/game pausado nao deve continuar executando frames logicos enquanto o Shell VM-backed esta foreground;
|
||||
- a existencia simultanea de um Game pausado e um Shell VM-backed foreground precisa ser tratada como politica de SystemOS/lifecycle, nao como detalhe do render worker.
|
||||
|
||||
Essa pergunta foi separada na `DSC-0041`. Para `DSC-0040`, o ponto minimo esta respondido: render ownership deve acompanhar o foreground visual owner e invalidar submissions do owner anterior por epoch/generation.
|
||||
|
||||
### Topico 7 - Erros, drops e telemetria de render
|
||||
|
||||
**Status:** direcao respondida.
|
||||
|
||||
**Pergunta de fechamento:** quais eventos minimos o sistema registra para render produzido, consumido, descartado, atrasado, apresentado e com erro?
|
||||
|
||||
Quando rasterizacao sai do fluxo da VM, panic/erro de render, frame drop, atraso, consumo e present precisam ser reportados sem quebrar determinismo da VM. Sem telemetria minima, latest-wins pode esconder perda de frames.
|
||||
|
||||
**Direcao aceita:** render assíncrono e best-effort observavel, nao handshake semantico com a VM. A VM produz frames sequenciais no ritmo do `FrameScheduler`; o worker consome/apresenta o mais recente possivel; drops, repeats, erros e descartes por epoch/stale ownership aparecem em telemetry, mas nao alteram diretamente a semantica do programa dentro da VM.
|
||||
|
||||
**Contrato minimo:**
|
||||
|
||||
- a VM nao observa erro/drop de render como retorno sincrono nem como semantica de programa;
|
||||
- render telemetry e preocupacao de host/runtime/system, debugger, profiler e certificacao;
|
||||
- erro de raster descarta a submission afetada, registra telemetry e preserva o ultimo frame valido/surface atual quando possivel;
|
||||
- erro de present registra telemetry e pode escalar para politica de host/system fault se for recorrente;
|
||||
- panic no worker deve virar falha controlada de worker/backend, nao panic propagado para a VM;
|
||||
- o programa dentro da VM nao deve depender de confirmacao de present para avancar logica.
|
||||
|
||||
**Counters minimos:**
|
||||
|
||||
- `produced_submissions`;
|
||||
- `replaced_before_consume`;
|
||||
- `consumed_submissions`;
|
||||
- `presented_frames`;
|
||||
- `repeated_presents`;
|
||||
- `render_errors`;
|
||||
- `present_errors`;
|
||||
- `stale_epoch_discards`;
|
||||
- `shutdown_discards`.
|
||||
|
||||
**IDs/estado minimo:**
|
||||
|
||||
- `last_produced_frame_id`;
|
||||
- `last_consumed_frame_id`;
|
||||
- `last_presented_frame_id`;
|
||||
- `last_dropped_frame_id`;
|
||||
- `last_error_frame_id`;
|
||||
- `active_render_epoch`.
|
||||
|
||||
**Eventos minimos:**
|
||||
|
||||
- submission substituida no single-slot antes de consumo;
|
||||
- worker consumiu uma submission;
|
||||
- worker descartou submission por epoch/owner obsoleto;
|
||||
- worker apresentou frame;
|
||||
- worker repetiu ultimo frame por ausencia de submission nova;
|
||||
- erro de raster;
|
||||
- erro de present;
|
||||
- shutdown/cancel descartou pending/current.
|
||||
|
||||
## Fechamento dos Topicos
|
||||
|
||||
Esta agenda pode ser considerada madura para decisao quando os sete topicos acima tiverem uma resposta de direcao. As respostas nao precisam implementar render worker agora, mas precisam ser concretas o suficiente para produzir uma decision sem reabrir a arquitetura base durante o plan.
|
||||
|
||||
## Criterio para Encerrar
|
||||
|
||||
Esta agenda pode virar decisao quando houver consenso sobre:
|
||||
|
||||
- protocolo de handoff VM/render;
|
||||
- ownership de submissions e recursos compartilhados;
|
||||
- politica de backpressure;
|
||||
- fronteira entre runtime contract e implementacao host/hardware;
|
||||
- telemetria minima;
|
||||
- o que fica fora de escopo antes do primeiro worker real.
|
||||
|
||||
## Discussion
|
||||
|
||||
Aberta em 2026-06-04 apos verificar que `DSC-0038` preparou snapshots fechados e latest-wins, mas nao decidiu thread/core separado.
|
||||
|
||||
Atualizacao de 2026-06-04:
|
||||
|
||||
Antes de discutir worker/thread de render, precisamos fechar uma pre-condicao de composicao do pacote atual. A pergunta operacional foi: comandos de primitivas em `gfx2d` sao desenhados apos qualquer blit/raster dos layers?
|
||||
|
||||
O estado atual e misto:
|
||||
|
||||
- No caminho direto `Gfx::render_game2d_frame_packet`, `render_no_scene_frame()` roda antes e depois `packet.gfx2d` e aplicado. Nesse caso, primitivas ficam depois da composicao base.
|
||||
- No caminho real de `Hardware::publish_render_submission`, quando `frame_composer.active_scene_id().is_some()`, o codigo ignora o `Game2DFramePacket` recebido e chama `frame_composer.render_frame(&mut self.gfx)`.
|
||||
- `FrameComposer::render_frame` atualiza cache/resolver e chama `gfx.render_scene_from_cache(...)`, que faz o blit/raster dos layers, mas nao aplica `packet.gfx2d`.
|
||||
|
||||
Conclusao provisoria: para frames com scene ativa, ainda nao ha garantia de que `gfx2d` seja desenhado apos os layer blits; na pratica, esses comandos podem ser descartados nesse branch. Isso deve ser resolvido antes de transformar `RenderSubmission` em fronteira de handoff para outro worker/core, porque o worker precisa consumir o pacote fechado completo, nao reconstruir comportamento a partir de estado vivo do `FrameComposer`.
|
||||
|
||||
Resposta de direcao em 2026-06-04:
|
||||
|
||||
As primitivas `gfx2d` devem funcionar como overlay do frame Game 2D. Elas precisam ser desenhadas apos a composicao canonical de scene/layers/sprites tanto em frames sem scene ativa quanto em frames com scene ativa. O comportamento esperado e:
|
||||
|
||||
```text
|
||||
Game2D composer/layers/sprites
|
||||
-> gfx2d primitives overlay
|
||||
-> present/publication
|
||||
```
|
||||
|
||||
Isso implica que o branch com scene ativa em `Hardware::publish_render_submission` nao deve contornar o `Game2DFramePacket` nem perder `packet.gfx2d`. A solucao futura deve fazer o consumidor de `RenderSubmissionPacket::Game2D` aplicar a mesma ordem de composicao nos dois caminhos.
|
||||
|
||||
Essa regra tambem reforca a fronteira necessaria para render worker/thread: o pacote fechado deve conter tudo que o consumidor precisa para compor o frame visivel. O worker nao deve depender de chamar um caminho alternativo baseado em estado vivo do `FrameComposer` que ignora parte do packet.
|
||||
|
||||
Atualizacao sobre Shell UI em 2026-06-04:
|
||||
|
||||
`ShellUi` e `Game2D` sao separados no contrato e no roteamento, mas compartilham os mesmos helpers finais de desenho no `Gfx`. `ShellUiFramePacket` contem comandos `gfxui`, enquanto `Game2DFramePacket` contem `composer` + `gfx2d`. No consumidor local, `apply_gfxui_command` e `apply_gfx2d_command` chamam os mesmos primitives finais (`clear`, `fill_rect`, `draw_line`, `draw_text`, etc.).
|
||||
|
||||
Mover o render real para outro core/thread nao deve atrapalhar Shell UI se a fronteira for respeitada: Shell update/layout/input continuam no core logico, produzem um `ShellUiFramePacket` fechado, e o render worker consome apenas esse snapshot imutavel.
|
||||
|
||||
O risco especifico do Shell UI nao e rasterizar em outro core. O risco e deixar o worker depender de estado vivo de Shell/SystemOS, janelas, ponteiros ou input enquanto desenha. Hoje o Hub monta o packet lendo estado de OS/janelas/input e publica imediatamente. Num modelo paralelo, essa montagem deve continuar antes do handoff; o worker deve receber so comandos fechados e recursos estaveis.
|
||||
|
||||
Portanto, para Shell UI, a regra de handoff deve ser:
|
||||
|
||||
```text
|
||||
Shell/SystemOS update + input sampling
|
||||
-> build ShellUiFramePacket from current UI state
|
||||
-> hand off immutable ShellUi submission
|
||||
-> render worker consumes commands only
|
||||
```
|
||||
|
||||
Isso preserva a UI sobre primitivas sem exigir que o render worker entenda window manager, foco, input ou lifecycle.
|
||||
|
||||
Direcao refinada em 2026-06-04:
|
||||
|
||||
Render paralelo faz mais sentido como capacidade para workloads de game 2D/3D do que como obrigacao universal do runtime. Um app UI/Shell pode nao se beneficiar de separar rasterizacao em outro core, porque seu custo principal tende a estar em estado de UI, layout, input, foco, janelas e lifecycle, nao em um pipeline grafico pesado.
|
||||
|
||||
Portanto, a decisao futura nao deve assumir que todo `RenderSubmission` passa obrigatoriamente por um worker dedicado. A politica deve poder variar por `AppMode`/pipeline:
|
||||
|
||||
- `Game2D`/futuro `Game3D` podem usar handoff para render worker/core quando houver ganho real de frame time ou isolamento.
|
||||
- `ShellUi` pode continuar em consumo sincrono/local se isso for mais simples, deterministico e barato.
|
||||
- O contrato comum deve continuar sendo o packet fechado; a politica de execucao do consumidor pode ser diferente por pipeline.
|
||||
|
||||
Essa distincao evita otimizar a Shell UI como se fosse um renderer de jogo. Para UI, o valor principal de `ShellUiFramePacket` e manter a fronteira limpa e testavel; paralelismo deve ser opcional.
|
||||
|
||||
## Resolution
|
||||
|
||||
Direcao da agenda respondida. Os sete topicos tem recomendacao suficiente para virar decision:
|
||||
|
||||
- `Game2DFramePacket` deve ser snapshot completo, com `gfx2d` como overlay apos composicao de scene/layers/sprites;
|
||||
- recursos pesados cruzam a fronteira por IDs/handles estaveis e APIs read-only, nao por handles mutaveis vivos;
|
||||
- handoff base e single-slot latest-wins, sem bloquear a VM/produtor;
|
||||
- frame pacing fica sob `FrameClock`/`FrameScheduler`, nao sob ACK do render worker;
|
||||
- politica de render varia por `AppMode`/pipeline: Game frame-paced; Shell lifecycle/event-driven e local/sincrono por default;
|
||||
- transicoes de foreground visual owner usam epoch/generation para invalidar submissions obsoletas;
|
||||
- telemetria minima torna drops, repeats, erros e stale discards observaveis sem virar semantica da VM.
|
||||
|
||||
Detalhes de foreground stack, Game pausado e coexistencia com Shell VM-backed foram separados na `DSC-0041`.
|
||||
|
||||
## Next Step
|
||||
|
||||
Transformar esta agenda em decision antes de qualquer spec ou codigo de render worker.
|
||||
@ -0,0 +1,172 @@
|
||||
---
|
||||
id: AGD-0042
|
||||
ticket: real-render-worker-establishment
|
||||
title: Real Render Worker Establishment
|
||||
status: open
|
||||
created: 2026-06-06
|
||||
resolved:
|
||||
decision:
|
||||
tags: [runtime, renderer, worker, concurrency, host, hal, architecture]
|
||||
---
|
||||
|
||||
## Contexto
|
||||
|
||||
`DEC-0031` fechou a arquitetura base da fronteira VM/render: submissions fechadas, handoff single-slot latest-wins, pacing por `FrameScheduler`, politica explicita por `AppMode`, ownership/epoch e telemetria.
|
||||
|
||||
A implementacao atual ja tem a base local/sincrona e um `LocalRenderWorker` cooperativo por capability flag. Isso valida o roteamento e a politica, mas ainda nao estabelece um worker real em outra thread/core. O proximo passo arquitetural e transformar esse prototipo em uma unidade de execucao real sem reabrir a decisao base.
|
||||
|
||||
Esta agenda existe para discutir somente o estabelecimento do worker real. Ela nao deve redecidir `gfx2d` como overlay, o packet boundary, AppMode policy, ou latest-wins; esses pontos pertencem a `DEC-0031`.
|
||||
|
||||
## Problema
|
||||
|
||||
Um worker real precisa cruzar fronteiras que o prototipo local ainda evita:
|
||||
|
||||
- ownership e lifetime de recursos compartilhados entre VM/logical core e render worker;
|
||||
- como o worker recebe, consome, rasteriza e apresenta submissions sem `&mut Hardware`, `&mut Gfx`, `FrameComposer` vivo ou estado mutavel da VM;
|
||||
- como o viewport cache/read model fica seguro e barato;
|
||||
- como shutdown, stop token, current work e stale owner funcionam quando ha trabalho realmente em voo;
|
||||
- onde fica o present loop e se ele roda a 60Hz independentemente da VM;
|
||||
- como erros de render/present deixam de ser apenas panic containment e viram resultado tipado;
|
||||
- como host desktop, hardware proprio, outro core, DMA ou coprocessador mapeiam para o mesmo contrato.
|
||||
|
||||
## Pontos Criticos
|
||||
|
||||
### 1. Ownership do worker
|
||||
|
||||
Precisamos decidir se o worker real pertence ao runtime, ao host, a HAL, ou a uma camada hibrida. `DEC-0031` diz que host/HAL fornece capability concreta, mas `RenderManager` coordena contrato. Falta definir o boundary operacional.
|
||||
|
||||
### 2. Surface e backend renderizavel
|
||||
|
||||
O worker nao pode receber `&mut Hardware` ou `&mut Gfx` da VM thread. Precisamos de um objeto/capability renderizavel que seja owned pelo worker ou mediado por host.
|
||||
|
||||
### 3. Recursos read-only e viewport cache
|
||||
|
||||
Glyph/scene banks ja tem boundary read-only inicial. O viewport cache ainda precisa de um modelo concreto: snapshot, `Arc` read-only, double-buffer cache, cache materializado por frame, ou service proprietario.
|
||||
|
||||
### 4. Current work e cancelamento
|
||||
|
||||
O `RenderManager` ja descarta pending e rejeita stale epoch antes de present. Com worker real, uma submission pode estar em rasterizacao. Precisamos definir stop token, epoch check antes de present, bounded join e descarte de current work.
|
||||
|
||||
### 5. Present loop e frame repeat
|
||||
|
||||
Hoje repeated present e telemetria/hook. Um worker real provavelmente precisa de loop de present/display cadence. Falta decidir se o worker apresenta a 60Hz, se o host faz scanout/repeat, e como isso conversa com `FrameScheduler`.
|
||||
|
||||
### 6. Erros tipados
|
||||
|
||||
`RenderSurface` hoje e infalivel e panic containment vira `PresentFailed`. Para worker real, render/present deveria retornar erro tipado, distinguindo falha recuperavel, backend lost, surface lost, panic, shutdown e stale discard.
|
||||
|
||||
### 7. Testabilidade
|
||||
|
||||
Precisamos de testes que provem thread boundary, latest-wins sob atraso real, shutdown com current work em voo, stale epoch durante rasterizacao, repeat do ultimo frame e ausencia de bloqueio da VM.
|
||||
|
||||
## Opcoes
|
||||
|
||||
### Opcao A - Worker real dentro do runtime
|
||||
|
||||
**Abordagem:** `RenderManager` ou um novo `RenderWorkerRuntime` cria e gerencia uma thread de render, canais/slots, stop token e lifecycle.
|
||||
|
||||
**Pros:**
|
||||
- contrato fica perto de `RenderManager`;
|
||||
- facil testar com runtime puro;
|
||||
- menos dependencia de host desktop.
|
||||
|
||||
**Contras:**
|
||||
- risco de runtime assumir detalhes de surface/window que pertencem ao host;
|
||||
- pode ficar ruim para hardware proprio, DMA ou coprocessador;
|
||||
- exige abstrair muito bem o backend renderizavel.
|
||||
|
||||
**Manutenibilidade:** boa se o backend for uma trait pequena e owned pelo worker; ruim se vazar `Hardware`/`Gfx` vivo.
|
||||
|
||||
### Opcao B - Worker real como responsabilidade do host
|
||||
|
||||
**Abordagem:** runtime fecha submissions e handoff; host implementa thread/core/present loop usando uma capability HAL/host.
|
||||
|
||||
**Pros:**
|
||||
- encaixa melhor desktop windowing, swapchain, surface lost e display cadence;
|
||||
- facilita mapeamento para plataformas diferentes;
|
||||
- runtime continua sem detalhe de thread/window.
|
||||
|
||||
**Contras:**
|
||||
- testes de contrato podem ficar mais integrados e menos unitarios;
|
||||
- risco de cada host reinterpretar o contrato;
|
||||
- `RenderManager` precisa expor hooks suficientes sem virar passivo demais.
|
||||
|
||||
**Manutenibilidade:** boa para plataformas diversas, desde que exista uma suite de contrato obrigatoria.
|
||||
|
||||
### Opcao C - Worker como HAL/backend owned, coordenado pelo runtime
|
||||
|
||||
**Abordagem:** runtime possui `RenderManager` e policy; HAL/host fornece um `RenderBackend`/`RenderWorkerBackend` owned e thread-safe. Um `RenderWorkerController` conecta handoff, stop token, epoch e telemetry.
|
||||
|
||||
**Pros:**
|
||||
- separa contrato runtime de implementacao de host;
|
||||
- permite worker thread no desktop e outro core/DMA em hardware;
|
||||
- cria ponto unico para testes de contrato;
|
||||
- evita passar `&mut Hardware` ou `&mut Gfx` pela fronteira.
|
||||
|
||||
**Contras:**
|
||||
- mais desenho inicial;
|
||||
- exige definir traits novas com cuidado;
|
||||
- pode ser excessivo se o primeiro worker real for apenas desktop.
|
||||
|
||||
**Manutenibilidade:** melhor direcao se quisermos preservar portabilidade e nao acoplar runtime a winit/surface.
|
||||
|
||||
### Opcao D - Adiar worker real e manter prototipo local
|
||||
|
||||
**Abordagem:** nao implementar worker real agora; apenas fortalecer testes/spec e manter `LocalRenderWorker`.
|
||||
|
||||
**Pros:**
|
||||
- menor risco imediato;
|
||||
- evita mexer em host/surface antes da necessidade real.
|
||||
|
||||
**Contras:**
|
||||
- nao valida thread/core real;
|
||||
- deixa lacunas de Send/Sync, shutdown current work e present cadence;
|
||||
- pode mascarar problemas de ownership ate tarde.
|
||||
|
||||
**Manutenibilidade:** aceitavel por curto prazo, fraca se a demanda agora e paralelismo real.
|
||||
|
||||
## Sugestao / Recomendacao
|
||||
|
||||
Recomendo seguir pela **Opcao C - Worker como HAL/backend owned, coordenado pelo runtime**.
|
||||
|
||||
O desenho deve manter `RenderManager` como dono de policy, epoch, handoff e telemetry, mas introduzir uma camada operacional para worker real com:
|
||||
|
||||
- backend/render surface owned pelo worker ou pelo host;
|
||||
- handoff single-slot sem bloquear VM;
|
||||
- stop token e bounded shutdown;
|
||||
- check de epoch/owner antes de present;
|
||||
- erro tipado para render/present;
|
||||
- present cadence explicita, com repeat do ultimo frame quando nao houver submission nova;
|
||||
- testes de contrato que rodem sem janela nativa sempre que possivel.
|
||||
|
||||
Essa recomendacao preserva `DEC-0031` e evita transformar o runtime puro em dono de detalhes de window/swapchain.
|
||||
|
||||
## Perguntas em Aberto
|
||||
|
||||
- [ ] O primeiro worker real deve nascer no host desktop/winit ou em uma abstracao runtime/HAL testavel sem janela?
|
||||
- [ ] Qual trait substitui `RenderSurface::consume_submission(&RenderSubmission) -> ()` para erro tipado?
|
||||
- [ ] O worker owns `Gfx`/framebuffer, ou `Gfx` continua em `Hardware` e precisa ser dividido?
|
||||
- [ ] Como o viewport cache sera exposto ao worker: snapshot por frame, `Arc` read-only, double-buffer, ou service proprietario?
|
||||
- [ ] Quem roda o present loop de 60Hz: worker, host event loop, ou uma autoridade de display separada?
|
||||
- [ ] Como testar current work em voo sem depender de sleeps/flakiness?
|
||||
- [ ] Como mapear shutdown: stop accepting, discard pending, cancel current, join bounded, preserve last surface?
|
||||
- [ ] Quais tipos precisam de prova `Send + Sync` antes do primeiro worker real?
|
||||
- [ ] Shell continua fora do worker no primeiro passo, ou devemos provar explicitamente que capability Game nao afeta Shell?
|
||||
|
||||
## Criterio para Encerrar
|
||||
|
||||
Esta agenda pode virar decision quando tivermos uma resposta clara para:
|
||||
|
||||
- ownership/layer responsavel pelo worker real;
|
||||
- trait/backend de render/present e modelo de erro;
|
||||
- modelo de recurso read-only, especialmente viewport cache;
|
||||
- protocolo de shutdown/current work;
|
||||
- present cadence/repeat;
|
||||
- plano de testes para thread/core real;
|
||||
- escopo do primeiro worker real, incluindo o que fica explicitamente fora.
|
||||
|
||||
## Discussion
|
||||
|
||||
- 2026-06-06: Agenda criada apos a execucao de `DSC-0040`, que fechou a arquitetura base mas deixou o worker real como etapa futura deliberada.
|
||||
|
||||
## Resolution
|
||||
@ -1,245 +0,0 @@
|
||||
---
|
||||
id: DEC-0031
|
||||
ticket: vm-render-parallel-execution-boundary
|
||||
title: VM and Render Parallel Execution Boundary
|
||||
status: accepted
|
||||
created: 2026-06-05
|
||||
ref_agenda: AGD-0040
|
||||
tags: [runtime, renderer, vm, concurrency, architecture, perf]
|
||||
---
|
||||
|
||||
## Status
|
||||
|
||||
Open decision draft generated from accepted agenda `AGD-0040`.
|
||||
|
||||
This decision is ready for review/acceptance. Once accepted, it becomes the normative contract for any spec or code plan that introduces a real render worker/core.
|
||||
|
||||
## Contexto
|
||||
|
||||
`DSC-0038` established `RenderSubmission` as a closed typed snapshot. That gives Prometeu the data boundary needed for future concurrency, but it did not define the operational contract for running VM/logical execution and render consumption on different threads/cores.
|
||||
|
||||
The current runtime consumes submissions synchronously through local `Hardware`/`Gfx` paths. Moving rasterization/presentation out of the VM path requires explicit rules for packet completeness, shared resources, handoff, pacing, lifecycle ownership, and telemetry.
|
||||
|
||||
## Decisao
|
||||
|
||||
Prometeu SHALL treat VM execution and render consumption as separate responsibilities connected by closed render submissions.
|
||||
|
||||
For the first real asynchronous render model, the runtime SHALL use a single-slot latest-wins handoff for Game pipelines, paced by a frame scheduler, with render ownership guarded by epoch/generation and observable through telemetry. Shell/System UI SHALL remain lifecycle/event-driven and local/synchronous by default, while preserving the same closed-packet boundary.
|
||||
|
||||
This decision does not require implementing the worker immediately. It locks the architecture that any future worker implementation MUST follow.
|
||||
|
||||
## Rationale
|
||||
|
||||
The design preserves the console/game timing model without allowing the VM to depend on render success. It also avoids an unbounded queue, stale frame presentation, mutable access to live VM/renderer state, and accidental treatment of Shell UI as a game renderer.
|
||||
|
||||
The decision keeps the first worker model small:
|
||||
|
||||
- the VM publishes at most one latest pending submission;
|
||||
- the worker consumes owned immutable submissions;
|
||||
- the frame scheduler, not render ACK, paces logical Game frames;
|
||||
- lifecycle transitions invalidate stale visual ownership;
|
||||
- telemetry reports drops/repeats/errors without changing VM semantics.
|
||||
|
||||
## Invariantes / Contrato
|
||||
|
||||
### 1. Packet completo
|
||||
|
||||
`RenderSubmissionPacket::Game2D` MUST be a complete frame description for the render consumer.
|
||||
|
||||
The Game2D consumer MUST compose in this order:
|
||||
|
||||
```text
|
||||
Game2D composer / scene / layers / sprites
|
||||
-> gfx2d primitives overlay
|
||||
-> publication / present
|
||||
```
|
||||
|
||||
The active-scene path MUST NOT bypass the packet or drop `gfx2d`. `gfx2d` primitives are a final overlay both with and without an active scene.
|
||||
|
||||
### 2. Recursos compartilhados
|
||||
|
||||
Packets crossing the VM/render boundary MUST remain small and owned. Heavy resources MUST NOT be copied into every submission.
|
||||
|
||||
The packet SHALL carry stable IDs/handles. Large resident resources such as glyph banks, scene banks, assets, and viewport cache materializations SHALL be accessed through read-only APIs.
|
||||
|
||||
The viewport cache belongs to the logical core. The render worker MAY read it through a read-only API after logical/core preparation has completed. Resolver updates, cache refreshes, asset installation, and bank residency changes MUST happen before handoff or in an owning service, not during worker rasterization.
|
||||
|
||||
The system does not guarantee visual integrity when a developer/framework swaps resources behind an in-flight submission in a way that violates asset discipline. Submissions refer to resource IDs; disciplined replacement is the responsibility of the developer/framework layer.
|
||||
|
||||
Any implementation that crosses a Rust thread boundary MUST prove the handoff and read-only resource APIs are safe for sharing. The worker MUST NOT receive `&mut Hardware`, `&mut Gfx`, live `FrameComposer`, or mutable VM/runtime state.
|
||||
|
||||
### 3. Handoff
|
||||
|
||||
The base handoff protocol SHALL be single-slot latest-wins.
|
||||
|
||||
The producer moves an owned closed submission into a pending slot. If the worker has not consumed that pending submission and the producer publishes a newer one, the newer submission replaces the older one. Replacement MUST be counted as a dropped/replaced-before-consume event.
|
||||
|
||||
The worker owns any submission it has taken from the slot. A currently-rendering submission is outside the pending slot.
|
||||
|
||||
The VM/producer MUST NOT block waiting for worker ACK, consumption, raster completion, or present completion. Worker consumed/presented status is telemetry only.
|
||||
|
||||
Shell UI is outside the worker protocol by default. A future configuration MAY reuse the same handoff for Shell, but that is not the default policy.
|
||||
|
||||
### 4. Frame pacing
|
||||
|
||||
Game logical frames SHALL be paced by a `FrameClock`/`FrameScheduler` authority, not by render-worker ACK.
|
||||
|
||||
The VM MUST NOT run freely ahead of display cadence. The target is one logical Game frame per frame tick and at most one pending submission ahead of the worker. The worker presents at display cadence, initially 60Hz where available, and repeats the last valid frame if no new valid submission exists.
|
||||
|
||||
`FRAME_SYNC` remains the canonical end of a VM logical frame. The old budget mechanism MUST NOT be used as the normal way to cut or advance a logical frame. Budget/cycle/time accounting remains for certification, watchdog, diagnostics, and overrun reporting.
|
||||
|
||||
If a logical frame exceeds the display window, logical frames remain sequential. The runtime records overrun/stutter and the worker repeats the last valid frame. The delayed submission represents the next sequential logical frame, not a skipped `N+k` frame.
|
||||
|
||||
Input sampling for Game SHOULD occur at the start of an authorized logical frame. Repeated presents without a new logical frame MUST NOT imply new input sampling or a hidden logical update.
|
||||
|
||||
### 5. Politica por AppMode / pipeline
|
||||
|
||||
Render execution policy SHALL be explicit by AppMode/pipeline.
|
||||
|
||||
Game workloads are frame-paced by definition. Current `AppMode::Game` and future explicit Game2D/Game3D modes SHALL use the frame scheduler and MAY use a render worker by default when the host/runtime supports it, with synchronous/local fallback.
|
||||
|
||||
Shell/System UI is lifecycle/event-driven. It MUST NOT inherit the Game logical frame loop. Shell UI SHALL publish local/synchronous by default and render by invalidation/event/lifecycle. Shell VM-backed apps follow Shell lifecycle and MUST NOT declare an independent frame-paced workload under this decision.
|
||||
|
||||
Firmware/system screens such as splash, crash, and hub follow Shell/local policy unless a later decision creates a more specific policy.
|
||||
|
||||
SystemOS/lifecycle decides the semantic profile/AppMode. `RenderManager` executes the render policy. Host/HAL provides capabilities and concrete execution.
|
||||
|
||||
### 6. Lifecycle, epoch e ownership
|
||||
|
||||
Every submission that may cross an asynchronous boundary MUST carry enough ownership context to reject stale presentation. This includes frame identity plus render ownership such as epoch/generation and owner/app/mode identity as needed.
|
||||
|
||||
Any foreground visual-owner transition SHALL increment/apply a render epoch or equivalent generation through a central `RenderManager` API. SystemOS/lifecycle decides that a semantic transition occurred; `RenderManager` applies the render ownership transition.
|
||||
|
||||
Transitions that MUST invalidate stale pending/current submissions include:
|
||||
|
||||
- Game -> Shell/Hub;
|
||||
- Shell/Hub -> Game;
|
||||
- crash screen;
|
||||
- splash or system screen takeover;
|
||||
- cartridge/app swap, even if `AppMode` remains the same;
|
||||
- shutdown/stop.
|
||||
|
||||
The worker MAY finish raster work for an obsolete submission, but it MUST check epoch/owner before present and MUST NOT present frames that no longer match active ownership.
|
||||
|
||||
The same physical surface MAY be shared by Game, Shell, Hub, splash, and crash screens, but logical ownership MUST be explicit. On Shell -> Game, the runtime MAY keep the previous Shell/Hub surface visible until the first valid Game submission; clearing is a visual policy, not a correctness requirement.
|
||||
|
||||
Shutdown MUST stop presentation of obsolete work, discard pending submissions, invalidate current work through epoch/stop token, and terminate/join the worker in a bounded way. It MUST NOT drain obsolete frames to the screen.
|
||||
|
||||
Foreground stack, Game pause/resume, and coexistence of paused Game with VM-backed Shell apps are outside this decision and are tracked separately by `DSC-0041`.
|
||||
|
||||
### 7. Erros, drops e telemetria
|
||||
|
||||
Asynchronous render is observable best-effort, not a semantic handshake with the VM.
|
||||
|
||||
Render drops, repeated presents, stale-epoch discards, raster errors, and present errors MUST be reported through runtime/host telemetry. They MUST NOT directly alter VM program semantics, and VM code MUST NOT depend on "this frame was presented" to advance logic.
|
||||
|
||||
Minimum counters:
|
||||
|
||||
- `produced_submissions`;
|
||||
- `replaced_before_consume`;
|
||||
- `consumed_submissions`;
|
||||
- `presented_frames`;
|
||||
- `repeated_presents`;
|
||||
- `render_errors`;
|
||||
- `present_errors`;
|
||||
- `stale_epoch_discards`;
|
||||
- `shutdown_discards`.
|
||||
|
||||
Minimum IDs/state:
|
||||
|
||||
- `last_produced_frame_id`;
|
||||
- `last_consumed_frame_id`;
|
||||
- `last_presented_frame_id`;
|
||||
- `last_dropped_frame_id`;
|
||||
- `last_error_frame_id`;
|
||||
- `active_render_epoch`.
|
||||
|
||||
Minimum events:
|
||||
|
||||
- submission replaced in the pending slot before consumption;
|
||||
- worker consumed a submission;
|
||||
- worker discarded a submission due to stale epoch/owner;
|
||||
- worker presented a frame;
|
||||
- worker repeated the last frame because no new valid submission existed;
|
||||
- raster error;
|
||||
- present error;
|
||||
- shutdown/cancel discarded pending/current work.
|
||||
|
||||
Raster error on a submission SHOULD discard that submission, record telemetry, and preserve the last valid frame/current surface when possible. Present errors SHOULD record telemetry and MAY escalate to host/system fault policy if repeated. Worker panic MUST become controlled worker/backend failure and MUST NOT propagate as a VM panic.
|
||||
|
||||
## Impactos
|
||||
|
||||
### Spec
|
||||
|
||||
Specs need to describe:
|
||||
|
||||
- closed render packet completeness;
|
||||
- handoff and pacing model;
|
||||
- render ownership epoch/generation;
|
||||
- AppMode/pipeline policy;
|
||||
- minimum telemetry surface.
|
||||
|
||||
### Runtime
|
||||
|
||||
`RenderManager` needs to become the central owner of render handoff, policy execution, epoch/generation, and render telemetry. It remains coordinator, not renderer.
|
||||
|
||||
### Host / HAL
|
||||
|
||||
Host/HAL provides concrete execution capability: synchronous/local render, render worker thread, separate core, DMA/copresenter, or fallback. Host/HAL does not decide lifecycle ownership.
|
||||
|
||||
### Firmware / SystemOS
|
||||
|
||||
SystemOS/lifecycle remains the semantic owner of mode/app/task transitions. Firmware state changes must route visual ownership transitions through the render ownership API when asynchronous render exists.
|
||||
|
||||
### Tests
|
||||
|
||||
Plans derived from this decision must include tests for:
|
||||
|
||||
- active-scene Game2D preserving `gfx2d` overlay after layer composition;
|
||||
- latest-wins replacement telemetry;
|
||||
- stale epoch discard before present;
|
||||
- Shell local/default policy remaining independent from Game pacing;
|
||||
- logical frame overrun producing repeat/stutter telemetry without frame skip semantics.
|
||||
|
||||
## Alternativas Descartadas
|
||||
|
||||
### Fila crescente de submissions
|
||||
|
||||
Rejected because it increases latency, memory usage, and stale frame risk. The first worker model should not accumulate old frames.
|
||||
|
||||
### Worker como dono do frame counter canonico
|
||||
|
||||
Rejected because it mixes pacing authority with raster/present completion. Frame cadence belongs to the frame scheduler; the worker is a consumer/presenter.
|
||||
|
||||
### Shell sempre no render worker
|
||||
|
||||
Rejected because Shell/System UI is lifecycle/event-driven. Forcing worker usage adds complexity without clear benefit.
|
||||
|
||||
### Capturar recursos pesados por frame
|
||||
|
||||
Rejected because it is expensive and makes resource lifetime policy obscure. Packets should carry IDs and use read-only resident resources.
|
||||
|
||||
### ACK de present como parte da semantica da VM
|
||||
|
||||
Rejected because it couples deterministic VM progress to host/render timing and failure modes.
|
||||
|
||||
## Referencias
|
||||
|
||||
- `AGD-0040`: VM and Render Parallel Execution Boundary.
|
||||
- `DSC-0038` / `LSN-0047`: typed render submissions preserve domain boundaries.
|
||||
- `DSC-0031` / `LSN-0040`: AppMode separates Game and System/Shell profiles.
|
||||
- `DSC-0032` / `LSN-0041`: SystemOS owns lifecycle semantics.
|
||||
- `DSC-0035` / `LSN-0044`: Shell liveness depends on task-owned focused window.
|
||||
- `DSC-0036` / `LSN-0045`: Hub UI slices prove lifecycle boundaries.
|
||||
- `DSC-0041`: foreground stack, Game pause, and VM-backed Shell coexistence.
|
||||
|
||||
## Propagacao Necessaria
|
||||
|
||||
- Create a plan before spec or code execution.
|
||||
- First plan should probably separate immediate packet correctness from future worker infrastructure.
|
||||
- Spec text must be in English.
|
||||
- Lessons must be created only after execution publishes spec/code state.
|
||||
|
||||
## Revision Log
|
||||
|
||||
- 2026-06-05: Initial decision draft generated from accepted `AGD-0040`.
|
||||
@ -1,62 +0,0 @@
|
||||
---
|
||||
id: PLN-0087
|
||||
ticket: vm-render-parallel-execution-boundary
|
||||
title: Fix Game2D Packet Overlay Composition
|
||||
status: done
|
||||
created: 2026-06-05
|
||||
ref_decisions: [DEC-0031]
|
||||
tags: [runtime, renderer, game2d, packet, overlay]
|
||||
---
|
||||
|
||||
## Briefing
|
||||
|
||||
`DEC-0031` requires `RenderSubmissionPacket::Game2D` to be a complete frame description. The current active-scene path can bypass the packet and lose `gfx2d` overlay commands.
|
||||
|
||||
## Objective
|
||||
|
||||
Make Game2D packet consumption identical for active-scene and no-scene frames: scene/layers/sprites first, then `gfx2d` primitives as final overlay.
|
||||
|
||||
## Dependencies
|
||||
|
||||
- Source decision: `DEC-0031`.
|
||||
- Existing Game2D packet types in `crates/console/prometeu-hal`.
|
||||
- Existing publish path in `crates/console/prometeu-drivers`.
|
||||
|
||||
## Scope
|
||||
|
||||
- Update Game2D render publication so active-scene rendering consumes the packet and applies `gfx2d`.
|
||||
- Keep Shell UI behavior unchanged.
|
||||
- Add regression tests for active scene plus primitive overlay.
|
||||
|
||||
## Non-Goals
|
||||
|
||||
- Do not introduce a render worker.
|
||||
- Do not change frame pacing, telemetry, lifecycle, or AppMode policy.
|
||||
- Do not redesign `FrameComposer` beyond what is needed to consume the packet correctly.
|
||||
|
||||
## Execution Method
|
||||
|
||||
1. Inspect `Hardware::publish_render_submission`, `Gfx::render_game2d_frame_packet`, and `FrameComposer::render_frame`.
|
||||
2. Replace the active-scene branch that bypasses `Game2DFramePacket` with a packet-consuming path.
|
||||
3. Ensure `gfx2d` commands are applied after scene/layer/sprite composition in all Game2D branches.
|
||||
4. Add a test fixture with an active scene and a primitive overlay that would visibly overwrite or mark the composed layer.
|
||||
5. Add a no-scene regression test if current coverage does not already lock the overlay order.
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
- Active-scene Game2D frames render `gfx2d` after layer/sprite composition.
|
||||
- No-scene Game2D frames preserve the existing overlay behavior.
|
||||
- `Hardware::publish_render_submission` does not discard `packet.gfx2d`.
|
||||
- Tests fail on the old active-scene bypass behavior.
|
||||
|
||||
## Tests
|
||||
|
||||
- Unit or integration test around Game2D packet publication.
|
||||
- Pixel/assertion test for overlay-after-scene ordering where practical.
|
||||
- Existing renderer tests continue to pass.
|
||||
|
||||
## Affected Artifacts
|
||||
|
||||
- `crates/console/prometeu-drivers/src/hardware.rs`
|
||||
- `crates/console/prometeu-hal/src/render_submission.rs`
|
||||
- `crates/console/prometeu-system` or renderer test modules as needed.
|
||||
@ -1,63 +0,0 @@
|
||||
---
|
||||
id: PLN-0088
|
||||
ticket: vm-render-parallel-execution-boundary
|
||||
title: Define Read-Only Render Resource Boundary
|
||||
status: done
|
||||
created: 2026-06-05
|
||||
ref_decisions: [DEC-0031]
|
||||
tags: [runtime, renderer, resources, cache, banks]
|
||||
---
|
||||
|
||||
## Briefing
|
||||
|
||||
`DEC-0031` requires render packets to carry small owned data and stable resource IDs, while heavy banks/caches remain resident and read-only to render consumers.
|
||||
|
||||
## Objective
|
||||
|
||||
Define and enforce the read-only resource boundary needed before any worker can safely read scene/glyph/cache data.
|
||||
|
||||
## Dependencies
|
||||
|
||||
- Source decision: `DEC-0031`.
|
||||
- `PLN-0087` should clarify the packet consumer path before this plan finalizes worker-facing APIs.
|
||||
|
||||
## Scope
|
||||
|
||||
- Identify every resource read during Game2D rendering.
|
||||
- Classify data as packet-owned, resident read-only, or logical-core mutable preparation state.
|
||||
- Add trait/API boundaries for render read access where missing.
|
||||
- Document which types must be `Send + Sync` for a real threaded worker.
|
||||
|
||||
## Non-Goals
|
||||
|
||||
- Do not make resource swaps transactional.
|
||||
- Do not capture `Arc<GlyphBank>` or `Arc<SceneBank>` inside every submission.
|
||||
- Do not implement background asset loading policy.
|
||||
|
||||
## Execution Method
|
||||
|
||||
1. Trace Game2D render reads from packet to glyph bank, scene bank, viewport cache, and framebuffer helpers.
|
||||
2. Create a short internal module-level contract for render resource access.
|
||||
3. Add or refine read-only access traits for banks/cache without exposing mutable runtime state.
|
||||
4. Add compile-time assertions or targeted tests for `Send + Sync` where a threaded worker will require them.
|
||||
5. Keep resource identity in submissions as IDs/handles, not heavy ownership captures.
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
- Render consumer APIs can be described as packet-owned plus read-only resource access.
|
||||
- No worker-facing API requires `&mut Hardware`, `&mut Gfx`, live `FrameComposer`, or mutable VM state.
|
||||
- Shared read APIs that cross thread boundaries have explicit `Send + Sync` expectations.
|
||||
- Existing synchronous renderer behavior remains unchanged.
|
||||
|
||||
## Tests
|
||||
|
||||
- Compile-time trait assertions for read-only resource APIs where practical.
|
||||
- Unit tests for read-only bank/cache access.
|
||||
- Existing asset/scene rendering tests continue to pass.
|
||||
|
||||
## Affected Artifacts
|
||||
|
||||
- `crates/console/prometeu-hal`
|
||||
- `crates/console/prometeu-system`
|
||||
- `crates/console/prometeu-drivers`
|
||||
- Relevant renderer/resource tests.
|
||||
@ -1,62 +0,0 @@
|
||||
---
|
||||
id: PLN-0089
|
||||
ticket: vm-render-parallel-execution-boundary
|
||||
title: Introduce Render Handoff Abstraction
|
||||
status: done
|
||||
created: 2026-06-05
|
||||
ref_decisions: [DEC-0031]
|
||||
tags: [runtime, renderer, handoff, latest-wins]
|
||||
---
|
||||
|
||||
## Briefing
|
||||
|
||||
`DEC-0031` requires a single-slot latest-wins handoff where the producer never blocks on render ACK and replacement before consumption is observable.
|
||||
|
||||
## Objective
|
||||
|
||||
Introduce a render handoff abstraction that can be used synchronously today and by a worker later.
|
||||
|
||||
## Dependencies
|
||||
|
||||
- Source decision: `DEC-0031`.
|
||||
- `PLN-0093` should define telemetry counters before final instrumentation is wired.
|
||||
|
||||
## Scope
|
||||
|
||||
- Add a small handoff type or trait around one pending owned `RenderSubmission`.
|
||||
- Support publish, take latest, replace pending, and drain/discard operations.
|
||||
- Report replacement/drop events to telemetry hooks.
|
||||
- Integrate the abstraction into `RenderManager` without starting a worker.
|
||||
|
||||
## Non-Goals
|
||||
|
||||
- Do not spawn a thread.
|
||||
- Do not implement frame pacing.
|
||||
- Do not change Shell UI default rendering policy.
|
||||
|
||||
## Execution Method
|
||||
|
||||
1. Locate `RenderManager::latest_complete_submission` ownership and publication flow.
|
||||
2. Introduce a handoff module with single pending slot semantics.
|
||||
3. Move `RenderSubmission` into the slot on publication.
|
||||
4. Make `take_latest` transfer ownership to the consumer.
|
||||
5. Count replacement when a pending submission is overwritten before consumption.
|
||||
6. Keep current synchronous publication working by immediately taking and rendering through the same abstraction.
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
- `RenderManager` no longer relies on an unconstrained raw `Option<RenderSubmission>` for the future worker boundary.
|
||||
- Publishing a newer pending submission replaces the old one without blocking.
|
||||
- The consumer receives owned submissions.
|
||||
- Replacement before consume is observable.
|
||||
|
||||
## Tests
|
||||
|
||||
- Unit tests for empty take, publish/take, publish/replace/take, and drain/discard.
|
||||
- Integration smoke test that existing synchronous render still presents frames.
|
||||
|
||||
## Affected Artifacts
|
||||
|
||||
- `crates/console/prometeu-system/src/services/vm_runtime/render_manager.rs`
|
||||
- New or existing render handoff module under `crates/console/prometeu-system`.
|
||||
- Render manager tests.
|
||||
@ -1,63 +0,0 @@
|
||||
---
|
||||
id: PLN-0090
|
||||
ticket: vm-render-parallel-execution-boundary
|
||||
title: Add Render Frame Pacing Contract
|
||||
status: done
|
||||
created: 2026-06-05
|
||||
ref_decisions: [DEC-0031]
|
||||
tags: [runtime, frame-clock, scheduler, vm]
|
||||
---
|
||||
|
||||
## Briefing
|
||||
|
||||
`DEC-0031` separates Game logical frame pacing from render worker ACK. Game frames are paced by a frame clock/scheduler and still end at `FRAME_SYNC`.
|
||||
|
||||
## Objective
|
||||
|
||||
Define and implement the runtime contract that authorizes Game logical frames without using render present completion as ACK.
|
||||
|
||||
## Dependencies
|
||||
|
||||
- Source decision: `DEC-0031`.
|
||||
- `PLN-0091` should define which AppModes consume this policy.
|
||||
|
||||
## Scope
|
||||
|
||||
- Introduce or formalize a `FrameClock`/`FrameScheduler` authority for Game workloads.
|
||||
- Ensure Game VM runs at most one logical frame per authorized frame tick.
|
||||
- Preserve `FRAME_SYNC` as logical frame end.
|
||||
- Record overrun/repeat conditions through telemetry hooks.
|
||||
|
||||
## Non-Goals
|
||||
|
||||
- Do not make Shell UI run a game loop.
|
||||
- Do not implement catch-up frames or logical frame skipping.
|
||||
- Do not tie VM progress to render ACK.
|
||||
|
||||
## Execution Method
|
||||
|
||||
1. Inspect current tick/budget/`FRAME_SYNC` handling.
|
||||
2. Identify where a frame tick should authorize Game VM execution.
|
||||
3. Introduce a narrow scheduling API consumed by Game lifecycle code.
|
||||
4. Preserve budget/cycle/time accounting only for watchdog, certification, and diagnostics.
|
||||
5. Add telemetry points for logical-frame-overrun and no-new-frame/repeat.
|
||||
6. Document the distinction between logical frame ID, produced submission ID, and presented frame ID.
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
- Game VM cannot run unlimited logical frames ahead of the frame clock.
|
||||
- Render worker or render consumer ACK is not required to start the next logical frame.
|
||||
- Slow logical frames remain sequential and produce overrun/stutter telemetry.
|
||||
- Shell lifecycle remains unaffected.
|
||||
|
||||
## Tests
|
||||
|
||||
- Unit tests for scheduler permitting one Game frame per tick.
|
||||
- Test that no catch-up `N+k` logical frame is produced after overrun.
|
||||
- Regression tests around `FRAME_SYNC` behavior.
|
||||
|
||||
## Affected Artifacts
|
||||
|
||||
- VM runtime scheduling modules.
|
||||
- Firmware/Game running step.
|
||||
- Telemetry interfaces touched by pacing.
|
||||
@ -1,63 +0,0 @@
|
||||
---
|
||||
id: PLN-0091
|
||||
ticket: vm-render-parallel-execution-boundary
|
||||
title: Implement AppMode Render Policy Matrix
|
||||
status: done
|
||||
created: 2026-06-05
|
||||
ref_decisions: [DEC-0031]
|
||||
tags: [runtime, appmode, shell, game, policy]
|
||||
---
|
||||
|
||||
## Briefing
|
||||
|
||||
`DEC-0031` requires render execution policy to be explicit by AppMode/pipeline: Game is frame-paced and may use worker; Shell/System UI is lifecycle-driven and local/synchronous by default.
|
||||
|
||||
## Objective
|
||||
|
||||
Add an explicit render policy matrix so Game and Shell rendering cannot accidentally share the wrong lifecycle or pacing model.
|
||||
|
||||
## Dependencies
|
||||
|
||||
- Source decision: `DEC-0031`.
|
||||
- `PLN-0090` defines the Game pacing contract.
|
||||
|
||||
## Scope
|
||||
|
||||
- Represent render policy for current `AppMode::Game` and `AppMode::Shell`.
|
||||
- Make policy selection a SystemOS/lifecycle decision executed by `RenderManager`.
|
||||
- Add host/runtime capability fallback for worker-supported vs local render.
|
||||
- Keep Shell VM-backed apps under Shell lifecycle.
|
||||
|
||||
## Non-Goals
|
||||
|
||||
- Do not rename `AppMode::Game` to `Game2D` in this plan.
|
||||
- Do not implement Game3D.
|
||||
- Do not define Game pause/resume foreground stack; that belongs to `DSC-0041`.
|
||||
|
||||
## Execution Method
|
||||
|
||||
1. Locate `AppMode` routing through cartridge load, firmware state, SystemOS, and `RenderManager`.
|
||||
2. Add a render policy enum or equivalent explicit matrix.
|
||||
3. Route Game to frame-paced policy with optional worker capability.
|
||||
4. Route Shell/system screens to local/synchronous lifecycle policy.
|
||||
5. Add assertions/tests that Shell UI does not consume Game frame scheduler.
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
- Policy is explicit and testable for Game and Shell.
|
||||
- Shell UI remains local/synchronous by default.
|
||||
- Game can declare worker-capable policy without requiring the worker to exist.
|
||||
- Host/runtime capability fallback is represented without moving ownership decisions to host.
|
||||
|
||||
## Tests
|
||||
|
||||
- Unit tests for AppMode-to-render-policy mapping.
|
||||
- Lifecycle test proving Shell does not require Game frame ticks.
|
||||
- Regression test for Game still producing frame-paced submissions.
|
||||
|
||||
## Affected Artifacts
|
||||
|
||||
- `AppMode` routing modules.
|
||||
- `RenderManager`.
|
||||
- Firmware load/run steps.
|
||||
- SystemOS lifecycle integration tests.
|
||||
@ -1,64 +0,0 @@
|
||||
---
|
||||
id: PLN-0092
|
||||
ticket: vm-render-parallel-execution-boundary
|
||||
title: Add Render Epoch Ownership Transitions
|
||||
status: done
|
||||
created: 2026-06-05
|
||||
ref_decisions: [DEC-0031]
|
||||
tags: [runtime, lifecycle, render-epoch, ownership]
|
||||
---
|
||||
|
||||
## Briefing
|
||||
|
||||
`DEC-0031` requires foreground visual-owner transitions to invalidate stale render work using epoch/generation and owner identity.
|
||||
|
||||
## Objective
|
||||
|
||||
Add render epoch/ownership metadata and transition APIs so stale submissions cannot be presented after mode, app, crash, cartridge, or shutdown transitions.
|
||||
|
||||
## Dependencies
|
||||
|
||||
- Source decision: `DEC-0031`.
|
||||
- `PLN-0089` provides the handoff abstraction.
|
||||
|
||||
## Scope
|
||||
|
||||
- Add epoch/generation and owner identity to render submission metadata.
|
||||
- Add central `RenderManager` API for applying ownership transitions.
|
||||
- Integrate lifecycle transitions that change visual owner.
|
||||
- Reject stale pending/current submissions before present.
|
||||
|
||||
## Non-Goals
|
||||
|
||||
- Do not implement smooth visual transitions.
|
||||
- Do not define Game pause/resume stack semantics from `DSC-0041`.
|
||||
- Do not give host/HAL authority to decide ownership.
|
||||
|
||||
## Execution Method
|
||||
|
||||
1. Define render owner metadata shape: epoch/generation plus mode/app/surface owner as needed.
|
||||
2. Extend `RenderSubmission` metadata and constructors.
|
||||
3. Add `RenderManager` transition API that increments/applies epoch.
|
||||
4. Call the API from SystemOS/firmware lifecycle transition points.
|
||||
5. Update render consumption to check ownership before present.
|
||||
6. Add discard telemetry hook for stale epoch.
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
- Game -> Shell, Shell -> Game, crash, splash, cartridge/app swap, and shutdown can invalidate stale render work.
|
||||
- Worker/current consumer cannot present a submission with stale epoch/owner.
|
||||
- Host/HAL does not decide semantic ownership.
|
||||
- Same physical surface can be reused with distinct logical ownership.
|
||||
|
||||
## Tests
|
||||
|
||||
- Unit test stale epoch discard before present.
|
||||
- Integration test mode transition with pending Game submission.
|
||||
- Test cartridge/app swap increments ownership even when AppMode remains unchanged.
|
||||
|
||||
## Affected Artifacts
|
||||
|
||||
- `RenderSubmission` metadata.
|
||||
- `RenderManager`.
|
||||
- Firmware/SystemOS transition code.
|
||||
- Render publication path.
|
||||
@ -1,66 +0,0 @@
|
||||
---
|
||||
id: PLN-0093
|
||||
ticket: vm-render-parallel-execution-boundary
|
||||
title: Add Render Telemetry Counters and Events
|
||||
status: done
|
||||
created: 2026-06-05
|
||||
ref_decisions: [DEC-0031]
|
||||
tags: [runtime, renderer, telemetry, diagnostics]
|
||||
---
|
||||
|
||||
## Briefing
|
||||
|
||||
`DEC-0031` requires render drops, repeats, stale discards, render errors, and present errors to be observable without becoming VM semantics.
|
||||
|
||||
## Objective
|
||||
|
||||
Add the minimum render telemetry surface required for asynchronous render diagnostics and certification.
|
||||
|
||||
## Dependencies
|
||||
|
||||
- Source decision: `DEC-0031`.
|
||||
- `PLN-0089` and `PLN-0092` provide main event sources.
|
||||
|
||||
## Scope
|
||||
|
||||
- Add minimum counters and last-frame IDs from `DEC-0031`.
|
||||
- Add event recording hooks for handoff, consume, present, repeat, stale discard, errors, and shutdown discard.
|
||||
- Expose telemetry through existing runtime/host diagnostics patterns.
|
||||
- Ensure VM program behavior cannot observe telemetry as render ACK.
|
||||
|
||||
## Non-Goals
|
||||
|
||||
- Do not build a UI profiler.
|
||||
- Do not add VM syscalls for present ACK.
|
||||
- Do not define host-specific logging formats beyond necessary hooks.
|
||||
|
||||
## Execution Method
|
||||
|
||||
1. Locate current telemetry facilities and atomic counter patterns.
|
||||
2. Add render telemetry structure with counters and last IDs.
|
||||
3. Wire replacement-before-consume from handoff.
|
||||
4. Wire consumed/presented/repeated from consumer path.
|
||||
5. Wire stale epoch and shutdown discards.
|
||||
6. Wire render/present error reporting.
|
||||
7. Add read-only diagnostics access for host/debug tooling.
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
- All minimum counters and IDs from `DEC-0031` exist.
|
||||
- Latest-wins replacement is measurable.
|
||||
- Repeated presents and stale epoch discards are measurable.
|
||||
- Telemetry is not a blocking ACK path for the VM.
|
||||
|
||||
## Tests
|
||||
|
||||
- Unit tests for counter increments.
|
||||
- Handoff replacement telemetry test.
|
||||
- Stale epoch discard telemetry test.
|
||||
- Error path telemetry test where render/present errors can be simulated.
|
||||
|
||||
## Affected Artifacts
|
||||
|
||||
- Runtime telemetry modules.
|
||||
- `RenderManager`.
|
||||
- Render handoff and publication paths.
|
||||
- Host/debug telemetry readers.
|
||||
@ -1,60 +0,0 @@
|
||||
---
|
||||
id: PLN-0094
|
||||
ticket: vm-render-parallel-execution-boundary
|
||||
title: Specify Async Render Boundary
|
||||
status: done
|
||||
created: 2026-06-05
|
||||
ref_decisions: [DEC-0031]
|
||||
tags: [spec, runtime, renderer, architecture]
|
||||
---
|
||||
|
||||
## Briefing
|
||||
|
||||
`DEC-0031` needs canonical English spec coverage before worker-oriented code becomes normative.
|
||||
|
||||
## Objective
|
||||
|
||||
Publish the async render boundary contract in the canonical specs location.
|
||||
|
||||
## Dependencies
|
||||
|
||||
- Source decision: `DEC-0031`.
|
||||
- Should run before large worker implementation plans are executed.
|
||||
|
||||
## Scope
|
||||
|
||||
- Add or update English spec text for packet completeness, handoff, pacing, AppMode policy, epoch ownership, and telemetry.
|
||||
- Link the spec language to runtime concepts without exposing implementation-only details.
|
||||
- Keep `DSC-0041` foreground stack details out of this spec pass except as explicit out-of-scope reference.
|
||||
|
||||
## Non-Goals
|
||||
|
||||
- Do not document future Game3D behavior beyond extensibility notes.
|
||||
- Do not write lessons; lessons happen after execution.
|
||||
- Do not encode implementation file paths as spec requirements.
|
||||
|
||||
## Execution Method
|
||||
|
||||
1. Locate canonical specs for runtime/render/AppMode.
|
||||
2. Add a section for asynchronous render boundary or update the closest existing spec.
|
||||
3. Translate normative parts of `DEC-0031` into concise English spec language.
|
||||
4. Add out-of-scope note for Game pause/resume and VM-backed Shell coexistence under `DSC-0041`.
|
||||
5. Cross-check terminology against existing specs.
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
- Canonical specs describe the async render boundary in English.
|
||||
- Spec language covers all seven decision areas.
|
||||
- No Portuguese text is introduced in specs.
|
||||
- The spec does not require worker implementation before the plan for it exists.
|
||||
|
||||
## Tests
|
||||
|
||||
- Documentation review.
|
||||
- `rg` check for accidental Portuguese in touched spec files.
|
||||
- Existing doc/spec validation scripts if present.
|
||||
|
||||
## Affected Artifacts
|
||||
|
||||
- Canonical specs location in the repository.
|
||||
- `discussion/workflow/decisions/DEC-0031-vm-and-render-parallel-execution-boundary.md` as reference only.
|
||||
@ -1,66 +0,0 @@
|
||||
---
|
||||
id: PLN-0095
|
||||
ticket: vm-render-parallel-execution-boundary
|
||||
title: Prototype Local Render Worker Capability
|
||||
status: done
|
||||
created: 2026-06-05
|
||||
ref_decisions: [DEC-0031]
|
||||
tags: [runtime, host, renderer, worker, prototype]
|
||||
---
|
||||
|
||||
## Briefing
|
||||
|
||||
`DEC-0031` allows Game pipelines to use a render worker when host/runtime capabilities support it, with local/synchronous fallback.
|
||||
|
||||
## Objective
|
||||
|
||||
Prototype the first local render worker capability behind the established handoff, policy, epoch, and telemetry contracts.
|
||||
|
||||
## Dependencies
|
||||
|
||||
- `PLN-0087` through `PLN-0093` should be complete or accepted as prerequisites.
|
||||
- `PLN-0094` should publish the spec boundary before this becomes production work.
|
||||
|
||||
## Scope
|
||||
|
||||
- Add a host/runtime capability flag for render worker support.
|
||||
- Spawn a local worker for Game policy only.
|
||||
- Consume the single-slot handoff.
|
||||
- Present at display cadence or the nearest available host cadence.
|
||||
- Preserve synchronous/local fallback.
|
||||
|
||||
## Non-Goals
|
||||
|
||||
- Do not optimize performance beyond proving the contract.
|
||||
- Do not enable Shell worker by default.
|
||||
- Do not implement hardware-specific core/DMA behavior.
|
||||
|
||||
## Execution Method
|
||||
|
||||
1. Add capability wiring for worker-supported vs local render.
|
||||
2. Create worker lifecycle owned by runtime/host integration according to `RenderManager` policy.
|
||||
3. Make worker consume owned submissions through the handoff.
|
||||
4. Check epoch/owner before present.
|
||||
5. Emit telemetry for consume, present, repeat, stale discard, and errors.
|
||||
6. Keep a build/runtime path that uses the existing synchronous renderer.
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
- Game rendering can run through a local worker in a controlled configuration.
|
||||
- Shell rendering remains local/synchronous by default.
|
||||
- Worker does not access live mutable VM, `Hardware`, `Gfx`, or `FrameComposer` state outside approved boundaries.
|
||||
- Fallback to synchronous/local render remains available.
|
||||
|
||||
## Tests
|
||||
|
||||
- Worker smoke test with Game submission.
|
||||
- Fallback mode smoke test.
|
||||
- Stale epoch discard test while worker is active.
|
||||
- Thread shutdown test covered with `PLN-0096`.
|
||||
|
||||
## Affected Artifacts
|
||||
|
||||
- Host desktop runtime integration.
|
||||
- `RenderManager`.
|
||||
- Render handoff.
|
||||
- Render backend/driver integration points.
|
||||
@ -1,70 +0,0 @@
|
||||
---
|
||||
id: PLN-0096
|
||||
ticket: vm-render-parallel-execution-boundary
|
||||
title: Define Render Shutdown and Failure Handling
|
||||
status: done
|
||||
created: 2026-06-05
|
||||
ref_decisions: [DEC-0031]
|
||||
tags: [runtime, renderer, shutdown, errors]
|
||||
---
|
||||
|
||||
## Briefing
|
||||
|
||||
`DEC-0031` requires shutdown to stop obsolete presentation, discard pending/current work, and terminate worker execution in a bounded way. Worker panic must become controlled failure, not VM panic.
|
||||
|
||||
## Objective
|
||||
|
||||
Define and implement render shutdown, cancellation, and failure handling for both synchronous and worker-capable paths.
|
||||
|
||||
## Dependencies
|
||||
|
||||
- `PLN-0089` handoff abstraction.
|
||||
- `PLN-0092` epoch/ownership transitions.
|
||||
- `PLN-0093` telemetry.
|
||||
- `PLN-0095` if a real worker is being exercised.
|
||||
|
||||
## Scope
|
||||
|
||||
- Add stop token or equivalent cancellation state for worker/current render work.
|
||||
- Discard pending submissions on shutdown.
|
||||
- Prevent obsolete current work from presenting after shutdown/owner change.
|
||||
- Convert worker panic/render backend failure into controlled runtime/host error state.
|
||||
- Record shutdown discards and errors in telemetry.
|
||||
|
||||
## Non-Goals
|
||||
|
||||
- Do not design full crash UI policy beyond render ownership requirements.
|
||||
- Do not implement automatic worker restart unless existing host policy already supports it.
|
||||
- Do not expose failure ACK to VM program semantics.
|
||||
|
||||
## Execution Method
|
||||
|
||||
1. Define shutdown state machine for render consumer.
|
||||
2. Add bounded worker termination behavior where worker exists.
|
||||
3. Add pending/current discard paths.
|
||||
4. Ensure present path checks stop/epoch before publishing.
|
||||
5. Wrap worker entrypoint with panic/error containment.
|
||||
6. Add telemetry for shutdown discards, render errors, present errors, and worker failure.
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
- Shutdown does not drain obsolete frames to screen.
|
||||
- Pending work is discarded.
|
||||
- Current work cannot present after stop/epoch invalidation.
|
||||
- Worker failure is reported without panicking the VM.
|
||||
- Shutdown completes in bounded time.
|
||||
|
||||
## Tests
|
||||
|
||||
- Unit test pending discard on shutdown.
|
||||
- Integration test shutdown during currently-rendering submission.
|
||||
- Simulated worker panic/error test.
|
||||
- Telemetry assertions for shutdown/error counters.
|
||||
|
||||
## Affected Artifacts
|
||||
|
||||
- Render handoff.
|
||||
- Worker runtime integration.
|
||||
- `RenderManager`.
|
||||
- Telemetry modules.
|
||||
- Host error handling.
|
||||
@ -1,61 +0,0 @@
|
||||
---
|
||||
id: PLN-0097
|
||||
ticket: vm-render-parallel-execution-boundary
|
||||
title: Add Async Render Integration Test Matrix
|
||||
status: done
|
||||
created: 2026-06-05
|
||||
ref_decisions: [DEC-0031]
|
||||
tags: [runtime, renderer, tests, integration]
|
||||
---
|
||||
|
||||
## Briefing
|
||||
|
||||
`DEC-0031` spans packet correctness, resource boundaries, handoff, pacing, AppMode policy, epoch ownership, telemetry, and failure behavior. These need integration coverage across plans.
|
||||
|
||||
## Objective
|
||||
|
||||
Create an integration test matrix that proves the async render boundary contracts work together and prevents regressions while plans are implemented incrementally.
|
||||
|
||||
## Dependencies
|
||||
|
||||
- Source decision: `DEC-0031`.
|
||||
- This plan can start early as test scaffolding and expand as other plans land.
|
||||
|
||||
## Scope
|
||||
|
||||
- Define a test matrix mapping each `DEC-0031` invariant to at least one test.
|
||||
- Add reusable fixtures for Game2D submissions, Shell UI submissions, stale epoch, handoff replacement, and frame repeat.
|
||||
- Ensure tests run in local/synchronous mode and, when available, worker mode.
|
||||
|
||||
## Non-Goals
|
||||
|
||||
- Do not require real hardware backend.
|
||||
- Do not require visual screenshot testing unless the existing test stack already supports it.
|
||||
- Do not test `DSC-0041` foreground stack semantics.
|
||||
|
||||
## Execution Method
|
||||
|
||||
1. Build a matrix with rows for each decision invariant.
|
||||
2. Identify existing tests that already cover rows.
|
||||
3. Add missing tests as focused runtime/renderer integration tests.
|
||||
4. Add helpers to construct deterministic submissions and resource IDs.
|
||||
5. Run matrix in synchronous mode first.
|
||||
6. Add worker-mode variants when `PLN-0095` exists.
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
- Each `DEC-0031` invariant has at least one automated or explicitly documented validation.
|
||||
- Test fixtures distinguish Game and Shell policies.
|
||||
- Tests cover stale epoch discard, latest-wins replacement, repeated present, render error telemetry, and active-scene overlay.
|
||||
- The matrix is referenced by later implementation plans.
|
||||
|
||||
## Tests
|
||||
|
||||
- This plan is itself test-focused.
|
||||
- Required categories: packet composition, handoff, pacing, AppMode policy, epoch, telemetry, shutdown/failure.
|
||||
|
||||
## Affected Artifacts
|
||||
|
||||
- Runtime/renderer integration tests.
|
||||
- Test fixtures/helpers.
|
||||
- Any existing CI test grouping that needs to include the new tests.
|
||||
Loading…
x
Reference in New Issue
Block a user