Used to key GPU dispatch memoization within a single VisionGpuExecutor::run() call, so an op run earlier in a sequence with identical parameters can be reused rather than redispatched (e.g. Canny reusing an earlier Sobel step).
370{
371 size_t seed = std::hash<std::string_view> {}(Reflect::enum_to_string(op));
372
373 std::visit([&seed](const auto& p) {
374 using T = std::decay_t<decltype(p)>;
375 if constexpr (std::is_same_v<T, std::monostate>) {
376 } else if constexpr (std::is_same_v<T, ThresholdParams>) {
377 hash_combine(seed, std::hash<float> {}(p.value));
378 } else if constexpr (std::is_same_v<T, ThresholdAdaptiveParams>) {
379 hash_combine(seed, std::hash<uint32_t> {}(p.block_size));
381 } else if constexpr (std::is_same_v<T, NormalizeRangeParams>) {
384 } else if constexpr (std::is_same_v<T, GaussianBlurParams>) {
386 } else if constexpr (std::is_same_v<T, FilterSeparableParams>) {
387 for (float v : p.kernel_x)
389 for (float v : p.kernel_y)
391 } else if constexpr (std::is_same_v<T, CannyParams>) {
393 hash_combine(seed, std::hash<float> {}(p.low_threshold));
394 hash_combine(seed, std::hash<float> {}(p.high_threshold));
395 } else if constexpr (std::is_same_v<T, MorphParams>) {
397 } else if constexpr (std::is_same_v<T, HarrisParams>) {
400 } else if constexpr (std::is_same_v<T, ExtractPeaksParams>) {
402 hash_combine(seed, std::hash<uint32_t> {}(p.nms_radius));
403 } else if constexpr (std::is_same_v<T, TrackKeypointsParams>) {
404 hash_combine(seed, std::hash<uint32_t> {}(p.window_radius));
405 hash_combine(seed, std::hash<uint32_t> {}(p.max_iterations));
406 hash_combine(seed, std::hash<float> {}(p.eigen_threshold));
407 hash_combine(seed, std::hash<float> {}(p.error_threshold));
408 } else if constexpr (std::is_same_v<T, FindContoursParams>) {
410 hash_combine(seed, std::hash<uint32_t> {}(p.max_contours));
411 }
412 },
413 params);
414
415 return seed;
416}
void hash_combine(size_t &seed, size_t value)
Combine a hash into an existing seed, FNV-style.