Dela via


Blockkomprimering

Blockkomprimering är en förlustfri teknik för texturkomprimering som används för att minska texturstorlek och minnesanvändning, vilket ger en prestandaökning. En blockkomprimerad textur kan vara mindre än en struktur med 32 bitar per färg.

Blockkomprimering är en strukturkomprimeringsteknik för att minska texturstorleken. Jämfört med en textur med 32 bitar per färg kan en blockkomprimerad textur vara upp till 75 procent mindre. Program ser vanligtvis en prestandaökning när du använder blockkomprimering på grund av det mindre minnesavtrycket.

Även om den är förlustfull fungerar blockkomprimering bra och rekommenderas för alla texturer som transformeras och filtreras av bildbehandlingskedjan. Strukturer som är direkt mappade till skärmen (gränssnittselement som ikoner och text) är inte bra val för komprimering eftersom artefakter är mer märkbara.

En blockkomprimerad struktur måste skapas som en multipel av storlek 4 i alla dimensioner och kan inte användas som utdata från pipelinen.

Så här fungerar blockkomprimering

Blockkomprimering är en teknik för att minska mängden minne som krävs för att lagra färgdata. Genom att lagra vissa färger i sin ursprungliga storlek och andra färger med hjälp av ett kodningsschema kan du avsevärt minska mängden minne som krävs för att lagra bilden. Eftersom maskinvaran automatiskt avkodar komprimerade data, finns det ingen prestandastraff för att använda komprimerade texturer.

Om du vill se hur komprimering fungerar kan du titta på följande två exempel. I det första exemplet beskrivs mängden minne som används vid lagring av okomprimerade data. I det andra exemplet beskrivs mängden minne som används vid lagring av komprimerade data.

Lagra okomprimerade data

Följande bild representerar en icke-komprimerad 4×4-textur. Anta att varje färg innehåller en enskild färgkomponent (till exempel röd) och lagras i en byte minne.

en okomprimerad 4x4-struktur

Okomprimerade data anges i minnet sekventiellt och kräver 16 byte, enligt följande bild.

okomprimerade data i sekventiellt minne

Lagra komprimerade data

Nu när du har sett hur mycket minne en okomprimerad bild använder kan du ta en titt på hur mycket minne en komprimerad bild sparar. I BC4--komprimeringsformatet lagras 2 färger (1 byte vardera) och 16 3-bitarsindex (48 bitar eller 6 byte) som används för att interpolera de ursprungliga färgerna i strukturen, som du ser i följande bild.

bc4-komprimeringsformatet

Det totala utrymmet som krävs för att lagra komprimerade data är 8 byte, vilket är en minnesbesparing på 50 procent jämfört med det okomprimerade exemplet. Besparingarna är ännu större när mer än en färgkomponent används.

De stora minnesbesparingar som blockkomprimering ger kan leda till ökad prestanda. Den här prestandan sker på bekostnad av bildkvaliteten (på grund av färginterpolation); den lägre kvaliteten är dock ofta inte märkbar.

I nästa avsnitt visas hur Direct3D aktiverar blockkomprimering i ett program.

Använda blockkomprimering

Skapa en blockkomprimerad struktur precis som en icke-komprimerad textur förutom att du anger ett blockkomprimerat format.

Skapa sedan en vy för att binda strukturen till pipelinen Eftersom en blockkomprimerad textur endast kan användas som indata till en skuggningsfas vill du skapa en skuggningsresursvy.

Använd en blockkomprimerad textur på samma sätt som du använder en icke-komprimerad textur. Om programmet får en minnespekare för blockkomprimerade data måste du ta hänsyn till minnesutfyllnaden i en mipmap som gör att den deklarerade storleken skiljer sig från den faktiska storleken.

Virtuell storlek jämfört med fysisk storlek

Om du har programkod som använder en minnespekare för att gå över minnet på en blockkomprimerad struktur, finns det ett viktigt övervägande som kan kräva en ändring i programkoden. En blockkomprimerad struktur måste vara en multipel av 4 i alla dimensioner eftersom blockkomprimeringsalgoritmerna fungerar på 4x4 texelblock. Det här är ett problem för en mipmap vars initiala dimensioner är delbara med 4, men inte indelade nivåer. Följande diagram visar skillnaden i område mellan den virtuella (deklarerade) storleken och den fysiska (faktiska) storleken för varje mipmap-nivå.

okomprimerade och komprimerade mipmap-nivåer

Till vänster i diagrammet visas storlekarna på mipmap-nivån som genereras för en okomprimerad 60×40-struktur. Den översta nivåns storlek hämtas från API-anropet som genererar strukturen. varje efterföljande nivå är hälften så stor som föregående nivå. För en icke-komprimerad struktur finns det ingen skillnad mellan den virtuella (deklarerade) storleken och den fysiska (faktiska) storleken.

Till höger i diagrammet visas storlekarna på mipmap-nivån som genereras för samma 60×40-struktur med komprimering. Observera att både den andra och tredje nivån har minnesutfyllnad för att göra storleksfaktorerna 4 på varje nivå. Detta är nödvändigt så att algoritmerna kan fungera på 4×4 texelblock. Detta är särskilt tydligt om du tänker på mipmap-nivåer som är mindre än 4×4; Storleken på dessa mycket små mipmap-nivåer avrundas upp till närmaste faktor 4 när textureminnet allokeras.

Samplingsmaskinvaran använder den virtuella storleken. När texturen samplas ignoreras minnesutfyllnaden. För mipmap-nivåer som är mindre än 4×4 används endast de första fyra texellerna för en 2×2-karta, och endast den första texeln används av ett 1×1-block. Det finns dock ingen API-struktur som exponerar den fysiska storleken (inklusive minnesutfyllnad).

Sammanfattningsvis bör du vara noga med att använda justerade minnesblock när du kopierar regioner som innehåller blockkomprimerade data. Om du vill göra detta i ett program som hämtar en minnespekare kontrollerar du att pekaren använder ythöjden för att ta hänsyn till den fysiska minnesstorleken.

Komprimeringsalgoritmer

Blockkomprimeringstekniker i Direct3D delar upp okomprimerade texturdata i 4×4 block, komprimerar varje block och lagrar sedan de komprimerade data. För denna anledning förväntas texturer som ska komprimeras ha dimensioner som är multiplar av 4.

blockkomprimering

Föregående diagram visar en struktur som är partitionerad i texelblock. Det första blocket visar layouten för de 16 texels som är märkta a-p, men varje block har samma organisation av data.

Direct3D implementerar flera komprimeringsscheman, var och en implementerar en annan kompromiss mellan antalet lagrade komponenter, antalet bitar per komponent och mängden förbrukat minne. Använd den här tabellen för att välja det format som fungerar bäst med den typ av data och den datamatchning som passar bäst för ditt program.

Källdata Datakomprimeringsupplösning (i bitar) Välj det här komprimeringsformatet
Färg och alfa med tre komponenter Färg (5:6:5), Alfa (1) eller ingen alfa BC1
Färg och alfa med tre komponenter Färg (5:6:5), Alfa (4) BC2
Färg och alfa med tre komponenter Färg (5:6:5), Alfa (8) BC3
Färg för en komponent En komponent (8) BC4
Färg med två komponenter Två komponenter (8:8) BC5

BC1

Använd det första blockkomprimeringsformatet (BC1) (antingen DXGI_FORMAT_BC1_TYPELESS, DXGI_FORMAT_BC1_UNORM eller DXGI_BC1_UNORM_SRGB) för att lagra färgdata med tre komponenter med en färg på 5:6:5 (5 bitar rött, 6 bitar grönt, 5 bitar blått). Detta gäller även om data också innehåller 1-bitars alfa. Om vi antar en struktur på 4×4 med största möjliga dataformat minskar BC1-formatet det minne som krävs från 48 byte (16 färger × 3 komponenter/färg × 1 byte/komponent) till 8 byte minne.

Algoritmen arbetar med 4×4 block av texlar. I stället för att lagra 16 färger sparar algoritmen 2 referensfärger (color_0 och color_1) och 16 2-bitars färgindex (blockerar a–p), enligt följande diagram.

layouten för bc1-komprimering

Färgindexen (a–p) används för att leta upp de ursprungliga färgerna från en färgtabell. Färgtabellen innehåller 4 färger. De två första färgerna – color_0 och color_1 – är de lägsta och högsta färgerna. De andra två färgerna, color_2 och color_3, är mellanliggande färger som beräknas med linjär interpolation.

color_2 = 2/3*color_0 + 1/3*color_1
color_3 = 1/3*color_0 + 2/3*color_1

De fyra färgerna tilldelas 2-bitars indexvärden som sparas i block a–p.

color_0 = 00
color_1 = 01
color_2 = 10
color_3 = 11

Slutligen jämförs var och en av färgerna i block a–p med de fyra färgerna i färgtabellen, och indexet för den närmaste färgen lagras i 2-bitarsblocken.

Den här algoritmen lämpar sig även för data som innehåller 1-bitars alfa. Den enda skillnaden är att color_3 är inställd på 0 (som representerar en transparent färg) och color_2 är en linjär blandning av color_0 och color_1.

color_2 = 1/2*color_0 + 1/2*color_1;
color_3 = 0;

BC2

Använd BC2-formatet (antingen DXGI_FORMAT_BC2_TYPELESS, DXGI_FORMAT_BC2_UNORM eller DXGI_BC2_UNORM_SRGB) för att lagra data som innehåller färg- och alfadata med låg samtidighet (använd BC3- för mycket sammanhängande alfadata). BC2-formatet lagrar RGB-data som en 5:6:5-färg (5 bitar rött, 6 bitar grönt, 5 bitar blått) och alfa som ett separat 4-bitarsvärde. Om vi antar en 4×4-struktur med största möjliga dataformat minskar den här komprimeringstekniken det minne som krävs från 64 byte (16 färger × 4 komponenter/färg × 1 byte/komponent) till 16 byte minne.

BC2-formatet lagrar färger med samma antal bitar och datalayout som BC1- format. BC2 kräver dock ytterligare 64 bitar minne för att lagra alfadata, enligt följande diagram.

layouten för bc2-komprimering

BC3

Använd BC3-formatet (antingen DXGI_FORMAT_BC3_TYPELESS, DXGI_FORMAT_BC3_UNORM eller DXGI_BC3_UNORM_SRGB) för att lagra mycket sammanhängande färgdata (använd BC2- med mindre sammanhängande alfadata). BC3-formatet lagrar färgdata med 5:6:5-färg (5 bitar rött, 6 bitar grönt, 5 bitar blått) och alfadata med en byte. Om vi antar en 4×4-struktur med största möjliga dataformat minskar den här komprimeringstekniken det minne som krävs från 64 byte (16 färger × 4 komponenter/färg × 1 byte/komponent) till 16 byte minne.

BC3-formatet lagrar färger med samma antal bitar och datalayout som BC1- format. BC3 kräver dock ytterligare 64 bitar minne för att lagra alfadata. BC3-formatet hanterar alfa genom att lagra två referensvärden och interpolera mellan dem (på samma sätt som BC1 lagrar RGB-färg).

Algoritmen arbetar med 4×4 block av texlar. I stället för att lagra 16 alfavärden lagrar algoritmen 2 referens alfa (alpha_0 och alpha_1) och 16 3-bitars färgindex (alfa a till p), enligt följande diagram.

layouten för bc3-komprimering

BC3-formatet använder alfaindexen (a–p) för att leta upp de ursprungliga färgerna från en uppslagstabell som innehåller 8 värden. De två första värdena– alpha_0 och alpha_1 – är minimi- och maxvärdena. de övriga sex mellanliggande värdena beräknas med linjär interpolation.

Algoritmen avgör antalet interpolerade alfavärden genom att undersöka de två referens alfavärdena. Om alpha_0 är större än alpha_1 interpolerar BC3 6 alfavärden. annars interpolerar den 4. När BC3 endast interpolerar 4 alfavärden anges ytterligare två alfavärden (0 för helt transparent och 255 för helt ogenomskinlig). BC3 komprimerar alfavärdena i 4×4-texelområdet genom att lagra bitkoden som motsvarar de interpolerade alfavärdena som bäst matchar den ursprungliga alfan för en viss 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

Använd BC4-formatet för att lagra färgdata med en komponent med 8 bitar för varje färg. Som ett resultat av den ökade noggrannheten (jämfört med BC1) är BC4 idealisk för att lagra flyttalsdata i intervallet [0 till 1] med hjälp av DXGI_FORMAT_BC4_UNORM-formatet och [-1 till +1] med hjälp av DXGI_FORMAT_BC4_SNORM format. Om vi antar en 4×4-struktur med största möjliga dataformat minskar den här komprimeringstekniken det minne som krävs från 16 byte (16 färger × 1 komponenter/färg × 1 byte/komponent) till 8 byte.

Algoritmen arbetar med 4×4 block av texlar. I stället för att lagra 16 färger lagrar algoritmen 2 referensfärger (red_0 och red_1) och 16 3-bitars färgindex (röd a till rött p), enligt följande diagram.

layouten för bc4-komprimering

Algoritmen använder 3-bitarsindex för att söka efter färger från en färgtabell som innehåller 8 färger. De två första färgerna– red_0 och red_1 – är de lägsta och högsta färgerna. Algoritmen beräknar återstående färger med linjär interpolation.

Algoritmen avgör antalet interpolerade färgvärden genom att undersöka de två referensvärdena. Om red_0 är större än red_1 interpolerar BC4 6 färgvärden. annars interpolerar den 4. När BC4 endast interpolerar 4 färgvärden, anger den ytterligare två färgvärden (0,0f för helt transparent och 1,0f för helt ogenomskinlig). BC4 komprimerar alfavärdena i 4×4-texelområdet genom att lagra bitkoden som motsvarar de interpolerade alfavärden som bäst matchar den ursprungliga alfan för en viss texel.

BC4_UNORM

Interpoleringen av data med en komponent görs som i följande kodexempel.

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
}

Referensfärgerna tilldelas 3-bitarsindex (000–111 eftersom det finns 8 värden), som sparas i block röd a till rött p under komprimering.

BC4_SNORM

DXGI_FORMAT_BC4_SNORM är exakt samma, förutom att data kodas i SNORM-intervallet och när 4 färgvärden interpoleras. Interpoleringen av data med en komponent görs som i följande kodexempel.

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
}

Referensfärgerna tilldelas 3-bitarsindex (000–111 eftersom det finns 8 värden), som sparas i block röd a till rött p under komprimering.

BC5

Använd BC5-formatet för att lagra färgdata med två komponenter med 8 bitar för varje färg. Som ett resultat av den ökade noggrannheten (jämfört med BC1) är BC5 perfekt för att lagra flyttalsdata i intervallet [0 till 1] med hjälp av DXGI_FORMAT_BC5_UNORM-formatet och [-1 till +1] med hjälp av DXGI_FORMAT_BC5_SNORM format. Om vi antar en 4×4-struktur med största möjliga dataformat minskar den här komprimeringstekniken det minne som krävs från 32 byte (16 färger × 2 komponenter/färg × 1 byte/komponent) till 16 byte.

Algoritmen arbetar med 4×4 block av texlar. I stället för att lagra 16 färger för båda komponenterna lagrar algoritmen 2 referensfärger för varje komponent (red_0, red_1, green_0 och green_1) och 16 3-bitars färgindex för varje komponent (röd till röd p och grön a till grön p), enligt följande diagram.

layouten för bc5-komprimering

Algoritmen använder 3-bitarsindex för att söka efter färger från en färgtabell som innehåller 8 färger. De två första färgerna – red_0 och red_1 (eller green_0 och green_1)– är de lägsta och högsta färgerna. Algoritmen beräknar återstående färger med linjär interpolation.

Algoritmen avgör antalet interpolerade färgvärden genom att undersöka de två referensvärdena. Om red_0 är större än red_1 interpolerar BC5 6 färgvärden. annars interpolerar den 4. När BC5 endast interpolerar 4 färgvärden anges de återstående två färgvärdena till 0,0f och 1,0f.

BC5_UNORM

Interpoleringen av data med en komponent görs som i följande kodexempel. Beräkningarna för de gröna komponenterna är liknande.

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
}

Referensfärgerna tilldelas 3-bitarsindex (000–111 eftersom det finns 8 värden), som sparas i block röd a till rött p under komprimering.

BC5_SNORM

DXGI_FORMAT_BC5_SNORM är exakt samma, förutom att data kodas i SNORM-intervallet och när 4 datavärden interpoleras är de två ytterligare värdena -1,0f och 1,0f. Interpoleringen av data med en komponent görs som i följande kodexempel. Beräkningarna för de gröna komponenterna är liknande.

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
}

Referensfärgerna tilldelas 3-bitarsindex (000–111 eftersom det finns 8 värden), som sparas i block röd a till rött p under komprimering.

Formatkonvertering

Direct3D möjliggör kopior mellan förstrukturerade texturer och blockkomprimerade texturer med samma bitbredd.

Du kan kopiera resurser mellan några olika formattyper. Den här typen av kopieringsåtgärd utför en typ av formatkonvertering som omtolkar resursdata som en annan formattyp. Tänk på det här exemplet som visar skillnaden mellan omtolkning av data med hur en mer typisk typ av konvertering fungerar:

FLOAT32 f = 1.0f;
UINT32 u;

Om du vill omtolka "f" som typ av "u" använder du memcpy:

memcpy( &u, &f, sizeof( f ) ); // 'u' becomes equal to 0x3F800000.

I föregående omtolkning ändras inte det underliggande värdet för data. memcpy omtolkar floaten som ett osignerat heltal.

Om du vill utföra den mer typiska typen av konvertering använder du tilldelning:

u = f; // 'u' becomes 1.

I föregående konvertering ändras det underliggande värdet för data.

I följande tabell visas de tillåtna käll- och målformat som du kan använda i den här omtolkningstypen för formatkonvertering. Du måste koda värdena korrekt för att omtolkningen ska fungera som förväntat.

Bitbredd Okomprimerad resurs Block-Compressed resurs
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

komprimerade strukturresurser