A necessidade de recursos de streaming
Os recursos de streaming são necessários para que a memória da GPU não seja desperdiçada armazenando regiões de superfícies que não serão acessadas e para informar ao hardware como filtrar blocos adjacentes.
Recursos de streaming ou texturas esparsas
Os recursos de streaming (chamados de recursos em blocos no Direct3D 11) são grandes recursos lógicos que usam pequenas quantidades de memória física.
Outro nome para recursos de streaming é texturas esparsas. "Esparso" transmite tanto a natureza lado a lado dos recursos quanto talvez a principal razão para colocá-los lado a lado - que nem todos devem ser mapeados de uma só vez. Na verdade, um aplicativo poderia criar um recurso de streaming no qual nenhum dado é criado para todas as regiões+mips do recurso, intencionalmente. Portanto, o conteúdo em si pode ser esparso, e o mapeamento do conteúdo na memória da unidade de processamento gráfico (GPU) em um determinado momento seria um subconjunto disso (ainda mais esparso).
Sem o mosaico, as alocações de memória são gerenciadas na granularidade de sub-recursos
Em um sistema gráfico (ou seja, o sistema operacional, o driver de exibição e o hardware gráfico) sem suporte a recursos de streaming, o sistema gráfico gerencia todas as alocações de memória do Direct3D na granularidade de sub-recursos.
Para um buffer, todo o buffer é o sub-recurso.
Para uma Textura (por exemplo, Texture2D), cada nível de mip é um sub-recurso; para uma matriz de textura (por exemplo, Texture2DArray), cada nível de mip em uma determinada fatia de matriz é um sub-recurso. O sistema gráfico expõe apenas a capacidade de gerenciar o mapeamento de alocações nessa granularidade de sub-recursos. No contexto de recursos de streaming, "mapeamento" refere-se a tornar os dados visíveis para a GPU.
Sem mosaico, não é possível acessar apenas uma pequena parte da cadeia de mipmap
Suponha que um aplicativo saiba que uma operação de renderização específica só precisa acessar uma pequena parte de uma cadeia de mipmap de imagem (talvez nem mesmo a área completa de um determinado mipmap). Idealmente, o aplicativo poderia informar o sistema gráfico sobre essa necessidade. O sistema gráfico só se preocuparia em garantir que a memória necessária fosse mapeada na GPU sem paginar muita memória.
Na realidade, sem suporte a recursos de streaming, o sistema gráfico só pode ser informado sobre a memória que precisa ser mapeada na GPU na granularidade de sub-recursos (por exemplo, um intervalo de níveis completos de mipmap que podem ser acessados). Também não há falha de demanda no sistema gráfico, portanto, potencialmente, muito excesso de memória da GPU deve ser usado para mapear sub-recursos completos antes que um comando de renderização que faça referência a qualquer parte da memória seja executado. Esse é apenas um problema que dificulta o uso de grandes alocações de memória no Direct3D sem suporte a recursos de streaming.
Paginação de software para dividir a superfície em blocos menores
A paginação de software pode ser usada para dividir a superfície em blocos pequenos o suficiente para o hardware manipular.
O Direct3D dá suporte a superfícies Texture2D com até 16384 pixels em um determinado lado. Uma imagem com 16384 de largura por 16384 de altura e 4 bytes por pixel consumiria 1 GB de memória de vídeo (e adicionar mipmaps dobraria essa quantidade). Na prática, todos os 1 GB raramente precisariam ser referenciados em uma única operação de renderização.
Alguns desenvolvedores de jogos modelam superfícies de terreno de até 128K por 128K. A maneira como eles fazem isso funcionar em GPUs existentes é quebrar a superfície em blocos pequenos o suficiente para o hardware suportar. O aplicativo deve descobrir quais blocos podem ser necessários e carregá-los em um cache de texturas na GPU - um sistema de paginação de software.
Uma desvantagem significativa dessa abordagem vem do hardware não saber nada sobre a paginação que está acontecendo: quando uma parte de uma imagem precisa ser mostrada na tela que se estende por blocos, o hardware não sabe como executar a filtragem de função fixa (ou seja, eficiente) entre blocos. Isso significa que o aplicativo que gerencia seu próprio bloco de software deve recorrer à filtragem manual de textura no código do sombreador (que se torna muito caro se um filtro anisotrópico de boa qualidade for desejado) e/ou desperdiçar medianizes de criação de memória em torno de blocos que contêm dados de blocos vizinhos para que a filtragem de hardware de função fixa possa continuar a fornecer alguma assistência.
Tornando a representação lado a lado de alocações de superfície um recurso de primeira classe
Se uma representação lado a lado de alocações de superfície for um recurso de primeira classe no sistema gráfico, o aplicativo poderá informar ao hardware quais blocos disponibilizar. Dessa forma, menos memória de GPU é desperdiçada armazenando regiões de superfícies que o aplicativo sabe que não serão acessadas, e o hardware pode entender como filtrar blocos adjacentes, aliviando parte da dor experimentada pelos desenvolvedores que executam o bloco de software por conta própria.
Mas para fornecer uma solução completa, algo deve ser feito para lidar com o fato de que, independentemente de o ladrilho dentro de uma superfície ser suportado, a dimensão máxima da superfície é atualmente 16384 - nem perto dos 128K+ que os aplicativos já desejam. Exigir apenas que o hardware suporte tamanhos de textura maiores é uma abordagem, no entanto, há custos significativos e/ou compensações para seguir esse caminho.
O caminho do filtro de textura e o caminho de renderização do Direct3D já estão saturados em termos de precisão no suporte a texturas de 16K com os outros requisitos, como suporte a extensões de visor que caem da superfície durante a renderização ou dão suporte ao encapsulamento de textura da borda da superfície durante a filtragem. Uma possibilidade é definir uma compensação de modo que, à medida que o tamanho da textura aumenta além de 16K, a funcionalidade/precisão seja abandonada de alguma maneira. Mesmo com essa concessão, no entanto, custos adicionais de hardware podem ser necessários em termos de capacidade de endereçamento em todo o sistema de hardware para ir para tamanhos de textura maiores.
Problema com texturas grandes: precisão para locais na superfície
Um problema que entra em jogo à medida que as texturas ficam muito grandes é que as coordenadas de textura de ponto flutuante de precisão única (e os interpoladores associados para dar suporte à rasterização) ficam sem precisão para especificar locais na superfície com precisão. Seguiria uma filtragem de textura nervosa. Uma opção cara seria exigir suporte a interpoladores de precisão dupla, embora isso possa ser um exagero, dada uma alternativa razoável.
Permitindo que vários recursos de diferentes dimensões compartilhem memória
Outro cenário que pode ser atendido por recursos de streaming é permitir que vários recursos de diferentes dimensões/formatos compartilhem a mesma memória. Às vezes, os aplicativos têm conjuntos exclusivos de recursos que não são usados ao mesmo tempo, ou recursos que são criados apenas para uso muito breve e depois destruídos, seguidos pela criação de outros recursos. Uma forma de generalidade que pode sair dos "recursos de streaming" é que é possível permitir que o usuário aponte vários recursos diferentes para a mesma memória (sobreposta). Em outras palavras, a criação e destruição de "recursos" (que definem uma dimensão/formato e assim por diante) pode ser dissociada do gerenciamento da memória subjacente aos recursos do ponto de vista do aplicativo.
Tópicos relacionados