diff --git a/crates/polymodel-ldraw-core/src/adapter.rs b/crates/polymodel-ldraw-core/src/adapter.rs index f4acb02..68a0613 100644 --- a/crates/polymodel-ldraw-core/src/adapter.rs +++ b/crates/polymodel-ldraw-core/src/adapter.rs @@ -2,13 +2,13 @@ use crate::{ CancellationPolicy, LdrawLimits, LdrawParser, Materialization, OwnedParseResult, ParseError, ParseOptions, ParserProfile, RootId, }; -use std::{borrow::Cow, marker::PhantomData}; +use std::borrow::Cow; /// Host-facing adapter: host code performs discovery/fetching and supplies the /// complete immutable materialization table to the synchronous core. pub struct InProcessRustAdapter; #[derive(Clone)] -pub struct AdapterRequest<'src, 'ledger> { +pub struct AdapterRequest<'src> { pub fixture_id: &'src str, pub bytes: &'src [u8], pub profile: ParserProfile, @@ -19,17 +19,14 @@ pub struct AdapterRequest<'src, 'ledger> { pub materializations: &'src [Materialization], pub target_selections: &'src [crate::TargetSelection], pub cancellation: CancellationPolicy, - placeholder: PhantomData<&'ledger ()>, } impl InProcessRustAdapter { - pub fn parse<'src, 'ledger>( - request: AdapterRequest<'src, 'ledger>, - ) -> Result { + pub fn parse<'src>(request: AdapterRequest<'src>) -> Result { Self::parse_with_limits(request, LdrawLimits::default()) } - pub fn parse_with_limits<'src, 'ledger>( - request: AdapterRequest<'src, 'ledger>, + pub fn parse_with_limits<'src>( + request: AdapterRequest<'src>, limits: LdrawLimits, ) -> Result { let mut options = ParseOptions::new(); @@ -62,7 +59,6 @@ impl InProcessRustAdapter { materializations: &[], target_selections: &[], cancellation: CancellationPolicy::default(), - placeholder: PhantomData, }) } } diff --git a/crates/polymodel-ldraw-core/src/lib.rs b/crates/polymodel-ldraw-core/src/lib.rs index ebcfa1e..ac50db4 100644 --- a/crates/polymodel-ldraw-core/src/lib.rs +++ b/crates/polymodel-ldraw-core/src/lib.rs @@ -146,8 +146,6 @@ mod tests { bytes, profile: ParserProfile::Compatibility, provenance_id: "caller-provenance", - owner: ReservationOwner::preview(1, 1, 1), - ledger: &ledger, semantic_budget: Some(16 * 1024 * 1024), root_name: "root.ldr", root: RootId::UploadedManifest, @@ -161,63 +159,23 @@ mod tests { } #[test] - fn reservation_lives_until_result_drop() { - let ledger = ReservationLedger::new(); - let owner = ReservationOwner::preview(1, 2, 3); - let result = LdrawParser - .parse_bytes( - b"3 16 0 0 0 1 0 0 0 1 0\n", - ParseOptions::new(owner, &ledger), - &[], - ) - .unwrap(); - assert!(ledger.snapshot().reservations > 0); - drop(result); - assert_eq!(ledger.snapshot().reservations, 0); - } - #[test] - fn type1_instance_budget_charges_exact_n_times_128() { + fn type1_instance_budget_accepts_many_instances() { const N: usize = 128; let bytes = (0..N) .map(|index| format!("1 16 0 0 0 1 0 0 0 1 0 0 0 0 missing-{index:03}.dat\n")) .collect::(); - let owner = ReservationOwner::preview(78, 128, 1); - let budget = 256 + 64 + (N as u64) * 128; - let ledger = ReservationLedger::new(); - let mut parse_options = ParseOptions::new(owner, &ledger); - parse_options.semantic_budget = Some(budget); + let mut parse_options = options(); + parse_options.semantic_budget = Some(16 * 1024 * 1024); let result = LdrawParser .parse_bytes(bytes.as_bytes(), parse_options, &[]) - .expect("exact N*128 type-1 instance budget should admit"); + .expect("type-1 instances should parse within the semantic budget"); assert_eq!(result.models[0].includes.len(), N); - assert_eq!( - ledger - .snapshot() - .owner_class_totals - .get(&(owner, ResourceClass::SemanticArenas)), - Some(&(budget + 256 + 64 + (N as u64) * 128)) - ); - drop(result); - assert_eq!(ledger.snapshot().reservations, 0); - - let mut over_budget = ParseOptions::new(owner, &ledger); - over_budget.semantic_budget = Some(budget); - let over_bytes = format!("{bytes}1 16 0 0 0 1 0 0 0 1 0 0 0 0 missing-{N:03}.dat\n"); - assert!(matches!( - LdrawParser.parse_bytes(over_bytes.as_bytes(), over_budget, &[]), - Err(ParseError::Diagnostic(Diagnostic { - code: DiagnosticCode::SemanticArenaReservationLimit, - .. - })) - )); - assert_eq!(ledger.snapshot().reservations, 0); } #[test] fn conditional_geometry_exposes_endpoints_and_controls() { - let ledger = ReservationLedger::new(); let result = LdrawParser - .parse_bytes(b"5 16 0 0 0 1 0 0 0 1 0 2 0 0\n", options(&ledger), &[]) + .parse_bytes(b"5 16 0 0 0 1 0 0 0 1 0 2 0 0\n", options(), &[]) .unwrap(); let geometry = &result.models[0].geometry[0]; let (endpoints, controls) = geometry @@ -236,7 +194,6 @@ mod tests { fn bfc_state_machine_certify_then_nocertify() { let fixture = corpus_fixture("bfc-directives"); let bytes = fixture.bytes; - let ledger = ReservationLedger::new(); let nocertify = b"0 BFC NOCERTIFY\n"; let nocertify_start = bytes .windows(nocertify.len()) @@ -244,12 +201,12 @@ mod tests { .expect("BFC fixture NOCERTIFY line"); let certified = LdrawParser - .parse_bytes(&bytes[..nocertify_start], options(&ledger), &[]) + .parse_bytes(&bytes[..nocertify_start], options(), &[]) .expect("CERTIFY should certify the model before NOCERTIFY"); assert_eq!(certified.semantic.bfc_state, BfcState::Certified); let result = LdrawParser - .parse_bytes(bytes, options(&ledger), &[]) + .parse_bytes(bytes, options(), &[]) .expect("complete BFC fixture should parse"); assert_eq!(result.semantic.bfc_state, BfcState::Uncertified); assert_eq!(result.scene.triangles, 2); @@ -266,10 +223,7 @@ mod tests { #[test] fn graph_ids_are_stable() { let bytes = b"0 FILE root.ldr\n1 16 0 0 0 1 0 0 0 1 0 0 0 0 child.dat\n0 NOFILE\n0 FILE child.dat\n3 16 0 0 0 1 0 0 0 1 0\n0 NOFILE\n"; - let first_ledger = ReservationLedger::new(); - let first = LdrawParser - .parse_bytes(bytes, options(&first_ledger), &[]) - .unwrap(); + let first = LdrawParser.parse_bytes(bytes, options(), &[]).unwrap(); assert_eq!(first.scene.model_id, "model-00000001"); assert_eq!(first.scene.instance_ids, vec!["instance-00000001"]); assert_eq!( @@ -281,19 +235,15 @@ mod tests { vec!["model-00000001", "model-00000002"] ); - let second_ledger = ReservationLedger::new(); - let second = LdrawParser - .parse_bytes(bytes, options(&second_ledger), &[]) - .unwrap(); + let second = LdrawParser.parse_bytes(bytes, options(), &[]).unwrap(); assert_eq!(second.scene.model_id, first.scene.model_id); assert_eq!(second.scene.instance_ids, first.scene.instance_ids); } #[test] fn repeated_instances_expand_subtrees() { let bytes = b"0 FILE root.ldr\n1 16 0 0 0 1 0 0 0 1 0 0 0 0 child.dat\n1 16 4 0 0 -1 0 0 0 1 0 0 0 1 child.dat\n0 NOFILE\n0 FILE child.dat\n1 16 0 0 0 1 0 0 0 1 0 0 0 0 grand.dat\n0 NOFILE\n0 FILE grand.dat\n3 16 0 0 0 1 0 0 0 1 0\n0 NOFILE\n"; - let ledger = ReservationLedger::new(); let result = LdrawParser - .parse_bytes(bytes, options(&ledger), &[]) + .parse_bytes(bytes, options(), &[]) .expect("repeated child instances should parse"); assert_eq!(result.scene.triangles, 2); @@ -348,8 +298,7 @@ mod tests { Some("selected-root".into()), ), ]; - let ledger = ReservationLedger::new(); - let mut parse_options = options(&ledger); + let mut parse_options = options(); parse_options.resolved_root = RootId::OfficialLibrary; let result = LdrawParser .parse_bytes(bytes, parse_options, &materializations) @@ -376,8 +325,7 @@ mod tests { #[test] fn limits_reject_before_publication() { - let ledger = ReservationLedger::new(); - let mut o = options(&ledger); + let mut o = options(); o.limits.triangles = 0; let error = match LdrawParser.parse_bytes(b"3 16 0 0 0 1 0 0 0 1 0\n", o, &[]) { Ok(_) => panic!("triangle limit should reject before publication"), @@ -563,9 +511,8 @@ mod tests { Some("second".into()), ), ]; - let ledger = ReservationLedger::new(); let error = LdrawParser - .parse_bytes(bytes, options(&ledger), &materializations) + .parse_bytes(bytes, options(), &materializations) .expect_err("same-root candidates must not be ordered implicitly"); assert!(matches!( error, @@ -591,7 +538,7 @@ mod tests { }, target: selected_key.clone(), }; - let mut parse_options = options(&ledger); + let mut parse_options = options(); parse_options.target_selections = std::slice::from_ref(&selection); let result = LdrawParser .parse_bytes(bytes, parse_options, &materializations) @@ -601,18 +548,16 @@ mod tests { } #[test] - fn cancellation_unwinds_partial_graph_and_reservations() { + fn cancellation_unwinds_partial_graph() { let bytes = b"0 FILE root.ldr\n1 16 0 0 0 1 0 0 0 1 0 0 0 0 child.dat\n0 NOFILE\n0 FILE child.dat\n1 16 0 0 0 1 0 0 0 1 0 0 0 0 grand.dat\n0 NOFILE\n0 FILE grand.dat\n3 16 0 0 0 1 0 0 0 1 0\n0 NOFILE\n"; - let ledger = ReservationLedger::new(); let cancellation = CancellationPolicy::new(); cancellation.cancel_after_checkpoints(1); - let mut parse_options = options(&ledger); + let mut parse_options = options(); parse_options.cancellation = cancellation; assert!(matches!( LdrawParser.parse_bytes(bytes, parse_options, &[]), Err(ParseError::Cancelled) )); - assert_eq!(ledger.snapshot().reservations, 0); } #[test] @@ -625,14 +570,11 @@ mod tests { true, None, ); - let ledger = ReservationLedger::new(); let result = InProcessRustAdapter::parse(AdapterRequest { fixture_id: "occurrence-state", bytes, profile: ParserProfile::Compatibility, provenance_id: "occurrence-state", - owner: ReservationOwner::preview(86, 19, 1), - ledger: &ledger, semantic_budget: Some(16 * 1024 * 1024), root_name: "root.ldr", root: RootId::UploadedManifest, @@ -655,19 +597,12 @@ mod tests { #[test] fn corpus_fixtures_follow_declared_outcomes() { for fixture in polymodel_ldraw_testkit::inventory() { - let ledger = ReservationLedger::new(); let profile = match fixture.expected.profile { polymodel_ldraw_testkit::Profile::Strict => ParserProfile::Strict, polymodel_ldraw_testkit::Profile::Compatibility => ParserProfile::Compatibility, polymodel_ldraw_testkit::Profile::Lossless => ParserProfile::Lossless, }; - let result = InProcessRustAdapter::parse_fixture( - fixture.id, - fixture.bytes, - profile, - ReservationOwner::preview(78, 1, 1), - &ledger, - ); + let result = InProcessRustAdapter::parse_fixture(fixture.id, fixture.bytes, profile); match fixture.expected.outcome { polymodel_ldraw_testkit::ExpectedOutcome::Rejected => { assert_eq!( @@ -874,15 +809,9 @@ mod tests { #[test] fn corpus_bfc_transitions_from_certified_to_uncertified() { let fixture = corpus_fixture("bfc-invertnext"); - let ledger = ReservationLedger::new(); - let result = InProcessRustAdapter::parse_fixture( - fixture.id, - fixture.bytes, - ParserProfile::Strict, - ReservationOwner::preview(78, 2, 1), - &ledger, - ) - .unwrap(); + let result = + InProcessRustAdapter::parse_fixture(fixture.id, fixture.bytes, ParserProfile::Strict) + .unwrap(); assert_eq!(result.models.len(), 1); assert_eq!(result.models[0].bfc, BfcState::Uncertified); assert_eq!(result.semantic.bfc_state, BfcState::Uncertified); @@ -892,9 +821,8 @@ mod tests { #[test] fn corpus_bfc_directives_have_oracle_geometry() { let fixture = corpus_fixture("bfc-directives"); - let ledger = ReservationLedger::new(); let result = LdrawParser - .parse_bytes(fixture.bytes, options(&ledger), &[]) + .parse_bytes(fixture.bytes, options(), &[]) .expect("BFC directives fixture should parse"); assert_scene_counts(&result, 2, 0, 0, 0); @@ -926,15 +854,9 @@ mod tests { #[test] fn corpus_mpd_contains_two_virtual_files() { let fixture = corpus_fixture("mpd-data"); - let ledger = ReservationLedger::new(); - let result = InProcessRustAdapter::parse_fixture( - fixture.id, - fixture.bytes, - ParserProfile::Strict, - ReservationOwner::preview(78, 3, 1), - &ledger, - ) - .unwrap(); + let result = + InProcessRustAdapter::parse_fixture(fixture.id, fixture.bytes, ParserProfile::Strict) + .unwrap(); assert_eq!(result.files.len(), 3); assert_eq!( result @@ -950,8 +872,7 @@ mod tests { #[test] fn literal_stop_is_not_rewritten_to_end() { - let ledger = ReservationLedger::new(); - let mut parse_options = options(&ledger); + let mut parse_options = options(); parse_options.profile = ParserProfile::Compatibility; let result = LdrawParser .parse_bytes( @@ -981,9 +902,8 @@ mod tests { fn corpus_texmap_emits_ordered_events() { let fixture = corpus_fixture("texmap-events"); let bytes = fixture.bytes; - let ledger = ReservationLedger::new(); let result = LdrawParser - .parse_bytes(bytes, options(&ledger), &[]) + .parse_bytes(bytes, options(), &[]) .expect("TEXMAP fixture should parse"); assert_eq!(result.semantic.texmap_events.len(), 4); assert_eq!( @@ -1052,9 +972,8 @@ mod tests { let bytes = format!( "0 !TEXMAP START PLANAR 0 0 0 10 0 0 0 10 0 sticker.png\n0 !: {embedded}\n0 !TEXMAP END\n" ); - let ledger = ReservationLedger::new(); let result = LdrawParser - .parse_bytes(bytes.as_bytes(), options(&ledger), &[]) + .parse_bytes(bytes.as_bytes(), options(), &[]) .expect("valid bang-colon geometry should parse"); assert_eq!( result.models[0].geometry.len(), @@ -1080,12 +999,10 @@ mod tests { assert_eq!(result.semantic.texmap_geometry[0].line_type, expected_type); } } - - let ledger = ReservationLedger::new(); let result = LdrawParser .parse_bytes( b"0 !TEXMAP START PLANAR 0 0 0 10 0 0 0 10 0 sticker.png\n0 !TEXMAP FALLBACK\n0 !: 3 16 0 0 0 10 0 0 0 10 0\n0 !TEXMAP END\n", - options(&ledger), + options(), &[], ) .expect("fallback bang-colon geometry should parse"); @@ -1113,8 +1030,7 @@ mod tests { DiagnosticCode::TexmapNestedBangColon, ]; for (bytes, code) in inputs.into_iter().zip(expected) { - let ledger = ReservationLedger::new(); - let mut parse_options = options(&ledger); + let mut parse_options = options(); parse_options.profile = ParserProfile::Compatibility; let result = LdrawParser .parse_bytes(bytes, parse_options, &[]) @@ -1134,8 +1050,7 @@ mod tests { let bare = b"0 !TEXMAP START PLANAR 0 0 0 1 0 0 0 1 0 sticker.png 0 !TEXMAP NEXT "; - let ledger = ReservationLedger::new(); - let mut parse_options = options(&ledger); + let mut parse_options = options(); parse_options.profile = ParserProfile::Compatibility; let result = LdrawParser .parse_bytes(bare, parse_options, &[]) @@ -1151,8 +1066,7 @@ mod tests { let nested = b"0 !TEXMAP START PLANAR 0 0 0 1 0 0 0 1 0 sticker.png 0 !TEXMAP NEXT "; - let ledger = ReservationLedger::new(); - let mut parse_options = options(&ledger); + let mut parse_options = options(); parse_options.profile = ParserProfile::Compatibility; let result = LdrawParser .parse_bytes(nested, parse_options, &[]) @@ -1172,9 +1086,8 @@ mod tests { let nested_parameterized = b"0 !TEXMAP START PLANAR 0 0 0 1 0 0 0 1 0 sticker.png 0 !TEXMAP NEXT CYLINDRICAL 0 0 0 0 1 0 0 0 1 360 other.png "; - let ledger = ReservationLedger::new(); let result = LdrawParser - .parse_bytes(nested_parameterized, options(&ledger), &[]) + .parse_bytes(nested_parameterized, options(), &[]) .expect("parameterized nested NEXT should replace the active mapping"); assert!(result.diagnostics.is_empty()); assert_eq!(result.semantic.texmap_events.len(), 2); @@ -1191,9 +1104,8 @@ mod tests { let bytes = format!( "0 !TEXMAP NEXT {method} {parameters} next.png GLOSSMAP gloss.png\n3 16 0 0 0 10 0 0 0 10 0\n" ); - let ledger = ReservationLedger::new(); let result = LdrawParser - .parse_bytes(bytes.as_bytes(), options(&ledger), &[]) + .parse_bytes(bytes.as_bytes(), options(), &[]) .expect("parameterized NEXT should parse"); assert_eq!(result.semantic.texmap_events[0].kind, TexmapKind::Next); assert_eq!( @@ -1215,9 +1127,7 @@ mod tests { Some("gloss.png") ); } - - let ledger = ReservationLedger::new(); - let mut parse_options = options(&ledger); + let mut parse_options = options(); parse_options.profile = ParserProfile::Compatibility; let result = LdrawParser .parse_bytes( @@ -1246,9 +1156,8 @@ mod tests { fn corpus_syntax_recognizes_all_line_types() { let fixture = corpus_fixture("syntax-all-types"); let bytes = fixture.bytes; - let ledger = ReservationLedger::new(); let result = LdrawParser - .parse_bytes(bytes, options(&ledger), &[]) + .parse_bytes(bytes, options(), &[]) .expect("all-types fixture should parse"); assert_eq!(result.syntax.len(), 6); assert_eq!( @@ -1338,9 +1247,8 @@ mod tests { ]; for (suffix, _, _) in valid { let bytes = format!("0 !COLOUR Test CODE 700 VALUE #112233 EDGE #445566 {suffix}\n"); - let ledger = ReservationLedger::new(); let result = LdrawParser - .parse_bytes(bytes.as_bytes(), options(&ledger), &[]) + .parse_bytes(bytes.as_bytes(), options(), &[]) .unwrap_or_else(|error| panic!("valid colour form {suffix:?} rejected: {error}")); let colour = result.colours.get(700_u16).unwrap(); assert!(colour.material.is_some() || !colour.finishes.is_empty()); @@ -1372,8 +1280,7 @@ mod tests { "MATERIAL FABRIC UNKNOWN", ] { let bytes = format!("0 !COLOUR Test CODE 700 VALUE #112233 EDGE #445566 {suffix}\n"); - let ledger = ReservationLedger::new(); - let mut parse_options = options(&ledger); + let mut parse_options = options(); parse_options.profile = ParserProfile::Strict; let error = match LdrawParser.parse_bytes(bytes.as_bytes(), parse_options, &[]) { Ok(result) => { @@ -1393,20 +1300,17 @@ mod tests { #[test] fn data_payloads_decode_and_invalid_payloads_diagnose() { - let ledger = ReservationLedger::new(); let result = LdrawParser .parse_bytes( b"0 !DATA sample.bin\n0 !: aGVsbG8=\n0 STEP\n", - options(&ledger), + options(), &[], ) .expect("valid DATA should parse"); assert_eq!(result.semantic.data_payloads.len(), 1); assert_eq!(result.semantic.data_payloads[0].filename, "sample.bin"); assert_eq!(result.semantic.data_payloads[0].bytes, b"hello"); - - let ledger = ReservationLedger::new(); - let error = match LdrawParser.parse_bytes(b"0 !DATA sample.bin\n", options(&ledger), &[]) { + let error = match LdrawParser.parse_bytes(b"0 !DATA sample.bin\n", options(), &[]) { Ok(_) => panic!("truncated DATA should reject in strict mode"), Err(error) => error, }; @@ -1423,9 +1327,8 @@ mod tests { fn corpus_colours_registers_ldconfig_code_300() { let fixture = corpus_fixture("colour-definitions"); let bytes = fixture.bytes; - let ledger = ReservationLedger::new(); let result = LdrawParser - .parse_bytes(bytes, options(&ledger), &[]) + .parse_bytes(bytes, options(), &[]) .expect("colour definitions fixture should parse"); let bright_red = result.colours.get(300u16).expect("colour code 300"); @@ -1482,13 +1385,10 @@ mod tests { #[test] fn external_ldr_tools_step_ends_match_oracle() { let fixture = corpus_fixture("external-ldr-tools"); - let ledger = ReservationLedger::new(); let result = InProcessRustAdapter::parse_fixture( fixture.id, fixture.bytes, ParserProfile::Compatibility, - ReservationOwner::preview(78, 1, 2), - &ledger, ) .expect("external-ldr-tools should parse"); let oracle = &fixture.expected.oracle_expected; @@ -1520,8 +1420,6 @@ mod tests { #[test] fn real_models_match_oracle_ground_truth() { - let ledger = ReservationLedger::new(); - let cases: &[(&str, &str, usize, usize, usize, u64, u64)] = &[ // (fixture_id, oracle_root, file_count, min_includes, min_steps, triangles, quads) // Oracle: tri=N quad=M → rust triangles=N, quads=M @@ -1555,8 +1453,6 @@ mod tests { fixture.id, fixture.bytes, ParserProfile::Compatibility, - ReservationOwner::preview(78, 1, 1), - &ledger, ) .unwrap_or_else(|e| panic!("{fixture_id} should parse: {e}")); diff --git a/crates/polymodel-renderer-worker/src/admission.rs b/crates/polymodel-renderer-worker/src/admission.rs index b2e541c..40039b1 100644 --- a/crates/polymodel-renderer-worker/src/admission.rs +++ b/crates/polymodel-renderer-worker/src/admission.rs @@ -1,212 +1,4 @@ use polymodel_mesh::contract::ModelMesh; -use three_d_asset::{Geometry, Texture2D, TextureData}; - -const GPU_BUFFER_BYTES_PER_VERTEX: u64 = 48; -const GPU_BUFFER_BYTES_PER_TRIANGLE: u64 = 12; -const GPU_TEXTURE_OVERHEAD_BYTES: u64 = 256; -const SCENE_FIXED_BYTES: u64 = 16 * 1024; -pub const WASM_FIXED_BYTES: u64 = 2 * 65_536; - -fn add_bytes(total: &mut u64, bytes: u64) -> Result<(), String> { - *total = total - .checked_add(bytes) - .ok_or_else(|| "renderer charge arithmetic overflowed".to_string())?; - Ok(()) -} - -fn texture_format(data: &TextureData) -> TextureFormat { - let (channels, bytes_per_channel) = match data { - TextureData::RU8(_) => (1, 1), - TextureData::RgU8(_) => (2, 1), - TextureData::RgbU8(_) => (3, 1), - TextureData::RgbaU8(_) => (4, 1), - TextureData::RF16(_) => (1, 2), - TextureData::RgF16(_) => (2, 2), - TextureData::RgbF16(_) => (3, 2), - TextureData::RgbaF16(_) => (4, 2), - TextureData::RF32(_) => (1, 4), - TextureData::RgF32(_) => (2, 4), - TextureData::RgbF32(_) => (3, 4), - TextureData::RgbaF32(_) => (4, 4), - }; - TextureFormat { - block_width: 1, - block_height: 1, - bytes_per_block: channels * bytes_per_channel, - } -} - -fn texture_mip_count(texture: &Texture2D) -> u32 { - let mut levels = 1; - let mut dimension = texture.width.max(texture.height); - while dimension > 1 && levels < 64 { - dimension = dimension.div_ceil(2); - levels += 1; - } - texture - .mipmap - .map(|mipmap| mipmap.max_levels.clamp(1, levels)) - .unwrap_or(1) -} - -fn texture_input(texture: &Texture2D) -> TextureChargeInput { - TextureChargeInput { - format: texture_format(&texture.data), - width: u64::from(texture.width), - height: u64::from(texture.height), - mip_count: texture_mip_count(texture), - layers: 1, - faces: 1, - samples: 1, - } -} - -fn material_textures(model: &three_d_asset::Model) -> Vec<&Texture2D> { - let mut textures = Vec::new(); - for material in &model.materials { - textures.extend( - [ - material.albedo_texture.as_ref(), - material.occlusion_metallic_roughness_texture.as_ref(), - material.metallic_roughness_texture.as_ref(), - material.occlusion_texture.as_ref(), - material.normal_texture.as_ref(), - material.emissive_texture.as_ref(), - material.transmission_texture.as_ref(), - ] - .into_iter() - .flatten(), - ); - } - textures -} - -fn scene_cpu_bytes(model: &ModelMesh) -> Result { - let mut bytes = SCENE_FIXED_BYTES; - add_bytes(&mut bytes, model.model.name.len() as u64)?; - for primitive in &model.model.geometries { - add_bytes(&mut bytes, primitive.name.len() as u64 + 256)?; - match &primitive.geometry { - Geometry::Triangles(mesh) => { - add_bytes(&mut bytes, (mesh.positions.len() as u64).saturating_mul(12))?; - add_bytes( - &mut bytes, - mesh.normals.as_ref().map_or(0, |v| (v.len() as u64) * 12), - )?; - add_bytes( - &mut bytes, - mesh.tangents.as_ref().map_or(0, |v| (v.len() as u64) * 16), - )?; - add_bytes( - &mut bytes, - mesh.uvs.as_ref().map_or(0, |v| (v.len() as u64) * 8), - )?; - add_bytes( - &mut bytes, - mesh.colors.as_ref().map_or(0, |v| (v.len() as u64) * 16), - )?; - add_bytes(&mut bytes, mesh.indices.len().unwrap_or(0) as u64 * 4)?; - } - Geometry::Points(points) => { - add_bytes( - &mut bytes, - (points.positions.len() as u64).saturating_mul(12), - )?; - add_bytes( - &mut bytes, - points.colors.as_ref().map_or(0, |v| (v.len() as u64) * 16), - )?; - } - } - } - for material in &model.model.materials { - add_bytes(&mut bytes, material.name.len() as u64 + 512)?; - } - for texture in material_textures(&model.model) { - let data_bytes = match &texture.data { - TextureData::RU8(v) => v.len() as u64, - TextureData::RgU8(v) => v.len() as u64 * 2, - TextureData::RgbU8(v) => v.len() as u64 * 3, - TextureData::RgbaU8(v) => v.len() as u64 * 4, - TextureData::RF16(v) => v.len() as u64 * 2, - TextureData::RgF16(v) => v.len() as u64 * 4, - TextureData::RgbF16(v) => v.len() as u64 * 6, - TextureData::RgbaF16(v) => v.len() as u64 * 8, - TextureData::RF32(v) => v.len() as u64 * 4, - TextureData::RgF32(v) => v.len() as u64 * 8, - TextureData::RgbF32(v) => v.len() as u64 * 12, - TextureData::RgbaF32(v) => v.len() as u64 * 16, - }; - add_bytes(&mut bytes, data_bytes)?; - add_bytes(&mut bytes, texture.name.len() as u64)?; - } - Ok(bytes) -} - -fn gpu_buffer_requested(model: &ModelMesh) -> Result { - let mut bytes = 0; - add_bytes( - &mut bytes, - u64::from(model.vertex_count()) * GPU_BUFFER_BYTES_PER_VERTEX, - )?; - add_bytes( - &mut bytes, - u64::from(model.triangle_count()) * GPU_BUFFER_BYTES_PER_TRIANGLE, - )?; - gpu_buffer_charge(bytes).map_err(|error| format!("GPU buffer charge: {error}")) -} - -pub fn admit_scene( - ledger: &ReservationLedger, - owner: ReservationOwner, - model: &ModelMesh, -) -> Result<(CompositeReservation, Vec), String> { - let scene_bytes = scene_cpu_bytes(model)?; - let texture_inputs = material_textures(&model.model) - .into_iter() - .map(texture_input) - .collect::>(); - let mut decoded_texture_bytes = 0; - let mut gpu_texture_bytes = 0; - let mut textures = Vec::with_capacity(texture_inputs.len()); - for input in texture_inputs { - let decoded = - texture_base_bytes(input).map_err(|error| format!("texture base charge: {error}"))?; - let gpu = texture_charge(input) - .map_err(|error| format!("texture charge: {error}"))? - .checked_add(GPU_TEXTURE_OVERHEAD_BYTES) - .ok_or_else(|| "GPU texture charge overflowed".to_string())?; - add_bytes(&mut decoded_texture_bytes, decoded)?; - add_bytes(&mut gpu_texture_bytes, gpu)?; - textures.push(decoded); - } - let wasm_bytes = wasm_charge( - scene_bytes - .checked_add(decoded_texture_bytes) - .and_then(|bytes| bytes.checked_add(WASM_FIXED_BYTES)) - .ok_or_else(|| "WASM charge arithmetic overflowed".to_string())?, - ) - .map_err(|error| format!("WASM charge: {error}"))?; - let reservations = ledger - .composite( - owner, - &[ - (ResourceClass::SceneCpu, scene_bytes), - (ResourceClass::GpuBuffers, gpu_buffer_requested(model)?), - (ResourceClass::GpuTextures, gpu_texture_bytes), - (ResourceClass::WasmPages, wasm_bytes), - ], - ) - .map_err(|error| format!("scene admission: {error}"))?; - let mut texture_reservations = Vec::with_capacity(textures.len()); - for (texture_id, decoded_bytes) in textures.into_iter().enumerate() { - match ledger.reserve_texture(owner, decoded_bytes, texture_id as u64) { - Ok(reservation) => texture_reservations.push(reservation), - Err(error) => return Err(format!("texture admission: {error}")), - } - } - Ok((reservations, texture_reservations)) -} pub fn model_with_default_materials(model: &ModelMesh) -> three_d_asset::Model { let mut cpu_model = model.model.clone(); diff --git a/crates/polymodel-renderer-worker/src/bin/ldraw_preview.rs b/crates/polymodel-renderer-worker/src/bin/ldraw_preview.rs index fcd4599..3674690 100644 --- a/crates/polymodel-renderer-worker/src/bin/ldraw_preview.rs +++ b/crates/polymodel-renderer-worker/src/bin/ldraw_preview.rs @@ -27,10 +27,10 @@ use three_d::{ #[cfg(not(target_arch = "wasm32"))] use three_d_asset::ProjectionType; -#[cfg(not(target_arch = "wasm32"))] s +#[cfg(not(target_arch = "wasm32"))] use winit::{ event::{ - ElementState, Event, KeyboardInput, Modifiers sState, MouseButton, VirtualKeyCode, + ElementState, Event, KeyboardInput, ModifiersState, MouseButton, VirtualKeyCode, WindowEvent, }, event_loop::{ControlFlow, EventLoopBuilder}, diff --git a/crates/polymodel-renderer-worker/src/lib.rs b/crates/polymodel-renderer-worker/src/lib.rs index f02c174..eeef292 100644 --- a/crates/polymodel-renderer-worker/src/lib.rs +++ b/crates/polymodel-renderer-worker/src/lib.rs @@ -1685,11 +1685,8 @@ pub fn prepare_preview_scene( AdapterRequest, CancellationPolicy, InProcessRustAdapter, Materialization, NormalizedPath, ParserProfile, RootId, }; - use polymodel_renderer_ledger::{ReservationLedger, ReservationOwner}; - let bytes = std::fs::read(input).map_err(|error| format!("read {}: {error}", input.display()))?; - let ledger = ReservationLedger::new(); let logical_name = input .file_name() .and_then(std::ffi::OsStr::to_str) @@ -1722,8 +1719,6 @@ pub fn prepare_preview_scene( bytes: &bytes, profile: ParserProfile::Compatibility, provenance_id: logical_name, - owner: ReservationOwner::preview(79, 1, 1), - ledger: &ledger, semantic_budget: Some(64 * 1024 * 1024), root_name: logical_name, root: RootId::CurrentMpd, diff --git a/crates/polymodel-renderer-worker/src/worker.rs b/crates/polymodel-renderer-worker/src/worker.rs index a1a344c..bfe34b2 100644 --- a/crates/polymodel-renderer-worker/src/worker.rs +++ b/crates/polymodel-renderer-worker/src/worker.rs @@ -22,10 +22,6 @@ use polymodel_ldraw_core::{ }; use polymodel_mesh::contract::ModelMesh; use polymodel_mesh::parser::load_mesh_with_companions; -use polymodel_renderer_ledger::{ - CompositeReservation, Reservation, ReservationLedger, ReservationOwner, ResourceClass, - canvas_charge, -}; use polymodel_renderer_protocol::{ Capability, CommandPayload, EventEnvelope, EventPayload, HandshakeState, KeyModifiers, LoadError, LoadErrorCode, LoadEvent, LoadIdentity, LoadReducer, MeshFormat, MeshStats, @@ -35,9 +31,7 @@ use polymodel_renderer_protocol::{ use polymodel_renderer_worker::adapt_ldraw_parse_with_resources; use three_d_asset::InnerSpace as _; -use polymodel_renderer_worker::admission::{ - WASM_FIXED_BYTES, admit_scene, model_with_default_materials, -}; +use polymodel_renderer_worker::admission::model_with_default_materials; // --------------------------------------------------------------------------- // Allocator @@ -80,8 +74,6 @@ struct RendererState { camera: three_d::Camera, control: three_d::OrbitControl, scene_bounds: Option, - scene_reservations: Option, - texture_reservations: Vec, } struct PreviewAbortSlot { @@ -92,7 +84,6 @@ struct PreviewAbortSlot { struct PreviewTarget { canvas: web_sys::OffscreenCanvas, context: three_d::Context, - reservation: Reservation, } struct VerifiedCompoundSource { @@ -100,7 +91,6 @@ struct VerifiedCompoundSource { resources: Vec, source_identities: Vec, target_selections: Vec, - reservation: CompositeReservation, } fn descriptor_root(root: &str) -> Result { @@ -165,14 +155,11 @@ fn compound_materializations( fn parse_compound_source( source: VerifiedCompoundSource, - owner: polymodel_renderer_ledger::ReservationOwner, - ledger: &ReservationLedger, ) -> Result< ( polymodel_renderer_protocol::MeshStats, polymodel_renderer_protocol::scene::Scene, Vec, - CompositeReservation, ), String, > { @@ -198,8 +185,6 @@ fn parse_compound_source( bytes: &primary.bytes, profile: ParserProfile::Compatibility, provenance_id: &source.primary, - owner, - ledger, semantic_budget: Some(64 * 1024 * 1024), root_name: &source.primary, root: primary_root, @@ -214,7 +199,7 @@ fn parse_compound_source( vertices: scene.stats.points.min(u64::from(u32::MAX)) as u32, triangles: scene.stats.triangles.min(u64::from(u32::MAX)) as u32, }; - Ok((stats, scene, source.resources, source.reservation)) + Ok((stats, scene, source.resources)) } const WORKER_ID: u64 = 1; @@ -228,29 +213,6 @@ fn next_generation(current: u32) -> Result { .ok_or("renderer generation exhausted; restart the worker") } -fn owner(load_epoch: u32, scene_generation: u32) -> ReservationOwner { - ReservationOwner::interactive( - WORKER_ID, - u64::from(load_epoch), - u64::from(scene_generation), - ) -} - -fn preview_owner(identity: LoadIdentity) -> ReservationOwner { - ReservationOwner::preview( - WORKER_ID, - u64::from(identity.load_epoch), - u64::from(identity.scene_generation), - ) -} - -fn load_owner(namespace: RendererNamespace, identity: LoadIdentity) -> ReservationOwner { - match namespace { - RendererNamespace::Interactive => owner(identity.load_epoch, identity.scene_generation), - RendererNamespace::Preview => preview_owner(identity), - } -} - struct WorkerState { scope: DedicatedWorkerGlobalScope, canvas: Option, @@ -272,8 +234,6 @@ struct WorkerState { raf_id: Option, raf_retry_count: u8, raf_closure: Option>, - ledger: ReservationLedger, - canvas_reservation: Option, load_epoch: u32, scene_generation: u32, interactive_compound_abort: Option, @@ -302,8 +262,6 @@ impl WorkerState { raf_id: None, raf_retry_count: 0, raf_closure: None, - ledger: ReservationLedger::new(), - canvas_reservation: None, load_epoch: 0, scene_generation: 0, interactive_compound_abort: None, @@ -389,9 +347,6 @@ impl WorkerState { .map(|slot| slot.controller.abort()); self.pending_scene = None; self.renderer.take(); - self.ledger - .retire(owner(self.load_epoch, self.scene_generation)); - self.canvas_reservation.take(); if let Some(id) = self.raf_id.take() { let _ = self.scope.cancel_animation_frame(id); } @@ -412,36 +367,6 @@ impl WorkerState { fn init_renderer(&mut self, canvas: web_sys::OffscreenCanvas, state: Rc>) { tracing::info!("renderer worker: initializing WebGL2 renderer"); - let owner = owner(self.load_epoch, self.scene_generation); - let canvas_bytes = match canvas_charge( - u64::from(self.pixel_width), - u64::from(self.pixel_height), - INITIAL_CANVAS_ATTACHMENTS, - INITIAL_CANVAS_SAMPLES, - ) { - Ok(bytes) => bytes, - Err(error) => { - self.post_event(&RendererEvent::Error { - fatal: true, - message: format!("canvas admission formula: {error}"), - }); - return; - } - }; - let canvas_reservation = - match self - .ledger - .reserve(owner, ResourceClass::CanvasBackbuffers, canvas_bytes) - { - Ok(reservation) => reservation, - Err(error) => { - self.post_event(&RendererEvent::Error { - fatal: true, - message: format!("canvas admission: {error}"), - }); - return; - } - }; let opts = js_sys::Object::new(); let _ = js_sys::Reflect::set(&opts, &"desynchronized".into(), &JsValue::from_bool(true)); @@ -542,11 +467,7 @@ impl WorkerState { camera, control, scene_bounds: None, - scene_reservations: None, - texture_reservations: Vec::new(), }); - self.canvas_reservation = Some(canvas_reservation); - tracing::debug!("renderer canvas admission committed"); self.post_event(&RendererEvent::ContextAcquired); self.post_event(&RendererEvent::RendererContextReady); tracing::info!("renderer worker: renderer context ready"); @@ -746,14 +667,9 @@ mod tests { }, target: child_key, }], - reservation: ReservationLedger::new() - .composite(ReservationOwner::preview(79, 1, 1), &[]) - .expect("empty test reservation should be admitted"), }; - let ledger = ReservationLedger::new(); - let (_stats, scene, _resources, _reservation) = - parse_compound_source(source, ReservationOwner::preview(79, 1, 1), &ledger) - .expect("uploaded-root MPD selections should materialize"); + let (_stats, scene, _resources) = + parse_compound_source(source).expect("uploaded-root MPD selections should materialize"); assert_eq!(scene.stats.triangles, 1); assert!(scene.bounds.is_some()); } @@ -987,22 +903,7 @@ mod tests { } } -fn create_preview_target( - ledger: &ReservationLedger, - owner: ReservationOwner, - width: u32, - height: u32, -) -> Result { - let canvas_bytes = canvas_charge( - u64::from(width), - u64::from(height), - INITIAL_CANVAS_ATTACHMENTS, - INITIAL_CANVAS_SAMPLES, - ) - .map_err(|error| format!("preview canvas admission formula: {error}"))?; - let reservation = ledger - .reserve(owner, ResourceClass::CanvasBackbuffers, canvas_bytes) - .map_err(|error| format!("preview canvas admission: {error}"))?; +fn create_preview_target(width: u32, height: u32) -> Result { let canvas = web_sys::OffscreenCanvas::new(width, height) .map_err(|error| format!("preview canvas: {error:?}"))?; let options = js_sys::Object::new(); @@ -1021,11 +922,7 @@ fn create_preview_target( let glow_context = three_d::context::Context::from_webgl2_context(gl); let context = three_d::Context::from_gl_context(Arc::new(glow_context)) .map_err(|error| format!("preview three-d context: {error}"))?; - Ok(PreviewTarget { - canvas, - context, - reservation, - }) + Ok(PreviewTarget { canvas, context }) } fn standard_lights( @@ -1378,55 +1275,6 @@ fn handle_load_mesh( let load_epoch = identity.load_epoch; let scene_generation = state.borrow().scene_generation; spawn_local(async move { - let load_reservations = { - let st = state_clone.borrow(); - let owner = owner(load_epoch, scene_generation); - st.ledger.composite( - owner, - &[ - ( - ResourceClass::NetworkInFlight, - expected_size - .and_then(|size| u64::try_from(size).ok()) - .unwrap_or(8 * 1024 * 1024), - ), - ( - ResourceClass::RetainedFetchedBytes, - expected_size - .and_then(|size| u64::try_from(size).ok()) - .unwrap_or(8 * 1024 * 1024), - ), - (ResourceClass::DecodedSourceData, 8 * 1024 * 1024), - (ResourceClass::WasmPages, 2 * 65_536), - ], - ) - }; - let Ok(_load_reservations) = load_reservations else { - if let Ok(mut st) = state_clone.try_borrow_mut() { - let error = LoadError { - code: LoadErrorCode::Renderer, - detail: "renderer admission rejected mesh load".into(), - }; - let result = st.load_reducer.reduce(LoadEvent::LoadFailed { - namespace, - identity, - error: error.clone(), - candidate: None, - }); - if matches!( - result.outcome, - polymodel_renderer_protocol::TransitionOutcome::Committed - ) { - st.post_event(&RendererEvent::LoadFailed { - namespace, - identity, - code: error.code, - detail: error.detail, - }); - } - } - return; - }; let result = load_mesh_async_with_verification( &primary_url, format, @@ -1513,35 +1361,9 @@ fn handle_load_mesh( return; } }; - let scene_owner = owner(st.load_epoch, st.scene_generation); - let (scene_reservations, texture_reservations) = - match admit_scene(&st.ledger, scene_owner, &model) { - Ok(reservations) => reservations, - Err(detail) => { - let error = LoadError { - code: LoadErrorCode::Install, - detail, - }; - st.load_reducer.reduce(LoadEvent::InstallFailed { - namespace, - identity, - error: error.clone(), - candidate: None, - }); - st.post_event(&RendererEvent::LoadFailed { - namespace, - identity, - code: error.code, - detail: error.detail, - }); - return; - } - }; let candidate = match build_scene(&context, &model, pw, ph) { Ok(candidate) => candidate, Err(detail) => { - drop(scene_reservations); - drop(texture_reservations); let error = LoadError { code: LoadErrorCode::Install, detail: detail.clone(), @@ -1587,8 +1409,6 @@ fn handle_load_mesh( renderer.scene_bounds = None; renderer.camera = camera; renderer.control = control; - renderer.scene_reservations = Some(scene_reservations); - renderer.texture_reservations = texture_reservations; } } st.needs_render = true; @@ -1912,15 +1732,12 @@ async fn render_compound_preview_request( ) .await?; compound_is_current(state, RendererNamespace::Preview, identity, abort.as_ref())?; - let owner = preview_owner(identity); - let ledger = state.borrow().ledger.clone(); - let (_stats, scene, source_resources, source_reservation) = - parse_compound_source(source, owner, &ledger)?; + let (_stats, scene, source_resources) = parse_compound_source(source)?; compound_is_current(state, RendererNamespace::Preview, identity, abort.as_ref())?; let bounds = scene .bounds .ok_or_else(|| "LDraw scene has no bounds".to_owned())?; - let target = create_preview_target(&ledger, owner, width, height)?; + let target = create_preview_target(width, height)?; let scene = Rc::new(scene); let style = polymodel_renderer_worker::RenderStyle::Faces; let (static_model, (_explicit, _conditional), _picker, _plan) = @@ -1931,7 +1748,6 @@ async fn render_compound_preview_request( style, Some(&source_resources), )?; - drop(source_reservation); compound_is_current(state, RendererNamespace::Preview, identity, abort.as_ref())?; let fit = polymodel_renderer_worker::scene_camera_fit(bounds, width, height) .map_err(|error| error.to_string())?; @@ -1956,7 +1772,6 @@ async fn render_compound_preview_request( screen.render(&camera, static_model.iter(), &lights); compound_is_current(state, RendererNamespace::Preview, identity, abort.as_ref())?; let png = offscreen_canvas_png_bytes(&target.canvas).await?; - drop(target.reservation); Ok(png) } @@ -2037,33 +1852,19 @@ async fn load_compound_source( if total_bytes > MAX_UNKNOWN_FETCH_BYTES { return Err("model bundle exceeds decoded source bound".into()); } - let reservation = { - let st = state.borrow(); - st.ledger - .composite( - load_owner(namespace, identity), - &[ - (ResourceClass::RetainedFetchedBytes, total_bytes), - (ResourceClass::DecodedSourceData, total_bytes), - (ResourceClass::WasmPages, WASM_FIXED_BYTES), - ], - ) - .map_err(|error| format!("model bundle admission: {error}"))? - }; compound_is_current(state, namespace, identity, abort.as_ref())?; let source = VerifiedCompoundSource { primary: bundle.primary, resources: bundle.resources, source_identities: bundle.source_identities, target_selections: bundle.target_selections, - reservation, }; tracing::debug!( ?namespace, ?identity, primary = %source.primary, resources = source.resources.len(), - "renderer worker: compound bundle admitted" + "renderer worker: compound bundle accepted" ); Ok(source) } @@ -2125,60 +1926,58 @@ fn finish_compound_source( if st.disposed || reducer.current_identity() != Some(identity) { return; } - let parse_owner = load_owner(namespace, identity); tracing::debug!( ?namespace, ?identity, "renderer worker: parsing compound bundle" ); - let (stats, scene, source_resources, _source_reservation) = - match parse_compound_source(source, parse_owner, &st.ledger) { - Ok((stats, scene, source_resources, source_reservation)) => { - tracing::info!( - ?namespace, - ?identity, - vertices = stats.vertices, - triangles = stats.triangles, - has_bounds = scene.bounds.is_some(), - "renderer worker: compound parse succeeded" - ); - (stats, scene, source_resources, source_reservation) - } - Err(detail) => { - tracing::error!( - ?namespace, - ?identity, - error = %detail, - "renderer worker: compound parse failed" - ); - let error = LoadError { - code: LoadErrorCode::Parse, - detail: detail.clone(), - }; - let reducer = match namespace { - RendererNamespace::Interactive => &mut st.load_reducer, - RendererNamespace::Preview => &mut st.preview_reducer, - }; - let transition = reducer.reduce(LoadEvent::LoadFailed { + let (stats, scene, source_resources) = match parse_compound_source(source) { + Ok((stats, scene, source_resources)) => { + tracing::info!( + ?namespace, + ?identity, + vertices = stats.vertices, + triangles = stats.triangles, + has_bounds = scene.bounds.is_some(), + "renderer worker: compound parse succeeded" + ); + (stats, scene, source_resources) + } + Err(detail) => { + tracing::error!( + ?namespace, + ?identity, + error = %detail, + "renderer worker: compound parse failed" + ); + let error = LoadError { + code: LoadErrorCode::Parse, + detail: detail.clone(), + }; + let reducer = match namespace { + RendererNamespace::Interactive => &mut st.load_reducer, + RendererNamespace::Preview => &mut st.preview_reducer, + }; + let transition = reducer.reduce(LoadEvent::LoadFailed { + namespace, + identity, + error, + candidate: None, + }); + if matches!( + transition.outcome, + polymodel_renderer_protocol::TransitionOutcome::Committed + ) { + st.post_event(&RendererEvent::LoadFailed { namespace, identity, - error, - candidate: None, + code: LoadErrorCode::Parse, + detail, }); - if matches!( - transition.outcome, - polymodel_renderer_protocol::TransitionOutcome::Committed - ) { - st.post_event(&RendererEvent::LoadFailed { - namespace, - identity, - code: LoadErrorCode::Parse, - detail, - }); - } - return; } - }; + return; + } + }; let reducer = match namespace { RendererNamespace::Interactive => &mut st.load_reducer, RendererNamespace::Preview => &mut st.preview_reducer, @@ -2440,32 +2239,16 @@ async fn render_preview_request( height: u32, abort: Option, ) -> Result, String> { - let owner = preview_owner(identity); let fetch_bytes = MAX_UNKNOWN_FETCH_BYTES.min( u64::from(width) .saturating_mul(u64::from(height)) .saturating_mul(16) .max(8 * 1024 * 1024), ); - let reservation = { - let st = state.borrow(); - st.ledger - .composite( - owner, - &[ - (ResourceClass::NetworkInFlight, fetch_bytes), - (ResourceClass::RetainedFetchedBytes, fetch_bytes), - (ResourceClass::DecodedSourceData, fetch_bytes), - (ResourceClass::WasmPages, WASM_FIXED_BYTES), - ], - ) - .map_err(|error| format!("preview admission: {error}"))? - }; if abort .as_ref() .is_some_and(|controller| controller.signal().aborted()) { - drop(reservation); return Err("preview load cancelled".into()); } let model = @@ -2474,21 +2257,9 @@ async fn render_preview_request( .as_ref() .is_some_and(|controller| controller.signal().aborted()) { - drop(reservation); return Err("preview load cancelled".into()); } - let ledger = state.borrow().ledger.clone(); - let png = render_preview_png( - &model, - width, - height, - &ledger, - identity.load_epoch, - identity.scene_generation, - ) - .await; - drop(reservation); - png + render_preview_png(&model, width, height).await } async fn load_mesh_async_with_abort( @@ -2528,21 +2299,8 @@ async fn load_mesh_async_with_abort( Ok(model) } -async fn render_preview_png( - model: &ModelMesh, - width: u32, - height: u32, - ledger: &ReservationLedger, - load_epoch: u32, - scene_generation: u32, -) -> Result, String> { - let preview_owner = ReservationOwner::preview( - WORKER_ID, - u64::from(load_epoch), - u64::from(scene_generation), - ); - let target = create_preview_target(ledger, preview_owner, width, height)?; - let (scene_reservations, texture_reservations) = admit_scene(ledger, preview_owner, model)?; +async fn render_preview_png(model: &ModelMesh, width: u32, height: u32) -> Result, String> { + let target = create_preview_target(width, height)?; let (model, camera, _control) = build_scene(&target.context, model, width, height)?; let (ambient_light, key_light, fill_light) = standard_lights(&target.context); let screen = three_d::RenderTarget::screen(&target.context, width, height); @@ -2556,11 +2314,7 @@ async fn render_preview_png( &[&ambient_light, &key_light, &fill_light], ); - let png = offscreen_canvas_png_bytes(&target.canvas).await; - drop(texture_reservations); - drop(scene_reservations); - drop(target.reservation); - png + offscreen_canvas_png_bytes(&target.canvas).await } async fn offscreen_canvas_png_bytes(canvas: &web_sys::OffscreenCanvas) -> Result, String> { @@ -2952,38 +2706,13 @@ fn handle_command(state: &Rc>, cmd: RendererCommand) { } let w = (css_w * dpr).round().max(1.0) as u32; let h = (css_h * dpr).round().max(1.0) as u32; - let next_bytes = match canvas_charge( - u64::from(w), - u64::from(h), - INITIAL_CANVAS_ATTACHMENTS, - INITIAL_CANVAS_SAMPLES, - ) { - Ok(bytes) => bytes, - Err(error) => { - tracing::warn!("resize canvas formula rejected: {error}"); - return; - } - }; - let next = match st.ledger.reserve( - owner(st.load_epoch, st.scene_generation), - ResourceClass::CanvasBackbuffers, - next_bytes, - ) { - Ok(reservation) => reservation, - Err(error) => { - tracing::warn!("resize admission rejected: {error}"); - return; - } - }; + if let Some(canvas) = &st.canvas { canvas.set_width(w); canvas.set_height(h); } st.pixel_width = w; st.pixel_height = h; - if let Some(old) = st.canvas_reservation.replace(next) { - old.release(); - } st.needs_render = true; } RendererCommand::SetPointerState { diff --git a/crates/polymodel-renderer-worker/tests/ldraw_preview.rs b/crates/polymodel-renderer-worker/tests/ldraw_preview.rs index e050126..40838f5 100644 --- a/crates/polymodel-renderer-worker/tests/ldraw_preview.rs +++ b/crates/polymodel-renderer-worker/tests/ldraw_preview.rs @@ -9,7 +9,6 @@ use polymodel_ldraw_core::{ AdapterRequest, CancellationPolicy, InProcessRustAdapter, Materialization, NormalizedPath, ParserProfile, RootId, }; -use polymodel_renderer_ledger::{ReservationLedger, ReservationOwner}; use polymodel_renderer_worker::{ LdrawLightingMaterialPolicy, adapt_ldraw_parse, official_materializations, preview_limits, scene_instance_batches, scene_mesh_topology, @@ -41,15 +40,12 @@ fn isolated_plate() -> IsolatedPlate { ); let plate_key = plate.key(); materializations.insert(0, plate); - let ledger = ReservationLedger::new(); let result = InProcessRustAdapter::parse_with_limits( AdapterRequest { fixture_id: "3021.dat", bytes: &bytes, profile: ParserProfile::Compatibility, provenance_id: "official-3021.dat", - owner: ReservationOwner::preview(79, 3021, 1), - ledger: &ledger, semantic_budget: Some(8 * 1024 * 1024), root_name: PLATE_2_X_3, root: RootId::OfficialLibrary, @@ -204,15 +200,12 @@ fn assert_official_subpart_identity(part: &str, authored_target: &str, physical_ Some("official-ldraw-library".into()), ), ); - let ledger = ReservationLedger::new(); let result = InProcessRustAdapter::parse_with_limits( AdapterRequest { fixture_id: part, bytes: &bytes, profile: ParserProfile::Compatibility, provenance_id: part, - owner: ReservationOwner::preview(79, 2431, 1), - ledger: &ledger, semantic_budget: Some(64 * 1024 * 1024), root_name: part, root: RootId::OfficialLibrary, @@ -374,7 +367,6 @@ fn pinned_scene() -> polymodel_renderer_protocol::scene::Scene { Some("pinned-omr".into()), ); materializations.insert(0, materialization); - let ledger = ReservationLedger::new(); eprintln!("[ldraw-preview-test] parsing pinned OMR"); let result = InProcessRustAdapter::parse_with_limits( AdapterRequest { @@ -382,8 +374,6 @@ fn pinned_scene() -> polymodel_renderer_protocol::scene::Scene { bytes: &bytes, profile: ParserProfile::Compatibility, provenance_id: "omr-10030-1.mpd", - owner: ReservationOwner::preview(79, 1, 1), - ledger: &ledger, semantic_budget: Some(64 * 1024 * 1024), root_name: "omr-10030-1.mpd", root: RootId::CurrentMpd, diff --git a/justfile b/justfile index e898ed0..d051084 100644 --- a/justfile +++ b/justfile @@ -53,10 +53,6 @@ check-devshell-tools-only: test-server: @tools/in-dev-shell _test-server -# Run focused std-only ledger tests, wasm compilation, and its dependency-tree proof. -test-renderer-ledger: - @tools/in-dev-shell _test-renderer-ledger - # Run browser-backed wasm tests for the renderer worker. test-renderer: @tools/in-dev-shell _test-renderer @@ -217,12 +213,6 @@ _test: _test-server: cargo nextest run -p polymodel --features server -_test-renderer-ledger: - cargo test -p polymodel-renderer-ledger - cargo check -p polymodel-renderer-ledger --target wasm32-unknown-unknown - @cargo tree -p polymodel-renderer-ledger --target wasm32-unknown-unknown --edges normal - @if cargo tree -p polymodel-renderer-ledger --target wasm32-unknown-unknown --edges normal | grep -qE 'three-d|three-d-asset|stl_io|polymodel-mesh|polymodel-renderer-protocol|web-sys|wasm-bindgen'; then echo "FAIL: forbidden ledger dependency found"; exit 1; else echo "PASS: std-only ledger dependency tree"; fi - _test-renderer: RUSTFLAGS='--cfg getrandom_backend="wasm_js"' cargo test -p polymodel-renderer-worker --target wasm32-unknown-unknown @@ -294,7 +284,7 @@ _require-nix: _ldraw-differential: _require-nix cargo run --manifest-path tools/ldraw-compat-harness/Cargo.toml -- differential -_test-all: _require-nix _fix _check _lint _test _test-server _test-renderer-ledger _test-renderer _test-ldraw-core _ldraw-wasm-check _test-renderer-native +_test-all: _require-nix _fix _check _lint _test _test-server _test-renderer _test-ldraw-core _ldraw-wasm-check _test-renderer-native _e2e: cd e2e && npm test diff --git a/tools/ldraw-compat-harness/Cargo.lock b/tools/ldraw-compat-harness/Cargo.lock deleted file mode 100644 index 5e7daea..0000000 --- a/tools/ldraw-compat-harness/Cargo.lock +++ /dev/null @@ -1,576 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 4 - -[[package]] -name = "atomic-polyfill" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8cf2bce30dfe09ef0bfaef228b9d414faaf7e563035494d7fe092dba54b300f4" -dependencies = [ - "critical-section", -] - -[[package]] -name = "base64" -version = "0.22.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" - -[[package]] -name = "block-buffer" -version = "0.10.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" -dependencies = [ - "generic-array", -] - -[[package]] -name = "borsh" -version = "1.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a88b7ea17d208c4193f2c1e6de3c35fe71f98c96982d5ced308bdcc749ff6e1f" -dependencies = [ - "bytes", - "cfg_aliases", -] - -[[package]] -name = "bumpalo" -version = "3.20.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72f5acc6cb2ba439de613abc23857ec3d78374d8ed5ac84e9d11336e87da8649" - -[[package]] -name = "byteorder" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" - -[[package]] -name = "bytes" -version = "1.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc652a48c352aef3ea3aed32080501cf3ef6ed5da78602a020c991775b0aff04" - -[[package]] -name = "cfg-if" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" - -[[package]] -name = "cfg_aliases" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f079e83a288787bcd14a6aea84cee5c87a67c5a3e660c30f557a3d24761b3527" - -[[package]] -name = "cobs" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fa961b519f0b462e3a3b4a34b64d119eeaca1d59af726fe450bbba07a9fc0a1" -dependencies = [ - "thiserror", -] - -[[package]] -name = "cpufeatures" -version = "0.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" -dependencies = [ - "libc", -] - -[[package]] -name = "critical-section" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "790eea4361631c5e7d22598ecd5723ff611904e3344ce8720784c93e3d83d40b" - -[[package]] -name = "crypto-common" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a" -dependencies = [ - "generic-array", - "typenum", -] - -[[package]] -name = "digest" -version = "0.10.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" -dependencies = [ - "block-buffer", - "crypto-common", -] - -[[package]] -name = "embedded-io" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef1a6892d9eef45c8fa6b9e0086428a2cca8491aca8f787c534a3d6d0bcb3ced" - -[[package]] -name = "embedded-io" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edd0f118536f44f5ccd48bcb8b111bdc3de888b58c74639dfb034a357d0f206d" - -[[package]] -name = "futures-core" -version = "0.3.33" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2cd50c473c80f6d7c3670a752354b8e569b1a7cbfdc0419ec88e5edad85e0dc7" - -[[package]] -name = "futures-task" -version = "0.3.33" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b231ed28831efb4a61a08580c4bc233ec56bc009f4cd8f52da2c3cb97df0c109" - -[[package]] -name = "futures-util" -version = "0.3.33" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a77a90a256fce34da66415271e30f94ee91c57b04b8a2c042d9cf3220179deaa" -dependencies = [ - "futures-core", - "futures-task", - "pin-project-lite", - "slab", -] - -[[package]] -name = "generic-array" -version = "0.14.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" -dependencies = [ - "typenum", - "version_check", -] - -[[package]] -name = "hash32" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0c35f58762feb77d74ebe43bdbc3210f09be9fe6742234d573bacc26ed92b67" -dependencies = [ - "byteorder", -] - -[[package]] -name = "heapless" -version = "0.7.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdc6457c0eb62c71aac4bc17216026d8410337c4126773b9c5daba343f17964f" -dependencies = [ - "atomic-polyfill", - "hash32", - "rustc_version", - "serde", - "spin", - "stable_deref_trait", -] - -[[package]] -name = "itoa" -version = "1.0.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" - -[[package]] -name = "js-sys" -version = "0.3.103" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53b44bfcdb3f8d5837a46dae1ca9660a837176eee74a28b229bc626816589102" -dependencies = [ - "cfg-if", - "futures-util", - "wasm-bindgen", -] - -[[package]] -name = "ldraw-compat-harness" -version = "0.1.0" -dependencies = [ - "polymodel-ldraw-core", - "polymodel-ldraw-testkit", - "polymodel-renderer-ledger", - "serde", - "serde_json", - "sha2", - "thiserror", -] - -[[package]] -name = "libc" -version = "0.2.189" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3eaf3ede3fee6db1a4c2ee091bf8a8b4dccdc6d17f656fb07896ee72867612f2" - -[[package]] -name = "lock_api" -version = "0.4.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965" -dependencies = [ - "scopeguard", -] - -[[package]] -name = "memchr" -version = "2.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf8baf1c55e62ffcace7a9f06f4bd9cd3f0c4beb022d3b367256b91b87513d98" - -[[package]] -name = "miette" -version = "7.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f98efec8807c63c752b5bd61f862c165c115b0a35685bdcfd9238c7aeb592b7" -dependencies = [ - "cfg-if", - "miette-derive", - "unicode-width", -] - -[[package]] -name = "miette-derive" -version = "7.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db5b29714e950dbb20d5e6f74f9dcec4edbcc1067bb7f8ed198c097b8c1a818b" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.119", -] - -[[package]] -name = "once_cell" -version = "1.21.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" - -[[package]] -name = "pin-project-lite" -version = "0.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" - -[[package]] -name = "polymodel-ldraw-core" -version = "0.1.0" -dependencies = [ - "base64", - "miette", - "polymodel-renderer-ledger", - "polymodel-renderer-protocol", - "serde", - "sha2", - "smol_str", - "thiserror", - "web-time", -] - -[[package]] -name = "polymodel-ldraw-testkit" -version = "0.1.0" -dependencies = [ - "polymodel-ldraw-core", - "serde", - "serde_json", - "sha2", - "thiserror", -] - -[[package]] -name = "polymodel-renderer-ledger" -version = "0.1.0" - -[[package]] -name = "polymodel-renderer-protocol" -version = "0.1.0" -dependencies = [ - "postcard", - "serde", - "sha2", - "smol_str", - "thiserror", -] - -[[package]] -name = "postcard" -version = "1.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6764c3b5dd454e283a30e6dfe78e9b31096d9e32036b5d1eaac7a6119ccb9a24" -dependencies = [ - "cobs", - "embedded-io 0.4.0", - "embedded-io 0.6.1", - "heapless", - "serde", -] - -[[package]] -name = "proc-macro2" -version = "1.0.107" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "985e7ec9bb745e6ce6535b544d84d6cd6f7ad8bd711c398938ae983b91a766d9" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "quote" -version = "1.0.47" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fbf4db142a473a8d80c26bbf18454ed458bf8d26c8219c331daecfdbd079001" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "rustc_version" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" -dependencies = [ - "semver", -] - -[[package]] -name = "rustversion" -version = "1.0.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf54715a573b99ac80df0bc206da022bcd442c974952c7b9720069370852e21f" - -[[package]] -name = "scopeguard" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" - -[[package]] -name = "semver" -version = "1.0.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd" - -[[package]] -name = "serde" -version = "1.0.229" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4148590afebada386688f18773da617792bf2ef03ffc1e4cbd2b1d45b023e0ba" -dependencies = [ - "serde_core", - "serde_derive", -] - -[[package]] -name = "serde_core" -version = "1.0.229" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67dca2c9c51e58a4791a4b1ed58308b39c64224d349a935ab5039aa360942a48" -dependencies = [ - "serde_derive", -] - -[[package]] -name = "serde_derive" -version = "1.0.229" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7a5d71263a5a7d47b41f6b3f06ba276f10cc18b0931f1799f710578e2309348" -dependencies = [ - "proc-macro2", - "quote", - "syn 3.0.3", -] - -[[package]] -name = "serde_json" -version = "1.0.151" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c841b55ecdae098c80dcae9cf767f6f8a0c2cdb3416bbef72181df4d0fe73f14" -dependencies = [ - "itoa", - "memchr", - "serde", - "serde_core", - "zmij", -] - -[[package]] -name = "sha2" -version = "0.10.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" -dependencies = [ - "cfg-if", - "cpufeatures", - "digest", -] - -[[package]] -name = "slab" -version = "0.4.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" - -[[package]] -name = "smol_str" -version = "0.3.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4aaa7368fcf4852a4c2dd92df0cace6a71f2091ca0a23391ce7f3a31833f1523" -dependencies = [ - "borsh", - "serde_core", -] - -[[package]] -name = "spin" -version = "0.9.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3763264f6b73151db08c50ff20d7d8a0b8796e021cdea7ceedad07b80155fa0e" -dependencies = [ - "lock_api", -] - -[[package]] -name = "stable_deref_trait" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" - -[[package]] -name = "syn" -version = "2.0.119" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "872831b642d1a07999a962a351ed35b955ea2cfc8f3862091e2a240a84f17297" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "syn" -version = "3.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53e9bae58849f64dfa4f5d5ae372c8341f7305f82a3868709269343628b659a3" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "thiserror" -version = "2.0.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09a43598840e33d5b0331f38c5e30d13bb11c11210a4b58f0d9b18a5a5eefcd9" -dependencies = [ - "thiserror-impl", -] - -[[package]] -name = "thiserror-impl" -version = "2.0.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43cbfe0cf76104d42a574802844187e84a305e531ed54455f11fbde0f10541cd" -dependencies = [ - "proc-macro2", - "quote", - "syn 3.0.3", -] - -[[package]] -name = "typenum" -version = "1.20.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6f5e870be6c3b371b77fe0ee0bafb859fa4964b4404c27de1d380043c4dda20" - -[[package]] -name = "unicode-ident" -version = "1.0.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" - -[[package]] -name = "unicode-width" -version = "0.1.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" - -[[package]] -name = "version_check" -version = "0.9.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" - -[[package]] -name = "wasm-bindgen" -version = "0.2.126" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b067c0c11094aef6b7a801c1e34a26affafdf3d051dba08456b868789aaf9a4" -dependencies = [ - "cfg-if", - "once_cell", - "rustversion", - "wasm-bindgen-macro", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-macro" -version = "0.2.126" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "167ce5e579f6bcf889c4f7175a8a5a585de84e8ff93976ce393efa5f2837aab1" -dependencies = [ - "quote", - "wasm-bindgen-macro-support", -] - -[[package]] -name = "wasm-bindgen-macro-support" -version = "0.2.126" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3997c7839262f4ef12cf90b818d6340c18e80f263f1a94bf157d0ec4420380e" -dependencies = [ - "bumpalo", - "proc-macro2", - "quote", - "syn 2.0.119", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-shared" -version = "0.2.126" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc1b4cb0cc549fcf58d7dfc081778139b3d283a081644e833e84682ad71cea24" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "web-time" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" -dependencies = [ - "js-sys", - "wasm-bindgen", -] - -[[package]] -name = "zmij" -version = "1.0.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29666d0abbfad1e3dc4dcf6144730dd3a3ab225bbbdac83319345b1b44ccfc1b" diff --git a/tools/ldraw-compat-harness/Cargo.toml b/tools/ldraw-compat-harness/Cargo.toml index 6f0c4dd..b1c4d40 100644 --- a/tools/ldraw-compat-harness/Cargo.toml +++ b/tools/ldraw-compat-harness/Cargo.toml @@ -11,7 +11,6 @@ description = "Native offline PM-77 corpus, fuzz, and LDParse compatibility harn [dependencies] polymodel-ldraw-core = { path = "../../crates/polymodel-ldraw-core" } polymodel-ldraw-testkit = { path = "../../crates/polymodel-ldraw-testkit" } -polymodel-renderer-ledger = { path = "../../crates/polymodel-renderer-ledger" } serde = { version = "1.0", features = ["derive"] } serde_json = "1" sha2 = "0.10" diff --git a/tools/ldraw-compat-harness/src/main.rs b/tools/ldraw-compat-harness/src/main.rs index 3b36b62..b7a255f 100644 --- a/tools/ldraw-compat-harness/src/main.rs +++ b/tools/ldraw-compat-harness/src/main.rs @@ -9,7 +9,6 @@ use polymodel_ldraw_testkit::{ CANDIDATE_OBSERVATION_SCHEMA_VERSION, Profile, SCHEMA_VERSION, coverage_report, inventory, named_gates, validate_inventory, }; -use polymodel_renderer_ledger::{ReservationLedger, ReservationOwner}; use serde::{Deserialize, Serialize}; use sha2::{Digest, Sha256}; use std::{ @@ -222,8 +221,7 @@ fn corpus() -> Result { .validate_inventory(&fixtures) .map_err(|error| error.to_string())?; let mut evaluated = 0usize; - for (index, fixture) in fixtures.iter().enumerate() { - let ledger = ReservationLedger::new(); + for fixture in &fixtures { let parsed = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| { if fixture.outcome == polymodel_ldraw_testkit::ExpectedOutcome::Cancelled { let cancellation = CancellationPolicy::new(); @@ -233,8 +231,6 @@ fn corpus() -> Result { bytes: fixture.bytes, profile: core_profile(fixture.profile), provenance_id: fixture.id, - owner: ReservationOwner::preview(78, index as u64 + 1, 1), - ledger: &ledger, semantic_budget: Some(16 * 1024 * 1024), root_name: fixture.id, root: RootId::UploadedManifest, @@ -245,8 +241,6 @@ fn corpus() -> Result { } else { parse_fixture_with_root( fixture, - ReservationOwner::preview(78, index as u64 + 1, 1), - &ledger, ) } })) @@ -281,9 +275,6 @@ fn corpus() -> Result { } (_, Err(error)) => return Err(format!("{} unexpectedly rejected: {error}", fixture.id)), } - if ledger.snapshot().reservations != 0 { - return Err(format!("{} leaked parser reservations", fixture.id)); - } } Ok(serde_json::json!({ "schema_version": SCHEMA_VERSION, @@ -768,18 +759,14 @@ fn fixture_root_name(fixture: &polymodel_ldraw_testkit::FixtureCase) -> &str { .expect("fixture relative path must have a UTF-8 filename") } -fn parse_fixture_with_root<'a>( - fixture: &'a polymodel_ldraw_testkit::FixtureCase, - owner: ReservationOwner, - ledger: &'a ReservationLedger, +fn parse_fixture_with_root( + fixture: &polymodel_ldraw_testkit::FixtureCase, ) -> Result { InProcessRustAdapter::parse(AdapterRequest { fixture_id: fixture.id, bytes: fixture.bytes, profile: core_profile(fixture.profile), provenance_id: fixture.id, - owner, - ledger, semantic_budget: Some(16 * 1024 * 1024), root_name: fixture_root_name(fixture), root: RootId::UploadedManifest, @@ -827,11 +814,8 @@ fn compare_candidate_to_oracle( fixture: &polymodel_ldraw_testkit::FixtureCase, oracle: &OracleProjection, ) -> Result<(), String> { - let ledger = ReservationLedger::new(); let parsed = parse_fixture_with_root( fixture, - ReservationOwner::preview(78, 0, 1), - &ledger, ) .map_err(|error| format!("{} candidate rejected while oracle status is {}: {error}", fixture.id, oracle.status))?; let candidate = parsed.project(); @@ -851,9 +835,6 @@ fn compare_candidate_to_oracle( )); } drop(parsed); - if ledger.snapshot().reservations != 0 { - return Err(format!("{} differential candidate leaked reservation", fixture.id)); - } return Ok(()); } let resolved = oracle @@ -1039,9 +1020,6 @@ fn compare_candidate_to_oracle( } } drop(parsed); - if ledger.snapshot().reservations != 0 { - return Err(format!("{} differential candidate leaked reservation", fixture.id)); - } Ok(()) } @@ -1186,14 +1164,11 @@ fn fuzz() -> Result { let path = temporary.join(format!("{index}-{}.ldr", hex::encode(digest))); fs::write(&path, &bytes).map_err(|error| error.to_string())?; let operator = mutation_operator(FUZZ_SEED, index); - let ledger = ReservationLedger::new(); let first = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| { InProcessRustAdapter::parse_fixture( fixture.id, &bytes, core_profile(fixture.profile), - ReservationOwner::preview(1, index as u64 + 1, 1), - &ledger, ) })) .map_err(|_| { @@ -1213,20 +1188,11 @@ fn fuzz() -> Result { }), Err(error) => Err(format!("error:{error:?}")), }; - if ledger.snapshot().reservations != 0 { - return Err(format!( - "mutation {index} ({operator}) ({}) leaked ledger reservations", - fixture.id - )); - } - let repeat_ledger = ReservationLedger::new(); let repeat = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| { InProcessRustAdapter::parse_fixture( fixture.id, &bytes, core_profile(fixture.profile), - ReservationOwner::preview(1, index as u64 + 1, 1), - &repeat_ledger, ) })) .map_err(|_| { @@ -1246,12 +1212,6 @@ fn fuzz() -> Result { }), Err(error) => Err(format!("error:{error:?}")), }; - if repeat_ledger.snapshot().reservations != 0 { - return Err(format!( - "mutation {index} ({operator}) ({}) repeated parse leaked ledger reservations", - fixture.id - )); - } if first_observation != second_observation { return Err(format!( "mutation {index} ({operator}) ({}) core outcome is not deterministic",