From 499ad4ec7b9af3beacadba1484919b9537b987f7 Mon Sep 17 00:00:00 2001 From: Confetti3 Date: Tue, 11 Aug 2026 23:04:50 -0700 Subject: [PATCH 1/2] fix: prevent Shadowkeep map startup deadlock --- .gitattributes | 10 +++++++++- .github/workflows/ci.yml | 14 ++++++++++++++ crates/render/src/renderer/submit/mod.rs | 14 +++++++++++--- src/world/shadowkeep_map.rs | 24 +++++++++++++++++++++--- 4 files changed, 55 insertions(+), 7 deletions(-) diff --git a/.gitattributes b/.gitattributes index 21256661..c638d7b4 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1 +1,9 @@ -* text=auto \ No newline at end of file +* text=auto eol=lf +*.bmp binary +*.dll binary +*.dxbc binary +*.ico binary +*.jpg binary +*.lib binary +*.png binary +*.webp binary \ No newline at end of file diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c79f33a0..7a3ed62e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -14,6 +14,7 @@ concurrency: env: CARGO_TERM_COLOR: always + LIB: ${{ github.workspace }}\lib jobs: format: @@ -69,3 +70,16 @@ jobs: - run: cargo build --profile dist --locked --no-default-features --bin alkahest-prebl - run: Copy-Item lib\SDL3.dll target\dist\SDL3.dll - run: target\dist\alkahest-prebl.exe --version + - name: Assemble test build + if: github.ref == 'refs/heads/main' + shell: pwsh + run: | + New-Item -ItemType Directory target\package + Copy-Item target\dist\alkahest-prebl.exe,target\dist\SDL3.dll,LICENSE,THIRD_PARTY_NOTICES.md target\package\ + - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 + if: github.ref == 'refs/heads/main' + with: + name: alkahest-sunrise-windows-x64-${{ github.sha }} + path: target/package + if-no-files-found: error + retention-days: 14 diff --git a/crates/render/src/renderer/submit/mod.rs b/crates/render/src/renderer/submit/mod.rs index faf7fcb5..fc653474 100755 --- a/crates/render/src/renderer/submit/mod.rs +++ b/crates/render/src/renderer/submit/mod.rs @@ -1143,6 +1143,7 @@ impl Renderer { let sky_illumination = 0.03 + 0.97 * daylight; let externs = self.externs.read(); let target_pixel_to_world = externs.view.target_pixel_to_world; + let camera_position = externs.view.position; let sky_state = ShadowkeepSkyState::from_externs(&externs); let include_sun = debug_pipeline.is_none_or(|pipeline| pipeline.has_sun()); let sun_color = if include_sun { @@ -1155,7 +1156,7 @@ impl Renderer { cmd, &ShadowkeepSkyConstants { target_pixel_to_world, - camera_position: self.externs.read().view.position, + camera_position, sun_direction, zenith_color: sky_state.zenith * sky_illumination, horizon_color: sky_state.horizon * sky_illumination, @@ -2438,7 +2439,8 @@ impl Renderer { fn prepare_externs(&self, cmd: &mut CommandList, view: &View) { let fb_res = view.framebuffer_resolution(); - let misc = &self.frame_packet.read().misc; + let frame_packet = self.frame_packet.read(); + let misc = &frame_packet.misc; // let cam_view = Mat4::from_cols( // [-0.962532818, -0.027713167, -0.269745320, 0.000000000].into(), @@ -2647,6 +2649,11 @@ impl Renderer { ext.atmosphere.unk1e8 = ext.get_global_channel_by_id(0xe685c537).x; ext.atmosphere.unk1ec = ext.get_global_channel_by_id(0xe4a1bf60).x; } + // Release both frame-state guards before helpers reacquire them below. + // parking_lot locks are not reentrant; retaining `ext` here deadlocks + // the first rendered frame after a map finishes loading. + drop(ext); + drop(frame_packet); // The current fixed 37-register transparent setup belongs to the // post-BL scope layout. Shadowkeep owns a shorter, differently laid @@ -2747,8 +2754,9 @@ impl Renderer { fn prepare_main_view_externs(&self, view: &MainView) { let fb_res = view.surfaces.framebuffer_resolution(); + let frame_packet = self.frame_packet.read(); + let misc = &frame_packet.misc; let mut ext = self.externs.write(); - let misc = &self.frame_packet.read().misc; // ext.deferred.gbuffer_resolution_scale_offset = // vec4(fb_res.0 as f32, fb_res.1 as f32, 0.0, 0.0); diff --git a/src/world/shadowkeep_map.rs b/src/world/shadowkeep_map.rs index de4887c6..8ec726b7 100644 --- a/src/world/shadowkeep_map.rs +++ b/src/world/shadowkeep_map.rs @@ -2878,7 +2878,7 @@ pub fn load_shadowkeep_map_into_world( report.sky_object_color_stage_mask |= color_stages.bits(); report.sky_object_deferred_stage_mask |= deferred_stages.bits(); if !deferred_stages.is_empty() { - tracing::info!( + tracing::debug!( collection = %collection_tag, model = %model_tag, deferred_stage_mask = format_args!("0x{:08X}", deferred_stages.bits()), @@ -2933,7 +2933,7 @@ pub fn load_shadowkeep_map_into_world( progress .visual_resources_loaded .fetch_add(1, Ordering::Relaxed); - tracing::info!( + tracing::debug!( collection = %collection_tag, origin = candidate.sources.label(), index, @@ -2995,7 +2995,25 @@ pub fn load_shadowkeep_map_into_world( .reduce(|left, right| left.union(&right)); report.inspection = inspection.finalize(); report.inspection.validate(&world)?; - debug_assert!(report.entity_resource_accounting_is_complete()); + if !report.entity_resource_accounting_is_complete() { + tracing::error!( + entity_resource_class_counts = ?report.entity_resource_class_counts, + loaded_entity_resource_classes = ?report.loaded_entity_resource_classes, + deferred_entity_resource_classes = ?report.deferred_entity_resource_classes, + failed_entity_resource_classes = ?report.failed_entity_resource_classes, + "Shadowkeep entity-resource accounting is incomplete" + ); + report.diagnostic( + progress, + MapLoadDiagnostic { + table: tag, + entry_offset: 0, + resource_class: 0, + error: "internal entity-resource accounting is incomplete; the map was retained" + .to_owned(), + }, + ); + } tracing::info!( map = %tag, scenario = ?report.scenario, From 9ce83d23df11dc48f03876881083c623852024f0 Mon Sep 17 00:00:00 2001 From: Confetti3 Date: Tue, 11 Aug 2026 23:08:34 -0700 Subject: [PATCH 2/2] docs: foreground Alkahest fork attribution --- README.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index b9b5b450..746ba9bc 100644 --- a/README.md +++ b/README.md @@ -3,6 +3,8 @@

# Project Sunrise — Alkahest Pre-BL +> **This repository is a fork of [Alkahest](https://github.com/cohaereo/alkahest), created by [cohaereo](https://github.com/cohaereo/cohaereo). Project Sunrise would not exist without cohaereo's original architecture, renderer, tooling, and years of work. This fork builds on that foundation for preserved Shadowkeep / Season of Arrivals package support.** + Alkahest Pre-BL is a Windows desktop map viewer and research renderer for user-supplied Destiny 2 Shadowkeep / Season of Arrivals package files. It lets @@ -95,8 +97,10 @@ GitHub artifact provenance before a draft release is created. - **Promotional identity and artwork:** Solus — [YouTube](https://youtube.com/@solus-yt) · [X / Twitter](https://x.com/solus_yt). -- **Renderer foundation:** [Alkahest](https://github.com/cohaereo/alkahest) - and its contributors. +- **Upstream author and renderer foundation:** [cohaereo](https://github.com/cohaereo/cohaereo), + creator of [Alkahest](https://github.com/cohaereo/alkahest). Project Sunrise + is a fork and would not exist without his work. Additional credit belongs to + Alkahest's contributors. ## Data and affiliation