Build Packages / Create release (push) Successful in 21s
Build Packages / build:portable:macos-arm64:nocuda (push) Successful in 5m11s
Build Packages / build:rugnux:linux-aarch64:cuda (push) Successful in 7m47s
Build Packages / build:portable:linux-x86_64:nocuda (push) Successful in 13m9s
Build Packages / HDF5 consumer tests (DIALS, XDS) (push) Successful in 24m3s
Build Packages / build:portable:linux-x86_64:cuda (push) Successful in 15m53s
Build Packages / build:jfjoch:rocky8:nocuda (push) Successful in 16m4s
Build Packages / build:portable:windows-x86_64:nocuda (push) Successful in 22m33s
Build Packages / build:jfjoch:rocky9:nocuda (push) Successful in 17m46s
Build Packages / build:portable:windows-x86_64:cuda (push) Successful in 26m48s
Build Packages / build:jfjoch:ubuntu2204:nocuda (push) Successful in 14m35s
Build Packages / build:jfjoch:ubuntu2404:nocuda (push) Successful in 20m11s
Build Packages / build:jfjoch:rocky8:cuda-sls9 (push) Successful in 23m11s
Build Packages / build:jfjoch:rocky9:cuda-sls9 (push) Successful in 25m28s
Build Packages / Generate python client (push) Successful in 20s
Build Packages / Build documentation (push) Successful in 1m4s
Build Packages / build:jfjoch:rocky8:cuda (push) Successful in 23m8s
Build Packages / build:jfjoch:ubuntu2204:cuda (push) Successful in 15m47s
Build Packages / build:jfjoch:rocky9:cuda (push) Successful in 25m30s
Build Packages / build:jfjoch:ubuntu2404:cuda (push) Successful in 18m34s
Build Packages / Unit tests (push) Successful in 1h34m12s
Build Packages / Validation Battery (push) Successful in 35m33s
The two pixel-level differences left between the Metal kernels and the CPU engine are closed:
- clip_sums follows the radial curve handed over by RadialBackgroundFromRings (RadialClipOffset, written
out line for line as radial_clip_offset; the curve in buffer 11, BraggPassAFrame::n_curve), so the
CPU fallback for such frames (3467c2191) is removed;
- box_sums counts the saturated signal-disk pixels (BraggBoxSums::n_saturated), so a still's overload
kept as a lower bound counts them at the saturation limit, as on the CPU and CUDA.
Everything else - the gain (clip floor, sigma floor, fit floor, Finalize), the radial correction and D14 -
is the CPU engine's own host code on the Metal path already.
The structs the host hands the kernels carry static_asserts on their size in the shared headers, so the
host and the Metal compiler check the same numbers.
The [Metal] bit-identity test now covers the handed-over curve under every integrator, stills keeping
overloads (overloads_kept compared and required non-zero), gains 4 and 1.7, and a footprint still with a
curve; `clipped` is compared too. A [portable] CPU-only case checks everywhere that these cases reach
their modes. Not compiled here (no macOS): the Mac CI job is the check.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015CeEGgpKdfkCTJb3YNMJcu
(cherry picked from commit 285d40c99b6356a52d224e610bc7b28d69973a06)
61 lines
3.2 KiB
C++
61 lines
3.2 KiB
C++
// SPDX-FileCopyrightText: 2026 Filip Leonarski, Paul Scherrer Institute <filip.leonarski@psi.ch>
|
|
// SPDX-License-Identifier: GPL-3.0-only
|
|
|
|
#pragma once
|
|
|
|
// Pass B of BraggIntegrationEngineCPU, the profile fit, as the data it hands on. The CPU works out in
|
|
// double what one reflection's fit needs (BraggFitSetup), the fit itself is single precision
|
|
// (BraggFitOut), and the CPU finishes it in double. The Metal engine runs the middle on the GPU, so this
|
|
// is compiled by the host and by the Metal compiler (no default member initialisers, as in BraggPassA.h).
|
|
|
|
#ifndef __METAL_VERSION__
|
|
#include <cstdint>
|
|
|
|
#include "BraggExp.h" // the Metal engine puts it in front
|
|
#endif
|
|
|
|
struct BraggFitSetup {
|
|
float px, py; // predicted position
|
|
int32_t cx, cy; // profile grid centre
|
|
int32_t Rf; // grid half-size
|
|
int32_t shell; // the learned profile of this shell, or -1: the Gaussian below
|
|
uint32_t cells; // where the Metal engine keeps the Gaussian, Gf^2 floats
|
|
int32_t fit; // 0: not fitted (no pass A result, or overloaded)
|
|
int32_t footprint; // the stencil has a measured footprint: it decides the signal disk
|
|
float fx, fy; // sub-pixel offset of the prediction from the grid centre
|
|
float ux, uy; // radial direction
|
|
float inv_2s2r, inv_2s2t; // 1 / (2 sigma^2), radially and tangentially
|
|
float bkg; // background per pixel
|
|
float B, v_min; // the variance model's floor, and the least variance a weight takes
|
|
float I0; // the box sum, where the fit starts
|
|
};
|
|
|
|
struct BraggFitOut {
|
|
float p_grid, p_valid, p_own; // profile mass on the detector, readable, and this reflection's own
|
|
float p_peak, p_lost_peak; // the largest profile value, and the largest one unreadable
|
|
float m_all, m_read; // mass in the signal disk, and the part the box sum read
|
|
float I, den, wsum; // the fit; den = 0 when it did not run or failed
|
|
};
|
|
|
|
// What the Metal engine's fit kernel is told about the frame, beside the stencil.
|
|
struct BraggPassBFrame {
|
|
int32_t width, height;
|
|
float r1_sq;
|
|
int32_t R; // the learned profiles' grid half-size
|
|
int32_t use_owner, exclude; // as in BraggPassAFrame
|
|
uint32_t n; // reflections
|
|
};
|
|
|
|
// Compiled on both sides, so a layout the host and the Metal compiler disagree on fails to compile.
|
|
static_assert(sizeof(BraggFitSetup) == 76, "BraggFitSetup layout shared with the Metal kernels");
|
|
static_assert(sizeof(BraggFitOut) == 40, "BraggFitOut layout shared with the Metal kernels");
|
|
static_assert(sizeof(BraggPassBFrame) == 28, "BraggPassBFrame layout shared with the Metal kernels");
|
|
|
|
// The Gaussian profile's (unnormalised) value at grid offset (dx, dy).
|
|
inline float BraggGaussian(int dx, int dy, float fx, float fy, float ux, float uy, float inv_2s2r,
|
|
float inv_2s2t) {
|
|
const float ex = dx - fx, ey = dy - fy;
|
|
const float rad = ex * ux + ey * uy, tn = -ex * uy + ey * ux;
|
|
return BraggExp(-rad * rad * inv_2s2r - tn * tn * inv_2s2t);
|
|
}
|