use concinnity_core::blob::{MeshBoundsRecord, PhysicsBudgetRecord, ResourceKind, SceneGroup};
use crate::ecs::{BlobAssetDef, ResourceRecord};
#[derive(Debug, Clone, Default, PartialEq)]
pub struct TextureSourceInfo {
pub name_id: u32,
pub source: String,
pub image_index: u32,
}
#[derive(Debug, Clone, Default, PartialEq)]
pub struct MeshSourceInfo {
pub source: String,
pub primitive_index: u32,
pub lod_levels: u32,
pub lod_distances: Vec<f32>,
}
pub struct PipelineResult {
pub defs: Vec<BlobAssetDef>,
pub names: Vec<String>,
pub resources: Vec<ResourceRecord>,
pub scene_groups: Vec<SceneGroup>,
pub mesh_bounds: Vec<MeshBoundsRecord>,
pub physics_budget: Option<PhysicsBudgetRecord>,
pub(crate) mesh_component_names: Vec<(u32, String)>,
pub payloads: Vec<Vec<u8>>,
pub(crate) cache_hits: usize,
pub(crate) cache_misses: usize,
pub texture_sources: Vec<TextureSourceInfo>,
pub mesh_sources: Vec<MeshSourceInfo>,
pub(crate) resource_locks: Vec<crate::blob::LockedResource>,
}
impl PipelineResult {
pub fn resource_names(&self, kind: ResourceKind) -> Vec<u32> {
let mut names = Vec::new();
for (record, lock) in self.resources.iter().zip(self.resource_locks.iter()) {
if record.resource_kind != kind as u8 {
continue;
}
let slot = record.handle as usize;
if names.len() <= slot {
names.resize(slot + 1, 0);
}
names[slot] = lock.id.unwrap_or_default();
}
names
}
pub fn resource_payload(&self, kind: ResourceKind, name: &str) -> Option<&[u8]> {
let record = self
.resources
.iter()
.zip(self.resource_locks.iter())
.find(|(r, l)| r.resource_kind == kind as u8 && l.name == name)?
.0;
let loc = record.payload.as_ref()?;
let blob = self.payloads.get(loc.blob_index as usize)?;
let start = usize::try_from(loc.offset).ok()?;
let end = start.checked_add(usize::try_from(loc.len).ok()?)?;
blob.get(start..end)
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::pipeline::build_pipeline_from_str;
use crate::pipeline::fixtures::SHADER_BUILD_LOCK;
#[test]
fn resource_payload_slices_the_named_resource() {
let _guard = SHADER_BUILD_LOCK.lock().unwrap_or_else(|e| e.into_inner());
crate::compile::shader::install_stub_toolchain();
let world = concat!(
r#"{"name":"prism","type":"SkinnedMesh","args":{"#,
r#""vertices":[{"pos":[0,0,0]},{"pos":[1,0,0]},{"pos":[0,1,0]}],"#,
r#""indices":[0,1,2],"skeleton":[{"name":"root","parent":-1}],"#,
r#""scale":[1,1,1]}}"#,
"\n",
);
let result = build_pipeline_from_str(world, None, None).expect("build");
let bytes = result
.resource_payload(ResourceKind::SkinnedMesh, "prism")
.expect("named payload");
let payload =
concinnity_core::gfx::mesh_payload::deserialise_skinned_with_lods(bytes).unwrap();
assert_eq!(payload.vertices.len(), 3);
assert_eq!(payload.joints[0].name, "root");
assert!(
result
.resource_payload(ResourceKind::SkinnedMesh, "ghost")
.is_none()
);
assert!(
result
.resource_payload(ResourceKind::Texture, "prism")
.is_none()
);
}
}