Eu acho que é comumente aceito que o tempo real é tudo o que está acima de interativo. E interativo é definido como "responde à entrada, mas não é suave no fato de que a animação parece irregular".
Portanto, o tempo real dependerá da velocidade dos movimentos que precisamos representar. Projetos de cinema a 24 FPS e é tempo suficiente para muitos casos.
Então, quantos polígonos uma máquina pode lidar é facilmente verificável, verificando você mesmo. Basta criar um pequeno patch VBO como um teste simples e um contador de FPS, muitas amostras do DirectX ou do OpenGL fornecerão o local de teste perfeito para esse benchmark.
Você descobrirá se possui uma placa gráfica de ponta que pode exibir cerca de 1 milhão de polígonos em tempo real. No entanto, como você disse, os mecanismos não reivindicarão suporte com tanta facilidade porque os dados da cena do mundo real causarão vários porcos de desempenho não relacionados à contagem de polígonos.
Você tem:
- taxa de preenchimento
- amostragem de textura
- Saída ROP
- desenhar chamadas
- processar switches de destino
- atualizações de buffer (uniforme ou outro)
- overdraw
- complexidade do sombreador
- complexidade do pipeline (algum feedback usado? sombreamento de geometria iterativa? oclusão?)
- pontos de sincronização com a CPU (readback de pixel?)
- riqueza de polígonos
Dependendo dos pontos fracos e fortes de uma placa gráfica específica, um ou outro desses pontos será o gargalo. Não é como se pode dizer com certeza "aí, é esse".
EDITAR:
Eu queria acrescentar que não se pode usar a figura de especificação GFlops de uma placa específica e mapeá-la linearmente para a capacidade de empurrar polígonos. Devido ao fato de que o tratamento com polígonos precisa passar por um gargalo seqüencial no pipeline de gráficos, conforme explicado em detalhes aqui: https://fgiesen.wordpress.com/2011/07/03/a-trip-through-the-graphics -pipeline-2011-part-3 /
TLDR: os vértices devem caber em um pequeno cache antes da montagem primitiva, que é nativamente uma coisa seqüencial (a ordem do buffer de vértice é importante).
Se você comparar a GeForce 7800 (9 anos?) Com a 980 deste ano, parece que o número de operações por segundo em que ele é capaz aumentou mil vezes. Mas você pode apostar que não empurrará polígonos mil vezes mais rápido (o que seria de cerca de 200 bilhões por segundo por essa métrica simples).
EDIT2:
Para responder à pergunta "o que se pode fazer para otimizar um mecanismo", como em "não perder muita eficiência em comutadores de estado e outras despesas gerais".
Essa é uma pergunta tão antiga quanto os próprios motores. E está se tornando mais complexo à medida que a história avança.
De fato, na situação do mundo real, os dados típicos da cena conterão muitos materiais, muitas texturas, muitos shaders diferentes, muitos alvos e passes de renderização e muitos buffers de vértices e assim por diante. Um mecanismo com o qual trabalhei trabalhou com a noção de pacotes:
Um pacote é o que pode ser renderizado com uma chamada de empate.
Ele contém identificadores para:
- buffer de vértice
- buffer de índice
- camera (dá o passe e renderiza o alvo)
- ID do material (fornece sombreador, texturas e UBO)
- distância ao olho
- é visível
Portanto, o primeiro passo de cada quadro é executar uma classificação rápida na lista de pacotes usando uma função de classificação com um operador que dê prioridade à visibilidade, depois passe, material, geometria e, finalmente, distância.
Desenhar objetos próximos obtém prioridade para maximizar o descarte precoce de Z.
Os passes são etapas fixas; portanto, não temos escolha a não ser respeitá-los.
O material é a coisa mais cara para mudar de estado após renderizar alvos.
Mesmo entre diferentes IDs de materiais, é possível fazer uma subordem usando um critério heurístico para diminuir o número de alterações no shader (mais caras nas operações de troca de estado do material) e, em segundo lugar, alterações na ligação da textura.
Após toda essa ordem, é possível aplicar mega texturização, texturização virtual e renderização sem atributo ( link ), se necessário.
Sobre a API do mecanismo, também é comum adiar a emissão dos comandos de configuração de estado exigidos pelo cliente. Se um cliente solicitar "definir câmera 0", é melhor apenas armazenar essa solicitação e, posteriormente, o cliente chamar "definir câmera 1", mas sem outros comandos, o mecanismo poderá detectar a inutilidade do primeiro comando e descartá-lo. . Isso é a eliminação da redundância, que é possível usando um paradigma "totalmente retido". Em oposição ao paradigma "imediato", que seria apenas um invólucro acima da API nativa e emitia os comandos corretamente, conforme solicitado pelo código do cliente. ( exemplo: virtrev )
E, finalmente, com o hardware moderno, um passo muito caro (para desenvolver), mas potencialmente altamente recompensador, é mudar a API para o estilo metal / manto / vulkan / DX12 e preparar os comandos de renderização manualmente.
Um mecanismo que prepara comandos de renderização cria um buffer que contém uma "lista de comandos" que é substituída em cada quadro.
Geralmente, existe uma noção de quadro "orçamento", que um jogo pode pagar. Você precisa fazer tudo em 16 milissegundos, para particionar claramente o tempo da GPU "2 ms para passagem de luz", "4 ms para passagem de materiais", "6 ms para iluminação indireta", "4 ms para pós-processos" ...