Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -79,14 +79,10 @@ pub(in crate::assets::mesh::gpu_mesh) struct UvVertexUploadSource<'a> {
}

fn float4_default_stream_bytes(vertex_count: usize, default: [f32; 4]) -> Vec<u8> {
let mut out = vec![0u8; vertex_count * 16];
for chunk in out.chunks_exact_mut(16) {
for (component, value) in default.iter().enumerate() {
let o = component * 4;
chunk[o..o + 4].copy_from_slice(&value.to_le_bytes());
}
}
out
default
.map(|f| f.to_le_bytes())
.as_flattened()
.repeat(vertex_count)
}

fn float2_zero_stream_bytes(vertex_count: usize) -> Vec<u8> {
Expand Down
130 changes: 94 additions & 36 deletions crates/renderide/src/assets/mesh/layout/streams.rs
Original file line number Diff line number Diff line change
Expand Up @@ -199,14 +199,90 @@ pub fn uv0_float2_stream_bytes(

/// Dense `vec2<f32>` vertex stream for an arbitrary two-component attribute.
///
/// Missing or unsupported attributes return zeros so optional embedded shader streams can still
/// bind a stable vertex buffer slot.
/// Missing attributes with supported fallback types will use the first present attribute.
/// Missing or unsupported attributes return zeros so optional embedded shader streams
/// can still bind a stable vertex buffer slot.
pub fn vertex_float2_stream_bytes(
vertex_data: &[u8],
vertex_count: usize,
stride: usize,
attrs: &[VertexAttributeDescriptor],
target: VertexAttributeType,
) -> Option<Vec<u8>> {
vertex_float2_stream_bytes_fallback(
vertex_data,
vertex_count,
stride,
attrs,
&vertex_attribute_fallbacks(target),
)
}

/// Vector of attribute types that can be used in order of preference
/// to fill a requested vertex stream with fallback.
fn vertex_attribute_fallbacks(target: VertexAttributeType) -> Vec<VertexAttributeType> {
match target {
VertexAttributeType::UV1 => vec![VertexAttributeType::UV1, VertexAttributeType::UV0],
VertexAttributeType::UV2 => vec![
VertexAttributeType::UV2,
VertexAttributeType::UV1,
VertexAttributeType::UV0,
],
VertexAttributeType::UV3 => vec![
VertexAttributeType::UV3,
VertexAttributeType::UV2,
VertexAttributeType::UV1,
VertexAttributeType::UV0,
],
VertexAttributeType::UV4 => vec![
VertexAttributeType::UV4,
VertexAttributeType::UV3,
VertexAttributeType::UV2,
VertexAttributeType::UV1,
VertexAttributeType::UV0,
],
VertexAttributeType::UV5 => vec![
VertexAttributeType::UV5,
VertexAttributeType::UV4,
VertexAttributeType::UV3,
VertexAttributeType::UV2,
VertexAttributeType::UV1,
VertexAttributeType::UV0,
],
VertexAttributeType::UV6 => vec![
VertexAttributeType::UV6,
VertexAttributeType::UV5,
VertexAttributeType::UV4,
VertexAttributeType::UV3,
VertexAttributeType::UV2,
VertexAttributeType::UV1,
VertexAttributeType::UV0,
],
VertexAttributeType::UV7 => vec![
VertexAttributeType::UV7,
VertexAttributeType::UV6,
VertexAttributeType::UV5,
VertexAttributeType::UV4,
VertexAttributeType::UV3,
VertexAttributeType::UV2,
VertexAttributeType::UV1,
VertexAttributeType::UV0,
],
_ => vec![target],
}
}

/// Dense `vec2<f32>` vertex stream for an arbitrary two-component attribute,
/// with a list of fallback targets to use in case of a missing attribute.
///
/// Missing or unsupported attributes return zeros so optional embedded shader streams
/// can still bind a stable vertex buffer slot.
fn vertex_float2_stream_bytes_fallback(
vertex_data: &[u8],
vertex_count: usize,
stride: usize,
attrs: &[VertexAttributeDescriptor],
targets: &[VertexAttributeType],
) -> Option<Vec<u8>> {
if vertex_count == 0 || stride == 0 {
return None;
Expand All @@ -216,15 +292,17 @@ pub fn vertex_float2_stream_bytes(
return None;
}
let mut out = vec![0u8; vertex_count * 8];
let Some(reader) = AttributeReader::from_attrs(
vertex_data,
vertex_count,
stride,
attrs,
target,
VertexDecodeKind::TexCoord,
2,
) else {
let Some(reader) = targets.iter().find_map(|&target| {
AttributeReader::from_attrs(
vertex_data,
vertex_count,
stride,
attrs,
target,
VertexDecodeKind::TexCoord,
2,
)
}) else {
return Some(out);
};
if should_parallelize_vertex_stream(vertex_count) {
Expand Down Expand Up @@ -328,8 +406,10 @@ fn vertex_float4_stream_bytes_with_kind(
if vertex_data.len() < need {
return None;
}
let mut out = vec![0u8; vertex_count * 16];
fill_float4_stream_with_default(&mut out, default);
let mut out = default
.map(|f| f.to_le_bytes())
.as_flattened()
.repeat(vertex_count);

let Some(reader) =
AttributeReader::from_attrs(vertex_data, vertex_count, stride, attrs, target, kind, 1)
Expand Down Expand Up @@ -423,8 +503,7 @@ pub fn color_float4_stream_bytes(
if vertex_data.len() < need {
return None;
}
let mut out = vec![0u8; vertex_count * 16];
fill_color_stream_with_white(&mut out);
let mut out = 1.0f32.to_le_bytes().repeat(vertex_count * 4);

let Some(reader) = AttributeReader::from_attrs(
vertex_data,
Expand Down Expand Up @@ -452,27 +531,6 @@ pub fn color_float4_stream_bytes(
Some(out)
}

fn fill_float4_stream_with_default(out: &mut [u8], default: [f32; 4]) {
let default = default.map(|value| value.to_le_bytes());
let write_chunk = |chunk: &mut [u8]| {
for (component, value) in default.iter().enumerate() {
let offset = component * 4;
chunk[offset..offset + 4].copy_from_slice(value);
}
};
if should_parallelize_vertex_stream(out.len() / 16) {
out.par_chunks_exact_mut(16)
.with_min_len(VERTEX_STREAM_PARALLEL_CHUNK_VERTICES)
.for_each(write_chunk);
} else {
out.chunks_exact_mut(16).for_each(write_chunk);
}
}

fn fill_color_stream_with_white(out: &mut [u8]) {
fill_float4_stream_with_default(out, [1.0; 4]);
}

fn decode_vertex_scalar(
vertex_data: &[u8],
base: usize,
Expand Down
Loading