ispc_texcomp/
bc7.rs

1use more_asserts::assert_ge;
2
3use crate::bindings::kernel;
4use crate::RgbaSurface;
5
6#[derive(Debug, Copy, Clone)]
7pub struct EncodeSettings {
8    pub mode_selection: [bool; 4usize],
9    pub refine_iterations: [u32; 8usize],
10    pub skip_mode2: bool,
11    pub fast_skip_threshold_mode1: u32,
12    pub fast_skip_threshold_mode3: u32,
13    pub fast_skip_threshold_mode7: u32,
14    pub mode45_channel0: u32,
15    pub refine_iterations_channel: u32,
16    pub channels: i32,
17}
18
19#[inline(always)]
20pub fn calc_output_size(width: u32, height: u32) -> usize {
21    // BC7 uses a fixed block size of 16 bytes (128 bits) and a fixed tile size of 4x4 texels.
22    let block_count = crate::cal_block_count(width, height, 4, 4) as usize;
23    block_count * 16
24}
25
26pub fn compress_blocks(settings: &EncodeSettings, surface: &RgbaSurface) -> Vec<u8> {
27    let output_size = calc_output_size(surface.width, surface.height);
28    let mut output = vec![0u8; output_size];
29    compress_blocks_into(settings, surface, &mut output);
30    output
31}
32
33pub fn compress_blocks_into(settings: &EncodeSettings, surface: &RgbaSurface, blocks: &mut [u8]) {
34    assert_ge!(
35        blocks.len(),
36        calc_output_size(surface.width, surface.height)
37    );
38    let mut surface = kernel::rgba_surface {
39        width: surface.width as i32,
40        height: surface.height as i32,
41        stride: surface.stride as i32,
42        ptr: surface.data.as_ptr() as *mut u8,
43    };
44    let mut settings = kernel::bc7_enc_settings {
45        mode_selection: settings.mode_selection,
46        refineIterations: [
47            settings.refine_iterations[0] as i32,
48            settings.refine_iterations[1] as i32,
49            settings.refine_iterations[2] as i32,
50            settings.refine_iterations[3] as i32,
51            settings.refine_iterations[4] as i32,
52            settings.refine_iterations[5] as i32,
53            settings.refine_iterations[6] as i32,
54            settings.refine_iterations[7] as i32,
55        ],
56        skip_mode2: settings.skip_mode2,
57        fastSkipTreshold_mode1: settings.fast_skip_threshold_mode1 as i32,
58        fastSkipTreshold_mode3: settings.fast_skip_threshold_mode3 as i32,
59        fastSkipTreshold_mode7: settings.fast_skip_threshold_mode7 as i32,
60        mode45_channel0: settings.mode45_channel0 as i32,
61        refineIterations_channel: settings.refine_iterations_channel as i32,
62        channels: settings.channels as i32,
63    };
64
65    unsafe {
66        kernel::CompressBlocksBC7_ispc(&mut surface, blocks.as_mut_ptr(), &mut settings);
67    }
68}
69
70#[inline(always)]
71pub fn opaque_ultra_fast_settings() -> EncodeSettings {
72    EncodeSettings {
73        channels: 3,
74        mode_selection: [false, false, false, true],
75        fast_skip_threshold_mode1: 3,
76        fast_skip_threshold_mode3: 1,
77        fast_skip_threshold_mode7: 0,
78        skip_mode2: true,
79        mode45_channel0: 0,
80        refine_iterations_channel: 0,
81        refine_iterations: [2, 2, 2, 1, 2, 2, 1, 0],
82    }
83}
84
85#[inline(always)]
86pub fn opaque_very_fast_settings() -> EncodeSettings {
87    EncodeSettings {
88        channels: 3,
89        mode_selection: [false, true, false, true],
90        fast_skip_threshold_mode1: 3,
91        fast_skip_threshold_mode3: 1,
92        fast_skip_threshold_mode7: 0,
93        skip_mode2: true,
94        mode45_channel0: 0,
95        refine_iterations_channel: 0,
96        refine_iterations: [2, 2, 2, 1, 2, 2, 1, 0],
97    }
98}
99
100#[inline(always)]
101pub fn opaque_fast_settings() -> EncodeSettings {
102    EncodeSettings {
103        channels: 3,
104        mode_selection: [false, true, false, true],
105        fast_skip_threshold_mode1: 12,
106        fast_skip_threshold_mode3: 4,
107        fast_skip_threshold_mode7: 0,
108        skip_mode2: true,
109        mode45_channel0: 0,
110        refine_iterations_channel: 0,
111        refine_iterations: [2, 2, 2, 1, 2, 2, 2, 0],
112    }
113}
114
115#[inline(always)]
116pub fn opaque_basic_settings() -> EncodeSettings {
117    EncodeSettings {
118        channels: 3,
119        mode_selection: [true, true, true, true],
120        fast_skip_threshold_mode1: 8 + 4,
121        fast_skip_threshold_mode3: 8,
122        fast_skip_threshold_mode7: 0,
123        skip_mode2: true,
124        mode45_channel0: 0,
125        refine_iterations_channel: 2,
126        refine_iterations: [2, 2, 2, 2, 2, 2, 2, 0],
127    }
128}
129
130#[inline(always)]
131pub fn opaque_slow_settings() -> EncodeSettings {
132    let more_refinement = 2;
133    EncodeSettings {
134        channels: 3,
135        mode_selection: [true, true, true, true],
136        fast_skip_threshold_mode1: 64,
137        fast_skip_threshold_mode3: 64,
138        fast_skip_threshold_mode7: 0,
139        skip_mode2: false,
140        mode45_channel0: 0,
141        refine_iterations_channel: 2 + more_refinement,
142        refine_iterations: [
143            2 + more_refinement,
144            2 + more_refinement,
145            2 + more_refinement,
146            2 + more_refinement,
147            2 + more_refinement,
148            2 + more_refinement,
149            2 + more_refinement,
150            0,
151        ],
152    }
153}
154
155#[inline(always)]
156pub fn alpha_ultra_fast_settings() -> EncodeSettings {
157    EncodeSettings {
158        channels: 4,
159        mode_selection: [false, false, true, true],
160        fast_skip_threshold_mode1: 0,
161        fast_skip_threshold_mode3: 0,
162        fast_skip_threshold_mode7: 4,
163        skip_mode2: true,
164        mode45_channel0: 3,
165        refine_iterations_channel: 1,
166        refine_iterations: [2, 1, 2, 1, 1, 1, 2, 2],
167    }
168}
169
170#[inline(always)]
171pub fn alpha_very_fast_settings() -> EncodeSettings {
172    EncodeSettings {
173        channels: 4,
174        mode_selection: [false, true, true, true],
175        fast_skip_threshold_mode1: 0,
176        fast_skip_threshold_mode3: 0,
177        fast_skip_threshold_mode7: 4,
178        skip_mode2: true,
179        mode45_channel0: 3,
180        refine_iterations_channel: 2,
181        refine_iterations: [2, 1, 2, 1, 2, 2, 2, 2],
182    }
183}
184
185#[inline(always)]
186pub fn alpha_fast_settings() -> EncodeSettings {
187    EncodeSettings {
188        channels: 4,
189        mode_selection: [false, true, true, true],
190        fast_skip_threshold_mode1: 4,
191        fast_skip_threshold_mode3: 4,
192        fast_skip_threshold_mode7: 8,
193        skip_mode2: true,
194        mode45_channel0: 3,
195        refine_iterations_channel: 2,
196        refine_iterations: [2, 1, 2, 1, 2, 2, 2, 2],
197    }
198}
199
200#[inline(always)]
201pub fn alpha_basic_settings() -> EncodeSettings {
202    EncodeSettings {
203        channels: 4,
204        mode_selection: [true, true, true, true],
205        fast_skip_threshold_mode1: 8 + 4,
206        fast_skip_threshold_mode3: 8,
207        fast_skip_threshold_mode7: 4,
208        skip_mode2: true,
209        mode45_channel0: 0,
210        refine_iterations_channel: 2,
211        refine_iterations: [2, 2, 2, 2, 2, 2, 2, 2],
212    }
213}
214
215#[inline(always)]
216pub fn alpha_slow_settings() -> EncodeSettings {
217    let more_refinement = 2;
218    EncodeSettings {
219        channels: 4,
220        mode_selection: [true, true, true, true],
221        fast_skip_threshold_mode1: 64,
222        fast_skip_threshold_mode3: 64,
223        fast_skip_threshold_mode7: 64,
224        skip_mode2: false,
225        mode45_channel0: 0,
226        refine_iterations_channel: 2 + more_refinement,
227        refine_iterations: [
228            2 + more_refinement,
229            2 + more_refinement,
230            2 + more_refinement,
231            2 + more_refinement,
232            2 + more_refinement,
233            2 + more_refinement,
234            2 + more_refinement,
235            2 + more_refinement,
236        ],
237    }
238}