História do 3dfx Voodoo1

imagem

Este é o segundo artigo da série "Cartões 3D do terremoto do final dos anos 90". Na primeira parte, examinamos a Rendition Vérité 1000 do final de 1996 e uma porta de jogo especial chamada vQuake. Rendition conseguiu derrotar todos no mercado Quake. Por um curto período, permaneceu a única placa capaz de lançar o blockbuster da id Software com aceleração de hardware.

Mas tudo isso mudou em janeiro de 1997, quando a id Software lançou uma nova versão do Quake chamada GLQuake. Como a porta foi criada usando o miniGL (um subconjunto do padrão OpenGL 1.1), qualquer fabricante de aceleradores de hardware poderia escrever drivers miniGL e participar da corrida de placas 3D. A partir desse momento, a possibilidade de competição estava aberta a todos. O objetivo era gerar o maior número possível de quadros por segundo. A recompensa foi a fama e o dinheiro dos clientes. Tendo estudado brevemente a história, pode-se entender que as duas autoridades da época sem dúvida consideravam os reis da montanha dois produtores.

Até agora, não há dúvida: o mundo do Quake é governado pelo vodu. E como o Quake domina o mundo dos jogos, a compra do 3Dfx Voodoo é quase inevitável para os jogadores.

- Tom's Hardware, 30 de novembro de 1997

3DFX Voodoo 1
- O padrão pelo qual todos os outros cartões são medidos.

- arquivo .plan de John Carmack. 12 de fevereiro de 1998 [2]

Apenas olhando as especificações [3] , que declaravam uma velocidade de preenchimento de 50 megapixels / s, eu imediatamente quis estudar esta placa e entender o que o 3dfx fez para criar um produto tão poderoso.

3dfx Interactive


Ross Smith, Scott Sellers e Gary Tarolli se conheceram quando trabalharam juntos na SGI [4] . Depois de trabalhar um pouco na Pellucid, onde tentaram vender placas IrisVision para PCs (em 1994, essas placas custam US $ 4000 cada), os colegas fundaram sua própria empresa com o apoio da Gordy Campbell TechFarm. A 3dfx Interactive, com sede em San Jose, Califórnia, foi fundada em 1994.

Inicialmente, a empresa pretendia criar poderosos sistemas de hardware para máquinas de fliperama, mas mudou seu curso desenvolvendo placas de PC. Havia três razões para isso.

  1. Bastante baixo preço de RAM.
  2. Começando com a RAM do FastPage e, em seguida, com a EDO, a latência na RAM diminuiu 30%. Agora a memória pode funcionar com uma frequência de até 50 MHz.
  3. Jogos em 3D (ou em pseudo-3D) tornaram-se cada vez mais populares. O sucesso de jogos como DOOM, Descent e Wing Commander III mostrou que um mercado para aceleradores 3D está prestes a surgir.

Os fundadores da empresa perceberam que precisavam criar algo poderoso, projetado para jogos e com um preço de varejo na faixa de 300 a 400 dólares. Em 1996, a empresa anunciou a criação da arquitetura SST1 (nomeada em homenagem aos fundadores - Sellers-Smith-Tarolli-1), que logo foi licenciada por vários OEMs, como Diamond, Canopus, Innovision e ColorMAX. Para sua criação, surgiu o nome de marketing "Voodoo1", enfatizando seu desempenho mágico.

Como no caso do V1000, ao criar cartões, os fabricantes só podiam alterar o tipo de RAM selecionado (EDO ou DRAM), a cor das placas e o arranjo físico dos chips. Quase todo o resto foi padronizado.


Diamond Monster 3D, imagem tomada de vgamuseum.info.


Canopus Pure3D, imagem retirada do vgamuseum.info.


BIOSTAR Venus 3D, imagem tomada de vgamuseum.info.


ORCHID 3D Justo, imagem retirada do vgamuseum.info.


Ao olhar para a placa SST1, foi impressionante a diferença entre seus concorrentes - Rendition Verite 1000 e NVidia NV1.

Primeiro, o 3dfx deu um passo ousado, abandonando o suporte à renderização 2D. O Voodoo1 tinha duas portas VGA, uma usada como saída e a outra como entrada. A placa foi desenvolvida como uma adição, tendo como entrada a saída de uma placa VGA bidimensional, já instalada no computador. Quando o usuário trabalhava com o sistema operacional (DOS ou Windows), o Voodoo1 simplesmente redirecionava o sinal da entrada VGA para a saída VGA. Ao alternar para o modo 3D, o Voodoo1 assumiu o controle da saída VGA e ignorou o sinal de sua entrada VGA. Algumas placas tiveram um interruptor mecânico que clicou ao alternar entre os modos 2D e 3D. Essa decisão significou que o cartão só pode ser usado para renderização em tela cheia, não havia modo de “janela”.

O segundo aspecto digno de nota do SST1 era que ele não era feito de uma CPU, mas de dois ASICs não programáveis ​​(circuito integrado específico da aplicação, circuitos integrados para fins especiais). Se você andar pelas trilhas dos pneus, poderá ver que cada um dos chips rotulados como “TMU” e “FBI” possui sua própria RAM. No cartão de memória, 4 mebibytes de RAM foram divididos igualmente: 2 mebibytes TMU para armazenar texturas e 2 mebibytes FBI para armazenar o buffer de cores e o buffer z, enquanto os valores foram armazenados respectivamente como RGBA de 16 bits e número inteiro / meio flutuante de 16 bits. Um cartão de memória com 4 mebibytes suporta resolução de até 640x480 (2 buffers de cores (640x480x2) para buffer duplo + 1 buffer de profundidade (640x480x2) = 1 843 200). Modelos posteriores com 4 mebibytes de RAM do FBI permitiram o uso de resoluções de até 800x600 (2x800x600x2 + 800x600x2 = 2.880.000).

Pipeline de renderização SST1


O transportador não é descrito em detalhes nas especificações. Segundo a minha interpretação, a vida de um triângulo consistia em cinco estágios.


  1. Um triângulo é criado e transformado no processador principal do computador (geralmente Pentium). Tais operações incluem multiplicação pela matriz do modelo / espaço de projeção, truncamento, divisão de perspectiva de vértice, cortando coordenadas homogêneas e transformando o campo de visão. No final desse processo, apenas triângulos visíveis do espaço na tela permanecem (devido ao recorte, um triângulo pode se transformar em dois).
  2. Usando o comando triangleCMD, os triângulos são enviados pelo barramento PCI para o Frame Buffer Interface (FBI). Eles são convertidos em consultas de seqüência de caracteres de varredura criadas pela Unidade de Mapeamento de Textura. Para cada elemento da linha de varredura (chamada de fragmento), a TMU realiza até quatro consultas de pesquisa por pixel se o desenvolvedor precisar de filtragem bilinear. A divisão de perspectiva fragmentada também é realizada na TMU.
  3. A TMU envia fragmentos para o FBI como um valor de cor RGBA de 16 bits texturizado + valor z de 16 bits.
  4. O FBI executa testes de fragmento no buffer z, comparando-os com a RAM dedicada, que armazena valores RGBA e valores z do buffer de quadros.
  5. Por fim, a iluminação é aplicada ao fragmento com base em seu atributo de cor e em uma pesquisa na tabela de neblina de 64 elementos. Se for necessário misturar, o FBI combina o fragmento resultante com o que já está no buffer de cores.

Fato interessante: se você é um entusiasta do 3D, provavelmente conhece o código raiz quadrada reversa rápida, que ficou famoso graças ao código original do Quake 3:

float Q_rsqrt(float number) { long i; float x2, y; const float threehalfs = 1.5f; x2 = number * 0.5f; y = number; i = * (long*) &y; // evil floating point bit level hacking i = 0x5f3759df - ( i >> 1 ); // what the fuck? y = * ( float * ) &i; y = y * ( threehalfs - ( x2 * y * y ) ); // 1st iteration return y; } 

Em busca de [5], a fonte Q_rsqrt Rys for Software entrou em contato com Gary Tarolli, que disse que usou esse código enquanto ainda trabalhava na SGI. Portanto, é justo supor que ele também foi usado no pipeline SST1.

Algo não corresponde


Tendo se familiarizado com o transportador e sabendo que cada componente (TMU, FBI, EDO RAM) opera com uma frequência de 50 MHz, podemos entender que há algum tipo de erro nos cálculos e o cartão não pode atingir uma velocidade de 50 megapixels / s. Dois problemas tiveram que ser resolvidos aqui.

Primeiro, a TMU precisou ler quatro texels para realizar a filtragem de textura bilinear. Isso significa que são necessários quatro ciclos de acesso à RAM, o que levaria a uma falta de dados para a TMU e a uma taxa de preenchimento de 50/4 = 12,5 megapixels / s.

Há outro gargalo no nível do FBI. Se a verificação do buffer z estiver ativada, antes de escrever ou descartar o valor z recebido do fragmento deve ser comparado com o que já está no buffer z. Se o teste foi bem-sucedido, o valor deve ser registrado. Estas são duas operações com RAM, que levaram a uma redução na taxa de preenchimento pela metade: 50/2 = 25 megapixels / s.

TMU de intercalação de quatro vias


A solução para o problema de quatro amostras no estágio TMU é mencionada na especificação SST1.

A intercalação completa é implementada no caminho de dados da memória de textura, que permite que um único banco acesse dados, independentemente do endereço usado para acessar dados em outros bancos.

- Especificação SST1

Não indica se o barramento usa multiplexação de endereço ou barramentos de dados e endereços comuns. É mais fácil descobrir se você as desenha sem multiplexação e sem separação.


Independentemente dos detalhes, a arquitetura da TMU permitiu receber texels de 4 x 16 bits por ciclo. Se os dados de entrada chegarem na frequência correta, a TMU poderá executar a divisão de fragmentos por w e, em seguida, gerar o valor z do fragmento (16 bits) e a cor do fragmento (16 bits), que foram transmitidos ao FBI.

FBI de intercalação bidirecional


A solução para o problema de duas operações de acesso à RAM no estágio do FBI também não está descrita na especificação. No entanto, o documento menciona uma taxa de preenchimento de 100 megapixels / s alcançada com o glClear devido à capacidade de gravar dois pixels por ciclo, e isso nos faz entender que o entrelaçamento bidirecional foi usado aqui.


O FBI leu e gravou dois pixels por vez (2 x 1 pixels consistindo em cores de 16 bits e z = 64 bits de 16 bits). Para fazer isso, o endereço de 21 bits gera dois endereços de 20 bits, nos quais o bit menos significativo é descartado para leitura / gravação de dois pixels em ordem. Como o algoritmo de linha raster necessário para escrever / ler em linhas horizontais se move da esquerda para a direita, a leitura de dois pixels ordinais por vez funcionou muito bem.

Barramento de 64 bits TMU-> FBI


A peça final do quebra-cabeça é o barramento FBI-TMU de 64 bits. Quase nada está escrito sobre isso na especificação, mas seu comportamento pode ser entendido pelos dados que o FBI consome. Como o FBI processa dois pixels por vez, é razoável supor que a TMU não envia texels o mais rápido possível, mas os combina como duas cores de 16 bits + valor z de 16 bits.

Programação Voodoo1


No nível mais baixo, a programação do Voodoo1 foi feita usando registros mapeados na memória. A API consiste em um número surpreendentemente pequeno de comandos, existem apenas cinco deles: TRIANGLECMD (com um ponto fixo), FTRIANGLECMD (com um ponto flutuante), NOPCMD (sem operação), FASTFILLCMD (limpeza de buffer) e SWAPBUFFERCMD relacionados ao carregamento de registros de dados para configurações de mixagem, teste z, downloads de cores de neblina e muito mais. O carregamento de textura na VRAM foi realizado através de 8 RAM de gravação de apenas 8 mebibytes com mapeamento de memória.

Programação (Real) Voodoo1


Os desenvolvedores programaram o Voodoo1 através da API Glide [6] . A lógica de design da API foi inspirada no IRIS GL / OpenGL, que usava uma máquina de estado e prefixos para tudo (somente "gr" era usado em vez de "gl", e os programadores precisavam controlar o VRAM, como agora é feito no Vulkan.

 #include <glide.h> void main( void ) { GrHwConfiguration hwconfig; grGlideInit(void); grSstSelect( 0 ); grSstQueryHardware(&hwconfig); grSstSelect(0); grSstWinOpen(null, GR_RESOLUTION_640x480, GR_REFRESH_60HZ, GR_COLORFORMAT_RGBA, GR_ORIGIN_LOWER_LEFT, 2, 0); grBufferClear(0, 0, 0); GrVertex A, B, C; ... // Init A, B, and C. guColorCombineFunction( GR_COLORCOMBINE_ITRGB ); grDrawTriangle(&A, &B, &C); grBufferSwap( 1 ); grGlideShutdown(); } 

MiniGL "padrão"


Embora o MiniGL fosse um subconjunto do padrão OpenGL 1.1, uma especificação nunca foi divulgada para ele. O MiniGL era "apenas os recursos que o Quake usa". Ao executar o objdump para o binário quake.exe, é fácil criar uma lista "oficial".

  $ objdump -p glquake.exe |  grep "gl"

 glAlphaFunc glDepthMask glLoadIdentity glShadeModel
 glBegin glDepthRange glLoadMatrixf glTexCoord2f
 glBlendFunc glDisable glMatrixMode glTexEnvf
 glClear glDrawBuffer glOrtho glTexImage2D
 glClearColor glEnable glPolygonMode glTexParameterf
 glColor3f glEnd glPopMatrix glTexSubImage2D
 glColor3ubv glFinish glPushMatrix glTranslatef
 glColor4f glFrustum glReadBuffer glVertex2f
 glColor4fv glGetFloatv glReadPixels glVertex3f
 glCullFace glGetString glRotatef glVertex3fv
 glDepthFunc glHint glScalef glViewport 


Se você começou a aprender OpenGL recentemente, deve se interessar por nomes de funções como glColor3f, glTexCoord2f, glVertex3f, glTranslatef, glBegin e glEnd. Eles foram usados ​​para um modo chamado “Modo imediato”, no qual a coordenada do vértice, a coordenada da textura, a manipulação da matriz e a cor eram indicadas por uma chamada de função por vez.

Foi assim que "naqueles dias" foi desenhado um texturizado e sombreado pelo triângulo de Gouraud.

 void Render { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glEnable(GL_TEXTURE_2D); glShadeModel(GL_SMOOTH); glBindTexture(GL_TEXTURE_2D, 1); // Assume a texture was loaded in textureId=1 glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(-1.0, 1.0, -1.0, 1.0, -1.0, 1.0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glBegin(GL_TRIANGLES); glColor3f(1.0f, 1.0f, 1.0f); glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f,-0.25f,0.0f); glColor3f(0.0f, 0.0f, 0.0f); glTexCoord2f(1.0f, 0.0f); glVertex3f(-0.5f,-0.25f,0.0f); glColor3f(0.5f, 0.5f, 0.5f); glTexCoord2f(0.0f, 1.0f); glVertex3f(-0.75f,0.25f,0.0f); glEnd(); 

GLQuake


A taxa máxima teórica de preenchimento de 50 megapixels / s deveria fornecer quase 50 quadros por segundo em uma resolução de 640x480. No entanto, como o Quake combinou duas camadas de texturas por superfície (uma para cores e outra para o mapa de luz), o SST1 teve que desenhar cada quadro duas vezes com mistura adicional na segunda passagem. Como resultado, Quake rodou a 26 fps no P166Mhz.

Ao reduzir a resolução para 512x384 na mesma máquina, foi possível obter 41 fps suaves [7] , que na época não podiam ser fornecidos por nenhum concorrente.

imagem

Renderização de software

imagem

GLQUAKE VOODOO1



Fato interessante: SST1 não era para todos. Algumas pessoas gostaram dos pixels e acharam a filtragem bilinear “embaçada”. Outros ficaram aborrecidos com a perda da correção gama.

Glquake parece uma porcaria. Eu acho que alguém pode argumentar com isso, mas vamos admitir - parece horrível, especialmente em placas NVidia. Nas placas 3dfx, nem tudo está tão ruim ... mas as cores ainda estão tremidas. No TNT2, a imagem é nojenta; ela é muito escura e sombria.

- @Frib, Glquake não oficial e guia de controle de qualidade [8]

3fdx Voodoo 2



Se eu dissesse que o 3dfx domina o mercado entre 1996 e 1998, isso seria um eufemismo. Após o SST1, a tecnologia Voodoo 2 elevou ainda mais a fasquia, graças à RAM EDO de 100 MHz, ASIC com uma frequência de 90 MHz e não apenas uma, mas duas TMUs, que permitem renderizar um quadro Quake com várias texturas (cor + iluminação) em uma passagem [9] . Essa tecnologia era um monstro real, e até as próprias placas gráficas pareciam luxuosas.

A velocidade de preenchimento no Voodoo 2 quase dobrou, chegando a 90 megapixels / s. Os benchmarks de tremores atingiram impressionantes 80 fps no Pentium II 266 MMX (comparado a 56 fps com o Voodoo1), de fato, atingindo os limites da lógica do jogo e dos recursos do monitor.

imagem

Voodoo super 2 12MB, imagem tomada de vgamuseum.info.

Infelizmente, após o lançamento do Voodoo3 em 1999, a história do 3dfx fez uma curva acentuada. Ela começou a se esforçar para desenvolver suas próprias placas universais e parou de vender a tecnologia OEM, diante da crescente concorrência.

Essa transição não foi concluída conforme o esperado, e o desempenho do Voodoo3 foi decepcionante em comparação com o GeForce 256 da NVidia, capaz de fornecer mosaico e iluminação de hardware (a Pentium fez essa parte no pipeline).

Em resposta à NVidia, o 3dfx cancelou o desenvolvimento do Voodoo4 para começar a construir o Voodoo5 com a tecnologia VSA-100 (Voodoo Scalable Architecture). O resultado foi inesperado: após o lançamento de “Napalm” (o codinome da placa), ela encontrou placas NVidia GeForce 2 e ATI Radeon mais poderosas. No final, em 28 de março de 2000, a 3dfx entrou em falência e foi comprada pela NVidia.

Para quem viveu no final dos anos 90 e teve o prazer de jogar Voodoo1 ou Voodoo2, a 3dfx continua sendo uma empresa de referência, simbolizando a excelência. Ela se tornou uma ode ao merecido sucesso alcançado através da coragem, talento excepcional e trabalho duro. Obrigado pessoal!

Referências


[1] Fonte: A história da Rendition Vérité 1000

[2] Fonte: John Carmack .plan. 12 Fev 1998

[3] Fonte: SST-1, MOTOR GRÁFICO DE ALTO DESEMPENHO PARA ACELERAÇÃO DE JOGOS 3D

[4] Fonte: 3dfx Oral History Panel

[5] Fonte: Origem do InvSqrt rápido do Quake3 ()

[6] Fonte: Guia de Programação Glide

[7] Fonte: Comparação de taxas de quadros no GLQuake usando cartões 3D Voodoo e Voodoo 2

[8] Fonte: Frib, Glquake não oficial e guia de controle de qualidade

[9] Fonte: VOODOO2 GRAPHICS MOTOR GRÁFICO DE ALTO DESEMPENHO PARA ACELERAÇÃO DE JOGOS 3D

Source: https://habr.com/ru/post/pt446860/


All Articles