|
| 1 | +name: Engine verify setup |
| 2 | +description: Toolchain, cargo-nextest, Rust cache, native deps and fixture cache for the engine verification suite |
| 3 | +inputs: |
| 4 | + target: |
| 5 | + description: Rust target triple |
| 6 | + required: true |
| 7 | + tier: |
| 8 | + description: fast or full (fixture cache key) |
| 9 | + required: true |
| 10 | + rust-cache: |
| 11 | + description: Restore the Rust build cache (build jobs only) |
| 12 | + default: "true" |
| 13 | +outputs: |
| 14 | + build-cache-key: |
| 15 | + description: Key to save the build cache under |
| 16 | + value: ${{ steps.build-key.outputs.key }} |
| 17 | + build-cache-hit: |
| 18 | + description: Whether the build cache was restored exactly |
| 19 | + value: ${{ steps.build-cache.outputs.cache-hit }} |
| 20 | + fixtures-hit: |
| 21 | + description: Whether the fixture cache was restored exactly |
| 22 | + value: ${{ steps.fixtures.outputs.cache-hit }} |
| 23 | + fixtures-key: |
| 24 | + description: Fixture cache key |
| 25 | + value: ${{ steps.fixtures.outputs.cache-primary-key }} |
| 26 | +runs: |
| 27 | + using: composite |
| 28 | + steps: |
| 29 | + # Only what the suite's dependency closure links against (no webkit/gtk), |
| 30 | + # plus lavapipe for software Vulkan rendering. |
| 31 | + - name: Linux packages |
| 32 | + if: runner.os == 'Linux' |
| 33 | + shell: bash |
| 34 | + run: | |
| 35 | + sudo apt-get update -qq |
| 36 | + sudo apt-get install -y -qq --no-install-recommends \ |
| 37 | + libasound2-dev libasound2-plugins libpipewire-0.3-dev libspa-0.2-dev libclang-dev \ |
| 38 | + libx11-dev libxrandr-dev libxcb1-dev libxcb-randr0-dev libxcb-shm0-dev \ |
| 39 | + libxcb-xfixes0-dev libxfixes-dev libwayland-dev libxkbcommon-dev \ |
| 40 | + libdbus-1-dev libudev-dev libva-dev mesa-vulkan-drivers libvulkan1 >/dev/null |
| 41 | +
|
| 42 | + - name: Rust toolchain |
| 43 | + if: inputs.rust-cache == 'true' |
| 44 | + uses: dtolnay/rust-toolchain@1.88.0 |
| 45 | + with: |
| 46 | + targets: ${{ inputs.target }} |
| 47 | + |
| 48 | + - name: cargo-nextest |
| 49 | + uses: taiki-e/install-action@v2 |
| 50 | + with: |
| 51 | + tool: cargo-nextest@0.9.148 |
| 52 | + |
| 53 | + # One cache entry per OS per day (saved by main, nightly and the CI dev |
| 54 | + # branches), restored by PRs. Unlike swatinem/rust-cache it includes the |
| 55 | + # workspace crates and is refreshed daily even when Cargo.lock is |
| 56 | + # unchanged, so a PR only rebuilds what changed since the last save. The |
| 57 | + # chain restarts every ISO week so stale artifacts cannot pile up. |
| 58 | + - name: Build cache key |
| 59 | + id: build-key |
| 60 | + if: inputs.rust-cache == 'true' |
| 61 | + shell: bash |
| 62 | + run: | |
| 63 | + # runner.environment separates GitHub-hosted from self-hosted |
| 64 | + # (Blacksmith) builds: their paths and toolchains differ, so one's |
| 65 | + # target directory would only force a rebuild on the other. |
| 66 | + # A new week starts a new chain, seeded from last week's newest cache |
| 67 | + # of the same provider so the first build of the week stays warm. |
| 68 | + py="$(command -v python3 || command -v python)" |
| 69 | + week="$("$py" -c 'import datetime as d; y, w, _ = d.datetime.now(d.timezone.utc).isocalendar(); print(f"{y}-W{w:02d}")')" |
| 70 | + last_week="$("$py" -c 'import datetime as d; y, w, _ = (d.datetime.now(d.timezone.utc) - d.timedelta(days=7)).isocalendar(); print(f"{y}-W{w:02d}")')" |
| 71 | + provider="verify-build-v3-${{ inputs.target }}-${{ runner.environment }}" |
| 72 | + base="$provider-$week" |
| 73 | + echo "base=$base" >> "$GITHUB_OUTPUT" |
| 74 | + echo "previous=$provider-$last_week" >> "$GITHUB_OUTPUT" |
| 75 | + echo "key=$base-${{ hashFiles('Cargo.lock', 'Cargo.toml', 'rust-toolchain.toml') }}-$(date -u +%Y%m%d)" >> "$GITHUB_OUTPUT" |
| 76 | +
|
| 77 | + - name: Restore build cache |
| 78 | + id: build-cache |
| 79 | + if: inputs.rust-cache == 'true' |
| 80 | + uses: actions/cache/restore@v4 |
| 81 | + with: |
| 82 | + path: | |
| 83 | + ~/.cargo/registry/index/ |
| 84 | + ~/.cargo/registry/cache/ |
| 85 | + ~/.cargo/git/db/ |
| 86 | + target/ci-verify/ |
| 87 | + key: ${{ steps.build-key.outputs.key }} |
| 88 | + restore-keys: | |
| 89 | + ${{ steps.build-key.outputs.base }}-${{ hashFiles('Cargo.lock', 'Cargo.toml', 'rust-toolchain.toml') }}- |
| 90 | + ${{ steps.build-key.outputs.base }}- |
| 91 | + ${{ steps.build-key.outputs.previous }}- |
| 92 | +
|
| 93 | + # Unchanged workspace crates are reused from the cache instead of being |
| 94 | + # rebuilt because the checkout touched every file (scripts/verify/mtime.py). |
| 95 | + - name: Reuse unchanged workspace crates |
| 96 | + if: inputs.rust-cache == 'true' |
| 97 | + shell: bash |
| 98 | + run: | |
| 99 | + "$(command -v python3 || command -v python)" scripts/verify/mtime.py apply target/ci-verify/verify-src-manifest.txt |
| 100 | +
|
| 101 | + - name: Native dependencies |
| 102 | + shell: bash |
| 103 | + env: |
| 104 | + RUST_TARGET_TRIPLE: ${{ inputs.target }} |
| 105 | + run: node scripts/setup.js |
| 106 | + |
| 107 | + - name: FFmpeg libraries on the loader path (Linux) |
| 108 | + if: runner.os == 'Linux' |
| 109 | + shell: bash |
| 110 | + run: echo "LD_LIBRARY_PATH=${{ github.workspace }}/target/native-deps/lib" >> "$GITHUB_ENV" |
| 111 | + |
| 112 | + # The app ships DXC next to its executable and cap-rendering looks for it |
| 113 | + # next to the test binary or in its profile dir; setup.js only fills |
| 114 | + # target/debug and target/release. Without it wgpu falls back to FXC. |
| 115 | + - name: DXC for the ci-verify profile (Windows) |
| 116 | + if: runner.os == 'Windows' |
| 117 | + shell: bash |
| 118 | + run: | |
| 119 | + mkdir -p target/ci-verify |
| 120 | + cp target/native-deps/dxc/dxcompiler.dll target/native-deps/dxc/dxil.dll target/ci-verify/ |
| 121 | +
|
| 122 | + # Debug builds of wgpu (the ci-verify profile keeps debug assertions) |
| 123 | + # enable the D3D12 debug layer whenever d3d12SDKLayers.dll exists. When |
| 124 | + # that DLL comes from an unserviced Graphics Tools feature older than the |
| 125 | + # D3D12 runtime (blacksmith-8vcpu-windows-2025: layers 10.0.26100.1591, |
| 126 | + # runtime 10.0.26100.33296), D3D12CreateDevice fails with E_INVALIDARG on |
| 127 | + # every adapter, WARP included, and every case fails "No GPU adapter |
| 128 | + # found". Hiding the mismatched layer makes D3D12GetDebugInterface report |
| 129 | + # DXGI_ERROR_SDK_COMPONENT_MISSING, which wgpu treats as "no debug layer". |
| 130 | + - name: Hide a D3D12 debug layer that does not match the runtime (Windows) |
| 131 | + if: runner.os == 'Windows' |
| 132 | + shell: pwsh |
| 133 | + run: | |
| 134 | + $sys = Join-Path $env:WINDIR 'System32' |
| 135 | + $layers = Join-Path $sys 'd3d12SDKLayers.dll' |
| 136 | + $core = Join-Path $sys 'D3D12Core.dll' |
| 137 | + if (-not (Test-Path $layers)) { Write-Host 'no D3D12 debug layer installed'; exit 0 } |
| 138 | + $lv = (Get-Item $layers).VersionInfo |
| 139 | + $cv = (Get-Item $core).VersionInfo |
| 140 | + $lver = "$($lv.FileMajorPart).$($lv.FileMinorPart).$($lv.FileBuildPart).$($lv.FilePrivatePart)" |
| 141 | + $cver = "$($cv.FileMajorPart).$($cv.FileMinorPart).$($cv.FileBuildPart).$($cv.FilePrivatePart)" |
| 142 | + Write-Host "D3D12 debug layer $lver, runtime $cver" |
| 143 | + if ($lver -eq $cver) { exit 0 } |
| 144 | + takeown /f $layers | Out-Null |
| 145 | + icacls $layers /grant "*S-1-5-32-544:F" | Out-Null |
| 146 | + Rename-Item $layers 'd3d12SDKLayers.dll.mismatched' |
| 147 | + Write-Host "hid the mismatched debug layer" |
| 148 | +
|
| 149 | + - name: FFmpeg DLLs on PATH (Windows) |
| 150 | + if: runner.os == 'Windows' |
| 151 | + shell: pwsh |
| 152 | + run: Add-Content -Path $env:GITHUB_PATH -Value "${{ github.workspace }}\target\ffmpeg\bin" |
| 153 | + |
| 154 | + - name: Fixture location |
| 155 | + shell: bash |
| 156 | + run: echo "CAP_VERIFY_FIXTURE_DIR=${{ runner.temp }}/verify-fixtures" >> "$GITHUB_ENV" |
| 157 | + |
| 158 | + # Fixtures are generated by code (including the real-pipeline Studio and |
| 159 | + # Instant recordings, ~1 min of real-time capture); the key is every |
| 160 | + # crate's source and build script, the vendored crates (wgpu-hal, tao), |
| 161 | + # the workspace manifest, lockfile and toolchain, plus the native deps. Exact key only: a fixture made |
| 162 | + # by an older generator is never reused. |
| 163 | + - name: Restore fixtures |
| 164 | + id: fixtures |
| 165 | + uses: actions/cache/restore@v4 |
| 166 | + with: |
| 167 | + path: ${{ runner.temp }}/verify-fixtures |
| 168 | + key: verify-fixtures-v1-${{ runner.os }}-${{ runner.environment }}-${{ inputs.tier }}-${{ hashFiles('crates/**/src/**', 'crates/**/build.rs', 'crates/**/Cargo.toml', 'Cargo.toml', 'Cargo.lock', 'rust-toolchain.toml', 'vendor/**', 'scripts/setup.js') }} |
0 commit comments