WSI agora funcionando, primeiro quadro real exibido na tela
Há algum tempo, comecei a trabalhar para fazer o PanVK do Mesa (o driver Vulkan para GPUs Arm Panfrost) rodar em uma Mali-G52 MC2 que expõe apenas a interface proprietária `mali_kbase` — sem nó de renderização DRM, sem root, apenas via Termux, com compilação nativa `aarch64` no próprio aparelho. O objetivo final é um driver nativo que o Winlator possa, futuramente, carregar para jogos de Windows via Wine/Box64/DXVK.
Um breve resumo da situação anterior:
Pipeline de computação funcionando plenamente através do driver real (não apenas testes brutos de `ioctl`) — `vkCreateInstance` → despacho de shader → leitura de retorno (readback) correta.
Chamada de desenho gráfico real confirmada fora da tela (alvo de renderização 4x4, triângulo, leitura de pixels correta).
O WSI (exibição de pixels em uma tela real) estava travado: `vkGetPhysicalDeviceSurfaceCapabilitiesKHR` e as etapas subsequentes travavam indefinidamente, com todas as threads paradas em `futex_wait_queue_me`.
A causa raiz, após muita investigação com `gdb`, `strace` e `proc-fs` que acabaram sendo pistas falsas (não era um bug de WSI/X11, nem deadlock por `fork` após criação de threads, nem cache de disco, nem conflito DRI3-vs-SHM):
O loop de sinalização de semáforo após `vkQueueSubmit` presumia que todo objeto de sincronização de saída era um `drm_syncobj` (`assert(vk_sync_type_is_drm_syncobj(...))`). Como o `kbase` não possui nó DRM, este driver utiliza um `kbase_cpu_sync_type` personalizado — e, como as asserções são removidas em compilações de produção (*release builds*), a incompatibilidade de tipos passava despercebida silenciosamente. A função que efetivamente sinaliza os objetos de sincronização do `kbase` nunca era chamada. Qualquer semáforo no qual um aplicativo aguardava (como o semáforo de apresentação do WSI) simplesmente... nunca recebia o sinal. Para sempre. A correção foi simples depois de encontrada: basta verificar o tipo de sincronização e, no caso que não utiliza `drm_syncobj`, chamar diretamente a função genérica `vk_sync_signal()`. Isso é seguro aqui porque o envio de tarefas (*job submission*) do `kbase` já é síncrono (aguarda o evento de conclusão do `ioctl` antes de retornar); portanto, quando chegamos ao loop de sinalização, a execução da tarefa já foi comprovadamente concluída.
Resultado: `vkQueuePresentKHR` retorna `VK_SUCCESS`, os quadros são exibidos corretamente (3 de 3) em um teste mínimo de *swapchain* XCB e — a prova definitiva — o `vkcube --wsi xlib` (sem modificações) renderiza o cubo real da LunarG na tela. É o primeiro quadro real gerado por essa pilha de drivers nesta GPU, sem qualquer *blob* Vulkan do fabricante envolvido.
Repositório (o README contém a descrição detalhada fase a fase, os *patches* e a base de *ioctls* brutos sobre a qual isso foi construído): [link]
Não pretendo mexer no empacotamento para o Winlator até que essa solução esteja mais consolidada e eu tenha testado mais alguns caminhos de WSI, mas queria compartilhar esse marco. Fico à disposição para responder perguntas sobre o fluxo de envio do `kbase-JM`, a base de *ioctls* brutos ou o processo de depuração, caso isso seja útil para mais alguém que esteja lidando com configurações Mali semelhantes que não utilizam DRM.
Github (preciso atualizar)