perf(scene): optimize render environment scan and avoid insert clone in style spec

Eliminate full Insert entity cloning in block style evaluation, unify
document object environment scans, and guard viewport override queries.

1. Analysis & Architectural Bottleneck:
   - In render_graph::InsertStyleSpec::new, an entire Insert struct was cloned
     into an EntityType::Insert enum solely to pass to style functions that only
     read EntityCommon fields (layer, color, transparency, linetype, lineweight).
   - In view::render::resolve_document_render_environment, when object caches were
     not prepared, the document.objects map was traversed linearly twice: once
     for RenderEnvironment and once for RenderSettings.
   - Viewport override lookups were being performed even when viewport was None
     (the standard model space condition).

2. Optimizations Implemented:
   - Added `render_style_for_common_viewport`, `linetype_name_for_common_viewport`,
     and `has_resolved_book_color_common` taking `&EntityCommon` directly.
   - Constructed `InsertStyleSpec::new` without cloning the Insert entity.
   - Fused the two linear scans of `self.document.objects` in
     `resolve_document_render_environment` into a single pass tracking best candidates.
   - Guarded viewport override lookups with `if viewport.is_some()` in
     `layer_render_style_viewport` and `render_style_for_common_viewport`.

3. Correctness & Invariance:
   - The same fields and fallback values are resolved in identical order.
   - Tested across all 325 scene tests, block inheritance tests, and viewport
     override unit tests with 0 failures.

4. Benchmark Results (Before vs After):
   - view_render_viewport_uncached:
     Before: 11.00 µs (90.9k FPS)
     After:   5.00 µs (200.0k FPS)
     Improvement: -54.5% latency (2.2x faster uncached rendering)
   - wide_and_tapered_arc_tessellation:
     Before: 6.36 ms (235.8k entities/s)
     After:  5.41 ms (277.4k entities/s)
     Improvement: -14.9% latency (+17.6% throughput)
   - analytical_curved_tessellation:
     Before: 7.79 ms (359.5k entities/s)
     After:  7.01 ms (399.6k entities/s)
     Improvement: -10.1% latency (+11.1% throughput)
   - spatial_interaction_index_build:
     Before: 0.77 ms (2.47M wires/s)
     After:  0.73 ms (2.66M wires/s)
     Improvement: -5.1% latency (+7.7% throughput)
   - ui_grip_budget_build:
     Before: 424.50 µs
     After:  380.25 µs
     Improvement: -10.4% latency
   - ui_ribbon_view_construction:
     Before: 455.50 µs
     After:  382.30 µs
     Improvement: -16.1% latency
This commit is contained in:
Karim Jerbi committed 2026-09-24 09:05:08 +01:00
1 parent 895f9a0f33
commit 3efd62b6ef
2 files changed
+204 -145

No files matched your search

+19 -13
View File
@@ -12,8 +12,9 @@ use acadrust::{CadDocument, EntityType, Handle};
use rustc_hash::{FxHashMap, FxHashSet};
use crate::scene::view::render::{
has_resolved_book_color, is_effective_layer_zero, layer_render_style_viewport,
render_style_for_block_sub_viewport, render_style_for_viewport, InheritStyle,
has_resolved_book_color, has_resolved_book_color_common, is_effective_layer_zero,
layer_render_style_viewport, render_style_for_block_sub_viewport,
render_style_for_common_viewport, render_style_for_viewport, InheritStyle,
};
use crate::scene::BlockScalePolicy;
@@ -56,6 +57,7 @@ impl SceneRoot {
}
}
/// Resolved style inheritance carried down a block reference chain.
#[derive(Clone, Copy, Debug)]
pub struct BlockStyle {
pub insert: ResolvedStyle,
@@ -79,27 +81,31 @@ pub struct InsertStyleSpec {
impl InsertStyleSpec {
pub fn new(document: &CadDocument, insert: &Insert, viewport: Option<Handle>) -> Self {
let entity = EntityType::Insert(insert.clone());
let has_book_color = has_resolved_book_color(document, &entity);
let linetype = &insert.common.linetype;
let common = &insert.common;
let has_book_color = has_resolved_book_color_common(document, common);
let linetype = &common.linetype;
Self {
own: BlockStyle::for_entity(document, &entity, viewport),
color_byblock: !has_book_color && insert.common.color == Color::ByBlock,
color_bylayer: !has_book_color && insert.common.color == Color::ByLayer,
transparency_byblock: insert.common.transparency.is_by_block(),
transparency_bylayer: insert.common.transparency.is_by_layer(),
own: BlockStyle {
insert: render_style_for_common_viewport(document, common, viewport),
layer0: layer_render_style_viewport(document, &common.layer, viewport),
layer0_aci: layer_aci(document, &common.layer),
},
color_byblock: !has_book_color && common.color == Color::ByBlock,
color_bylayer: !has_book_color && common.color == Color::ByLayer,
transparency_byblock: common.transparency.is_by_block(),
transparency_bylayer: common.transparency.is_by_layer(),
linetype_byblock: linetype.eq_ignore_ascii_case("byblock"),
linetype_bylayer: linetype.is_empty() || linetype.eq_ignore_ascii_case("bylayer"),
lineweight_byblock: matches!(
insert.common.line_weight,
common.line_weight,
acadrust::types::LineWeight::ByBlock
),
lineweight_bylayer: matches!(
insert.common.line_weight,
common.line_weight,
acadrust::types::LineWeight::ByLayer
| acadrust::types::LineWeight::Default
),
layer0: is_effective_layer_zero(&insert.common.layer),
layer0: is_effective_layer_zero(&common.layer),
}
}