BC6H Format
Format BC6H adalah format kompresi tekstur yang dirancang untuk mendukung ruang warna rentang dinamis tinggi (HDR) dalam data sumber.
- Tentang BC6H/DXGI_FORMAT_BC6H
- Implementasi BC6H
- Mendekode Format BC6H
- Format Titik Akhir Terkompresi BC6H
- Tanda tangani Ekstensi untuk Nilai Titik Akhir
- Mengubah Inversi untuk Nilai Titik Akhir
- Ketidaksamaan Titik Akhir Warna
- Topik terkait
Tentang BC6H/DXGI_FORMAT_BC6H
Format BC6H menyediakan kompresi berkualitas tinggi untuk gambar yang menggunakan tiga saluran warna HDR, dengan nilai 16-bit untuk setiap saluran warna nilai (16:16:16). Tidak ada dukungan untuk saluran alfa.
BC6H ditentukan oleh nilai enumerasi DXGI_FORMAT berikut:
- DXGI_FORMAT_BC6H_TYPELESS.
- DXGI_FORMAT_BC6H_UF16. Format BC6H ini tidak menggunakan bit tanda dalam nilai saluran warna titik mengambang 16-bit.
- DXGI_FORMAT_BC6H_SF16. Format BC6H ini menggunakan sign bit dalam nilai saluran warna titik mengambang 16-bit.
Catatan
Format titik mengambang 16 bit untuk saluran warna sering disebut sebagai format titik mengambang "setengah". Format ini memiliki tata letak bit berikut:
Format | Tata letak bit |
---|---|
UF16 (float tidak ditandatangani) | 5 bit eksponen + 11 bit mantissa |
SF16 (float bertanda tangan) | 1 bit tanda + 5 bit eksponen + 10 bit mantissa |
Format BC6H dapat digunakan untuk sumber daya tekstur Texture2D (termasuk array), Texture3D, atau TextureCube (termasuk array). Demikian pula, format ini berlaku untuk permukaan peta MIP apa pun yang terkait dengan sumber daya ini.
BC6H menggunakan ukuran blok tetap 16 byte (128 bit) dan ukuran petak tetap 4x4 texel. Seperti format SM sebelumnya, gambar tekstur yang lebih besar dari ukuran petak peta yang didukung (4x4) dikompresi dengan menggunakan beberapa blok. Identitas alamat ini juga berlaku untuk gambar tiga dimensi, peta MIP, peta kubus, dan array tekstur. Semua petak peta gambar harus dalam format yang sama.
Beberapa catatan penting tentang format BC6H:
- BC6H mendukung denormalisasi floating point, tetapi tidak mendukung INF (infinity) dan NaN (bukan angka). Pengecualian adalah mode BC6H yang ditandatangani (DXGI_FORMAT_BC6H_SF16), yang mendukung -INF (tak terbatas negatif). Perhatikan bahwa dukungan untuk -INF ini hanyalah artefak dari format itu sendiri, dan tidak didukung secara khusus oleh encoder untuk format ini. Secara umum, ketika encoder menemukan inf (positif atau negatif) atau data input NaN, mereka harus \ mengonversi data tersebut ke nilai representasi non-INF maksimum yang diizinkan, dan memetakan NaN ke 0 sebelum pemadatan.
- BC6H tidak mendukung saluran alfa.
- Dekoder BC6H melakukan dekompresi sebelum melakukan pemfilteran tekstur.
- Dekompresi BC6H harus sedikit akurat; artinya, perangkat keras harus mengembalikan hasil yang identik dengan dekoder yang dijelaskan dalam dokumentasi ini.
Implementasi BC6H
Blok BC6H terdiri dari bit mode, titik akhir terkompresi, indeks terkompresi, dan indeks partisi opsional. Format ini menentukan 14 mode berbeda.
Warna titik akhir disimpan sebagai triplet RGB. BC6H mendefinisikan palet warna pada garis perkiraan di sejumlah titik akhir warna yang ditentukan. Selain itu, tergantung pada mode, petak peta dapat dibagi menjadi dua wilayah atau diperlakukan sebagai satu wilayah, di mana petak peta dua wilayah memiliki sekumpulan titik akhir warna terpisah untuk setiap wilayah. BC6H menyimpan satu indeks palet per texel.
Dalam kasus dua wilayah, ada 32 partisi yang mungkin.
Mendekode Format BC6H
Pseudocode di bawah ini menunjukkan langkah-langkah untuk mendekompresi piksel pada (x,y) mengingat blok 16 byte BC6H.
decompress_bc6h(x, y, block)
{
mode = extract_mode(block);
endpoints;
index;
if(mode.type == ONE)
{
endpoints = extract_compressed_endpoints(mode, block);
index = extract_index_ONE(x, y, block);
}
else //mode.type == TWO
{
partition = extract_partition(block);
region = get_region(partition, x, y);
endpoints = extract_compressed_endpoints(mode, region, block);
index = extract_index_TWO(x, y, partition, block);
}
unquantize(endpoints);
color = interpolate(index, endpoints);
finish_unquantize(color);
}
Tabel berikut berisi jumlah bit dan nilai untuk masing-masing dari 14 format yang mungkin untuk blok BC6H.
Mode | Indeks Partisi | Partisi | Titik Akhir Warna | Bit Mode |
---|---|---|---|---|
1 | 46 bit | 5 bit | 75 bit (10,555, 10,555, 10,555) | 2 bit (00) |
2 | 46 bit | 5 bit | 75 bit (7666, 7666, 7666) | 2 bit (01) |
3 | 46 bit | 5 bit | 72 bit (11.555, 11.444, 11.444) | 5 bit (00010) |
4 | 46 bit | 5 bit | 72 bit (11.444, 11.555, 11.444) | 5 bit (00110) |
5 | 46 bit | 5 bit | 72 bit (11.444, 11.444, 11.555) | 5 bit (01010) |
6 | 46 bit | 5 bit | 72 bit (9555, 9555, 9555) | 5 bit (01110) |
7 | 46 bit | 5 bit | 72 bit (8666, 8555, 8555) | 5 bit (10010) |
8 | 46 bit | 5 bit | 72 bit (8555, 8666, 8555) | 5 bit (10110) |
9 | 46 bit | 5 bit | 72 bit (8555, 8555, 8666) | 5 bit (11010) |
10 | 46 bit | 5 bit | 72 bit (6666, 6666, 6666) | 5 bit (11110) |
11 | 63 bit | 0 bit | 60 bit (10,10, 10,10, 10,10) | 5 bit (00011) |
12 | 63 bit | 0 bit | 60 bit (11,9, 11,9, 11,9) | 5 bit (00111) |
13 | 63 bit | 0 bit | 60 bit (12,8, 12,8, 12,8) | 5 bit (01011) |
14 | 63 bit | 0 bit | 60 bit (16,4, 16,4, 16,4) | 5 bit (01111) |
Setiap format dalam tabel ini dapat diidentifikasi secara unik oleh bit mode. Sepuluh mode pertama digunakan untuk petak peta dua wilayah, dan bidang bit mode dapat memiliki panjang dua atau lima bit. Blok ini juga memiliki bidang untuk titik akhir warna terkompresi (72 atau 75 bit), partisi (5 bit), dan indeks partisi (46 bit).
Untuk titik akhir warna terkompresi, nilai dalam tabel sebelumnya mencatat presisi titik akhir RGB yang disimpan, dan jumlah bit yang digunakan untuk setiap nilai warna. Misalnya, mode 3 menentukan tingkat presisi titik akhir warna 11, dan jumlah bit yang digunakan untuk menyimpan nilai delta titik akhir yang diubah untuk warna merah, biru, dan hijau (masing-masing 5, 4, dan 4). Mode 10 tidak menggunakan kompresi delta, dan sebaliknya menyimpan keempat titik akhir warna secara eksplisit.
Empat mode blok terakhir digunakan untuk petak peta satu wilayah, di mana bidang mode adalah 5 bit. Blok ini memiliki bidang untuk titik akhir (60 bit) dan indeks terkompresi (63 bit). Mode 11 (seperti Mode 10) tidak menggunakan kompresi delta, dan sebaliknya menyimpan kedua titik akhir warna secara eksplisit.
Mode 10011, 10111, 11011, dan 11111 (tidak ditampilkan) dicadangkan. Jangan gunakan ini di encoder Anda. Jika perangkat keras diteruskan memblokir dengan salah satu mode ini yang ditentukan, blok yang didekompresi yang dihasilkan harus berisi semua nol di semua saluran kecuali untuk saluran alfa.
Untuk BC6H, saluran alfa harus selalu mengembalikan 1,0 terlepas dari modenya.
Set Partisi BC6H
Ada 32 set partisi yang mungkin untuk petak peta dua wilayah, dan yang ditentukan dalam tabel di bawah ini. Setiap blok 4x4 mewakili satu bentuk.
Dalam tabel set partisi ini, entri tebal dan bergaris bawah adalah lokasi indeks perbaikan untuk subset 1 (yang ditentukan dengan satu bit lebih sedikit). Indeks perbaikan untuk subset 0 selalu diindeks 0, karena partisi selalu diatur sedemikian sehingga indeks 0 selalu berada di subset 0. Urutan partisi berubah dari kiri atas ke kanan bawah, bergerak kiri ke kanan lalu atas ke bawah.
Format Titik Akhir Terkompresi BC6H
Tabel ini memperlihatkan bidang bit untuk titik akhir terkompresi sebagai fungsi format titik akhir, dengan setiap kolom menentukan pengodean dan setiap baris yang menentukan bidang bit. Pendekatan ini membutuhkan 82 bit untuk petak peta dua wilayah dan 65 bit untuk petak peta satu wilayah. Sebagai contoh, 5 bit pertama untuk pengodean satu wilayah [16 4] di atas (khususnya kolom paling kanan) adalah bit m[4:0], 10 bit berikutnya adalah bit rw[9:0], dan sebagainya dengan 6 bit terakhir yang berisi bw[10:15].
Nama bidang dalam tabel di atas didefinisikan sebagai berikut:
Bidang | Variabel |
---|---|
m | mode |
d | indeks bentuk |
Rw | endpt[0]. A[0] |
Rx | endpt[0]. B[0] |
Ry | berakhir[1]. A[0] |
Rz | berakhir[1]. B[0] |
gw | endpt[0]. A[1] |
Gx | endpt[0]. B[1] |
Gy | berakhir[1]. A[1] |
Gz | berakhir[1]. B[1] |
Bw | endpt[0]. A[2] |
Bx | endpt[0]. B[2] |
oleh | berakhir[1]. A[2] |
Bz | berakhir[1]. B[2] |
Endpt[i], di mana saya adalah 0 atau 1, masing-masing mengacu pada set titik akhir ke-0 atau ke-1.
Tanda tangani Ekstensi untuk Nilai Titik Akhir
Untuk petak peta dua wilayah, ada empat nilai titik akhir yang dapat ditandatangani diperluas. Berakhir[0]. ditandatangani hanya jika formatnya adalah format bertanda tangan; titik akhir lainnya ditandatangani hanya jika titik akhir diubah, atau jika formatnya adalah format yang ditandatangani. Kode di bawah ini menunjukkan algoritma untuk memperluas tanda nilai titik akhir dua wilayah.
static void sign_extend_two_region(Pattern &p, IntEndpts endpts[NREGIONS_TWO])
{
for (int i=0; i<NCHANNELS; ++i)
{
if (BC6H::FORMAT == SIGNED_F16)
endpts[0].A[i] = SIGN_EXTEND(endpts[0].A[i], p.chan[i].prec);
if (p.transformed || BC6H::FORMAT == SIGNED_F16)
{
endpts[0].B[i] = SIGN_EXTEND(endpts[0].B[i], p.chan[i].delta[0]);
endpts[1].A[i] = SIGN_EXTEND(endpts[1].A[i], p.chan[i].delta[1]);
endpts[1].B[i] = SIGN_EXTEND(endpts[1].B[i], p.chan[i].delta[2]);
}
}
}
Untuk petak peta satu wilayah, perilakunya sama, hanya dengan akhiran[1] dihapus.
static void sign_extend_one_region(Pattern &p, IntEndpts endpts[NREGIONS_ONE])
{
for (int i=0; i<NCHANNELS; ++i)
{
if (BC6H::FORMAT == SIGNED_F16)
endpts[0].A[i] = SIGN_EXTEND(endpts[0].A[i], p.chan[i].prec);
if (p.transformed || BC6H::FORMAT == SIGNED_F16)
endpts[0].B[i] = SIGN_EXTEND(endpts[0].B[i], p.chan[i].delta[0]);
}
}
Mengubah Inversi untuk Nilai Titik Akhir
Untuk petak peta dua wilayah, transformasi menerapkan inversi pengodean perbedaan, menambahkan nilai dasar pada akhir[0]. A ke tiga entri lain untuk total 9 operasi penambahan. Pada gambar di bawah ini, nilai dasar direpresentasikan sebagai "A0" dan memiliki presisi titik mengambang tertinggi. "A1," "B0," dan "B1" adalah semua delta yang dihitung dari nilai jangkar, dan nilai delta ini diwakili dengan presisi yang lebih rendah. (A0 sesuai dengan endpt[0]. A, B0 sesuai dengan endpt[0]. B, A1 sesuai dengan endpt[1]. A, dan B1 sesuai dengan endpt[1].B.)
Untuk petak peta satu wilayah hanya ada satu offset delta, dan oleh karena itu hanya 3 operasi penambahan.
Dekompresor harus memastikan bahwa hasil transformasi terbalik tidak akan meluap presisi endpt[0].a. Dalam kasus luapan, nilai yang dihasilkan dari transformasi terbalik harus dibungkus dalam jumlah bit yang sama. Jika presisi A0 adalah bit "p", maka algoritma transformasi adalah:
B0 = (B0 + A0) & ((1 << p) - 1)
Untuk format yang ditandatangani, hasil perhitungan delta juga harus diperpanjang. Jika operasi ekstensi tanda mempertimbangkan untuk memperpanjang kedua tanda, di mana 0 positif dan 1 negatif, maka ekstensi tanda 0 mengurus klem di atas. Setara, setelah klem di atas, hanya nilai 1 (negatif) yang perlu ditandatangani diperpanjang.
Ketidaksamaan Titik Akhir Warna
Mengingat titik akhir yang tidak dikompresi, langkah selanjutnya adalah melakukan unquantization awal titik akhir warna. Ini melibatkan tiga langkah:
- Ketidaksamaan palet warna
- Interpolasi palet
- Finalisasi unquantization
Memisahkan proses unquantization menjadi dua bagian (unquantization palet warna sebelum interpolasi dan unquantization akhir setelah interpolasi) mengurangi jumlah operasi perkalian yang diperlukan jika dibandingkan dengan proses unquantization penuh sebelum interpolasi palet.
Kode di bawah ini menggambarkan proses untuk mengambil perkiraan nilai warna 16-bit asli, lalu menggunakan nilai bobot yang disediakan untuk menambahkan 6 nilai warna tambahan ke palet. Operasi yang sama dilakukan pada setiap saluran.
int aWeight3[] = {0, 9, 18, 27, 37, 46, 55, 64};
int aWeight4[] = {0, 4, 9, 13, 17, 21, 26, 30, 34, 38, 43, 47, 51, 55, 60, 64};
// c1, c2: endpoints of a component
void generate_palette_unquantized(UINT8 uNumIndices, int c1, int c2, int prec, UINT16 palette[NINDICES])
{
int* aWeights;
if(uNumIndices == 8)
aWeights = aWeight3;
else // uNumIndices == 16
aWeights = aWeight4;
int a = unquantize(c1, prec);
int b = unquantize(c2, prec);
// interpolate
for(int i = 0; i < uNumIndices; ++i)
palette[i] = finish_unquantize((a * (64 - aWeights[i]) + b * aWeights[i] + 32) >> 6);
}
Sampel kode berikutnya menunjukkan proses interpolasi, dengan pengamatan berikut:
- Karena rentang penuh nilai warna untuk fungsi unquantize (di bawah) adalah dari -32768 hingga 65535, interpolator diimplementasikan menggunakan aritmatika bertanda tangan 17-bit.
- Setelah interpolasi, nilai diteruskan ke fungsi finish_unquantize (dijelaskan dalam sampel ketiga di bagian ini), yang menerapkan penskalaan akhir.
- Semua dekompresor perangkat keras diperlukan untuk mengembalikan hasil bit-akurat dengan fungsi-fungsi ini.
int unquantize(int comp, int uBitsPerComp)
{
int unq, s = 0;
switch(BC6H::FORMAT)
{
case UNSIGNED_F16:
if(uBitsPerComp >= 15)
unq = comp;
else if(comp == 0)
unq = 0;
else if(comp == ((1 << uBitsPerComp) - 1))
unq = 0xFFFF;
else
unq = ((comp << 16) + 0x8000) >> uBitsPerComp;
break;
case SIGNED_F16:
if(uBitsPerComp >= 16)
unq = comp;
else
{
if(comp < 0)
{
s = 1;
comp = -comp;
}
if(comp == 0)
unq = 0;
else if(comp >= ((1 << (uBitsPerComp - 1)) - 1))
unq = 0x7FFF;
else
unq = ((comp << 15) + 0x4000) >> (uBitsPerComp-1);
if(s)
unq = -unq;
}
break;
}
return unq;
}
finish_unquantize dipanggil setelah interpolasi palet. Fungsi unquantize menunda penskalaan sebesar 31/32 untuk ditandatangani, 31/64 untuk tidak ditandatangani. Perilaku ini diperlukan untuk mendapatkan nilai akhir ke dalam rentang setengah yang valid(-0x7BFF ~ 0x7BFF) setelah interpolasi palet selesai untuk mengurangi jumlah perkalian yang diperlukan. finish_unquantize menerapkan penskalaan akhir dan mengembalikan nilai pendek yang tidak ditandatangani kembali menjadi setengahnya.
unsigned short finish_unquantize(int comp)
{
if(BC6H::FORMAT == UNSIGNED_F16)
{
comp = (comp * 31) >> 6; // scale the magnitude by 31/64
return (unsigned short) comp;
}
else // (BC6H::FORMAT == SIGNED_F16)
{
comp = (comp < 0) ? -(((-comp) * 31) >> 5) : (comp * 31) >> 5; // scale the magnitude by 31/32
int s = 0;
if(comp < 0)
{
s = 0x8000;
comp = -comp;
}
return (unsigned short) (s | comp);
}
}
Topik terkait
Saran dan Komentar
https://aka.ms/ContentUserFeedback.
Segera hadir: Sepanjang tahun 2024 kami akan menghentikan penggunaan GitHub Issues sebagai mekanisme umpan balik untuk konten dan menggantinya dengan sistem umpan balik baru. Untuk mengetahui informasi selengkapnya, lihat:Kirim dan lihat umpan balik untuk