// SPDX-FileCopyrightText: 2026 Filip Leonarski, Paul Scherrer Institute // SPDX-License-Identifier: GPL-3.0-only #pragma once #include "BraggIntegrationEngine.h" class CompressedImage; // Plain-C++ reference/fallback engine: a faithful serial re-expression of BraggIntegrate2D (box // sum) and ProfileIntegrate2D (Kabsch profile fit) reading the preprocessed int32 image. Also the // numeric oracle the CUDA engine is checked against. class BraggIntegrationEngineCPU : public BraggIntegrationEngine { // Core integrator, templated on a pixel sampler so it reads either the preprocessed int32 buffer // or a raw CompressedImage of any pixel type - both presented per-pixel in the INT32_MIN(masked)/ // INT32_MAX(saturated) convention - without ever materialising a second full-image copy. // Full-frame scratch of RunImpl: the reflection mask and the signal-region owner map. Kept from // call to call rather than allocated per image - at 18 Mpixel that was 90 MB, a fresh mmap and a // page fault per 4 kB every call - and put back to their empty state one rectangle at a time: the // rectangles a call writes are recorded, and the next call clears exactly those before it starts. struct Rect { int x0, x1, y0, y1; }; std::vector refl_mask; std::vector owner; std::vector refl_mask_dirty; std::vector owner_dirty; template std::vector RunImpl(const Sampler &img, const std::vector &predicted, size_t npredicted, int64_t image_number); public: explicit BraggIntegrationEngineCPU(const DiffractionExperiment &experiment); using BraggIntegrationEngine::Run; // keep the preprocessed-buffer overload visible std::vector Run(const ImagePreprocessorBuffer &image, const std::vector &predicted, size_t npredicted, int64_t image_number) override; // FPGA workflow: integrate straight off the assembled detector image, reading only the pixels // inside each reflection disk (no whole-image conversion - the FPGA host cannot afford one at its // frame rate). Masked pixels carry the type minimum and saturated the type maximum. std::vector Run(const CompressedImage &image, const std::vector &predicted, size_t npredicted, int64_t image_number); };