Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
A compressão em bloco é uma técnica de compressão de textura com perdas para reduzir o tamanho da textura e o uso de memória, melhorando o desempenho. Uma textura compactada por bloco pode ser menor que uma textura com 32 bits por cor.
Compactação de bloco é uma técnica de compactação de textura para reduzir o tamanho da textura. Quando comparado a uma textura com 32 bits por cor, uma textura compactada em bloco pode ser até 75% menor. Os aplicativos geralmente veem um aumento de desempenho ao usar a compactação de blocos devido ao volume de memória menor.
Embora seja com perdas, a compressão de blocos funciona bem e é recomendada para todas as texturas que são processadas e filtradas pelo pipeline. Texturas mapeadas diretamente para a tela (elementos de interface do usuário, como ícones e texto) não são boas opções para compactação porque os artefatos são mais perceptíveis.
Uma textura compactada em bloco deve ser criada como um múltiplo de tamanho 4 em todas as dimensões e não pode ser usada como uma saída do pipeline.
Como funciona a compactação de blocos
A compactação de blocos é uma técnica para reduzir a quantidade de memória necessária para armazenar dados de cores. Armazenando algumas cores em seu tamanho original e outras cores usando um esquema de codificação, você pode reduzir drasticamente a quantidade de memória necessária para armazenar a imagem. Como o hardware decodifica automaticamente os dados compactados, não há nenhuma penalidade de desempenho por usar texturas compactadas.
Para ver como a compactação funciona, examine os dois exemplos a seguir. O primeiro exemplo descreve a quantidade de memória usada ao armazenar dados descompactados; o segundo exemplo descreve a quantidade de memória usada ao armazenar dados compactados.
Armazenando dados descompactados
A ilustração a seguir representa uma textura 4×4 não compactada. Suponha que cada cor contenha um único componente de cor (vermelho, por exemplo) e seja armazenada em um byte de memória.
Os dados não compactados são dispostos na memória sequencialmente e exigem 16 bytes, conforme mostrado na ilustração a seguir.
armazenando dados compactados
Agora que você viu a quantidade de memória que uma imagem descompactada usa, dê uma olhada na quantidade de memória que uma imagem compactada salva. O formato de compactação BC4 armazena 2 cores (1 byte cada) e 16 índices de 3 bits (48 bits ou 6 bytes) que são usados para interpolar as cores originais na textura, conforme mostrado na ilustração a seguir.
O espaço total necessário para armazenar os dados compactados é de 8 bytes, o que é uma economia de memória de 50% em relação ao exemplo não compactado. A economia é ainda maior quando mais de um componente de cor é usado.
A economia de memória substancial fornecida pela compactação de blocos pode levar a um aumento no desempenho. Esse desempenho vem ao custo da qualidade da imagem (devido à interpolação de cores); no entanto, a qualidade inferior geralmente não é perceptível.
A próxima seção mostra como o Direct3D habilita o uso da compactação de blocos em um aplicativo.
Usando compactação de blocos
Crie uma textura compactada em blocos de forma semelhante a uma textura não compactada, mas especificando um formato compactado em blocos.
Em seguida, crie uma exibição para ligar a textura ao pipeline. Como uma textura compactada em bloco pode ser usada apenas como entrada para um estágio de sombreador, você deve criar uma exibição de recurso de sombreador.
Use uma textura compactada em bloco da mesma maneira que você usaria uma textura descompactada. Se seu aplicativo obtiver um ponteiro de memória para dados compactados em bloco, você precisará considerar o preenchimento de memória em um mipmap que faz o tamanho declarado diferir do real.
Tamanho virtual versus tamanho físico
Se você tiver um código de aplicativo que usa um ponteiro de memória para percorrer a memória de uma textura compactada em bloco, há uma consideração importante que pode exigir uma modificação no código do aplicativo. Uma textura compactada em bloco deve ser um múltiplo de 4 em todas as dimensões porque os algoritmos de compactação de bloco operam em blocos texel 4x4. Isso será um problema para um mipmap cuja dimensões iniciais são divisíveis por 4, mas os níveis subdivididos não são. O diagrama a seguir mostra a diferença na área entre o tamanho virtual (declarado) e o tamanho físico (real) de cada nível de mipmap.
O lado esquerdo do diagrama mostra os tamanhos de nível de mipmap gerados para uma textura não compactada de 60×40. O tamanho de nível superior é obtido da chamada à API que gera a textura; cada nível subsequente é metade do tamanho do nível anterior. Para uma textura descompactada, não há diferença entre o tamanho virtual (declarado) e o tamanho físico (real).
O lado direito do diagrama apresenta os tamanhos dos níveis de mipmap gerados para a mesma textura de 60×40 com compactação. Observe que o segundo e o terceiro níveis têm preenchimento de memória para tornar os fatores de tamanhos de 4 em cada nível. Isso é necessário para que os algoritmos possam operar em blocos de 4x4 texels. Isso é especialmente evidente se você considerar níveis de mipmap inferiores a 4×4: o tamanho desses níveis de mipmap com tamanhos muito pequenos será arredondado para o múltiplo mais próximo de 4 quando a memória de textura for alocada.
O hardware de amostragem usa o tamanho virtual; quando a textura é amostrada, o preenchimento de memória é ignorado. Para níveis de mipmap menores que 4×4, somente os quatro primeiros texels serão usados para um mapa de 2×2, e somente o primeiro texel será usado por um bloco de 1×1. No entanto, não há nenhuma estrutura de API que exponha o tamanho físico (incluindo o preenchimento de memória).
Em resumo, tenha cuidado para usar blocos de memória alinhados ao copiar regiões que contêm dados compactados em bloco. Para fazer isso em um aplicativo que obtém um ponteiro de memória, verifique se o ponteiro usa o tom de superfície para considerar o tamanho da memória física.
Algoritmos de compressão
Técnicas de compactação de blocos no Direct3D dividem dados de textura descompactados em 4×4 blocos, compactam cada bloco e armazenam os dados. Por esse motivo, espera-se que as texturas que serão compactadas tenham dimensões de textura múltiplas de 4.
O diagrama anterior mostra uma textura particionada em blocos texel. O primeiro bloco mostra o layout dos 16 texels rotulados como a-p, mas cada bloco tem a mesma organização de dados.
O Direct3D implementa vários esquemas de compactação, cada um implementa uma compensação diferente entre o número de componentes armazenados, o número de bits por componente e a quantidade de memória consumida. Use esta tabela para ajudar a escolher o formato que funciona melhor com o tipo de dados e a resolução de dados que melhor se ajusta ao seu aplicativo.
| Dados de origem | Resolução de compactação de dados (em bits) | Escolha esse formato de compactação |
|---|---|---|
| Cor de três componentes e alfa | Cor (5:6:5), Alfa (1) ou nenhum alfa | BC1 |
| Cor de três componentes e alfa | Cor (5:6:5), Alfa (4) | BC2 |
| Cor de três componentes e alfa | Cor (5:6:5), Alfa (8) | BC3 |
| Cor monocomponente | Um componente (8) | BC4 |
| Cor de dois componentes | Dois componentes (8:8) | BC5 |
BC1
Use o primeiro formato de compactação de bloco (BC1) (DXGI_FORMAT_BC1_TYPELESS, DXGI_FORMAT_BC1_UNORM ou DXGI_BC1_UNORM_SRGB) para armazenar dados de cor de três componentes usando uma cor 5:6:5 (5 bits vermelho, 6 bits verde, 5 bits azul). Isso é verdadeiro mesmo se os dados também contiverem alfa de 1 bit. Supondo uma textura 4×4 usando o maior formato de dados possível, o formato BC1 reduz a memória necessária de 48 bytes (16 cores × 3 componentes/cor × 1 byte/componente) para 8 bytes de memória.
O algoritmo funciona em 4×4 blocos de texels. Em vez de armazenar 16 cores, o algoritmo salva duas cores de referência (color_0 e color_1) e índices de cores de 16 2 bits (blocos a-p), conforme mostrado no diagrama a seguir.
Os índices de cor (a-p) são usados para pesquisar as cores originais de uma tabela de cores. A tabela de cores contém quatro cores. As duas primeiras cores, color_0 e color_1, são as cores mínima e máxima. As outras duas cores, color_2 e color_3, são cores intermediárias calculadas com interpolação linear.
color_2 = 2/3*color_0 + 1/3*color_1
color_3 = 1/3*color_0 + 2/3*color_1
As quatro cores recebem valores de índice de 2 bits que serão salvos nos blocos a-p.
color_0 = 00
color_1 = 01
color_2 = 10
color_3 = 11
Por fim, cada uma das cores nos blocos a-p é comparada com as quatro cores na tabela de cores e o índice da cor mais próxima é armazenado nos blocos de 2 bits.
Esse algoritmo se presta a dados que contêm alfa de 1 bit também. A única diferença é que color_3 é definido como 0 (que representa uma cor transparente) e color_2 é uma mistura linear de color_0 e color_1.
color_2 = 1/2*color_0 + 1/2*color_1;
color_3 = 0;
BC2
Use o formato BC2 (DXGI_FORMAT_BC2_TYPELESS, DXGI_FORMAT_BC2_UNORM ou DXGI_BC2_UNORM_SRGB) para armazenar dados que contêm dados alfa e de cor com baixa coerência (use BC3 para dados alfa altamente coerentes). O formato BC2 armazena dados RGB como uma cor 5:6:5 (5 bits vermelho, 6 bits verde, 5 bits azul) e alfa como um valor separado de 4 bits. Supondo uma textura 4×4 usando o maior formato de dados possível, essa técnica de compactação reduz a memória necessária de 64 bytes (16 cores × 4 componentes/cor × 1 byte/componente) para 16 bytes de memória.
O formato BC2 armazena cores com o mesmo número de bits e layout de dados que o formato BC1
BC3
Use o formato BC3 (DXGI_FORMAT_BC3_TYPELESS, DXGI_FORMAT_BC3_UNORM ou DXGI_BC3_UNORM_SRGB) para armazenar dados de cores altamente coerentes (use BC2 com dados alfa menos coerentes). O formato BC3 armazena dados de cores usando a cor 5:6:5 (5 bits vermelho, 6 bits verde, 5 bits azul) e dados alfa usando um byte. Supondo uma textura 4×4 usando o maior formato de dados possível, essa técnica de compactação reduz a memória necessária de 64 bytes (16 cores × 4 componentes/cor × 1 byte/componente) para 16 bytes de memória.
O formato BC3 armazena cores com o mesmo número de bits e layout de dados que o formato BC1; no entanto, BC3 requer 64 bits adicionais de memória para armazenar os dados alfa. O formato BC3 manipula alfa armazenando dois valores de referência e interpolando entre eles (da mesma forma que BC1 armazena cor RGB).
O algoritmo funciona em 4×4 blocos de texels. Em vez de armazenar 16 valores alfa, o algoritmo armazena 2 alfas de referência (alpha_0 e alpha_1) e índices de cores de 16 3 bits (alfa a p), conforme mostrado no diagrama a seguir.
O formato BC3 usa os índices alfa (a-p) para pesquisar as cores originais de uma tabela de pesquisa que contém 8 valores. Os dois primeiros valores — alpha_0 e alpha_1 — são os valores mínimo e máximo; os outros seis valores intermediários são calculados usando interpolação linear.
O algoritmo determina o número de valores alfa interpolados examinando os dois valores alfa de referência. Se alpha_0 for maior que alpha_1, BC3 interpolará 6 valores alfa; caso contrário, interpolará 4. Quando BC3 interpola apenas 4 valores alfa, ele define dois valores alfa adicionais (0 para totalmente transparente e 255 para totalmente opaco). BC3 compacta os valores alfa na área texel 4×4 armazenando o código de bit correspondente aos valores alfa interpolados que correspondem mais de perto ao alfa original para um determinado texel.
if( alpha_0 > alpha_1 )
{
// 6 interpolated alpha values.
alpha_2 = 6/7*alpha_0 + 1/7*alpha_1; // bit code 010
alpha_3 = 5/7*alpha_0 + 2/7*alpha_1; // bit code 011
alpha_4 = 4/7*alpha_0 + 3/7*alpha_1; // bit code 100
alpha_5 = 3/7*alpha_0 + 4/7*alpha_1; // bit code 101
alpha_6 = 2/7*alpha_0 + 5/7*alpha_1; // bit code 110
alpha_7 = 1/7*alpha_0 + 6/7*alpha_1; // bit code 111
}
else
{
// 4 interpolated alpha values.
alpha_2 = 4/5*alpha_0 + 1/5*alpha_1; // bit code 010
alpha_3 = 3/5*alpha_0 + 2/5*alpha_1; // bit code 011
alpha_4 = 2/5*alpha_0 + 3/5*alpha_1; // bit code 100
alpha_5 = 1/5*alpha_0 + 4/5*alpha_1; // bit code 101
alpha_6 = 0; // bit code 110
alpha_7 = 255; // bit code 111
}
BC4
Use o formato BC4 para armazenar dados de cor de um componente usando 8 bits para cada cor. Como resultado do aumento da precisão (em comparação com bc1), BC4 é ideal para armazenar dados de ponto flutuante no intervalo de [0 a 1] usando o formato DXGI_FORMAT_BC4_UNORM e [-1 a +1] usando o formato DXGI_FORMAT_BC4_SNORM. Supondo uma textura 4×4 usando o maior formato de dados possível, essa técnica de compactação reduz a memória necessária de 16 bytes (16 cores × 1 componente/cor × 1 byte/componente) para 8 bytes.
O algoritmo funciona em 4×4 blocos de texels. Em vez de armazenar 16 cores, o algoritmo armazena 2 cores de referência (red_0 e red_1) e 16 índices de cores de 3 bits (vermelho de a até p), conforme mostrado no diagrama a seguir.
O algoritmo usa os índices de 3 bits para pesquisar cores de uma tabela de cores que contém 8 cores. As duas primeiras cores, red_0 e red_1, são as cores mínima e máxima. O algoritmo calcula as cores restantes usando interpolação linear.
O algoritmo determina o número de valores de cores interpolados examinando os dois valores de referência. Se red_0 for maior que red_1, BC4 interpolará 6 valores de cor; caso contrário, interpolará 4. Quando BC4 interpola apenas 4 valores de cor, ele define dois valores de cor adicionais (0,0f para totalmente transparente e 1,0f para totalmente opaco). BC4 compacta os valores alfa na área texel 4×4 armazenando o código de bit correspondente aos valores alfa interpolados que mais correspondem ao alfa original para um determinado texel.
BC4_UNORM
A interpolação dos dados de componente único é feita como no exemplo de código a seguir.
unsigned word red_0, red_1;
if( red_0 > red_1 )
{
// 6 interpolated color values
red_2 = (6*red_0 + 1*red_1)/7.0f; // bit code 010
red_3 = (5*red_0 + 2*red_1)/7.0f; // bit code 011
red_4 = (4*red_0 + 3*red_1)/7.0f; // bit code 100
red_5 = (3*red_0 + 4*red_1)/7.0f; // bit code 101
red_6 = (2*red_0 + 5*red_1)/7.0f; // bit code 110
red_7 = (1*red_0 + 6*red_1)/7.0f; // bit code 111
}
else
{
// 4 interpolated color values
red_2 = (4*red_0 + 1*red_1)/5.0f; // bit code 010
red_3 = (3*red_0 + 2*red_1)/5.0f; // bit code 011
red_4 = (2*red_0 + 3*red_1)/5.0f; // bit code 100
red_5 = (1*red_0 + 4*red_1)/5.0f; // bit code 101
red_6 = 0.0f; // bit code 110
red_7 = 1.0f; // bit code 111
}
As cores de referência são atribuídas a índices de 3 bits (000 a 111, já que há 8 valores), que serão salvos em blocos de 'vermelho a' até 'vermelho p' durante a compactação.
BC4_SNORM
O DXGI_FORMAT_BC4_SNORM é exatamente o mesmo, exceto que os dados são codificados no intervalo SNORM e quando quatro valores de cor são interpolados. A interpolação dos dados de componente único é feita como no exemplo de código a seguir.
signed word red_0, red_1;
if( red_0 > red_1 )
{
// 6 interpolated color values
red_2 = (6*red_0 + 1*red_1)/7.0f; // bit code 010
red_3 = (5*red_0 + 2*red_1)/7.0f; // bit code 011
red_4 = (4*red_0 + 3*red_1)/7.0f; // bit code 100
red_5 = (3*red_0 + 4*red_1)/7.0f; // bit code 101
red_6 = (2*red_0 + 5*red_1)/7.0f; // bit code 110
red_7 = (1*red_0 + 6*red_1)/7.0f; // bit code 111
}
else
{
// 4 interpolated color values
red_2 = (4*red_0 + 1*red_1)/5.0f; // bit code 010
red_3 = (3*red_0 + 2*red_1)/5.0f; // bit code 011
red_4 = (2*red_0 + 3*red_1)/5.0f; // bit code 100
red_5 = (1*red_0 + 4*red_1)/5.0f; // bit code 101
red_6 = -1.0f; // bit code 110
red_7 = 1.0f; // bit code 111
}
As cores de referência são atribuídas a índices de 3 bits (000 a 111, já que há 8 valores), que serão salvos em blocos de 'vermelho a' até 'vermelho p' durante a compactação.
BC5
Use o formato BC5 para armazenar dados de cor de dois componentes usando 8 bits para cada cor. Como resultado do aumento da precisão (em comparação com bc1), BC5 é ideal para armazenar dados de ponto flutuante no intervalo de [0 a 1] usando o formato DXGI_FORMAT_BC5_UNORM e [-1 a +1] usando o formato DXGI_FORMAT_BC5_SNORM. Supondo uma textura 4×4 usando o maior formato de dados possível, essa técnica de compactação reduz a memória necessária de 32 bytes (16 cores × 2 componentes/cor × 1 byte/componente) para 16 bytes.
O algoritmo funciona em 4×4 blocos de texels. Em vez de armazenar 16 cores para ambos os componentes, o algoritmo armazena 2 cores de referência para cada componente (red_0, red_1, green_0 e green_1) e 16 índices de cores de 3 bits para cada componente (red a até red p e green a até green p), conforme mostrado no diagrama a seguir.
O algoritmo usa os índices de 3 bits para pesquisar cores de uma tabela de cores que contém 8 cores. As duas primeiras cores — red_0 e red_1 (ou green_0 e green_1)— são as cores mínima e máxima. O algoritmo calcula as cores restantes usando interpolação linear.
O algoritmo determina o número de valores de cores interpolados examinando os dois valores de referência. Se red_0 for maior que red_1, BC5 interpolará 6 valores de cor; caso contrário, interpolará 4. Quando BC5 interpola apenas 4 valores de cor, ele define os dois valores de cor restantes em 0,0f e 1,0f.
BC5_UNORM
A interpolação dos dados de componente único é feita como no exemplo de código a seguir. Os cálculos para os componentes verdes são semelhantes.
unsigned word red_0, red_1;
if( red_0 > red_1 )
{
// 6 interpolated color values
red_2 = (6*red_0 + 1*red_1)/7.0f; // bit code 010
red_3 = (5*red_0 + 2*red_1)/7.0f; // bit code 011
red_4 = (4*red_0 + 3*red_1)/7.0f; // bit code 100
red_5 = (3*red_0 + 4*red_1)/7.0f; // bit code 101
red_6 = (2*red_0 + 5*red_1)/7.0f; // bit code 110
red_7 = (1*red_0 + 6*red_1)/7.0f; // bit code 111
}
else
{
// 4 interpolated color values
red_2 = (4*red_0 + 1*red_1)/5.0f; // bit code 010
red_3 = (3*red_0 + 2*red_1)/5.0f; // bit code 011
red_4 = (2*red_0 + 3*red_1)/5.0f; // bit code 100
red_5 = (1*red_0 + 4*red_1)/5.0f; // bit code 101
red_6 = 0.0f; // bit code 110
red_7 = 1.0f; // bit code 111
}
As cores de referência são atribuídas a índices de 3 bits (000 a 111, já que há 8 valores), que serão salvos em blocos de 'vermelho a' até 'vermelho p' durante a compactação.
BC5_SNORM
O DXGI_FORMAT_BC5_SNORM é exatamente o mesmo, exceto que os dados são codificados no intervalo SNORM e quando quatro valores de dados são interpolados, os dois valores adicionais são -1,0f e 1,0f. A interpolação dos dados de componente único é feita como no exemplo de código a seguir. Os cálculos para os componentes verdes são semelhantes.
signed word red_0, red_1;
if( red_0 > red_1 )
{
// 6 interpolated color values
red_2 = (6*red_0 + 1*red_1)/7.0f; // bit code 010
red_3 = (5*red_0 + 2*red_1)/7.0f; // bit code 011
red_4 = (4*red_0 + 3*red_1)/7.0f; // bit code 100
red_5 = (3*red_0 + 4*red_1)/7.0f; // bit code 101
red_6 = (2*red_0 + 5*red_1)/7.0f; // bit code 110
red_7 = (1*red_0 + 6*red_1)/7.0f; // bit code 111
}
else
{
// 4 interpolated color values
red_2 = (4*red_0 + 1*red_1)/5.0f; // bit code 010
red_3 = (3*red_0 + 2*red_1)/5.0f; // bit code 011
red_4 = (2*red_0 + 3*red_1)/5.0f; // bit code 100
red_5 = (1*red_0 + 4*red_1)/5.0f; // bit code 101
red_6 = -1.0f; // bit code 110
red_7 = 1.0f; // bit code 111
}
As cores de referência são atribuídas a índices de 3 bits (000 a 111, já que há 8 valores), que serão salvos em blocos de 'vermelho a' até 'vermelho p' durante a compactação.
Conversão de formato
O Direct3D permite cópias entre texturas pré-estruturadas e texturas compactadas em bloco das mesmas larguras de bit.
Você pode copiar recursos entre alguns tipos de formato. Esse tipo de operação de cópia executa um tipo de conversão de formato que reinterpreta dados de recurso como um tipo de formato diferente. Considere este exemplo que mostra a diferença entre reinterpretar dados com a maneira como um tipo mais típico de conversão se comporta:
FLOAT32 f = 1.0f;
UINT32 u;
Para reinterpretar 'f' como o tipo de 'u', use memcpy:
memcpy( &u, &f, sizeof( f ) ); // 'u' becomes equal to 0x3F800000.
Na reinterpretação anterior, o valor subjacente dos dados não é alterado; memcpy reinterpreta o float como um inteiro sem sinal.
Para executar o tipo mais típico de conversão, use a atribuição:
u = f; // 'u' becomes 1.
Na conversão anterior, o valor subjacente dos dados é alterado.
A tabela a seguir lista os formatos de origem e destino permitidos que você pode usar neste tipo de conversão de formato de reinterpretação. Você deve codificar os valores corretamente para que a reinterpretação funcione conforme o esperado.
| Largura do bit | Recurso descompactado | Recurso Block-Compressed |
|---|---|---|
| 32 | DXGI_FORMAT_R32_UINT DXGI_FORMAT_R32_SINT |
DXGI_FORMAT_R9G9B9E5_SHAREDEXP |
| 64 | DXGI_FORMAT_R16G16B16A16_UINT DXGI_FORMAT_R16G16B16A16_SINT DXGI_FORMAT_R32G32_UINT DXGI_FORMAT_R32G32_SINT |
DXGI_FORMAT_BC1_UNORM[_SRGB] DXGI_FORMAT_BC4_UNORM DXGI_FORMAT_BC4_SNORM |
| 128 | DXGI_FORMAT_R32G32B32A32_UINT DXGI_FORMAT_R32G32B32A32_SINT |
DXGI_FORMAT_BC2_UNORM[_SRGB] DXGI_FORMAT_BC3_UNORM[_SRGB] DXGI_FORMAT_BC5_UNORM DXGI_FORMAT_BC5_SNORM |