Tipos de recurso
Diferentes tipos de recursos têm um layout distinto (ou volume de memória). Todos os recursos usados pelo pipeline do Direct3D derivam de dois tipos básicos de recursos: buffers e texturas. Um buffer é uma coleção de dados brutos (elementos); Uma textura é uma coleção de texels (elementos de textura).
Há duas maneiras de especificar totalmente o layout (ou volume de memória) de um recurso:
Item | Descrição |
---|---|
Digitado |
Especifique totalmente o tipo quando o recurso for criado. |
Sem tipo |
Especifique totalmente o tipo quando o recurso estiver associado ao pipeline. |
Recursos de buffer
Um recurso de buffer é uma coleção de dados totalmente tipados; Internamente, um buffer contém elementos. Um elemento é composto de 1 a 4 componentes. Exemplos de tipos de dados de elemento incluem: um valor de dados compactado (como R8G8B8A8), um único inteiro de 8 bits, quatro valores flutuantes de 32 bits. Esses tipos de dados são usados para armazenar dados, como um vetor de posição, um vetor normal, uma coordenada de textura em um buffer de vértice, um índice em um buffer de índice ou estado do dispositivo.
Um buffer é criado como um recurso não estruturado. Como ele não é estruturado, um buffer não pode conter nenhum nível de mipmap, não é filtrado quando lido e não pode ser multiamostrado.
Tipos de buffer
Buffer de vértice
Um buffer é uma coleção de elementos; Um buffer de vértice contém dados por vértice. O exemplo mais simples é um buffer de vértice que contém um tipo de dados, como dados de posição. Ele pode ser visualizado como a ilustração a seguir.
Mais frequentemente, um buffer de vértice contém todos os dados necessários para especificar totalmente os vértices 3D. Um exemplo disso pode ser um buffer de vértice que contém coordenadas por posição de vértice, normal e textura. Esses dados geralmente são organizados como conjuntos de elementos por vértice, conforme mostrado na ilustração a seguir.
Esse buffer de vértice contém dados por vértice para oito vértices; Cada vértice armazena três elementos (coordenadas de posição, normal e textura). A posição e a normal são normalmente especificadas usando três floats de 32 bits e as coordenadas de textura usando dois floats de 32 bits.
Para acessar dados de um buffer de vértice, você precisa saber qual vértice acessar e estes outros parâmetros de buffer:
- Deslocamento - o número de bytes desde o início do buffer até os dados do primeiro vértice.
- BaseVertexLocation - o número de bytes do deslocamento para o primeiro vértice usado pela chamada de desenho apropriada.
Antes de criar um buffer de vértice, você precisa definir seu layout criando um objeto de layout de entrada. Depois que o objeto de layout de entrada for criado, associe-o ao estágio IA (Assembler de Entrada).
Buffer de índice
Um buffer de índice contém um conjunto sequencial de índices de 16 bits ou 32 bits; Cada índice é usado para identificar um vértice em um buffer de vértice. O uso de um buffer de índice com um ou mais buffers de vértice para fornecer dados ao estágio IA é chamado de indexação. Um buffer de índice pode ser visualizado como a ilustração a seguir.
Os índices sequenciais armazenados em um buffer de índice estão localizados com os seguintes parâmetros:
- Deslocamento - o número de bytes desde o início do buffer até o primeiro índice.
- StartIndexLocation - o número de bytes do deslocamento até o primeiro vértice usado pela chamada de desenho apropriada.
- IndexCount - o número de índices a serem renderizados.
Um buffer de índice pode unir várias faixas de linha ou triângulo (topologias primitivas) separando cada uma com um índice de corte de faixa. Um índice de corte de faixa permite que várias faixas de linha ou triângulo sejam desenhadas com uma única chamada de desenho. Um índice de corte de faixa é o valor máximo possível para o índice (0xffff para um índice de 16 bits 0xffffffff para um índice de 32 bits). O índice de corte de faixa redefine a ordem de enrolamento em primitivas indexadas e pode ser usado para remover a necessidade de triângulos degenerados que, de outra forma, poderiam ser necessários para manter a ordem de enrolamento adequada em uma faixa de triângulo. A ilustração a seguir mostra um exemplo de um índice de corte de faixa.
Buffer constante
O Direct3D tem um buffer para fornecer constantes de sombreador chamado buffer constante de sombreador ou simplesmente um buffer constante. Conceitualmente, ele se parece com um buffer de vértice de elemento único, conforme mostrado na ilustração a seguir.
Cada elemento armazena uma constante de componente de 1 a 4, determinada pelo formato dos dados armazenados.
Os buffers de constantes reduzem a largura de banda necessária para atualizar as constantes de sombreador, permitindo que as constantes de sombreador sejam agrupadas e confirmadas ao mesmo tempo, em vez de fazer chamadas individuais para confirmar cada constante separadamente.
Um sombreador continua a ler variáveis em um buffer constante diretamente pelo nome da variável da mesma maneira que as variáveis que não fazem parte de um buffer constante são lidas.
Cada estágio do sombreador permite até 15 buffers constantes de sombreador; Cada buffer pode conter até 4096 constantes.
Use um buffer constante para armazenar os resultados do estágio de saída de fluxo.
Consulte Constantes de sombreador (DirectX HLSL) para obter um exemplo de declaração de um buffer constante em um sombreador.
Recursos de textura
Um recurso de textura é uma coleção estruturada de dados projetada para armazenar texels. Ao contrário dos buffers, as texturas podem ser filtradas por amostradores de textura à medida que são lidas por unidades de sombreador. O tipo de textura afeta a forma como a textura é filtrada. Um texel representa a menor unidade de uma textura que pode ser lida ou gravada pelo pipeline. Cada texel contém de 1 a 4 componentes, organizados em um dos formatos DXGI (consulte DXGI_FORMAT).
As texturas são criadas como um recurso estruturado para que seu tamanho seja conhecido. No entanto, cada textura pode ser digitada ou sem tipo no momento da criação do recurso, desde que o tipo seja totalmente especificado usando uma exibição quando a textura estiver associada ao pipeline.
Tipos de textura
Existem vários tipos de texturas: 1D, 2D, 3D, cada uma das quais pode ser criada com ou sem mipmaps. O Direct3D também dá suporte a matrizes de textura e texturas com várias amostras.
Textura 1D
Uma textura 1D em sua forma mais simples contém dados de textura que podem ser endereçados com uma única coordenada de textura; Ele pode ser visualizado como uma matriz de texels, conforme mostrado na ilustração a seguir.
Cada texel contém vários componentes de cor, dependendo do formato dos dados armazenados. Adicionando mais complexidade, você pode criar uma textura 1D com níveis de mipmap, conforme mostrado na ilustração a seguir.
Um nível de mipmap é uma textura que é uma potência de dois menor do que o nível acima dele. O nível superior contém mais detalhes, cada nível subsequente é menor; para um mipmap 1D, o menor nível contém um texel. Os diferentes níveis são identificados por um índice chamado LOD (nível de detalhe); você pode usar o LOD para acessar uma textura menor ao renderizar a geometria que não está tão próxima da câmera.
Matriz de textura 1D
O Direct3D 10 também tem uma nova estrutura de dados para uma matriz de texturas. Uma matriz de texturas 1D se parece conceitualmente com a ilustração a seguir.
Essa matriz de textura contém três texturas. Cada uma das três texturas tem uma largura de textura de 5 (que é o número de elementos na primeira camada). Cada textura também contém um mipmap de 3 camadas.
Todas as matrizes de textura no Direct3D são uma matriz homogênea de texturas; Isso significa que cada textura em uma matriz de textura deve ter o mesmo formato e tamanho de dados (incluindo largura de textura e número de níveis de mipmap). Você pode criar matrizes de textura de tamanhos diferentes, desde que todas as texturas em cada matriz correspondam em tamanho.
Textura 2D e Matriz de Textura 2D
Um recurso Texture2D contém uma grade 2D de texels. Cada texel é endereçável por um vetor u, v. Por ser um recurso de textura, ele pode conter níveis de mipmap e sub-recursos. Um recurso de textura 2D totalmente preenchido se parece com a ilustração a seguir.
Esse recurso de textura contém uma única textura 3x5 com três níveis de mipmap.
Um recurso Texture2DArray é uma matriz homogênea de texturas 2D; Ou seja, cada textura tem o mesmo formato de dados e dimensões (incluindo níveis de mipmap). Ele tem um layout semelhante ao array de textura 1D, exceto que as texturas agora contêm dados 2D e, portanto, se parece com a ilustração a seguir.
Essa matriz de textura contém três texturas; Cada textura é 3x5 com dois níveis de mipmap.
Usando um Texture2DArray como um cubo de textura
Um cubo de textura é uma matriz de textura 2D que contém 6 texturas, uma para cada face do cubo. Um cubo de textura totalmente preenchido se parece com a ilustração a seguir.
Uma matriz de textura 2D que contém 6 texturas pode ser lida de dentro de sombreadores com as funções intrínsecas do mapa de cubo, depois que elas são associadas ao pipeline com uma exibição de textura de cubo. Os cubos de textura são endereçados a partir do sombreador com um vetor 3D apontando para fora do centro do cubo de textura.
Textura 3D
Um recurso Texture3D (também conhecido como textura de volume) contém um volume 3D de texels. Como é um recurso de textura, ele pode conter níveis de mipmap. Uma textura 3D totalmente preenchida se parece com a ilustração a seguir.
Quando uma fatia de mipmap de textura 3D é vinculada como uma saída de destino de renderização (com uma exibição de destino de renderização), a textura 3D se comporta de forma idêntica a uma matriz de textura 2D com n fatias. A fatia de renderização específica é escolhida no estágio do sombreador de geometria.
Não existe o conceito de uma matriz de textura 3D; portanto, um sub-recurso de textura 3D é um único nível de mipmap.
Sub-recursos
A API do Direct3D faz referência a recursos inteiros ou subconjuntos de recursos. Para especificar a parte dos recursos, o Direct3D cunhou o termo sub-recursos, que significa um subconjunto de um recurso.
Um buffer é definido como um único sub-recurso. As texturas são um pouco mais complicadas, pois existem vários tipos de textura diferentes (1D, 2D, etc.), alguns dos quais suportam níveis de mipmap e/ou matrizes de textura. Começando com o caso mais simples, uma textura 1D é definida como um único sub-recurso, conforme mostrado na ilustração a seguir.
Isso significa que a matriz de texels que compõem uma textura 1D está contida em um único sub-recurso.
Se você expandir uma textura 1D com três níveis de mipmap, ela poderá ser visualizada assim.
Pense nisso como uma única textura composta de três subtexturas. Cada subtextura é contada como um sub-recurso, portanto, essa textura 1D contém 3 sub-recursos. Uma subtextura (ou sub-recurso) pode ser indexada usando o nível de detalhe (LOD) para uma única textura. Ao usar uma matriz de texturas, acessar uma subtextura específica requer o LOD e a textura específica. Como alternativa, a API combina essas duas informações em um único índice de sub-recursos baseado em zero, conforme mostrado aqui.
Selecionando sub-recursos
Algumas APIs acessam um recurso inteiro, outras acessam uma parte de um recurso. As APIs que acessam uma parte de um recurso geralmente usam uma descrição de exibição para especificar os sub-recursos a serem acessados.
Essas figuras ilustram os termos usados por uma descrição de exibição ao acessar uma matriz de texturas.
Fatia de matriz
Dada uma matriz de texturas, cada textura com mipmaps, uma fatia de matriz (representada pelo retângulo branco) inclui uma textura e todas as suas subtexturas, conforme mostrado na ilustração a seguir.
Fatia Mip
Uma fatia mip (representada pelo retângulo branco) inclui um nível de mipmap para cada textura em uma matriz, conforme mostrado na ilustração a seguir.
Selecionando um único sub-recurso
Você pode usar esses dois tipos de fatias para escolher um único sub-recurso, conforme mostrado na ilustração a seguir.
Selecionando vários sub-recursos
Ou você pode usar esses dois tipos de fatias com o número de níveis de mipmap e/ou número de texturas, para escolher vários sub-recursos.
Independentemente do tipo de textura que você está usando, com ou sem mipmaps, com ou sem uma matriz de textura, geralmente há funções auxiliares fornecidas para calcular o índice de um sub-recurso específico.
Tipagem forte vs. fraca
A criação de um recurso totalmente tipado restringe o recurso ao formato com o qual foi criado. Isso permite que o runtime otimize o acesso, especialmente se o recurso for criado com sinalizadores indicando que ele não pode ser mapeado pelo aplicativo. Os recursos criados com um tipo específico não podem ser reinterpretados usando o mecanismo de exibição.
Em um recurso sem tipo, o tipo de dados é desconhecido quando o recurso é criado pela primeira vez. O aplicativo deve escolher entre os formatos sem tipo disponíveis. Você deve especificar o tamanho da memória a ser alocada e se o runtime precisará gerar as subtexturas em um mipmap.
No entanto, o formato de dados exato (se a memória será interpretada como inteiros, valores de ponto flutuante, inteiros sem sinal etc.) não é determinado até que o recurso seja associado ao pipeline com uma exibição. Como o formato de textura permanece flexível até que a textura seja associada ao pipeline, o recurso é chamado de armazenamento de tipo fraco. O armazenamento fracamente tipado tem a vantagem de poder ser reutilizado ou reinterpretado (em outro formato), desde que o bit componente do novo formato corresponda à contagem de bits do formato antigo.
Um único recurso pode ser associado a vários estágios de pipeline, desde que cada um tenha uma exibição exclusiva, que qualifique totalmente os formatos em cada local. Por exemplo, um recurso criado com um formato sem tipo pode ser usado como um formato FLOAT e um formato UINT em diferentes locais no pipeline simultaneamente.