Neste artigo vamos analisar o Sample Feedback Streaming, e perceber o que é, como funciona, e como ele traz os ganhos que a Microsoft anuncia.
Apesar de a altura não ser a mais propícia à minha concentração, dado o falecimento de um familiar muito próximo, tenho estado a tentar perceber o que o Sampler Feedback Streaming pode trazer ao mercado, e até que ponto ele é realmente inovador.
Segundo a Microsoft, o SFS permite:
- Poupança de até 2.5x de memória
- Menor leitura de dados por capacidade de ler apenas as partes das texturas que são efetivamente necessárias.
E para analisarmos e explicarmos como isso acontece, vamos ter de explicar algumas coisas… ou melhor… muitas coisas, nomeadamente:
- Uma explicação básica sobre texturação
- Um histórico do streaming de texturas
- As diferenças entre o PRT, e o PRT+ (Tambem chamado de Sampler Feedback Streaming, ou SFS)
- As diferenças face ao SFS da Xbox série X
E dado que há aqui muito que escrever… vamos começar:
Uma explicação básica sobre texturação
Cremos que o conceito de textura será o mais simples de explicar. Basicamente é uma imagem, que representa a superfície de um material ou objeto, que é envolvida num modelo 3D de forma a lhe dar o aspeto desejado.
E se isso é o básico, para que tudo funcione bem é necessário que duas situações existam:
- O uso de mipmaps
- A existência de filtragem de texturas.
Os Mipmaps
Basicamente as texturas são uma imagem 2D que são aplicadas a um objeto. Mas se uma textura ou imagem é algo que visualizamos na vertical, quando aplicadas a um mundo e objecto 3D, a sua posição muda, podendo aparecer inclinada, rodada ou até distorcida sobre várias zonas com formas diferentes se aplicada sobre um objecto complexo. Mas mesmo nos casos mais simples, como por exemplo uma textura de piso, o que víamos depois que acontecia no universo 3D é que nem todas todas as partes do objecto textura estavam à mesma distância do ecrã. E isso criava aberrações visuais.
Um exemplo do que falo:
O que temos aqui é uma textura com um padrão de tabuleiro de xadrez que é repetida e colocada sobre uma superfície que se encontra numa posição obliqua face à câmara. E o que vemos é que a sua rotação e torção, para se adaptar à posição do objecto em que está aplicada, funciona muito bem até uma determinada distância, dali para a frente o padrão começa a distorcer, e criam-se bandas com efeitos visuais diferentes.
Ora o ideal é que isso não existisse, e que o resultado fosse o mais perfeito possível, como na imagem que se segue:
Mas como se conseguir isto?
Basicamente com duas situações… Os Mipmaps… e a filtragem de texturas.
É devido a isto que surgem os mipmaps, um conceito que se torna relevante para toda esta explicação. Basicamente os mipmaps são versões da mesma textura, mas com diferentes resoluções. A ideia é não só melhorar com elas a qualidade de imagem ao evitar re-escalamentos em tempo real, mas acima de tudo o não se ter de colocar cópias de uma textura de grandes dimensões e com grande ocupação de memória em locais onde a mesma ocupará menos pixels e como tal sua qualidade não será percetível. E possuindo texturas alternativas com menor resolução e que ocupam menos RAM podemos fazer isso mesmo, colocando de acordo com a distância uma versão da textura mais adequada, evitando-se assim não só distorções no ecrã como poupando no uso da memória..
Eis aqui um exemplos de uma imagem e diversos mipmaps de menor resolução..
Como vemos, aqui temos várias cópias da mesma textura, mas com resoluções diferentes.
Num exemplo perfeito de uso desta imagem de cima (uma paisagem) Imaginemos uma cena que representa uma sala de arte com várias telas todas iguais com a imagem da foto, umas colocadas por detrás das outras, e consequentemente cada vez mais longe do ecrã!
Sem o uso dos mipmaps, a textura principal de maior resolução, também chamada de mip0, seria repetida em todas as telas, sendo re-escalada em tempo real e com cada cópia a usar a mesma quantidade de memória.
Mas com mipmaps, assim que a distância for adequada ao uso de uma imagem com a resolução imediatamente abaixo, a mip1, ela será usada. E a situação repetir-se-á com a mip2 e por aí fora.
A consequência acabaria por ser o uso da memória, que seria menor pois sempre que usavamos uma versão da textura com menor resolução esta gastaria menos RAM, para um efeito visual que até acabaria por ser superior devido a que nos casos onde tivéssemos distorção da imagem base, ela nunca seria exagerada.
Dependendo das cenas usadas podemos encontrar jogos com casos onde temos até 16 níveis de mips!
Mas apesar de os mipmaps ajudarem a resolver o problema, ele não resolvem tudo. Na imagem de cima, com o nosso padrão de xadrez, passar a colocar um mip mais baixo a partir de uma certa profundidade ajuda a diminuir o efeito de distorção. Mas a questão é que como referido, as texturas são retangulares e destinadas a serem vistas numa posição paralela ao ecrã. E naquele piso o que ali temos é a textura colocada obliquamente. E devido a isso ela vai ter sempre de sofrer distorção de perspetiva com a distância o que quer dizer que apesar de os mipmaps minimizarem o problema, ele sozinhos não resolvem a totalidade da situação.
E é aí que entra a filtragem das texturas!
A filtragem de texturas é igualmente essencial, até porque nem sempre podemos ter mipmaps. Um exemplo é um simulador de voo, em que temos sempre uma representação de um terreno que, tal como o aqui em discussão, se encontra numa perspetiva obliqua, e sempre em movimento. E se ali pensássemos em aplicar mipmaps teríamos de ter todo o mapa em vários níveis de resolução diferente, o que teria consequências gigantes na dimensão do jogo.
Daí que a filtragem acaba por ser essencial. Mas diga-se que dado que não é sobre ela que o artigo vai incidir, e só a tivemos de referir para que a explicação não ficasse com uma lacuna, apenas a vamos abordar muito sumariamente.
E nesse sentido podemos dizer que, basicamente, a filtragem faz correções à textura causadas pela perspetiva. A um ponto que ela sozinha pode substituir os mipmaps, apesar de não existir com esse intuito.
Num caso como o que temos em estudo, com o padrão, uma filtragem como o Anisotropic Filtering (o melhor dos métodos, e atualmente o mais mais usado), faria uma correção do género:
Basicamente o que importa reter é que a filtragem aplica correções a uma textura, re-escalando-a nas partes em que precisa, e ajustando-a à nova posição. E existem três tipos de filtragem, por ordem de qualidade e da pior para a melhor, a Bilinear, a Trilinear e a Anisotrópica.
Mas estamos a fugir do essencial, que são os mipmapings, e isto foi apenas um aparte necessário para uma explicação no final deste artigo.
Um histórico do streaming de texturas
-
- Método Classico
- PRT
- PRT+SF (SFS)
Método clássico
Este é o método original, onde tudo começou, sendo ele o mais básico e simples de todos. Basicamente, com o conceito de mipmaping, o que aconteceu foi que os criadores passaram a utilizar versões das texturas de menor resolução quando as mesmas estavam mais afastadas do ecrã. Antes tudo era feito com a textura principal, o mip0, mas depois, com os mipmaping foi possível reduzir o processamento e o uso da RAM ao se usar versões mais simples das texturas.
Mas este método era simplista demais, e eis que surge um auxiliar, as Partial Resident Textures, ou Virtual Textures.
O PRT (Partial Resident Textures, ou texturas parcialmente residentes)
O nome PRT surge do seu uso no Unreal Engine, onde a metodologia foi chamada assim. Mas a ID, criadora do método usado pela primeira vez no jogo Rage com o seu motor Idtech chamou-as originalmente de “Virtual Textures” ou texturas virtuais.
Esta metodologia pode ser implementada 100% por software, tendo alias sido nessa vertente que ela nasceu. Mas rapidamente foi passada para suporte hardware (mas abordaremos isso mais tarde).
A necessidade desta nova técnica surge não só porque a anterior se revelava insatisfatória, mas porque com os anos a dimensão do mip0 cresceu. E sabemos isso quando vemos que agora é comum o mip0 poder ter 4K ou até 8K de resolução, e isso, mesmo com o uso dos restantes mipmaps, acaba por criar um peso gigante na ocupação da memória do GPU.
Eis um exemplo onde o uso da memória era especialmente problemática:
Imaginemos uma cena onde temos uma personagem em primeiro plano, que usa uma camisola com uma textura 4K. Mas essa personagem está quase toda fora do ecrã, pelo que apenas um pedaço da textura é visível, com o resto ou fora do ecrã ou obstruído por outros objetos. Apesar de que so tinhamos um pedacinho da camisola visível, e com a personagem em primeiro plano, o que normalmente se fazia era carregar o mip0 para a RAM, aplicando-a e mostrando apenas o que era visível. Se imaginarem que essa textura é 4K e que toda ela era carregada para a RAM, para se mostrar apenas um pedacinho da mesma, facilmente se percebe que este é um caso de um uso da RAM que poderia ser otimizado.
Daí que surgiu uma ideia. E se pudéssemos carregar apenas partes da textura?
Foi com essa ideia em mente que surgiu o PRT.
Basicamente o PRT trabalha com mipmaps, mas acrescenta um novo conceito, Os “Tiled resources”, onde as diversas imagens deixam de ser tratadas como uma só, mas como sendo constituídas por “azulejos” de 128×128 pixels, e onde cada um desses azulejos pode ser lido para a RAM sem necessidade da leitura dos outros. Daí o nome “Tiled resources”, ou “Recursos de Azulejo”, que está na base da tecnologia.
Num exemplo, uma imagem que é a textura principal (mip0), que vamos considerar com uma resolução de 1024×1024 pixels. pode ser tratada como possuindo 8 azulejos na vertical e 8 na horizontal, num total de 64 partes. Já o mip1 que teria metade da resolução (512×512), com azulejos da mesma dimensão teria apenas 4 na vertical por 4 na horizontal, e o mip 2, novamente com metade da resolução do mip1 teria teria 2×2 azulejos,. Repetindo a coisa temos o mip 3 com metade da resolução do mip2, e que teria apenas 1 azulejo de 128×128 pixels.
Basicamente, dado ser possível ler-se cada um destes azulejos de forma individual, podemos criar composições com eles.
O quadrado inferior direito da imagem de cima mostra uma imagem de dimensão equivalente à do mip0, ou seja com 1024×1024 pixels, mas que é constituída por uma textura virtual, de qualidade variável, criada por azulejos dos diversos mipmaps.
Esta capacidade, se devidamente aplicada, permite resultados visualmente semelhantes mas com poupanças enormes no uso da RAM. Claro que no exemplo em causa, pelo baixo uso de azulejos com o mip0, a qualidade seria fraca, pelo que seria pouco praticável, mas é apenas um exemplo e uma prova de conceito, apesar que dependendo do nível de detalhe das texturas nas diversas partes podemos ter casos onde apenas nos interesse puxar o detalhe em certas zonas.
Curiosamente esta tecnologia foi passada ao hardware pela AMD, e apareceu nas suas Radeon 79xx, sendo que a Sony e a Microsoft deram a conhecer oficialmente o seu suporte na PS4 e Xbox One.
Ora o PRT é a base de tudo o que veio a seguir, e que se apoia sobre ele, melhorando-o. Quando a Microsoft refere que o SFS traz poupanças no uso da RAM, elas advêm basicamente daqui, do facto que o SFS tem o PRT como base. Eis a apresentação da Microsoft em 2013 sobre os “Tiled Resources”:
E da qual se retira o seguinte fotograma:
Basicamente as texturas comprimidas mostradas na demo ocupam 8 GB (algo que não caberia na RAM do GPU em causa), mas com o Granite SDK que usa os Tiled Resources com o suporte ao PRT, apenas 3 GB são necessários e colocados na RAM do GPU. É uma diminuição no uso da RAM de 2.66 vezes (recordam-se que a Microsoft referia que o SFS usaria até 2.5 x menos RAM… pois cá está).
O que isto nos permite concluir é que quando a Microsoft fala dos ganhos de poupança da RAM pelo uso do SFS, ela está a comparar o uso com um sistema que não use este tipo de tecnologia. Mas com o PRT a ser atualmente standard, essa referência é apenas indicativa pois na realidade nenhum sistema gastará mais memória. E para este ganho, basta este nível de suporte, pois é o uso destes “tiled resources” do PRT que é a responsável por ele, não sendo assim exclusivo do Sampler Feedback Anunciado.
As diferenças entre o PRT, e o PRT+ (Tambem chamado de Sampler Feedback Streaming, ou SFS)
O PRT+, tambem chamado de Sampler Feedback Streaming é a evolução do PRT. Foi apresentado pela Nvidia e basicamente acrescentou ao PRT uma capacidade nova, o Sample Feedback, o que levou a que ganhasse o nome alternativo de Sample Feedback Streaming ou SFS pelo facto de a tecnologia ter maioritariamente uso em jogos streaming.
Esta designação pode ser vista nos documentos oficiais da Microsoft sobre o Sample feedback Streaming, que se encontra aqui, e onde encontramos o seguinte texto:
Use of sampler feedback with streaming is sometimes abbreviated as SFS. It is also sometimes called sparse feedback textures, or SFT, or PRT+, which stands for “partially resident textures”.
O grande problema que se encontrava no PRT era que o mesmo estimava o que precisava em cada zona, mas com grandes probabilidades de falha. Com esta novidade do PRT+ pôde-se melhorar o existente, minimizando artefactos, e desperdícios de memoria. O sampling permite agora ler informação de qual textura se precisa para ser aplicada num pixel
Esta situação, associada à menor dimensão das texturas lidas pela criação de texturas virtuais com elementos dos vários mips é que permite minimizar ao máximo a ocupação do SSD, a segunda situação referida pela Microsoft.
As diferenças face ao SFS da Xbox série X
Mas apesar do mesmo nome, o SFS da XBox não é igual ao da Nvidia, possuindo diferenças proprietárias.
Segundo informação obtida (não confirmada e não oficial), uma das coisas acrescentadas foram caches destinadas ao processo de sampling, nomeadamente para a criação das “Residency Map” e das “Request Map”, de forma a melhorar o armazenamento de dados e permitir recuperações mais rápidas. Basicamente a situação, a confirmar-se não traz capacidades novas, mas é como se para aceder a um local tivessem de consultar um mapa, ou ver o resultado num GPS. Basicamente os resultados do GPS acabam por ser mais precisos e de acesso mais imediato.
Esta situação associada a um conjunto de novos filtros nas operações de Sampling, permitem que o processo seja mais eficaz e preciso do que com o PRT+ e que o processo de passagem entre mips seja mais suave e não direto, causando menos perturbações visuais. Isto é, segundo as mesmas fontes, conseguido pelo uso de uma filtragem bilinear de re-escalamento (e daí termos abordado a filtragem no início) que, apesar de ser o processo mais básico de filtragem existente, permite a criação de uma textura de transição, que suaviza o efeito visual da passagem.
Mário meus pêsames, te desejo força neste momento difícil.
Os meus sentimentos Mário, muita força!
Meus sentimentos, Mario.
Meus sentimentos…
Meus sinceros sentimentos, Mario! Que Deus conforte o seu coração e de seus familiares!
Sobre o SFS, mais do mesmo, inclusive na capacidade da MS fazer uma propaganda enorme em cima de algo meh.. Vai ter alguns quadros de baixíssima qualidade entre quadros de alta qualidade no meio da jogatina. “Incrível”
Meus pêsames , Mario. Excelente artigo , como sempre.
Meus sentimentos para você e a família Mário.
E parabéns pelo excelente artigo!
Será que esses caches para sampling vão ficar no SSD compondo a tal da memória virtual?
Não… Estamos a falar de uma tecnologia do GPU, com elementos no GPU. Os pedidos ao SSD são externos, e estás cachês apenas ajudam na obtenção e previsão de dados melhorando as performances do PRT+.
Mário, meus sentimentos pela tua perda.
Vai aqui, mas é para todos…
O meu muito obrigado!
Os meus sentimentos pela perda Sr Mário! Tudo o resto vale zero.
Não tenho nada a ver com o assunto mas foi devido a este flagelo que vivemos?
Não…
Meus sentimos Mario.
Obrigado pelo artigo.
Belo artigo Mario.
Leio seus artigos faz um bom tempo, porém nunca comentei aqui.
Obrigado por ser um sopro de ar fresco em uma Internet na qual os usuários usam assuntos técnicos interessantes como combustível para Flame War.
Prossiga com o excelente trabalho, abraços.
Obrigado.
Meus sentimentos Mário.
Que Deus conforte o coração de todos vocês nesse momento de tristeza.