215 lines
9.6 KiB
Markdown
215 lines
9.6 KiB
Markdown
---
|
|
id: AGD-0027
|
|
ticket: frame-composer-public-syscall-surface
|
|
title: Agenda - FrameComposer Public Syscall Surface
|
|
status: accepted
|
|
created: 2026-04-17
|
|
updated: 2026-04-17
|
|
tags: [gfx, runtime, syscall, abi, frame-composer, scene, camera, sprites]
|
|
---
|
|
|
|
## Contexto
|
|
|
|
`DEC-0014` e os planos `PLN-0017` a `PLN-0021` fecharam a migração interna do pipeline de frame para `FrameComposer`:
|
|
|
|
- `FrameComposer` virou o orquestrador canônico do frame;
|
|
- `Hardware` passou a agregá-lo ao lado de `Gfx`;
|
|
- scene, camera, cache, resolver e sprite emission migraram para ownership interno dele;
|
|
- o frame loop do runtime passou a renderizar via `FrameComposer.render_frame()`.
|
|
|
|
Isso resolveu a base operacional interna, mas não fechou a superfície pública equivalente para a VM. A ABI pública ainda expõe apenas o contrato legado de `gfx.set_sprite(...)`, enquanto `bind_scene(...)` e `set_camera(...)` existem apenas como APIs internas do driver.
|
|
|
|
Na prática, hoje temos uma assimetria:
|
|
|
|
- a base canônica do frame está em `FrameComposer`;
|
|
- mas a ABI pública ainda não trata `FrameComposer` como serviço canônico para scene, camera e sprites.
|
|
|
|
Essa lacuna impede a migração do restante da stack e também impede um stress cartridge que atravesse de verdade o pipeline novo por syscall pública.
|
|
|
|
## Problema
|
|
|
|
Precisamos definir a nova superfície pública de syscall para o pipeline canônico de `FrameComposer` sem reabrir a decisão já aceita sobre ownership interno do frame.
|
|
|
|
O problema concreto não é “adicionar 2 ou 3 syscalls”. Precisamos decidir:
|
|
|
|
- quais operações de `FrameComposer` viram ABI pública agora;
|
|
- se `gfx.set_sprite(...)` continua como shim legado ou perde status canônico;
|
|
- qual é o contrato mínimo de scene/camera que a VM pode observar/controlar;
|
|
- como nomear e versionar essa superfície pública sem criar um segundo modelo canônico concorrente;
|
|
- qual é a estratégia de transição para cartridge, runtime tests e stress tests;
|
|
- como propagar essa mudança para a spec canônica e, se necessário, para contratos de ABI e `ISA_CORE`.
|
|
|
|
## Pontos Criticos
|
|
|
|
- `DEC-0014` já fechou `FrameComposer` como base canônica interna; esta agenda não deve reabrir isso.
|
|
- A ABI pública atual ainda expõe `gfx.set_sprite(...)` com semântica herdada de índice/slot, mesmo que a implementação interna já use frame emission.
|
|
- `bind_scene(scene_bank_id)` e `set_camera(x, y)` já existem no driver, mas ainda não existem como syscalls públicas.
|
|
- Se a nova ABI expuser demais logo de início, vamos congelar cedo demais detalhes que ainda não provaram valor operacional.
|
|
- Se a nova ABI expuser de menos, manteremos um modelo híbrido por tempo demais:
|
|
- canônico internamente via `FrameComposer`;
|
|
- legado externamente via `Gfx`/`set_sprite`.
|
|
- Precisamos decidir se o namespace público continua em `gfx.*` por estabilidade do domínio, ou se devemos introduzir algo como `frame.*`.
|
|
- A transição precisa preservar compatibilidade suficiente para não quebrar cartridges e testes existentes antes da migração do restante.
|
|
- O contrato de sprite precisa deixar claro se o chamador ainda informa índice, se informa `layer`, e se `active` continua existindo na superfície pública.
|
|
- A mudança não pode ficar só em código/runtime; a spec canônica precisa ser atualizada para refletir o novo serviço público.
|
|
- Se o contrato público afetar superfícies documentadas de ABI ou o material de `ISA_CORE`, essa propagação precisa ser tratada como parte da mesma thread, não como follow-up solto.
|
|
|
|
## Opcoes
|
|
|
|
### Opcao 1 - Expor um núcleo mínimo canônico em `gfx.*`
|
|
|
|
**Como seria:**
|
|
Adicionar apenas a superfície mínima para a VM controlar o pipeline novo:
|
|
|
|
- `gfx.bind_scene(bank_id)`
|
|
- `gfx.unbind_scene()`
|
|
- `gfx.set_camera(x, y)`
|
|
- `gfx.emit_sprite(...)`
|
|
|
|
`gfx.set_sprite(...)` permaneceria por um período como shim legado de compatibilidade.
|
|
|
|
**Vantagens:**
|
|
- fecha rapidamente a lacuna operacional;
|
|
- habilita stress real do pipeline novo;
|
|
- reduz o tempo de convivência entre modelo canônico e legado;
|
|
- mantém o domínio público em `gfx`, evitando churn de namespace.
|
|
|
|
**Desvantagens:**
|
|
- introduz ABI nova que precisará de migração coordenada;
|
|
- exige definir `emit_sprite(...)` com cuidado para não herdar sem querer o modelo de slot.
|
|
|
|
### Opcao 2 - Expor scene/camera agora e adiar o contrato novo de sprite
|
|
|
|
**Como seria:**
|
|
Publicar apenas:
|
|
|
|
- `gfx.bind_scene(bank_id)`
|
|
- `gfx.unbind_scene()`
|
|
- `gfx.set_camera(x, y)`
|
|
|
|
Sprites continuariam publicamente via `gfx.set_sprite(...)` até uma segunda fase.
|
|
|
|
**Vantagens:**
|
|
- menor mudança imediata de ABI;
|
|
- desbloqueia o stress do world path e da câmera;
|
|
- reduz o volume inicial da migração pública.
|
|
|
|
**Desvantagens:**
|
|
- mantém dois modelos públicos de sprite por mais tempo;
|
|
- prolonga a semântica de compatibilidade do syscall legado;
|
|
- adia exatamente uma das partes centrais da migração para `FrameComposer`.
|
|
|
|
### Opcao 3 - Criar um novo namespace público separado, como `composer.*`
|
|
|
|
**Como seria:**
|
|
O pipeline novo ganha syscalls em um domínio separado, por exemplo:
|
|
|
|
- `composer.bind_scene`
|
|
- `composer.unbind_scene`
|
|
- `composer.set_camera`
|
|
- `composer.emit_sprite`
|
|
|
|
`gfx.*` ficaria como superfície legacy/low-level.
|
|
|
|
**Vantagens:**
|
|
- deixa explícita a mudança de serviço canônico;
|
|
- evita sobrecarregar semanticamente `gfx`.
|
|
|
|
**Desvantagens:**
|
|
- adiciona churn conceitual e de nomenclatura;
|
|
- fragmenta demais a superfície pública neste momento;
|
|
- cria um custo de transição maior sem benefício operacional evidente.
|
|
|
|
## Sugestao / Recomendacao
|
|
|
|
Seguir com a **Opcao 3**.
|
|
|
|
Direção recomendada:
|
|
|
|
- a superfície pública canônica deve migrar para o domínio `composer.*`;
|
|
- `FrameComposer` vira a base canônica também na ABI pública, com namespace próprio em vez de continuar semanticamente preso a `gfx.*`;
|
|
- o núcleo mínimo público deve ser:
|
|
- `composer.bind_scene(bank_id) -> status`
|
|
- `composer.unbind_scene()`
|
|
- `composer.set_camera(x, y)`
|
|
- `composer.emit_sprite(...) -> status`
|
|
- `gfx.set_sprite(...)` deve morrer e ser removido completamente do contrato público.
|
|
|
|
Para sprites, a recomendação provisória é:
|
|
|
|
- a nova ABI pública não deve exigir índice explícito;
|
|
- `composer.emit_sprite(...)` deve receber o payload completo necessário para o frame:
|
|
- `glyph_id`
|
|
- `palette_id`
|
|
- `x`
|
|
- `y`
|
|
- `layer`
|
|
- `bank_id`
|
|
- `flip_x`
|
|
- `flip_y`
|
|
- `priority`
|
|
- a ABI pode futuramente agrupar esse payload se isso melhorar ergonomia, mas o contrato mínimo deve nascer completo;
|
|
- `active` não deve continuar no contrato canônico novo;
|
|
- overflow continua sendo ignorado com status/telemetria adequada, sem trapar o runtime.
|
|
|
|
Para scene/camera, a recomendação provisória é:
|
|
|
|
- manter o contrato mínimo já aceito internamente;
|
|
- `bind_scene` por bank id;
|
|
- `unbind_scene` explícito;
|
|
- `set_camera(x, y)` em pixel space com top-left viewport.
|
|
- `bind_scene(...)`, `unbind_scene(...)` e `emit_sprite(...)` devem usar `ComposerOpStatus` como retorno operacional canônico.
|
|
|
|
## Perguntas em Aberto
|
|
|
|
- Resolvido:
|
|
- o nome público canônico de sprite será `composer.emit_sprite(...)`;
|
|
- o syscall novo de sprite nasce completo com `glyph_id`, `palette_id`, `x`, `y`, `layer`, `bank_id`, `flip_x`, `flip_y`, `priority`;
|
|
- `gfx.set_sprite(...)` deve morrer e ser removido completamente;
|
|
- não haverá leitura de estado nesta primeira fase;
|
|
- `bind_scene(...)`, `unbind_scene(...)` e `emit_sprite(...)` usarão `ComposerOpStatus`;
|
|
- A ABI nova precisa expor refresh explícito, ou isso deve continuar totalmente interno ao `FrameComposer`?
|
|
- Resolvido:
|
|
- a ABI nova não deve expor refresh explícito;
|
|
- o domínio público canônico será `composer.*`, não `gfx.*`.
|
|
|
|
## Criterio para Encerrar
|
|
|
|
Esta agenda pode ser encerrada quando houver acordo explícito sobre:
|
|
|
|
- a lista mínima de syscalls públicas canônicas do `FrameComposer`;
|
|
- o nome canônico da operação pública de sprite;
|
|
- a remoção completa de `gfx.set_sprite(...)` do contrato público;
|
|
- o formato de retorno/status das novas operações;
|
|
- a estratégia de transição necessária para decisão, plano e migração do restante da stack.
|
|
|
|
## Resolucao em Andamento
|
|
|
|
Direção atualmente acordada nesta agenda:
|
|
|
|
- o namespace público canônico será `composer.*`;
|
|
- o núcleo mínimo inicial será:
|
|
- `composer.bind_scene(bank_id) -> ComposerOpStatus`
|
|
- `composer.unbind_scene() -> ComposerOpStatus`
|
|
- `composer.set_camera(x, y)`
|
|
- `composer.emit_sprite(glyph_id, palette_id, x, y, layer, bank_id, flip_x, flip_y, priority) -> ComposerOpStatus`
|
|
- não haverá introspecção pública nesta primeira fase;
|
|
- refresh/cache policy continua interno ao `FrameComposer`;
|
|
- `gfx.set_sprite(...)` não terá caminho de compatibilidade e deve ser removido.
|
|
|
|
## Resolucao
|
|
|
|
Esta agenda fica aceita com os seguintes pontos fechados:
|
|
|
|
- o namespace público canônico do serviço será `composer.*`;
|
|
- a superfície mínima inicial será:
|
|
- `composer.bind_scene(bank_id) -> ComposerOpStatus`
|
|
- `composer.unbind_scene() -> ComposerOpStatus`
|
|
- `composer.set_camera(x, y)`
|
|
- `composer.emit_sprite(glyph_id, palette_id, x, y, layer, bank_id, flip_x, flip_y, priority) -> ComposerOpStatus`
|
|
- não haverá introspecção pública nesta primeira fase;
|
|
- não haverá refresh/cache policy público;
|
|
- `gfx.set_sprite(...)` deve ser removido completamente, sem shim de compatibilidade;
|
|
- a transição deve introduzir `composer.*` e remover `gfx.set_sprite(...)` na mesma thread de migração, com atualização coordenada de bytecode, cartridges, tests e runtime;
|
|
- a mesma thread deve atualizar a spec canônica do assunto e propagar a mudança para contratos de ABI e `ISA_CORE` quando essas superfícies forem impactadas pelo novo serviço público.
|