/* Copyright (c) 2026 The Khronos Group Inc.
 * Copyright (c) 2026 Valve Corporation
 * Copyright (c) 2026 LunarG, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "sync/sync_access_context.h"
#include "sync/sync_image.h"
#include "sync/sync_validation.h"
#include "state_tracker/buffer_state.h"

namespace syncval {

// Execute Action for each map entry in the generated ranges until it returns true
//
// Action is const w.r.t. map
// Action is allowed (assumed) to modify pos
// Action must not advance pos for ranges strictly < pos->first
// Action must handle range strictly less than pos->first correctly
// Action must handle pos == end correctly
// Action is assumed to only require invocation once per map entry
// Note: If Action invocations are heavyweight and inter-entry (gap) calls are not needed
//       add a template or function parameter to skip them. TBD.
template <typename Action>
bool ForEachEntryInRangesUntil(const AccessMap &map, ImageRangeGen &range_gen, Action &action) {
    using RangeType = ImageRangeGen::RangeType;
    using IndexType = RangeType::index_type;
    auto pos = map.LowerBound((*range_gen).begin);
    const auto end = map.end();
    IndexType skip_limit = 0;
    for (; range_gen->non_empty() && pos != end; ++range_gen) {
        RangeType range = *range_gen;
        // See if a prev pos has covered this range
        if (range.end <= skip_limit) {
            // Since the map is const, we needn't call action on the same pos again
            continue;
        }

        //  If the current range was *partially* covered be a previous pos, trim, such that Action is only
        //  called once for a given range (and pos)
        if (range.begin < skip_limit) {
            range.begin = skip_limit;
        }

        // Now advance pos as needed to match range
        if (pos->first.strictly_less(range)) {
            ++pos;
            if (pos == end) break;
            if (pos->first.strictly_less(range)) {
                pos = map.LowerBound(range.begin);
                if (pos == end) break;
            }
            assert(pos == map.LowerBound(range.begin));
        }

        // If the range intersects pos->first, consider Action performed for that map entry, and
        // make sure not to call Action for this pos for any subsequent ranges
        skip_limit = range.end > pos->first.begin ? pos->first.end : 0U;

        // Action is allowed to alter pos but shouldn't do so if range is strictly < pos->first
        if (action(range, end, pos)) return true;
    }

    // Action needs to handle the "at end " condition (and can be useful for recursive actions)
    for (; range_gen->non_empty(); ++range_gen) {
        if (action(*range_gen, end, pos)) return true;
    }

    return false;
}

template <typename DetectorRunner>
HazardResult DoDetect(const AccessContext &access_context, const AccessState &access_state, DetectorRunner detector_runner) {
    if (access_state.next_global_barrier_index < access_context.GetGlobalBarrierCount()) {
        AccessState new_access_state = AccessState::DefaultAccessState();
        new_access_state.Assign(access_state);
        access_context.ApplyGlobalBarriers(new_access_state);
        return detector_runner(new_access_state);
    } else {
        return detector_runner(access_state);
    }
}

class HazardDetector {
  public:
    HazardDetector(SyncAccessIndex access_index, const AccessContext &access_context)
        : access_info_(GetAccessInfo(access_index)), access_context_(access_context) {}

    HazardResult Detect(const AccessMap::const_iterator &pos) const {
        return DoDetect(access_context_, pos->second,
                        [this](const AccessState &access_state) { return access_state.DetectHazard(access_info_); });
    }

    HazardResult DetectAsync(const AccessMap::const_iterator &pos, ResourceUsageTag start_tag, QueueId queue_id) const {
        return DoDetect(access_context_, pos->second, [this, start_tag, queue_id](const AccessState &access_state) {
            return access_state.DetectAsyncHazard(access_info_, start_tag, queue_id);
        });
    }

  private:
    const SyncAccessInfo &access_info_;
    const AccessContext &access_context_;
};

class HazardDetectorAttachment {
  public:
    HazardDetectorAttachment(SyncAccessIndex access_index, const AttachmentAccess &attachment_access,
                             const AccessContext &access_context, bool detect_load_op_after_store_op_hazards)
        : access_info_(GetAccessInfo(access_index)),
          attachment_access_(attachment_access),
          access_context_(access_context),
          detect_load_op_after_store_op_hazards(detect_load_op_after_store_op_hazards) {}

    HazardResult Detect(const AccessMap::const_iterator &pos) const {
        const OrderingBarrier &ordering = GetOrderingRules(attachment_access_.ordering);
        return DoDetect(access_context_, pos->second, [this, &ordering](const AccessState &access_state) {
            return access_state.DetectHazard(access_info_, ordering, attachment_access_, 0, kQueueIdInvalid,
                                             detect_load_op_after_store_op_hazards);
        });
    }

    HazardResult DetectAsync(const AccessMap::const_iterator &pos, ResourceUsageTag start_tag, QueueId queue_id) const {
        return DoDetect(access_context_, pos->second, [this, start_tag, queue_id](const AccessState &access_state) {
            return access_state.DetectAsyncHazard(access_info_, start_tag, queue_id);
        });
    }

  private:
    const SyncAccessInfo &access_info_;
    const AttachmentAccess attachment_access_;
    const AccessContext &access_context_;
    const bool detect_load_op_after_store_op_hazards;
};

class HazardDetectFirstUse {
  public:
    HazardDetectFirstUse(const AccessState &recorded_use, QueueId queue_id, const ResourceUsageRange &tag_range,
                         const AccessContext &access_context, bool detect_load_op_after_store_op_hazards)
        : recorded_use_(recorded_use),
          queue_id_(queue_id),
          tag_range_(tag_range),
          access_context_(access_context),
          detect_load_op_after_store_op_hazards(detect_load_op_after_store_op_hazards) {}

    HazardResult Detect(const AccessMap::const_iterator &pos) const {
        return DoDetect(access_context_, pos->second, [this](const AccessState &access_state) {
            return access_state.DetectHazard(recorded_use_, queue_id_, tag_range_, detect_load_op_after_store_op_hazards);
        });
    }

    HazardResult DetectAsync(const AccessMap::const_iterator &pos, ResourceUsageTag start_tag, QueueId queue_id) const {
        return DoDetect(access_context_, pos->second, [this, start_tag, queue_id](const AccessState &access_state) {
            return access_state.DetectAsyncHazard(recorded_use_, tag_range_, start_tag, queue_id);
        });
    }

  private:
    const AccessState &recorded_use_;
    const QueueId queue_id_;
    const ResourceUsageRange &tag_range_;
    const AccessContext &access_context_;
    const bool detect_load_op_after_store_op_hazards;
};

struct HazardDetectorMarker {
    HazardDetectorMarker(const AccessContext &access_context) : access_context(access_context) {}

    HazardResult Detect(const AccessMap::const_iterator &pos) const {
        return DoDetect(access_context, pos->second,
                        [](const AccessState &access_state) { return access_state.DetectMarkerHazard(); });
    }

    HazardResult DetectAsync(const AccessMap::const_iterator &pos, ResourceUsageTag start_tag, QueueId queue_id) const {
        return DoDetect(access_context, pos->second, [start_tag, queue_id](const AccessState &access_state) {
            return access_state.DetectAsyncHazard(GetAccessInfo(SYNC_COPY_TRANSFER_WRITE), start_tag, queue_id);
        });
    }

    const AccessContext &access_context;
};

class BarrierHazardDetector {
  public:
    BarrierHazardDetector(const AccessContext &access_context, SyncAccessIndex access_index, VkPipelineStageFlags2 src_exec_scope,
                          SyncAccessFlags src_access_scope)
        : access_context_(access_context),
          access_info_(GetAccessInfo(access_index)),
          src_exec_scope_(src_exec_scope),
          src_access_scope_(src_access_scope) {}

    HazardResult Detect(const AccessMap::const_iterator &pos) const {
        return DoDetect(access_context_, pos->second, [this](const AccessState &access_state) {
            return access_state.DetectBarrierHazard(access_info_, kQueueIdInvalid, src_exec_scope_, src_access_scope_);
        });
    }

    HazardResult DetectAsync(const AccessMap::const_iterator &pos, ResourceUsageTag start_tag, QueueId queue_id) const {
        return DoDetect(access_context_, pos->second, [this, start_tag, queue_id](const AccessState &access_state) {
            return access_state.DetectAsyncHazard(access_info_, start_tag, queue_id);
        });
    }

  private:
    const AccessContext &access_context_;
    const SyncAccessInfo &access_info_;
    VkPipelineStageFlags2 src_exec_scope_;
    SyncAccessFlags src_access_scope_;
};

class EventBarrierHazardDetector {
  public:
    EventBarrierHazardDetector(SyncAccessIndex access_index, VkPipelineStageFlags2 src_exec_scope, SyncAccessFlags src_access_scope,
                               const AccessContext::ScopeMap &event_scope, QueueId queue_id, ResourceUsageTag scope_tag)
        : access_info_(GetAccessInfo(access_index)),
          src_exec_scope_(src_exec_scope),
          src_access_scope_(src_access_scope),
          event_scope_(event_scope),
          scope_queue_id_(queue_id),
          scope_tag_(scope_tag),
          scope_pos_(event_scope.begin()),
          scope_end_(event_scope.end()) {}

    HazardResult Detect(const AccessMap::const_iterator &pos) {
        // Need to piece together coverage of pos->first range:
        // Copy the range as we'll be chopping it up as needed
        AccessRange range = pos->first;
        const AccessState &access = pos->second;
        HazardResult hazard;

        bool in_scope = AdvanceScope(range);
        bool unscoped_tested = false;
        while (in_scope && !hazard.IsHazard()) {
            if (range.begin < ScopeBegin()) {
                if (!unscoped_tested) {
                    unscoped_tested = true;
                    hazard = access.DetectHazard(access_info_);
                }
                // Note: don't need to check for in_scope as AdvanceScope true means range and ScopeRange intersect.
                // Thus a [ ScopeBegin, range.end ) will be non-empty.
                range.begin = ScopeBegin();
            } else {  // in_scope implied that ScopeRange and range intersect
                hazard = access.DetectBarrierHazard(access_info_, ScopeState(), src_exec_scope_, src_access_scope_, scope_queue_id_,
                                                    scope_tag_);
                if (!hazard.IsHazard()) {
                    range.begin = ScopeEnd();
                    in_scope = AdvanceScope(range);  // contains a non_empty check
                }
            }
        }
        if (range.non_empty() && !hazard.IsHazard() && !unscoped_tested) {
            hazard = access.DetectHazard(access_info_);
        }
        return hazard;
    }

    HazardResult DetectAsync(const AccessMap::const_iterator &pos, ResourceUsageTag start_tag, QueueId queue_id) const {
        // Async barrier hazard detection can use the same path as the usage index is not IsRead, but is IsWrite
        return pos->second.DetectAsyncHazard(access_info_, start_tag, queue_id);
    }

  private:
    bool ScopeInvalid() const { return scope_pos_ == scope_end_; }
    bool ScopeValid() const { return !ScopeInvalid(); }
    void ScopeSeek(const AccessRange &range) { scope_pos_ = event_scope_.LowerBound(range.begin); }

    // Hiding away the std::pair grunge...
    ResourceAddress ScopeBegin() const { return scope_pos_->first.begin; }
    ResourceAddress ScopeEnd() const { return scope_pos_->first.end; }
    const AccessRange &ScopeRange() const { return scope_pos_->first; }
    const AccessState &ScopeState() const { return scope_pos_->second; }

    bool AdvanceScope(const AccessRange &range) {
        // Note: non_empty is (valid && !empty), so don't change !non_empty to empty...
        if (!range.non_empty()) return false;
        if (ScopeInvalid()) return false;

        if (ScopeRange().strictly_less(range)) {
            ScopeSeek(range);
        }

        return ScopeValid() && ScopeRange().intersects(range);
    }

    const SyncAccessInfo access_info_;
    VkPipelineStageFlags2 src_exec_scope_;
    SyncAccessFlags src_access_scope_;
    const AccessContext::ScopeMap &event_scope_;
    QueueId scope_queue_id_;
    const ResourceUsageTag scope_tag_;
    AccessContext::ScopeMap::const_iterator scope_pos_;
    AccessContext::ScopeMap::const_iterator scope_end_;
};

HazardResult AccessContext::DetectHazard(const vvl::Buffer &buffer, SyncAccessIndex access_index, const AccessRange &range) const {
    if (!SimpleBinding(buffer)) {
        return {};
    }
    const auto base_address = ResourceBaseAddress(buffer);
    HazardDetector detector(access_index, *this);
    return DetectHazardRange(detector, (range + base_address), DetectOptions::kDetectAll);
}

HazardResult AccessContext::DetectHazard(ImageRangeGen &range_gen, SyncAccessIndex current_usage) const {
    HazardDetector detector(current_usage, *this);
    return DetectHazardGeneratedRangeGen(detector, range_gen, DetectOptions::kDetectAll);
}

HazardResult AccessContext::DetectHazard(const vvl::Image &image, const VkImageSubresourceRange &subresource_range,
                                         SyncAccessIndex current_usage) const {
    const auto &sub_state = SubState(image);
    HazardDetector detector(current_usage, *this);
    ImageRangeGen range_gen = sub_state.MakeImageRangeGen(subresource_range, false);
    return DetectHazardGeneratedRangeGen(detector, range_gen, DetectOptions::kDetectAll);
}

HazardResult AccessContext::DetectHazard(const vvl::Image &image, const VkImageSubresourceRange &subresource_range,
                                         const VkOffset3D &offset, const VkExtent3D &extent, SyncAccessIndex current_usage) const {
    const auto &sub_state = SubState(image);
    HazardDetector detector(current_usage, *this);
    ImageRangeGen range_gen = sub_state.MakeImageRangeGen(subresource_range, offset, extent, false);
    return DetectHazardGeneratedRangeGen(detector, range_gen, DetectOptions::kDetectAll);
}

HazardResult AccessContext::DetectHazard(const vvl::ImageView &image_view, SyncAccessIndex current_usage) const {
    HazardDetector detector(current_usage, *this);
    ImageRangeGen range_gen = MakeImageRangeGen(image_view);
    return DetectHazardGeneratedRangeGen(detector, range_gen, DetectOptions::kDetectAll);
}

HazardResult AccessContext::DetectHazard(const vvl::ImageView &image_view, const VkOffset3D &offset, const VkExtent3D &extent,
                                         SyncAccessIndex current_usage) const {
    HazardDetector detector(current_usage, *this);
    ImageRangeGen range_gen(MakeImageRangeGen(image_view, offset, extent));
    return DetectHazardGeneratedRangeGen(detector, range_gen, DetectOptions::kDetectAll);
}

HazardResult AccessContext::DetectAttachmentHazard(ImageRangeGen &range_gen, SyncAccessIndex current_usage,
                                                   const AttachmentAccess &attachment_access) const {
    HazardDetectorAttachment detector(current_usage, attachment_access, *this,
                                      validator->syncval_settings.load_op_after_store_op_validation);
    return DetectHazardGeneratedRangeGen(detector, range_gen, DetectOptions::kDetectAll);
}

HazardResult AccessContext::DetectAttachmentHazard(const AttachmentViewGen &view_gen, AttachmentViewGen::Gen gen_type,
                                                   SyncAccessIndex current_usage, const AttachmentAccess &attachment_access,
                                                   uint32_t view_mask) const {
    if (view_mask == 0) {
        ImageRangeGen range_gen = view_gen.GetRangeGen(gen_type);
        return DetectAttachmentHazard(range_gen, current_usage, attachment_access);
    } else {
        uint32_t view_index = 0;
        while (view_mask) {
            if (view_mask & 1) {
                ImageRangeGen range_gen = view_gen.GetRangeGen(gen_type, view_index);
                auto hazard = DetectAttachmentHazard(range_gen, current_usage, attachment_access);
                if (hazard.IsHazard()) {
                    return hazard;
                }
            }
            view_mask >>= 1;
            view_index++;
        }
        return {};
    }
}

HazardResult AccessContext::DetectAttachmentHazard(const vvl::Image &image, const VkImageSubresourceRange &subresource_range,
                                                   bool is_depth_sliced, SyncAccessIndex current_usage,
                                                   const AttachmentAccess &attachment_access) const {
    const auto &sub_state = SubState(image);
    HazardDetectorAttachment detector(current_usage, attachment_access, *this, false);
    ImageRangeGen range_gen = sub_state.MakeImageRangeGen(subresource_range, is_depth_sliced);
    return DetectHazardGeneratedRangeGen(detector, range_gen, DetectOptions::kDetectAll);
}

HazardResult AccessContext::DetectAttachmentHazard(const vvl::ImageView &image_view, const VkOffset3D &offset,
                                                   const VkExtent3D &extent, SyncAccessIndex current_usage,
                                                   const AttachmentAccess &attachment_access) const {
    HazardDetectorAttachment detector(current_usage, attachment_access, *this,
                                      validator->syncval_settings.load_op_after_store_op_validation);
    ImageRangeGen range_gen(MakeImageRangeGen(image_view, offset, extent));
    return DetectHazardGeneratedRangeGen(detector, range_gen, DetectOptions::kDetectAll);
}

HazardResult AccessContext::DetectImageBarrierHazard(const vvl::Image &image, const VkImageSubresourceRange &subresource_range,
                                                     VkPipelineStageFlags2 src_exec_scope, const SyncAccessFlags &src_access_scope,
                                                     QueueId queue_id, const ScopeMap &scope_map, const ResourceUsageTag scope_tag,
                                                     AccessContext::DetectOptions options) const {
    EventBarrierHazardDetector detector(SyncAccessIndex::SYNC_IMAGE_LAYOUT_TRANSITION, src_exec_scope, src_access_scope, scope_map,
                                        queue_id, scope_tag);
    ImageRangeGen range_gen = SubState(image).MakeImageRangeGen(subresource_range, false);
    return DetectHazardGeneratedRangeGen(detector, range_gen, options);
}

HazardResult AccessContext::DetectImageBarrierHazard(const vvl::Image &image, VkPipelineStageFlags2 src_exec_scope,
                                                     const SyncAccessFlags &src_access_scope,
                                                     const VkImageSubresourceRange &subresource_range, bool is_depth_sliced,
                                                     const DetectOptions options) const {
    BarrierHazardDetector detector(*this, SyncAccessIndex::SYNC_IMAGE_LAYOUT_TRANSITION, src_exec_scope, src_access_scope);
    ImageRangeGen range_gen = SubState(image).MakeImageRangeGen(subresource_range, is_depth_sliced);
    return DetectHazardGeneratedRangeGen(detector, range_gen, options);
}

HazardResult AccessContext::DetectImageBarrierHazard(const AttachmentViewGen &view_gen, const SyncBarrier &barrier,
                                                     DetectOptions options) const {
    BarrierHazardDetector detector(*this, SyncAccessIndex::SYNC_IMAGE_LAYOUT_TRANSITION, barrier.src_exec_scope.exec_scope,
                                   barrier.src_access_scope);
    ImageRangeGen range_gen = view_gen.GetRangeGen(AttachmentViewGen::Gen::kViewSubresource);
    return DetectHazardGeneratedRangeGen(detector, range_gen, options);
}

HazardResult AccessContext::DetectSubpassTransitionHazard(const SubpassBarrier &subpass_barrier,
                                                          const AttachmentViewGen &attach_view) const {
    // Do the detection against the specific prior context independent of other contexts.  (Synchronous only)
    // Hazard detection for the transition can be against the merged of the barriers (it only uses src_...)
    const SyncBarrier merged_barrier(subpass_barrier.barriers);
    const AccessContext &src_subpass_context = *subpass_barrier.src_subpass_context;
    HazardResult hazard = src_subpass_context.DetectImageBarrierHazard(attach_view, merged_barrier, kDetectPrevious);
    if (!hazard.IsHazard()) {
        // The Async hazard check is against the current context's async set.
        SyncBarrier null_barrier = {};
        hazard = DetectImageBarrierHazard(attach_view, null_barrier, kDetectAsync);
    }

    return hazard;
}

// This is called with the *recorded* command buffers access context, with the
// *active* access context pass in, againsts which hazards will be detected
HazardResult AccessContext::DetectFirstUseHazard(QueueId queue_id, const ResourceUsageRange &tag_range,
                                                 const AccessContext &access_context) const {
    // If the context is finalized we have a fast path to find first accesses within a range
    if (finalized_) {
        for (const auto &single_tag : sorted_first_accesses_.IterateSingleTagFirstAccesses(tag_range)) {
            const AccessRange access_range = single_tag.p_key_value->first;
            const AccessState &access = single_tag.p_key_value->second;

            // For single tag first accesses we have exact search and can assert the find
            assert(access.FirstAccessInTagRange(tag_range));

            HazardDetectFirstUse detector(access, queue_id, tag_range, access_context,
                                          validator->syncval_settings.load_op_after_store_op_validation);
            HazardResult hazard = access_context.DetectHazardRange(detector, access_range, DetectOptions::kDetectAll);
            if (hazard.IsHazard()) {
                return hazard;
            }
        }
        for (const auto &multi_tag : sorted_first_accesses_.IterateMultiTagFirstAccesses(tag_range)) {
            const AccessRange access_range = multi_tag.p_key_value->first;
            const AccessState &access = multi_tag.p_key_value->second;

            // For multi tag first accesses the search is not exact, so we need to check for range inclusion
            // (on average multi tag search is faster than going over the entire access map)
            if (!access.FirstAccessInTagRange(tag_range)) {
                continue;
            }

            HazardDetectFirstUse detector(access, queue_id, tag_range, access_context,
                                          validator->syncval_settings.load_op_after_store_op_validation);
            HazardResult hazard = access_context.DetectHazardRange(detector, access_range, DetectOptions::kDetectAll);
            if (hazard.IsHazard()) {
                return hazard;
            }
        }
    }
    // The context is not finalized. We have to iterate over the entire access map
    else {
        for (const auto &recorded_access : access_state_map_) {
            // Cull any entries not in the current tag range
            if (!recorded_access.second.FirstAccessInTagRange(tag_range)) {
                continue;
            }
            HazardDetectFirstUse detector(recorded_access.second, queue_id, tag_range, access_context,
                                          validator->syncval_settings.load_op_after_store_op_validation);
            HazardResult hazard = access_context.DetectHazardRange(detector, recorded_access.first, DetectOptions::kDetectAll);
            if (hazard.IsHazard()) {
                return hazard;
            }
        }
    }
    return {};
}

HazardResult AccessContext::DetectVideoHazard(const vvl::VideoSession &vs_state, const vvl::VideoPictureResource &resource,
                                              SyncAccessIndex current_usage) const {
    const vvl::Image &image = *resource.image_state.get();
    const auto &sub_state = SubState(image);
    const auto offset = resource.GetEffectiveImageOffset(vs_state);
    const auto extent = resource.GetEffectiveImageExtent(vs_state);
    ImageRangeGen range_gen(sub_state.MakeImageRangeGen(resource.range, offset, extent, false));
    HazardDetector detector(current_usage, *this);
    return DetectHazardGeneratedRangeGen(detector, range_gen, DetectOptions::kDetectAll);
}

HazardResult AccessContext::DetectMarkerHazard(const vvl::Buffer &buffer, const AccessRange &range) const {
    if (!SimpleBinding(buffer)) {
        return HazardResult();
    }
    const VkDeviceSize base_address = ResourceBaseAddress(buffer);
    HazardDetectorMarker detector(*this);
    return DetectHazardRange(detector, (range + base_address), DetectOptions::kDetectAll);
}

template <typename Detector>
HazardResult AccessContext::DetectHazardRange(Detector &detector, const AccessRange &range, DetectOptions options) const {
    if (!range.non_empty()) {
        return {};
    }

    HazardResult hazard;

    if (static_cast<uint32_t>(options) & DetectOptions::kDetectAsync) {
        // Async checks don't require recursive lookups, as the async lists are
        // exhaustive for the top-level context so we'll check these first
        for (const auto &async_ref : async_) {
            hazard = async_ref.Context().DetectAsyncHazard(detector, range, async_ref.StartTag(), async_ref.GetQueueId());
            if (hazard.IsHazard()) {
                return hazard;
            }
        }
    }
    const bool detect_prev = (options & DetectOptions::kDetectPrevious) != 0;
    auto pos = access_state_map_.LowerBound(range.begin);
    hazard = DetectHazardOneRange(detector, detect_prev, pos, access_state_map_.end(), range);
    return hazard;
}

template <typename Detector>
HazardResult AccessContext::DetectHazardGeneratedRangeGen(Detector &detector, ImageRangeGen &range_gen,
                                                          DetectOptions options) const {
    HazardResult hazard;

    if ((options & DetectOptions::kDetectAsync) != 0) {
        // Async checks don't require recursive lookups, as the async lists are
        // exhaustive for the top-level context so we'll check these first
        for (const auto &async_ref : async_) {
            ImageRangeGen range_gen_copy(range_gen);  // original range gen is needed later
            hazard = async_ref.Context().DetectAsyncHazard(detector, range_gen_copy, async_ref.StartTag(), async_ref.GetQueueId());
            if (hazard.IsHazard()) return hazard;
        }
    }

    const bool detect_prev = (options & DetectOptions::kDetectPrevious) != 0;
    using ConstIterator = AccessMap::const_iterator;
    auto do_detect_hazard_range = [this, &detector, &hazard, detect_prev](const ImageRangeGen::RangeType &range,
                                                                          const ConstIterator &end, ConstIterator &pos) {
        hazard = DetectHazardOneRange(detector, detect_prev, pos, end, range);
        return hazard.IsHazard();
    };
    ForEachEntryInRangesUntil(access_state_map_, range_gen, do_detect_hazard_range);
    return hazard;
}

template <typename Detector>
HazardResult AccessContext::DetectAsyncHazard(const Detector &detector, const AccessRange &range, ResourceUsageTag async_tag,
                                              QueueId async_queue_id) const {
    assert(range.non_empty());
    HazardResult hazard;
    auto pos = access_state_map_.LowerBound(range.begin);
    if (pos != access_state_map_.end() && pos->first.begin < range.end) {
        hazard = detector.DetectAsync(pos, async_tag, async_queue_id);
    }
    return hazard;
}

template <typename Detector>
HazardResult AccessContext::DetectAsyncHazard(const Detector &detector, ImageRangeGen &range_gen, ResourceUsageTag async_tag,
                                              QueueId async_queue_id) const {
    using ConstIterator = AccessMap::const_iterator;
    HazardResult hazard;

    auto do_async_hazard_check = [&detector, async_tag, async_queue_id, &hazard](const ImageRangeGen::RangeType &range,
                                                                                 const ConstIterator &end, ConstIterator &pos) {
        while (pos != end && pos->first.begin < range.end) {
            hazard = detector.DetectAsync(pos, async_tag, async_queue_id);
            if (hazard.IsHazard()) return true;
            ++pos;
        }
        return false;
    };
    ForEachEntryInRangesUntil(access_state_map_, range_gen, do_async_hazard_check);
    return hazard;
}

template <typename Detector>
HazardResult AccessContext::DetectHazardOneRange(Detector &detector, bool detect_prev, AccessMap::const_iterator &pos,
                                                 const AccessMap::const_iterator &the_end, const AccessRange &range) const {
    HazardResult hazard;
    AccessRange gap = {range.begin, range.begin};

    while (pos != the_end && pos->first.begin < range.end) {
        // Cover any leading gap, or gap between entries
        if (detect_prev) {
            // TODO: After profiling we may want to change the descent logic such that we don't recur per gap...
            // Cover any leading gap, or gap between entries
            gap.end = pos->first.begin;  // We know this begin is < range.end
            if (gap.non_empty()) {
                // Recur on all gaps
                hazard = DetectPreviousHazard(detector, gap);
                if (hazard.IsHazard()) return hazard;
            }
            // Set up for the next gap.  If pos..end is >= range.end, loop will exit, and trailing gap will be empty
            gap.begin = pos->first.end;
        }

        hazard = detector.Detect(pos);
        if (hazard.IsHazard()) return hazard;
        ++pos;
    }

    if (detect_prev) {
        // Detect in the trailing empty as needed
        gap.end = range.end;
        if (gap.non_empty()) {
            hazard = DetectPreviousHazard(detector, gap);
        }
    }

    return hazard;
}

template <typename Detector>
HazardResult AccessContext::DetectPreviousHazard(Detector &detector, const AccessRange &range) const {
    if (subpass_barriers_.empty()) {
        return {};
    }
    AccessContext descent_context;
    ResolveSubpassDependencies(range, descent_context, false);

    AccessMap &descent_map = descent_context.access_state_map_;
    for (auto prev = descent_map.begin(); prev != descent_map.end(); ++prev) {
        HazardResult hazard = detector.Detect(prev);
        if (hazard.IsHazard()) {
            return hazard;
        }
    }
    return {};
}

}  // namespace syncval
