1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208
use crate::{ffi, DecodePosition, VertexDataAdapter};
use std::mem;
/// Reorders indices to reduce the number of GPU vertex shader invocations.
///
/// If index buffer contains multiple ranges for multiple draw calls,
/// this function needs to be called on each range individually.
pub fn optimize_vertex_cache(indices: &[u32], vertex_count: usize) -> Vec<u32> {
let mut optimized: Vec<u32> = vec![0; indices.len()];
unsafe {
ffi::meshopt_optimizeVertexCache(
optimized.as_mut_ptr(),
indices.as_ptr(),
indices.len(),
vertex_count,
);
}
optimized
}
/// Reorders indices to reduce the number of GPU vertex shader invocations.
///
/// If index buffer contains multiple ranges for multiple draw calls,
/// this function needs to be called on each range individually.
pub fn optimize_vertex_cache_in_place(indices: &mut [u32], vertex_count: usize) {
unsafe {
ffi::meshopt_optimizeVertexCache(
indices.as_mut_ptr(),
indices.as_ptr(),
indices.len(),
vertex_count,
);
}
}
/// Vertex transform cache optimizer for FIFO caches.
///
/// Reorders indices to reduce the number of GPU vertex shader invocations.
///
/// Generally takes ~3x less time to optimize meshes but produces inferior
/// results compared to `optimize_vertex_cache`.
///
/// If index buffer contains multiple ranges for multiple draw calls,
/// this function needs to be called on each range individually.
pub fn optimize_vertex_cache_fifo(
indices: &[u32],
vertex_count: usize,
cache_size: u32,
) -> Vec<u32> {
let mut optimized: Vec<u32> = vec![0; indices.len()];
unsafe {
ffi::meshopt_optimizeVertexCacheFifo(
optimized.as_mut_ptr(),
indices.as_ptr(),
indices.len(),
vertex_count,
cache_size,
);
}
optimized
}
/// Vertex transform cache optimizer for FIFO caches (in place).
///
/// Reorders indices to reduce the number of GPU vertex shader invocations.
///
/// Generally takes ~3x less time to optimize meshes but produces inferior
/// results compared to `optimize_vertex_cache_fifo_in_place`.
///
/// If index buffer contains multiple ranges for multiple draw calls,
/// this function needs to be called on each range individually.
pub fn optimize_vertex_cache_fifo_in_place(
indices: &mut [u32],
vertex_count: usize,
cache_size: u32,
) {
unsafe {
ffi::meshopt_optimizeVertexCacheFifo(
indices.as_mut_ptr(),
indices.as_ptr(),
indices.len(),
vertex_count,
cache_size,
);
}
}
/// Reorders vertices and changes indices to reduce the amount of GPU
/// memory fetches during vertex processing.
///
/// This functions works for a single vertex stream; for multiple vertex streams,
/// use `optimize_vertex_fetch_remap` + `remap_vertex_buffer` for each stream.
///
/// `indices` is used both as an input and as an output index buffer.
pub fn optimize_vertex_fetch<T: Clone + Default>(indices: &mut [u32], vertices: &[T]) -> Vec<T> {
let mut result: Vec<T> = vec![T::default(); vertices.len()];
let next_vertex = unsafe {
ffi::meshopt_optimizeVertexFetch(
result.as_mut_ptr().cast(),
indices.as_mut_ptr(),
indices.len(),
vertices.as_ptr().cast(),
vertices.len(),
mem::size_of::<T>(),
)
};
result.resize(next_vertex, T::default());
result
}
/// Vertex fetch cache optimizer (modifies in place)
/// Reorders vertices and changes indices to reduce the amount of GPU
/// memory fetches during vertex processing.
///
/// This functions works for a single vertex stream; for multiple vertex streams,
/// use `optimize_vertex_fetch_remap` + `remap_vertex_buffer` for each stream.
///
/// `indices` and `vertices` are used both as an input and as an output buffer.
pub fn optimize_vertex_fetch_in_place<T>(indices: &mut [u32], vertices: &mut [T]) -> usize {
unsafe {
ffi::meshopt_optimizeVertexFetch(
vertices.as_mut_ptr().cast(),
indices.as_mut_ptr(),
indices.len(),
vertices.as_ptr().cast(),
vertices.len(),
mem::size_of::<T>(),
)
}
}
/// Generates vertex remap to reduce the amount of GPU memory fetches during
/// vertex processing.
///
/// The resulting remap table should be used to reorder vertex/index buffers
/// using `optimize_remap_vertex_buffer`/`optimize_remap_index_buffer`.
pub fn optimize_vertex_fetch_remap(indices: &[u32], vertex_count: usize) -> Vec<u32> {
let mut result: Vec<u32> = vec![0; vertex_count];
let next_vertex = unsafe {
ffi::meshopt_optimizeVertexFetchRemap(
result.as_mut_ptr(),
indices.as_ptr(),
indices.len(),
vertex_count,
)
};
result.resize(next_vertex, 0u32);
result
}
/// Reorders indices to reduce the number of GPU vertex shader invocations
/// and the pixel overdraw.
///
/// `indices` must contain index data that is the result of `optimize_vertex_cache`
/// (*not* the original mesh indices!)
///
/// `threshold` indicates how much the overdraw optimizer can degrade vertex cache
/// efficiency (1.05 = up to 5%) to reduce overdraw more efficiently.
pub fn optimize_overdraw_in_place(
indices: &mut [u32],
vertices: &VertexDataAdapter<'_>,
threshold: f32,
) {
let vertex_data = vertices.reader.get_ref();
let vertex_data = vertex_data.as_ptr().cast::<u8>();
let positions = unsafe { vertex_data.add(vertices.position_offset) };
unsafe {
ffi::meshopt_optimizeOverdraw(
indices.as_mut_ptr(),
indices.as_ptr(),
indices.len(),
positions.cast(),
vertices.vertex_count,
vertices.vertex_stride,
threshold,
);
}
}
/// Reorders indices to reduce the number of GPU vertex shader invocations
/// and the pixel overdraw.
///
/// `indices` must contain index data that is the result of `optimize_vertex_cache`
/// (*not* the original mesh indices!)
///
/// `threshold` indicates how much the overdraw optimizer can degrade vertex cache
/// efficiency (1.05 = up to 5%) to reduce overdraw more efficiently.
pub fn optimize_overdraw_in_place_decoder<T: DecodePosition>(
indices: &mut [u32],
vertices: &[T],
threshold: f32,
) {
let positions = vertices
.iter()
.map(|vertex| vertex.decode_position())
.collect::<Vec<[f32; 3]>>();
unsafe {
ffi::meshopt_optimizeOverdraw(
indices.as_mut_ptr(),
indices.as_ptr(),
indices.len(),
positions.as_ptr().cast(),
positions.len(),
mem::size_of::<f32>() * 3,
threshold,
);
}
}