Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,12 @@ concurrency:
group: test-${{ github.ref }}
cancel-in-progress: true

defaults:
run:
# The shared entry point is Bash. PowerShell can return success after
# opening a .sh file without executing or waiting for its commands.
shell: bash

env:
CARGO_TERM_COLOR: always
# Pin macOS deployment target so cached object files carry a stable
Expand Down Expand Up @@ -73,6 +79,14 @@ jobs:
RUST_TEST_NOCAPTURE: "1"
run: ./scripts/ci-check.sh --quick --component shared-tests

- name: Retain executed shared-check summary
if: always()
uses: actions/upload-artifact@v4
with:
name: shared-check-summary-${{ matrix.os }}
path: target/ci/quick-shared-tests.json
if-no-files-found: error

- name: Upload failure evidence
if: failure()
uses: ./.github/actions/upload-ci-failure
Expand Down Expand Up @@ -235,6 +249,14 @@ jobs:
- name: full / host-build
run: ./scripts/ci-check.sh --full --component host-build

- name: Retain executed Windows-build summary
if: always()
uses: actions/upload-artifact@v4
with:
name: windows-build-summary
path: target/ci/full-host-build.json
if-no-files-found: error

- name: Upload failure evidence
if: failure()
uses: ./.github/actions/upload-ci-failure
Expand Down
53 changes: 53 additions & 0 deletions docs/evidence/windows-example-ci-v1.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# Windows example linking and CI execution

A native compile-and-link audit of all 20 canonical examples at `d610d6a`
produced 13 successful Windows executables and seven failures with the pinned
official Perry 0.5.1182 toolchain. This exposed failures that an inventory check
or `--no-link` compilation cannot establish as passing native builds.

Six examples still accessed `Color.White`, `Color.Red`, and other palette values
after `bloom/core` stopped exporting `Color` as a value. `Color` remains the RGBA
type; `Colors` is the public palette. Correcting those imports and accesses
makes Pong, Dungeon Crawl, Isometric RPG, Kart Racer, Space Blaster, and Voxel
Sandbox compile and link on the same compiler. Type annotations retain `Color`.
No renderer or library API changed.

The remaining `perry-embed` failure is independent. Perry 0.5.1182 does not
support the example's `bloomViewGetNativeHandle` call. Official 0.5.1219 supports
that API but its prebuilt standard library fails to link missing HTTP extension
symbols. Official 0.5.1220 had already exposed the same standard-library issue
in the original #153 work. The embedded-view example remains unqualified;
compiler source/build investigation continues rather than removing the example
from the required inventory.

## Hosted Windows execution gap

The #159 Windows shared-test job reported success in about one second. Its
retained log identifies PowerShell as the shell, invokes `ci-check.sh`, then
proceeds to cleanup without any Cargo output or test results. The cache action
also reports that its build paths do not exist. That status does not prove test
execution. Local Windows shared tests were run explicitly through Bash and
Cargo, so their previously published execution evidence remains valid.

The Tests workflow now selects Bash explicitly and requires the emitted shared
test summary on every host and the native-build summary on Windows. Artifact
upload fails when a summary is absent, making another silent non-execution a
failure. The CI command contract checks both the shell and required evidence.
Hosted execution on this correction still needs verification from actual Cargo
output and summary contents.

The first hosted run at `88bc633` executes Cargo and uploads both failure
summaries. It exposes a second setup defect: Git Bash prepends its own
`/usr/bin/link.exe` ahead of the MSVC linker. Cargo then invokes the hard-link
utility with Microsoft linker arguments. The shared CI entry point now restores
the active Visual Studio developer toolchain ahead of Git's tools and fails
with an actionable message if that configured linker is missing. The next
hosted run must verify the build and shared suite with that correction.

Audit commands, original failure logs, compiler-release metadata, source patch,
and the six corrected executable hashes are retained under
`tools/quality/out/windows-engine-plan/all-examples/`. The original audit is also
included in the [#159 evidence release](https://github.com/Bloom-Engine/engine/releases/tag/quality-evidence-ssgi-surface-20260911).

This is progress on #140/#142/#74. All-example PR compilation, real starter and
embedded-view startup, and clean package installation are still required.
99 changes: 28 additions & 71 deletions docs/windows-engine-plan.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,11 @@ first nine-scene Radeon evidence are in draft PR #154. Follow-up work starts at
| Work | Required completion evidence | Current state |
| --- | --- | --- |
| #127 Vulkan PT correctness | Three deterministic progressive and motion runs, both negative controls, finite intermediates, reset/lighting/rigid-motion checks, retained report | Canonical hardware gate, all four focused temporal tests, and CPU reference sanity check pass on Radeon/Vulkan; [report](evidence/issue-127-windows-vulkan-v1.md) and [raw evidence](https://github.com/Bloom-Engine/engine/releases/tag/quality-evidence-155-windows-vulkan-20260910) published |
| #128 Windows image discrepancies | Identify the first incorrect stage or document a reviewed backend-specific baseline decision; rerun the full strict corpus and reproducibility checks | [Cutout phase correction](evidence/windows-alpha-phase-v1.md) passes all nine Radeon image gates in two complete runs and both hosted Metal images. Reproducibility passes with 257 byte-identical artifacts. Both strict runs fail postflight host-load checks, so their timing remains unqualified |
| #135 / #149 temporal reconstruction | Enforced motion/producer/quality-preset corpus, representative scenes, fractional/native and frozen A/B timing, memory/resize checks, platform evidence | Device/resource, stationary SSGI, and profiler fixes are retained. The [surface reconstruction correction](evidence/windows-ssgi-surface-v1.md) passes the original HD startup limits on Radeon/Vulkan; all 93 local goldens that run pass, including lighting recovery. Full scene-image, timing, and platform qualification of that correction remain open, as does the wider representative corpus |
| #140 integration gates | Same required local/hosted lanes pass on exact source; release package startup and all-example evidence | All 24 hosted checks pass at #158 source `662a44f`, including macOS shared/golden tests, mobile target builds, native/web builds, browser startup, and canonical Metal images. Scheduled physical-hardware checks, all-example compilation, and release-install acceptance remain separate requirements |
| #128 Windows image discrepancies | Identify the first incorrect stage or document a reviewed backend-specific baseline decision; rerun the full strict corpus and reproducibility checks | Cutout and surface corrections pass all nine Radeon images. At #159 source `d610d6a`, full runs 2 and 3 pass every configured check and reproduce 257 artifacts byte-identically with matching metadata and timing differences inside existing noise bounds. Earlier invalid runs retain their failures; named hardware acceptance remains separate |
| #135 / #149 temporal reconstruction | Enforced motion/producer/quality-preset corpus, representative scenes, fractional/native and frozen A/B timing, memory/resize checks, platform evidence | Device/resource, stationary SSGI, and profiler fixes are retained. The surface correction passes original HD startup limits and 154,720 analytic receiver checks on Vulkan, DX12, and hosted Metal; 93 local goldens pass, including lighting recovery. The full Radeon corpus passes twice. Wider representative scenes, frozen A/B performance, memory/resize, and platform acceptance remain open |
| #140 integration gates | Same required local/hosted lanes pass on exact source; release package startup and all-example evidence | #159 has 24 successful CheckRun statuses, but Windows logs reveal no Cargo execution because Bash was invoked through PowerShell without an explicit shell. Local Windows execution is verified. This follow-up selects Bash and requires execution-summary artifacts; actual hosted validation is pending. All-example PR compilation and release-install acceptance remain separate requirements |
| #138 capability fallback | Actual constrained-adapter startup and relevant forced-tier corpus, truthful capability outputs | Existing implementation/evidence preserved; physical constrained-limit acceptance still needs proof |
| PR integration | Reviewable changes, passing required checks, full issue evidence, merge-ready rendering branch | #147 and the stacked fixes #154–#158 remain drafts; no merge performed |
| PR integration | Reviewable changes, passing required checks, full issue evidence, merge-ready rendering branch | #147 and the stacked fixes #154–#159 remain drafts; no merge performed |

## Engine work retained in scope

Expand Down Expand Up @@ -54,71 +54,28 @@ audit are saved in `tools/quality/out/windows-engine-plan/plan-requirements.json

## Current next steps

1. #155 source `64d5eed` has passing hosted checks and published evidence. The
archive SHA-256 is `de9c1beca73bfcf60bf79d3a612b72c072f726f6272576a7f0f60ffdbc7ce25d`.
CI run URLs and conclusions are in its separate `pr155-checks-64d5eed.json`
release asset. No draft PR has been merged.
2. The [profiler correction](evidence/windows-profiler-integrity-v1.md) on
`codex/windows-profiler-integrity` passes local contracts, lint, the quality
lane, and the complete shared suite. Its current-frame regression rejects
all 12 old Vulkan samples and passes with the correction on Vulkan and DX12.
Corrected SSGI timing covers 20 isolated runs, each with 120 complete GPU
frames. Hosted Metal's shared lane passes, but its Apple Paravirtual adapter
lacks timestamp queries: the profiler GPU regression explicitly skips.
The retained `--nocapture` log at `1965a0b` confirms this; a test reported as
"ok" after that early return does not qualify Metal GPU timing.
Its colored-shadow
failure exposed an [inverse-matrix upload defect](evidence/windows-transmitted-shadow-inverse-vp-v1.md);
the correction passes the isolated local check and rejects the wrong-color
control. At follow-up source `fa93690`, all 23 hosted checks and the complete
local shared suite pass. The shadow regression passes on Metal. The shadow archive
and CI receipt are published alongside the immutable profiler archive.
3. Diagnose Sponza and skinned/alpha against the portable baselines, then repair
HD temporal stability and complete the representative temporal/geometry
corpus. Recapture affected timing evidence with explicit coverage fields.
Disabling foliage shadow casting retains the Windows skinned/alpha mismatch;
canonical captures at `98cce62` pass on hosted Metal with SSIM 0.997442544 for
Sponza and 0.999417603 for skinned/alpha. That Apple Paravirtual adapter uses
the modern tier and software GI and exposes no timestamps. At `0dd8f67`,
[PR #157](https://github.com/Bloom-Engine/engine/pull/157) has all 24 hosted
checks passing; both Metal images pass with raw export enabled. The
[published diagnostic archive](https://github.com/Bloom-Engine/engine/releases/tag/quality-evidence-image-portability-20260910)
retains exact depth and MRT bytes, commands, checksums, and source identity.
On matching modern/software-GI paths, Windows still fails both images.
Skinned/alpha has 9,745 depth coverage disagreements before TAA, while
albedo RGB closely agrees on matching surfaces. Disabling foliage shadows
and an isolated isotropic alpha-sampling control retain the failure.
Exact cutout-input probes at `30e7625` identify a different Bayer phase
extent: Metal's observed extent predicts every inspected threshold away from
integer LOD boundaries. The [integer phase correction](evidence/windows-alpha-phase-v1.md)
preserves that approved grid on both backends. Focused Windows images now
pass at SSIM 0.986160457 and 0.990073442. At `662a44f`, all nine Radeon image
gates pass twice and reproducibility passes with 257 byte-identical artifacts.
Both full runs fail their unchanged postflight host-load checks: System CPU
exceeds the 75% per-process limit on Bistro, and in the second run also on
draw/light stress and weighted transparency. Those timing windows remain
unqualified. The [#158 evidence archive](https://github.com/Bloom-Engine/engine/releases/tag/quality-evidence-alpha-phase-20260910)
retains both failed strict runs and their separate passing image/repro checks.
All 24 hosted checks pass; the new cutout GPU regression actually executes on
Vulkan, DX12, and Metal. Raw export leaves unmodified Windows final PNGs byte-identical.
Shared-runner timing cannot qualify hardware budgets.
The HD TAA fixture originally failed at its required 16-frame warm-up and
passed diagnostic controls at 32, 64, and 128 frames. The follow-up
[surface correction](evidence/windows-ssgi-surface-v1.md) repairs depth-texel
coordinates and resolution-dependent normal reconstruction. It passes the
original 16-frame HD limits, removes the observed horizontal GI bands, and
preserves the existing lighting-recovery regression on Radeon/Vulkan.
Both isolated partial corrections fail. Full scene and platform checks of
the combined change remain in progress; no threshold or warm-up was relaxed.
4. Continue starter/all-example and release-install checks, asset/world streaming,
schema-generated APIs, components, and runtime UI against each issue's full
acceptance criteria. Hardware-specific acceptance remains open while local
work progresses.
1. Verify actual hosted Windows test and build execution. The
[CI and example correction](evidence/windows-example-ci-v1.md) explicitly
selects Bash and requires execution-summary artifacts. Its hosted run must
show Cargo output and successful summary contents before this gap is closed.
2. Finish all-example native linking, real starter/example startup, and clean
Windows installation. Six palette corrections bring the local link audit
from 13 to 19 successful examples out of 20. The embedded-view example needs
a newer Perry API, and both available newer Windows bundles have an
independent standard-library link failure that still needs resolution.
All-example compilation must become a required PR check.
3. Complete the wider temporal/geometry, performance, memory, resize, and
capability corpus. The
[HD surface correction](evidence/windows-ssgi-surface-v1.md) and two valid
full Radeon runs are [published with #159](https://github.com/Bloom-Engine/engine/releases/tag/quality-evidence-ssgi-surface-20260911).
All nine images pass; reproducibility retains 257 byte-identical artifacts.
The original 16-frame HD startup limits pass on Vulkan, DX12, and hosted
Metal. Earlier host-load failures remain invalid timing windows. Hosted
Metal lacks timestamp queries and cannot qualify GPU timing.
4. Complete API generation, streaming, components, runtime UI, and packaging
against the full issue requirements above, then prepare the draft stack for
review and integration. These outcomes include both implementation work and
acceptance evidence; they do not imply that every subsystem is absent.

The immediate order is to repair the HD temporal startup failure, obtain valid
full Radeon timing windows, and finish all-example startup and clean Windows
installation checks. Then complete the wider temporal/geometry corpus and the
engine API, streaming, component, and UI requirements above. These remaining
outcomes include both implementation work and acceptance evidence; they are not
a claim that each subsystem is absent. None requires waiting for an RTX 4080 to
continue local work.
Local work continues on the Radeon 760M. RTX-specific, physical constrained
adapter, and other unavailable hardware acceptance remains explicitly open.
14 changes: 7 additions & 7 deletions examples/dungeon-crawl/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import {
clearBackground, setTargetFPS, getDeltaTime, isKeyPressed, isKeyDown,
getScreenWidth, getScreenHeight, closeWindow, beginMode2D, endMode2D,
} from "bloom/core";
import { Color, Key, Camera2D } from "bloom/core";
import { Color, Colors, Key, Camera2D } from "bloom/core";
import { drawRect, drawCircle, drawRectLines } from "bloom/shapes";
import { drawText, measureText } from "bloom/text";
import { clamp, randomInt, randomFloat } from "bloom/math";
Expand Down Expand Up @@ -383,7 +383,7 @@ while (!windowShouldClose()) {
);
// HP bar
const hpRatio = enemies[i].hp / enemies[i].maxHp;
drawRect(enemies[i].x * TILE_SIZE, enemies[i].y * TILE_SIZE - 4, Math.floor(TILE_SIZE * hpRatio), 3, Color.Red);
drawRect(enemies[i].x * TILE_SIZE, enemies[i].y * TILE_SIZE - 4, Math.floor(TILE_SIZE * hpRatio), 3, Colors.Red);
}

// Draw player
Expand All @@ -398,9 +398,9 @@ while (!windowShouldClose()) {

// HUD
drawRect(0, 0, SCREEN_WIDTH, 35, { r: 0, g: 0, b: 0, a: 180 });
drawText("HP: " + player.hp.toString() + "/" + player.maxHp.toString(), 10, 8, 20, player.hp > player.maxHp / 3 ? Color.Green : Color.Red);
drawText("Floor: " + floor.toString(), 200, 8, 20, Color.White);
drawText("Turns: " + turnCount.toString(), 350, 8, 20, Color.LightGray);
drawText("HP: " + player.hp.toString() + "/" + player.maxHp.toString(), 10, 8, 20, player.hp > player.maxHp / 3 ? Colors.Green : Colors.Red);
drawText("Floor: " + floor.toString(), 200, 8, 20, Colors.White);
drawText("Turns: " + turnCount.toString(), 350, 8, 20, Colors.LightGray);

// Message log
if (messageTimer > 0) {
Expand All @@ -412,9 +412,9 @@ while (!windowShouldClose()) {
if (player.hp <= 0) {
drawRect(0, SCREEN_HEIGHT / 2 - 50, SCREEN_WIDTH, 100, { r: 0, g: 0, b: 0, a: 200 });
const deathMsg = "You have perished on floor " + floor.toString();
drawText(deathMsg, SCREEN_WIDTH / 2 - measureText(deathMsg, 24) / 2, SCREEN_HEIGHT / 2 - 20, 24, Color.Red);
drawText(deathMsg, SCREEN_WIDTH / 2 - measureText(deathMsg, 24) / 2, SCREEN_HEIGHT / 2 - 20, 24, Colors.Red);
const restartMsg = "Press ENTER to try again";
drawText(restartMsg, SCREEN_WIDTH / 2 - measureText(restartMsg, 18) / 2, SCREEN_HEIGHT / 2 + 15, 18, Color.LightGray);
drawText(restartMsg, SCREEN_WIDTH / 2 - measureText(restartMsg, 18) / 2, SCREEN_HEIGHT / 2 + 15, 18, Colors.LightGray);
}

endDrawing();
Expand Down
Loading
Loading