layers/kernel.h
| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | /// @file | ||
| 2 | /// @brief `ApplyKernel`, applying a kernel on whichever backend a layer context gives. | ||
| 3 | #pragma once | ||
| 4 | |||
| 5 | #include "terraingen/gpu/kernel.h" | ||
| 6 | #include "terraingen/layers/kernels/cell.h" | ||
| 7 | #include "terraingen/layers/layer.h" | ||
| 8 | #include "terraingen/raster/cell_loops.h" | ||
| 9 | |||
| 10 | #include <span> | ||
| 11 | |||
| 12 | namespace terraingen { | ||
| 13 | |||
| 14 | /// The position a kernel sees for surface point (x, y): measured from `origin`, in single | ||
| 15 | /// precision. | ||
| 16 | 74605001 | inline CellPosition MakeCellPosition(double x, double y, const Vec2d& origin) { | |
| 17 | 74605001 | CellPosition position; | |
| 18 | 74605001 | position.x = static_cast<float>(x - origin.x); | |
| 19 | 74605001 | position.y = static_cast<float>(y - origin.y); | |
| 20 | 74605001 | return position; | |
| 21 | } | ||
| 22 | |||
| 23 | /// Applies `kernel` (`ApplyCell` in its kernel header) to every sample holding data. | ||
| 24 | /// | ||
| 25 | /// A grid runs on the context's GPU backend when it has one and `RunKernel` can take the grid, | ||
| 26 | /// with the kernel `terraingen_add_kernel` compiled (`CompiledKernel`), otherwise on the CPU over | ||
| 27 | /// `context.threads`; points always run on the CPU. The CPU and the GPU evaluate the same kernel | ||
| 28 | /// header at the same positions, so they agree to within float rounding. | ||
| 29 | template <typename Kernel> | ||
| 30 | 41772527 | void ApplyKernel(SampleBlock& samples, const LayerContext& context, const Kernel& kernel, | |
| 31 | const Vec2d& origin) { | ||
| 32 | 41772527 | if (Raster<float>* grid = samples.Grid()) { | |
| 33 | 898 | if (context.backend != Backend::Cpu && | |
| 34 | 898 | RunKernel(context.backend, CompiledKernel<Kernel>(), | |
| 35 | std::as_bytes(std::span(&kernel, 1)), *grid, origin)) { | ||
| 36 | 13 | return; | |
| 37 | } | ||
| 38 | 870 | MapCells(*grid, context.threads, [&](float height, const Vec2d& centre) { | |
| 39 | 32036529 | return ApplyCell(kernel, height, MakeCellPosition(centre.x, centre.y, origin)); | |
| 40 | }); | ||
| 41 | 870 | return; | |
| 42 | } | ||
| 43 | 84340117 | for (std::size_t i = 0; i < samples.Size(); ++i) { | |
| 44 | 42568473 | if (!samples.IsNoData(i)) { | |
| 45 | 42568472 | const Vec2d p = samples.Position(i); | |
| 46 | 42568472 | samples.Height(i) = | |
| 47 | 42568472 | ApplyCell(kernel, samples.Height(i), MakeCellPosition(p.x, p.y, origin)); | |
| 48 | } | ||
| 49 | } | ||
| 50 | } | ||
| 51 | |||
| 52 | } // namespace terraingen | ||
| 53 |