ispc_tex/
bc7.rs

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