Skip to content

feat: 6849 loading screen by data - #8046

Merged
alejandro-jimenez-dcl merged 18 commits into
devfrom
feat/6849-loading-screen-by-data
Jun 5, 2026
Merged

feat: 6849 loading screen by data#8046
alejandro-jimenez-dcl merged 18 commits into
devfrom
feat/6849-loading-screen-by-data

Conversation

@alejandro-jimenez-dcl

@alejandro-jimenez-dcl alejandro-jimenez-dcl commented Apr 3, 2026

Copy link
Copy Markdown
Contributor

Pull Request Description

What does this PR change?

Replaces count-based scene loading progress with byte-weighted tracking so the loading bar reflects actual download volume rather than asset count. Implementation is gated behind a new feature flag (byte-weighted-loading-progress) for safe remote rollback.

Closes #6849.

Key pieces:

  • New SceneByteProgressTracker aggregates per-entity byte progress, credits finishes/deaths, and smooths output frame-rate independently.
  • LoadAssetBundleSystem issues a HEAD request (new GetDecompressedContentLengthOp on the web request controller) to learn each asset's decompressed size, then reports streamed bytes via IProgress<float>.
  • GatherGltfAssetsSystem drives the tracker each frame and reports the smoothed value to AsyncLoadProcessReport.
  • When the flag is off, ContentLength stays at -1 and the progress reporter is null; the tracker math collapses to count-based behaviour, matching today's loading screen.

Other notes:

  • Output is capped just below 1.0; only the explicit conclude path reports 1.0 to avoid auto-closing the loading screen mid finalize-wait.
  • Added SceneByteProgressTrackerShould (11 cases) covering register idempotency, credit balance, monotonicity, unknown-size weighting, in-progress reset, and dt-gated smoothing.

Test Instructions

  • Dont forget to test LSD as well.

    Test Steps

    1. Launch the client with the byte-weighted flag off (default for remote users), enter a scene, and observe the loading screen.
    2. Relaunch with alfa-byte-weighted-loading-progress on (editor defaults to on; remotely toggle via the feature flag service or --feature-flag arg), enter the same scene, and observe the loading screen.
    3. Expected: the bar progresses smoothly to completion in both runs and the loading screen closes at the same point. Difference between the two modes should be barely perceptible, the on-path may look slightly smoother on scenes with mixed asset sizes.
    4. Try a few more scenes (small, large, mostly-cached) with the flag on and off.

    Additional Testing Notes

    • Cached scenes: progress should still reach 100% promptly, no stalls.
    • Slow network / partially failing assets: bar should not get stuck or jump backwards.
    • Watch for any premature loading-screen dismissal (would indicate the < 1.0 cap is leaking through).

    Quality Checklist

    • Changes have been tested locally
    • Documentation has been updated (if required)
    • Performance impact has been considered (extra HEAD per AB, only when flag is on)
    • For SDK features: Test scene is included (n/a)

    Code Review Reference

    Please review our Code Review Standards before submitting.

@alejandro-jimenez-dcl alejandro-jimenez-dcl changed the title Feat/6849 loading screen by data feat: 6849 loading screen by data Apr 3, 2026
@github-actions

github-actions Bot commented Apr 3, 2026

Copy link
Copy Markdown
Contributor

@alejandro-jimenez-dcl alejandro-jimenez-dcl added the force-build Used to trigger a build on draft PR label Apr 3, 2026
@AnsisMalins

Copy link
Copy Markdown
Contributor

PR #8046, run #23942270238

Builds: Windows change, Windows baseline, macOS change, macOS baseline

Intel Core i3

Metric Change Baseline Delta Improvement
Samples 1945 2658
CPU average 46.2 ms 33.8 ms 12.4 ms -36.8% 🔴
CPU 1% worst 77.0 ms 57.5 ms 19.5 ms -33.9% 🔴
CPU 0.1% worst 187.9 ms 122.3 ms 65.6 ms -53.6% 🔴
GPU average 41.8 ms 17.7 ms 24.1 ms -135.9% 🔴
GPU 1% worst 51.0 ms 25.1 ms 25.8 ms -102.8% 🔴
GPU 0.1% worst 55.6 ms 28.5 ms 27.1 ms -95.0% 🔴

Comment thread Explorer/Assets/DCL/WebRequests/IStreamableLoadingProgress.cs Outdated
Comment thread Explorer/Assets/DCL/WebRequests/ITypedWebRequest.cs
Comment thread Explorer/Assets/DCL/WebRequests/ITypedWebRequest.cs Outdated

@dalkia dalkia left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Leaving some comments for possible simplifications

@alejandro-jimenez-dcl alejandro-jimenez-dcl self-assigned this Apr 14, 2026
…en-by-data

# Conflicts:
#	Explorer/Assets/DCL/Infrastructure/ECS/StreamableLoading/AssetBundles/LoadAssetBundleSystem.cs
Address PR review feedback and assembly cycle constraints.

- Drop IStreamableLoadingProgressHandler interface, use BCL
  IProgress<float> directly. StreamableLoadingState implements it.
- Move HEAD content-length lookup out of WebRequestController layer
  into LoadAssetBundleSystem. WebRequestController no longer references
  streamable loading concepts (avoids DCL.Network to ECS.Unity cycle).
- Replace progressHandler param with (expectedContentLength, progressReporter)
  pair across SendAsync chain.
- Extract byte-weighted progress bookkeeping from GatherGltfAssetsSystem
  into SceneByteProgressTracker (separately testable).
- Use HashSet<Entity> for tracked entities instead of Dictionary; read
  ContentLength fresh from StreamableLoadingState at finish time.
- Fix silent cancellation leak in polled SendRequest path: switch to
  UniTask.Yield(token) so OperationCanceledException propagates.
- Drop redundant SetProgress(0) and SetContentLength(-1) init in
  LoadAssetBundleSystem; pool reset already handles it. ContentLength
  unknown sentinel is now -1 consistently.
SceneByteProgressTracker now memoizes ContentLength on registration in a
Dictionary<Entity, long>, so CreditFinish/CreditDeath can credit the
stored size without re-reading StreamableLoadingState. GatherGltfAssetsSystem
only calls ReadLoadingState while an entity is still in LoadingState.Loading.

Average-size estimation is replaced with a fixed UNKNOWN_ASSET_BYTES (1 KB)
weight for assets that finished before their size was observed. This makes
the unknown-slot contribution to effectiveTotal symmetric with the credit
applied in CreditFinish, removing the prior drift between snapshot-time and
compute-time averages.
Add BYTE_WEIGHTED_LOADING_PROGRESS so the HEAD round-trip and progress
reporter in LoadAssetBundleSystem can be skipped at runtime. Flag off
leaves state.ContentLength = -1 and progressReporter null, which
collapses SceneByteProgressTracker math to count-based (every entity
worth one UNKNOWN slot) for safe remote rollback.

Tune the tracker so the on path looks better:
- UNKNOWN_ASSET_BYTES from 1024 to 1 so cache hits stop skewing the
  bar away from real-download bytes.
- Cap output below 1.0; AsyncLoadProcessReport.SetProgress(>=1f)
  auto-closes the loading screen and would fire mid finalize-wait
  window when in-progress credits saturate effectiveTotal. Only the
  explicit conclude path in GatherGltfAssetsSystem should report 1.0.
- Lerp toward target each frame to absorb spikes from per-entity main
  AB completions and bursty UWR reports.
@m3taphysics

Copy link
Copy Markdown
Contributor

PR #8046, run #26216237624

Builds: Windows change, Windows baseline, macOS change, macOS baseline

Framework 13 i7

Metric Change Baseline Delta Improvement
Samples 2700 2700
CPU average 33.3 ms 33.3 ms -0.0 ms 0.0%
CPU 1% worst 33.4 ms 33.8 ms -0.3 ms 1.0%
CPU 0.1% worst 33.7 ms 37.8 ms -4.1 ms 10.9% 🟢
GPU average 7.8 ms 7.6 ms 0.1 ms -1.9%
GPU 1% worst 20.5 ms 21.2 ms -0.7 ms 3.4% 🟢
GPU 0.1% worst 24.0 ms 29.1 ms -5.1 ms 17.4% 🟢

- Drop dead Math.Max from ComputeAndClamp lerp guard.
- Make smoothing frame-rate independent: take deltaTime parameter
  (GatherGltfAssetsSystem passes Update's t).
- Log warning on GetDecompressedContentLength HEAD failures instead
  of swallowing silently; cancellations stay silent.
- Add SceneByteProgressTrackerShould with 11 cases covering register
  idempotency, credit balance, monotonicity, unknown-size weighting,
  in-progress reset, and dt-gated smoothing.
- Expose SceneLifeCycle internals to DCL.EditMode.Tests.
@m3taphysics

Copy link
Copy Markdown
Contributor

PR #8046, run #26220799532

Builds: Windows change, Windows baseline, macOS change, macOS baseline

Framework 13 i7

Metric Change Baseline Delta Improvement
Samples 2700 2699
CPU average 33.3 ms 33.3 ms -0.0 ms 0.0%
CPU 1% worst 33.4 ms 33.5 ms -0.1 ms 0.4%
CPU 0.1% worst 33.5 ms 34.8 ms -1.3 ms 3.8% 🟢
GPU average 8.3 ms 8.2 ms 0.1 ms -1.5%
GPU 1% worst 19.8 ms 21.5 ms -1.7 ms 7.9% 🟢
GPU 0.1% worst 28.7 ms 34.1 ms -5.4 ms 15.9% 🟢

@alejandro-jimenez-dcl
alejandro-jimenez-dcl marked this pull request as ready for review May 21, 2026 11:37
@alejandro-jimenez-dcl
alejandro-jimenez-dcl requested review from a team as code owners May 21, 2026 11:37
@m3taphysics

Copy link
Copy Markdown
Contributor

PR #8046, run #26233784698

Builds: Windows change, Windows baseline, macOS change, macOS baseline

Framework 13 i7

Metric Change Baseline Delta Improvement
Samples 2700 2700
CPU average 33.3 ms 33.3 ms -0.0 ms 0.0%
CPU 1% worst 33.5 ms 33.7 ms -0.2 ms 0.6%
CPU 0.1% worst 34.4 ms 36.7 ms -2.2 ms 6.1% 🟢
GPU average 7.8 ms 7.9 ms -0.1 ms 1.0%
GPU 1% worst 20.0 ms 20.5 ms -0.6 ms 2.8%
GPU 0.1% worst 25.8 ms 28.2 ms -2.3 ms 8.3% 🟢

@m3taphysics

Copy link
Copy Markdown
Contributor

PR #8046, run #26281706672

Builds: Windows change, Windows baseline, macOS change, macOS baseline

Framework 13 i7

Metric Change Baseline Delta Improvement
Samples 2701 2700
CPU average 33.3 ms 33.3 ms 0.0 ms -0.0%
CPU 1% worst 33.8 ms 33.7 ms 0.0 ms -0.1%
CPU 0.1% worst 37.7 ms 37.3 ms 0.5 ms -1.3%
GPU average 8.3 ms 7.9 ms 0.3 ms -4.4% 🔴
GPU 1% worst 19.2 ms 19.1 ms 0.1 ms -0.3%
GPU 0.1% worst 27.2 ms 24.2 ms 3.0 ms -12.3% 🔴

@sandrade-dcl sandrade-dcl left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. Good job!

…en-by-data

# Conflicts:
#	Explorer/Assets/DCL/PluginSystem/World/AssetBundlesPlugin.cs
@m3taphysics

Copy link
Copy Markdown
Contributor

PR #8046, run #26942264212

Builds: Windows change, Windows baseline, macOS change, macOS baseline

How to read this table
  • Each build is measured 3 times. The values are the median, and (min–max) is the lowest and highest of those runs — a wide range means the metric is noisy and small differences are not trustworthy.
  • Δ is Change minus Baseline (a negative Δ means Change is faster).
  • 🟢 faster / 🔴 slower — a real difference: larger than both 3% and the run-to-run range.
  • ⚪ within noise — the difference is smaller than how much the build varies between its own runs, so it cannot be told apart from random variation. Treat it as no change.
  • Exceptions logged — exceptions found in the run logs; more than the baseline is flagged 🔴 even when frame times look fine.

Framework 13 i7

Metric Baseline Change Δ Result
Samples 2700 (×3) 2701 (×3)
CPU average 33.3 ms 33.3 ms -0.0 ms ⚪ within noise
CPU 1% worst 34.2 ms (33.8–35.0) 33.6 ms (33.5–33.6) -0.6 ms ⚪ within noise
CPU 0.1% worst 37.0 ms (35.4–49.7) 36.0 ms (34.0–36.4) -1.0 ms ⚪ within noise
GPU average 7.6 ms (7.1–8.2) 9.7 ms (8.5–9.7) 2.1 ms 🔴 28% slower
GPU 1% worst 19.8 ms (19.7–20.0) 17.8 ms (17.6–18.8) -2.0 ms 🟢 10% faster
GPU 0.1% worst 24.6 ms (24.2–24.8) 21.4 ms (18.4–25.9) -3.2 ms ⚪ within noise
Exceptions logged 48 46 -2 🟢 fewer errors

@m3taphysics

Copy link
Copy Markdown
Contributor

PR #8046, run #26945250405

Builds: Windows change, Windows baseline, macOS change, macOS baseline

How to read this table
  • Each build is measured 3 times. The values are the median, and (min–max) is the lowest and highest of those runs — a wide range means the metric is noisy and small differences are not trustworthy.
  • Δ is Change minus Baseline (a negative Δ means Change is faster).
  • 🟢 faster / 🔴 slower — a real difference: larger than both 3% and the run-to-run range.
  • ⚪ within noise — the difference is smaller than how much the build varies between its own runs, so it cannot be told apart from random variation. Treat it as no change.
  • Exceptions logged — exceptions found in the run logs; more than the baseline is flagged 🔴 even when frame times look fine.

Framework 13 i7

Metric Baseline Change Δ Result
Samples 2701 (×3) 2701 (×3)
CPU average 33.3 ms 33.3 ms -0.0 ms ⚪ within noise
CPU 1% worst 33.8 ms (33.7–34.1) 33.5 ms (33.4–33.6) -0.2 ms ⚪ within noise
CPU 0.1% worst 36.3 ms (36.2–38.1) 35.0 ms (34.0–35.9) -1.4 ms ⚪ within noise
GPU average 8.2 ms (7.2–8.3) 9.6 ms (8.5–10.0) 1.4 ms ⚪ within noise
GPU 1% worst 17.5 ms (17.3–18.8) 17.9 ms (17.0–18.1) 0.3 ms ⚪ within noise
GPU 0.1% worst 23.5 ms (22.5–23.8) 23.1 ms (19.4–23.9) -0.4 ms ⚪ within noise
Exceptions logged 44 44 0 ⚪ none new

@DafGreco DafGreco left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✔️ PR reviewed and approved by QA on both platforms following instructions playing both happy and un-happy path

Regressions for this ticket had been performed in order to verify that the normal flow is working as expected:

  • [ ✔️ ] Backpack and wearables in world
  • [ ✔️ ] Emotes in world and in backpack
  • [ ✔️ ] Teleport with map/coordinates/Jump In
  • [✔️ ] Chat and multiplayer
  • [ ✔️ ] Profile card
  • [✔️ ] Camera
  • [✔️ ] Settings

Evidence without flag ✅

20260604-1032-53.9187944.mp4

Evidence with flag ✅

evidenceloading.mp4

@alejandro-jimenez-dcl
alejandro-jimenez-dcl merged commit 4df8bd5 into dev Jun 5, 2026
16 of 18 checks passed
@alejandro-jimenez-dcl
alejandro-jimenez-dcl deleted the feat/6849-loading-screen-by-data branch June 5, 2026 07:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

force-build Used to trigger a build on draft PR

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[TECH DEBT] Loading Screen | Make progress bar download-data aware

6 participants