Meu servidor virou console: jogos do homelab na TV da sala

Levei os jogos do servidor para a TV da sala sem comprar hardware novo. Os três problemas que travaram o caminho, e por que nenhum deles aparece como erro no log.

Compartilhar
Meu servidor virou console: jogos do homelab na TV da sala

A placa de vídeo boa estava no servidor, no escritório. A TV boa estava na sala. A conta não fechava: comprar um PC para a sala seria pagar de novo por um hardware que já estava ali, ligado, ocioso a maior parte do dia.

Então em vez de comprar máquina, eu levei o jogo até a TV. O servidor virou o console: ele roda o jogo com a placa dedicada e manda vídeo comprimido para a sala. Funciona, e hoje é como eu jogo.

Este artigo é a parte que os tutoriais não contam: os três problemas que me travaram, e por que cada um acontecia.

A ideia

O software que faz isso é o Wolf, do projeto Games on Whales. Ele roda dentro de Docker, recebe a GPU por passagem direta e sobe uma sessão de jogo isolada em container. Na TV, um cliente leve se conecta e recebe o vídeo. Na prática é o mesmo princípio do GeForce Now, só que o datacenter é o seu escritório.

O primeiro detalhe que importa: a máquina tem duas GPUs, a dedicada e o vídeo integrado do processador. O Wolf precisa saber qual usar, e ele não adivinha.

WOLF_RENDER_NODE=/dev/dri/renderD129

Aqui, renderD129 é a placa dedicada e renderD128 é o vídeo integrado. Essa numeração não é fixa entre máquinas e pode até trocar entre reinicializações dependendo da ordem de carga dos drivers. Confira a sua antes de assumir a minha.

Armadilha 1: o codec que a sua placa não tem

Primeiro sintoma: tudo "funcionava", mas a imagem estava ruim e o processador ficava em uso alto sem motivo aparente. Jogo rodando, GPU tranquila, CPU sofrendo.

A causa: o Wolf tentava codificar o vídeo em AV1. A minha placa é uma RTX 3080, arquitetura Ampere. E Ampere não tem codificador AV1 em hardware, esse encoder só apareceu na série 40. Como o hardware não dava conta, a biblioteca caía silenciosamente no av1enc, que é codificação por software, na CPU.

Nada quebrava. Só ficava ruim, que é o pior tipo de defeito, porque não aparece em log de erro.

A correção é dizer ao Wolf para nem tentar. No config.toml, comentei os blocos de encoder AV1:

/etc/wolf/cfg/config.toml

# [[gstreamer.video.av1_encoders]]
# ... bloco inteiro comentado

Sem a opção na mesa, ele passa a usar o codificador de hardware que a placa realmente tem. A CPU esvazia e a imagem melhora.

A lição que vale além do Wolf: quando um software oferece uma lista de codecs, ele geralmente tenta na ordem e cai para o próximo em caso de falha. Se o fallback for software, você paga em CPU sem receber aviso. Vale conferir qual codificador está realmente sendo usado, não qual está disponível.

Armadilha 2: o DLSS que sumiu

Segundo problema: jogos com DLSS simplesmente não mostravam a opção. Como se a placa não fosse NVIDIA.

A causa está na fronteira entre três coisas que normalmente não se falam: container, driver NVIDIA e Proton. O nvidia-container-toolkit é quem injeta as bibliotecas da placa dentro do container. Ele faz um bom trabalho, mas não monta o diretório do Wine:

/usr/lib/x86_64-linux-gnu/nvidia/wine/

É ali que moram nvngx.dll e _nvngx.dll, as bibliotecas que o lado Windows do Proton precisa para enxergar o DLSS. Sem elas dentro do container, o jogo roda perfeitamente. Só que sem DLSS, e sem reclamar.

A correção é montar o diretório explicitamente na configuração do app:

mounts = [
  "/usr/lib/x86_64-linux-gnu/nvidia/wine/:/usr/lib/x86_64-linux-gnu/nvidia/wine/:ro"
]

Armadilha 3: a tela cortada

Terceiro: a imagem piscava e ficava cortada, como se a resolução estivesse errada. E estava.

O Wolf tem duas formas de montar a sessão gráfica. O padrão do projeto é o Sway, e isso é uma escolha deliberada: o gamescope tem suporte problemático em versões recentes do driver NVIDIA.

Acontece que o gamescope faz mais do que parece. Ele funciona como um compositor que segura a resolução: o jogo desenha na resolução que quiser, e o gamescope entrega para o sistema no tamanho certo. Sem ele, o jogo faz o próprio ajuste de modo de vídeo direto e briga com a sessão remota, que tem resolução fixa.

Daí a tela cortada e o piscar. Não é bug de driver: são dois softwares tentando definir a resolução ao mesmo tempo.

Bônus: o piscar que era outra coisa

Um jogo específico continuou piscando depois de tudo resolvido. Resident Evil 4, que usa D3D12. O log entregou:

vkd3d-proton: Multiple adapters found with LUID

Dentro do container do Steam existiam cerca de catorze drivers Vulkan registrados. Entre eles estavam o lvp_icd (o llvmpipe, que é renderização por software) e o driver aberto da NVIDIA. O llvmpipe se apresentava como uma segunda placa e colidia de identificador com a RTX 3080. O tradutor de DirectX 12 para Vulkan via duas placas com a mesma identidade e alternava entre elas.

A correção vai nas opções de inicialização do jogo, no Steam:

VK_DRIVER_FILES=/usr/share/vulkan/icd.d/nvidia_icd.json \
VK_ICD_FILENAMES=/usr/share/vulkan/icd.d/nvidia_icd.json \
VKD3D_FILTER_DEVICE_NAME=3080 %command%

Verificação objetiva: no log do Proton, a linha Found device deve listar só a NVIDIA, e o aviso de LUID tem que zerar. Se ainda aparecer, sobrou driver na lista.

Dois falsos alarmes que me custaram tempo

Vale registrar, porque perdi horas nos dois.

Os arquivos .dump não são travamentos. O Wolf grava um arquivo de rastreamento a cada inicialização, um por start, com o horário batendo com a leitura do arquivo de configuração. Ver uma pasta cheia deles não significa que o programa quebrou dezenas de vezes. Significa que ele foi iniciado dezenas de vezes.

A mensagem got the same buffer committed twice é ruído. Ela acompanha atividade de quadro: aparece com frequência quando o jogo está rodando bem, e some quando o jogo trava. É praticamente o oposto de um sinal de problema. Se ela parar, aí sim se preocupe.

E os bugs que não eram meus

Dois comportamentos do Resident Evil 4 sob Proton não têm nada a ver com a infraestrutura: o menu de configurações não aceitar alteração, e o jogo congelar ao sair. Estão reportados em PC comum, sem container nenhum. Antes de desmontar seu servidor procurando culpa, procure o número da issue.

O que ficou

Jogo na TV da sala com a placa que já estava paga, sem comprar hardware novo e sem abrir porta no roteador. O servidor continua fazendo tudo o que fazia antes. Quando ninguém está jogando, a GPU volta para as outras tarefas.

Se o seu servidor tem uma placa dedicada parada, esse caminho existe. Só não confie que vai funcionar de primeira: os três problemas que descrevi aqui não aparecem em nenhum log como erro. Eles aparecem como "está funcionando, mas está estranho", e é por isso que custam tanto tempo.

Se você for tentar, a ordem que eu recomendo é: primeiro confirme qual nó de render é a sua placa dedicada, depois resolva o codec, e só então vá para os jogos. Debugar tudo junto é o que transforma uma tarde em uma semana.