/*
 * Copyright (c) 2019-2026 Valve Corporation
 * Copyright (c) 2019-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_submit.h"
#include "sync/sync_validation.h"
#include "sync/sync_image.h"
#include "sync/sync_reporting.h"

namespace syncval {

AcquiredImage::AcquiredImage(const PresentedImage& presented, ResourceUsageTag acq_tag)
    : image(presented.image), generator(presented.range_gen), present_tag(presented.tag), acquire_tag(acq_tag) {}

bool AcquiredImage::Invalid() const { return vvl::StateObject::Invalid(image); }

SignalInfo::SignalInfo(const std::shared_ptr<const vvl::Semaphore>& semaphore_state, const QueueBatchContext::Ptr& batch,
                       const SyncExecScope& exec_scope, uint64_t timeline_value)
    : semaphore_state(semaphore_state),
      batch(batch),
      first_scope({batch->GetQueueId(), exec_scope}),
      timeline_value(timeline_value) {}

SignalInfo::SignalInfo(const std::shared_ptr<const vvl::Semaphore>& semaphore_state, uint64_t timeline_value)
    : semaphore_state(semaphore_state), first_scope(kQueueIdInvalid, SyncExecScope{}), timeline_value(timeline_value) {}

SignalInfo::SignalInfo(const std::shared_ptr<const vvl::Semaphore>& semaphore_state, const PresentedImage& presented,
                       ResourceUsageTag acquire_tag)
    : semaphore_state(semaphore_state),
      batch(presented.batch),
      first_scope(),
      acquired_image(std::make_shared<AcquiredImage>(presented, acquire_tag)) {}

void SignalsUpdate::OnBinarySignal(const vvl::Semaphore& semaphore_state, const QueueBatchContext::Ptr& batch,
                                   const VkSemaphoreSubmitInfo& submit_signal) {
    const VkSemaphore semaphore = semaphore_state.VkHandle();
    // Signal can't be registered in both lists at the same time.
    assert(!vvl::Contains(binary_signal_requests, semaphore) || !vvl::Contains(binary_unsignal_requests, semaphore));

    // Remove unsignal request (if any). It will be replaced by a signal request.
    const bool found_unsignal_request = binary_unsignal_requests.erase(semaphore);

    // Reject invalid signal
    if (!found_unsignal_request) {
        if (vvl::Contains(binary_signal_requests, semaphore) || vvl::Contains(sync_validator_.binary_signals_, semaphore)) {
            return;  // [core validation check]: binary semaphore signaled twice in a row
        }
    }
    // Register signal
    const VkQueueFlags queue_flags = batch->GetQueueSyncState()->GetQueueFlags();
    const auto exec_scope = SyncExecScope::MakeSrc(queue_flags, submit_signal.stageMask, VK_PIPELINE_STAGE_2_HOST_BIT);
    binary_signal_requests.emplace(semaphore, SignalInfo(semaphore_state.shared_from_this(), batch, exec_scope, 0));
}

bool SignalsUpdate::OnTimelineSignal(const vvl::Semaphore& semaphore_state, const std::shared_ptr<QueueBatchContext>& batch,
                                     const VkSemaphoreSubmitInfo& submit_signal) {
    const VkSemaphore semaphore = semaphore_state.VkHandle();
    std::vector<SignalInfo>& signals = timeline_signals[semaphore];

    // Reject invalid signal
    if (!signals.empty() && submit_signal.value <= signals.back().timeline_value) {
        return false;  // [core validation check]: strictly increasing signal values
    }

    // Do not register signal for external semaphore - external wait-before-signals are skipped
    // since there is no guarantee we can track the signal. Because of that it's possible that
    // signals have no way to be released (resolving waits can be wait-before-signals and are skipped)
    if (semaphore_state.Scope() != vvl::Semaphore::Scope::kInternal) {
        return false;
    }

    // Register signal
    const VkQueueFlags queue_flags = batch->GetQueueSyncState()->GetQueueFlags();
    const auto exec_scope = SyncExecScope::MakeSrc(queue_flags, submit_signal.stageMask, VK_PIPELINE_STAGE_2_HOST_BIT);
    signals.emplace_back(SignalInfo(semaphore_state.shared_from_this(), batch, exec_scope, submit_signal.value));
    return true;
}

bool SignalsUpdate::RegisterSignals(const BatchContextPtr& batch, const vvl::span<const VkSemaphoreSubmitInfo>& submit_signals) {
    bool registered_timeline_signal = false;
    for (const auto& submit_signal : submit_signals) {
        if (auto semaphore_state = sync_validator_.Get<vvl::Semaphore>(submit_signal.semaphore)) {
            if (semaphore_state->type == VK_SEMAPHORE_TYPE_BINARY) {
                OnBinarySignal(*semaphore_state, batch, submit_signal);
            } else {
                registered_timeline_signal |= OnTimelineSignal(*semaphore_state, batch, submit_signal);
            }
        }
    }
    return registered_timeline_signal;
}

std::optional<SignalInfo> SignalsUpdate::OnBinaryWait(VkSemaphore semaphore) {
    // Signal can't be registered in both lists at the same time.
    assert(!vvl::Contains(binary_signal_requests, semaphore) || !vvl::Contains(binary_unsignal_requests, semaphore));

    if (vvl::Contains(binary_unsignal_requests, semaphore)) {
        return {};  // [core validation check]: multi wait
    }

    // Get resolving signal
    std::optional<SignalInfo> resolving_signal;
    if (auto it = binary_signal_requests.find(semaphore); it != binary_signal_requests.end()) {
        resolving_signal.emplace(std::move(it->second));
        binary_signal_requests.erase(it);
    } else if (auto* registry_signal = vvl::Find(sync_validator_.binary_signals_, semaphore)) {
        resolving_signal.emplace(*registry_signal);
    } else {
        return {};  // [core validation check]: missing signal for binary wait
    }

    // Register unsignal request
    binary_unsignal_requests.emplace(semaphore);
    return resolving_signal;
}

std::optional<SignalInfo> SignalsUpdate::OnTimelineWait(VkSemaphore semaphore, uint64_t wait_value) {
    std::optional<SignalInfo> resolving_signal;
    // Search for the smallest signal value that resolves the wait.
    // At first check registered signals (they have smaller values)
    if (const std::vector<SignalInfo>* signals = vvl::Find(sync_validator_.timeline_signals_, semaphore)) {
        for (auto& signal : *signals) {
            if (wait_value <= signal.timeline_value) {
                resolving_signal.emplace(signal);
                break;
            }
        }
    }
    // then check the pending signals
    if (!resolving_signal.has_value()) {
        if (const std::vector<SignalInfo>* pending_signals = vvl::Find(timeline_signals, semaphore)) {
            for (auto& signal : *pending_signals) {
                if (wait_value <= signal.timeline_value) {
                    resolving_signal.emplace(signal);
                    break;
                }
            }
        }
    }
    // Register request to remove older signals
    if (resolving_signal.has_value()) {
        RemoveTimelineSignalsRequest request;
        request.semaphore = semaphore;
        request.signal_threshold_value = resolving_signal->timeline_value;
        request.queue = resolving_signal->first_scope.queue;
        remove_timeline_signals_requests.emplace_back(request);
    }
    return resolving_signal;  // empty result if it is a wait-before-signal
}

void SwapchainSubState::RecordPresentedImage(PresentedImage&& presented_image) {
    // All presented images are stored within the swapchain until the are reaquired.
    const uint32_t image_index = presented_image.image_index;
    if (image_index >= presented.size()) presented.resize(image_index + 1);

    // Use move semantics to avoid atomic operations on the contained shared_ptrs
    presented[image_index] = std::move(presented_image);
}

// We move from the presented images array 1) so we don't copy shared_ptr, and 2) to mark it acquired
PresentedImage SwapchainSubState::MovePresentedImage(uint32_t image_index) {
    if (presented.size() <= image_index) presented.resize(image_index + 1);
    PresentedImage ret_val = std::move(presented[image_index]);
    if (ret_val.Invalid()) {
        // If this is the first time the image has been acquired, then it's valid to have no present record, so we create one
        // Note: It's also possible this is an invalid acquire... but that's CoreChecks/Parameter validation's job to report
        ret_val = PresentedImage(base.shared_from_this(), image_index);
    }
    return ret_val;
}

void SwapchainSubState::GetPresentBatches(std::vector<QueueBatchContext::Ptr>& batches) const {
    for (const auto& presented_image : presented) {
        if (presented_image.batch) {
            batches.push_back(presented_image.batch);
        }
    }
}

class ApplySemaphoreBarrierAction {
  public:
    ApplySemaphoreBarrierAction(const SemaphoreScope& signal, const SemaphoreScope& wait) : signal_(signal), wait_(wait) {}
    void operator()(AccessState* access) const { access->ApplySemaphore(signal_, wait_); }

  private:
    const SemaphoreScope& signal_;
    const SemaphoreScope wait_;
};

class ApplyAcquireNextSemaphoreAction {
  public:
    ApplyAcquireNextSemaphoreAction(const SyncExecScope& wait_scope, ResourceUsageTag acquire_tag)
        : barrier_(GetAcquireBarrier(wait_scope)), acq_tag_(acquire_tag) {}
    void operator()(AccessState* access) const {
        // Note that the present operations may or may not be present, given that the fence wait may have cleared them out.
        // Also, if a subsequent present has happened, we *don't* want to protect that...
        if (access->LastWriteTag() <= acq_tag_) {
            access->ApplyBarrier(BarrierScope(barrier_), barrier_);
        }
    }

  private:
    static SyncBarrier GetAcquireBarrier(const SyncExecScope& wait_scope) {
        SyncBarrier barrier;
        barrier.src_exec_scope = getPresentSrcScope();
        barrier.src_access_scope = getPresentValidAccesses();
        barrier.dst_exec_scope = wait_scope;
        return barrier;
    }
    // kPresentSrcScope/kPresentValidAccesses cannot be regular global variables, because they use global
    // variables from another compilation unit (through syncStageAccessMaskByStageBit() call) for initialization,
    // and initialization of globals between compilation units is undefined. Instead they get initialized
    // on the first use (it's important to ensure this first use is also not initialization of some global!).
    static const SyncExecScope& getPresentSrcScope() {
        static const SyncExecScope kPresentSrcScope{VK_PIPELINE_STAGE_2_PRESENT_ENGINE_BIT_SYNCVAL,  // mask_param (unused)
                                                    VK_PIPELINE_STAGE_2_PRESENT_ENGINE_BIT_SYNCVAL,  // exec_scope
                                                    getPresentValidAccesses()};                      // valid_accesses
        return kPresentSrcScope;
    }
    static const SyncAccessFlags& getPresentValidAccesses() {
        static const SyncAccessFlags kPresentValidAccesses = SYNC_PRESENT_ENGINE_BIT_SYNCVAL_PRESENT_ACQUIRE_READ_BIT_SYNCVAL |
                                                             SYNC_PRESENT_ENGINE_BIT_SYNCVAL_PRESENT_PRESENTED_BIT_SYNCVAL;
        return kPresentValidAccesses;
    }

  private:
    SyncBarrier barrier_;
    ResourceUsageTag acq_tag_;
};

void LastSynchronizedPresent::Update(VkSwapchainKHR swapchain, ResourceUsageTag present_tag) {
    for (auto& entry : per_swapchain) {
        if (entry.first == swapchain) {
            entry.second = std::max(entry.second, present_tag);
            return;
        }
    }
    per_swapchain.emplace_back(std::make_pair(swapchain, present_tag));
}

void LastSynchronizedPresent::Merge(const LastSynchronizedPresent& other) {
    for (const auto& other_entry : other.per_swapchain) {
        Update(other_entry.first, other_entry.second);
    }
}

void LastSynchronizedPresent::OnDestroySwapchain(VkSwapchainKHR swapchain) {
    // TODO: add erase() to small_vector and use intead in the following code
    const auto copy = per_swapchain;
    per_swapchain.resize(0);
    for (const auto& entry : copy) {
        if (entry.first != swapchain) {
            per_swapchain.emplace_back(entry);
        }
    }
}

QueueBatchContext::QueueBatchContext(const SyncValidator& sync_state, const QueueSyncState& queue_state)
    : CommandExecutionContext(sync_state, queue_state.GetQueueFlags()),
      queue_state_(&queue_state),
      tag_range_(0, 0),
      access_context_(sync_state),
      current_access_context_(&access_context_),
      queue_sync_tag_(sync_state.GetQueueIdLimit(), ResourceUsageTag(0)) {
    sync_state_.stats.AddQueueBatchContext();
}

QueueBatchContext::QueueBatchContext(const SyncValidator& sync_state)
    : CommandExecutionContext(sync_state, 0),
      tag_range_(0, 0),
      access_context_(sync_state),
      current_access_context_(&access_context_),
      queue_sync_tag_(sync_state.GetQueueIdLimit(), ResourceUsageTag(0)) {
    sync_state_.stats.AddQueueBatchContext();
}

QueueBatchContext::~QueueBatchContext() { sync_state_.stats.RemoveQueueBatchContext(); }

void QueueBatchContext::Trim() {
    // Clean up unneeded access context contents and log information
    access_context_.TrimAndClearFirstAccess();

    ResourceUsageTagSet used_tags;
    access_context_.AddReferencedTags(used_tags);

    // Note: AccessContexts in the SyncEventsState are trimmed when created.
    events_context_.AddReferencedTags(used_tags);

    // Only conserve AccessLog references that are referenced by used_tags
    batch_log_.Trim(used_tags);
}

void QueueBatchContext::ResolveSubmittedCommandBuffer(const AccessContext& recorded_context, ResourceUsageTag offset) {
    GetCurrentAccessContext()->ResolveFromContext(QueueTagOffsetBarrierAction(GetQueueId(), offset), recorded_context);
}

VulkanTypedHandle QueueBatchContext::Handle() const { return queue_state_->Handle(); }

template <typename Predicate>
void QueueBatchContext::ApplyPredicatedWait(Predicate& predicate, const LastSynchronizedPresent& last_synchronized_present) {
    access_context_.EraseIf([this, &last_synchronized_present, &predicate](AccessMap::value_type& access) {
        AccessState& access_state = access.second;

        // Tell EraseIf to remove present accesses that are already synchronized according to LastSynchronizedPresent
        if (access_state.HasWriteOp() && access_state.LastWrite().IsPresent()) {
            const ResourceUsageRecord& usage_record = *batch_log_.GetAccessRecord(access_state.LastWriteTag()).record;
            assert(usage_record.alt_usage);
            assert(usage_record.alt_usage.GetCommand() == vvl::Func::vkQueuePresentKHR);
            const VkSwapchainKHR swapchain = usage_record.alt_usage.GetSwapchainHandle();
            for (const auto& [synchronized_swapchain, synchronized_present_tag] : last_synchronized_present.per_swapchain) {
                // NOTE: it is important to check that access belongs to a specific swapchain and not only
                // compare the tag values. It is possible to have accesses from a different swapchain that
                // are *not* synchronized and have tag values that satisfy tag comparison check.
                if (swapchain == synchronized_swapchain && access_state.LastWriteTag() <= synchronized_present_tag) {
                    return true;
                }
            }
        }

        // Tell eraseIf to remove accesses that become empty after applying predicate
        return access_state.ClearPredicatedAccesses<Predicate>(predicate);
    });
}

struct WaitQueueTagPredicate {
    QueueId queue;
    ResourceUsageTag tag;

    bool operator()(const ReadState& read_access) const {
        return read_access.queue == queue && read_access.tag <= tag &&
               read_access.stage != VK_PIPELINE_STAGE_2_PRESENT_ENGINE_BIT_SYNCVAL;
    }
    bool operator()(const AccessState& access) const {
        if (!access.HasWriteOp()) {
            return false;
        }
        const WriteState& write_state = access.LastWrite();
        return write_state.queue == queue && write_state.tag <= tag &&
               write_state.access_index != SYNC_PRESENT_ENGINE_SYNCVAL_PRESENT_PRESENTED_SYNCVAL;
    }
};

struct DeviceWaitPredicate {
    bool operator()(const ReadState& read_access) const {
        return read_access.stage != VK_PIPELINE_STAGE_2_PRESENT_ENGINE_BIT_SYNCVAL;
    }
    bool operator()(const AccessState& access) const {
        if (!access.HasWriteOp()) {
            return false;
        }
        return access.LastWrite().access_index != SYNC_PRESENT_ENGINE_SYNCVAL_PRESENT_PRESENTED_SYNCVAL;
    }
};

// Present operations matching only the *exactly* tagged present and acquire operations
struct WaitAcquirePredicate {
    ResourceUsageTag present_tag;
    ResourceUsageTag acquire_tag;

    bool operator()(const ReadState& read_access) const {
        return read_access.tag == acquire_tag && read_access.stage == VK_PIPELINE_STAGE_2_PRESENT_ENGINE_BIT_SYNCVAL;
    }
    bool operator()(const AccessState& access) const {
        if (!access.HasWriteOp()) {
            return false;
        }
        const WriteState& write_state = access.LastWrite();
        return write_state.tag == present_tag && write_state.access_index == SYNC_PRESENT_ENGINE_SYNCVAL_PRESENT_PRESENTED_SYNCVAL;
    }
};

void QueueBatchContext::ApplyTaggedWait(QueueId queue_id, ResourceUsageTag tag,
                                        const LastSynchronizedPresent& last_synchronized_present) {
    WaitQueueTagPredicate predicate{queue_id, tag};
    ApplyPredicatedWait(predicate, last_synchronized_present);

    // SwapChain acquire batch contexts have no queue
    if (queue_state_ && queue_id == GetQueueId()) {
        events_context_.ApplyTaggedWait(queue_state_->GetQueueFlags(), tag);
    }
}

void QueueBatchContext::ApplyDeviceWait(const LastSynchronizedPresent& last_synchronized_present) {
    DeviceWaitPredicate predicate;
    ApplyPredicatedWait(predicate, last_synchronized_present);

    // SwapChain acquire batch contexts have no queue
    if (queue_state_) {
        events_context_.ApplyTaggedWait(queue_state_->GetQueueFlags(), ResourceUsageRecord::kMaxIndex);
    }
}

void QueueBatchContext::ApplyAcquireWait(const AcquiredImage& acquired) {
    WaitAcquirePredicate predicate{acquired.present_tag, acquired.acquire_tag};
    ApplyPredicatedWait(predicate, {});
}

void QueueBatchContext::OnResourceDestroyed(const AccessRange& resource_range) {
    // Remove all accesses associated with the resource being destroyed
    access_context_.EraseIf([&resource_range](AccessMap::value_type& access) { return resource_range.includes(access.first); });
}

void QueueBatchContext::BeginRenderPassReplaySetup(ReplayState& replay, const SyncOpBeginRenderPass& begin_op) {
    current_access_context_ = replay.ReplayStateRenderPassBegin(queue_state_->GetQueueFlags(), begin_op, access_context_);
}

void QueueBatchContext::NextSubpassReplaySetup(ReplayState& replay) {
    current_access_context_ = replay.ReplayStateRenderPassNext();
}

void QueueBatchContext::EndRenderPassReplayCleanup(ReplayState& replay) {
    replay.ReplayStateRenderPassEnd(access_context_);
    current_access_context_ = &access_context_;
}

void QueueBatchContext::ResolvePresentSemaphoreWait(const SignalInfo& signal_info, const PresentedImages& presented_images) {
    assert(signal_info.batch);

    const AccessContext& from_context = signal_info.batch->access_context_;
    const SemaphoreScope& signal_scope = signal_info.first_scope;
    const QueueId queue_id = GetQueueId();
    const auto queue_flags = queue_state_->GetQueueFlags();
    SemaphoreScope wait_scope{queue_id, SyncExecScope::MakeDst(queue_flags, VK_PIPELINE_STAGE_2_PRESENT_ENGINE_BIT_SYNCVAL)};

    // If signal queue == wait queue, signal is treated as a memory barrier with an access scope equal to the present accesses
    SyncBarrier sem_barrier(signal_scope, wait_scope, SyncBarrier::AllAccess());
    const BatchBarrierOp sem_same_queue_op(wait_scope.queue, sem_barrier);

    // Need to import the rest of the same queue contents without modification
    SyncBarrier noop_barrier;
    const BatchBarrierOp noop_barrier_op(wait_scope.queue, noop_barrier);

    // Otherwise apply semaphore rules apply
    const ApplySemaphoreBarrierAction sem_not_same_queue_op(signal_scope, wait_scope);
    const SemaphoreScope noop_semaphore_scope(queue_id, noop_barrier.dst_exec_scope);
    const ApplySemaphoreBarrierAction noop_sem_op(signal_scope, noop_semaphore_scope);

    // For each presented image
    for (const auto& presented : presented_images) {
        if (signal_scope.queue == wait_scope.queue) {
            // If signal queue == wait queue, signal is treated as a memory barrier with an access scope equal to the
            // valid accesses for the sync scope.
            access_context_.ResolveFromContext(sem_same_queue_op, from_context, presented.range_gen);
            access_context_.ResolveFromContext(noop_barrier_op, from_context);
        } else {
            access_context_.ResolveFromContext(sem_not_same_queue_op, from_context, presented.range_gen);
            access_context_.ResolveFromContext(noop_sem_op, from_context);
        }
    }
}

void QueueBatchContext::ResolveSubmitSemaphoreWait(const SignalInfo& signal_info, VkPipelineStageFlags2 wait_mask) {
    assert(signal_info.batch);

    const SemaphoreScope& signal_scope = signal_info.first_scope;
    const auto queue_flags = queue_state_->GetQueueFlags();
    SemaphoreScope wait_scope{GetQueueId(), SyncExecScope::MakeDst(queue_flags, wait_mask)};

    const AccessContext& from_context = signal_info.batch->access_context_;
    if (signal_info.acquired_image) {
        const AcquiredImage& acquired_image = *signal_info.acquired_image;

        // Update last synchronized presentation
        if (acquired_image.present_tag != kInvalidTag) {
            const VkSwapchainKHR swapchain = acquired_image.image->create_from_swapchain;
            last_synchronized_present.Update(swapchain, acquired_image.present_tag);
        }

        // Import the *presenting* batch, but replacing presenting with acquired.
        ApplyAcquireNextSemaphoreAction apply_acq(wait_scope, acquired_image.acquire_tag);
        access_context_.ResolveFromContext(apply_acq, from_context, acquired_image.generator);

        // Grab the reset of the presenting QBC, with no effective barrier, won't overwrite the acquire, as the tag is newer
        SyncBarrier noop_barrier;
        const BatchBarrierOp noop_barrier_op(wait_scope.queue, noop_barrier);
        access_context_.ResolveFromContext(noop_barrier_op, from_context);
    } else {
        if (signal_scope.queue == wait_scope.queue) {
            // If signal queue == wait queue, signal is treated as a memory barrier with an access scope equal to the
            // valid accesses for the sync scope.
            SyncBarrier sem_barrier(signal_scope, wait_scope, SyncBarrier::AllAccess());
            const BatchBarrierOp sem_barrier_op(wait_scope.queue, sem_barrier);
            access_context_.ResolveFromContext(sem_barrier_op, from_context);
            events_context_.ApplyBarrier(sem_barrier.src_exec_scope, sem_barrier.dst_exec_scope, ResourceUsageRecord::kMaxIndex);
        } else {
            ApplySemaphoreBarrierAction sem_op(signal_scope, wait_scope);
            access_context_.ResolveFromContext(sem_op, signal_info.batch->access_context_);
        }
    }
}

void QueueBatchContext::ResolveLastBatch(const QueueBatchContext::ConstPtr& last_batch) {
    // Copy in the event state from the previous batch (on this queue)
    events_context_.DeepCopy(last_batch->events_context_);

    // If there are no semaphores to the previous batch, make sure a "submit order" non-barriered import is done
    access_context_.ResolveFromContext(last_batch->access_context_);
    ImportTags(*last_batch);

    last_synchronized_present.Merge(last_batch->last_synchronized_present);
}

void QueueBatchContext::ImportTags(const QueueBatchContext& from) {
    batch_log_.Import(from.batch_log_);

    // NOTE: Assumes that "from" has set its tag limit in its own queue_id slot
    size_t q_limit = queue_sync_tag_.size();
    assert(q_limit == from.queue_sync_tag_.size());
    for (size_t q = 0; q < q_limit; q++) {
        queue_sync_tag_[q] = std::max(queue_sync_tag_[q], from.queue_sync_tag_[q]);
    }
}

std::vector<QueueBatchContext::ConstPtr> QueueBatchContext::ResolvePresentWaits(vvl::span<const VkSemaphore> wait_semaphores,
                                                                                const PresentedImages& presented_images,
                                                                                SignalsUpdate& signals_update) {
    std::vector<ConstPtr> batches_resolved;
    for (VkSemaphore semaphore : wait_semaphores) {
        auto signal_info = signals_update.OnBinaryWait(semaphore);
        if (!signal_info) {
            continue;  // Binary signal not found [core validation check]
        }
        ResolvePresentSemaphoreWait(*signal_info, presented_images);
        ImportTags(*signal_info->batch);
        batches_resolved.emplace_back(std::move(signal_info->batch));
    }
    return batches_resolved;
}

bool QueueBatchContext::DoQueuePresentValidate(const Location& loc, const PresentedImages& presented_images) {
    bool skip = false;
    // Tag the presented images so record doesn't have to know the tagging scheme
    for (const PresentedImage& presented : presented_images) {
        ImageRangeGen range_gen = presented.range_gen;
        HazardResult hazard = access_context_.DetectHazard(range_gen, SYNC_PRESENT_ENGINE_SYNCVAL_PRESENT_PRESENTED_SYNCVAL);
        if (hazard.IsHazard()) {
            const VulkanTypedHandle swapchain_handle = vvl::StateObject::Handle(presented.swapchain_state.lock());
            const VulkanTypedHandle image_handle = vvl::StateObject::Handle(presented.image);

            LogObjectList objlist(queue_state_->Handle(), swapchain_handle, image_handle);

            std::ostringstream ss;
            ss << "swapchain image " << presented.image_index << " (";
            ss << sync_state_.FormatHandle(image_handle);
            ss << " from " << sync_state_.FormatHandle(swapchain_handle) << ")";
            const std::string resource_description = ss.str();

            const std::string error = sync_state_.error_messages_.PresentError(hazard, *this, vvl::Func::vkQueuePresentKHR,
                                                                               resource_description, presented.present_index);
            skip |= sync_state_.SyncError(hazard.Hazard(), objlist, loc, error);
            if (skip) {
                break;
            }
        }
    }
    return skip;
}

void QueueBatchContext::DoPresentOperations(const PresentedImages& presented_images) {
    // For present, tagging is internal to the presented image record.
    for (const auto& presented : presented_images) {
        // Update memory state
        presented.UpdateMemoryAccess(SYNC_PRESENT_ENGINE_SYNCVAL_PRESENT_PRESENTED_SYNCVAL, presented.tag, access_context_,
                                     SyncFlag::kPresent);
    }
}

void QueueBatchContext::LogPresentOperations(const PresentedImages& presented_images, uint64_t submit_index) {
    if (tag_range_.size()) {
        auto access_log = std::make_shared<AccessLog>();
        BatchAccessLog::BatchRecord batch{queue_state_};
        batch.submit_index = submit_index;
        batch.base_tag = tag_range_.begin;
        batch_log_.Insert(batch, tag_range_, access_log);
        access_log->reserve(tag_range_.size());
        assert(tag_range_.size() == presented_images.size());
        for (const auto& presented : presented_images) {
            access_log->emplace_back(PresentResourceRecord(static_cast<const PresentedImageRecord>(presented)));
        }
    }
}

void QueueBatchContext::DoAcquireOperation(const PresentedImage& presented) {
    // Only one tag for acquire.  The tag in presented is the present tag
    presented.UpdateMemoryAccess(SYNC_PRESENT_ENGINE_SYNCVAL_PRESENT_ACQUIRE_READ_SYNCVAL, tag_range_.begin, access_context_);
}

void QueueBatchContext::LogAcquireOperation(const PresentedImage& presented, vvl::Func command) {
    auto access_log = std::make_shared<AccessLog>();
    BatchAccessLog::BatchRecord batch{queue_state_};
    batch.base_tag = tag_range_.begin;
    batch_log_.Insert(batch, tag_range_, access_log);
    access_log->emplace_back(AcquireResourceRecord(presented, tag_range_.begin, command));
}

void QueueBatchContext::SetupAccessContext(const PresentedImage& presented) {
    if (presented.batch) {
        access_context_.ResolveFromContext(presented.batch->access_context_);
        ImportTags(*presented.batch);
    }
}

std::vector<QueueBatchContext::ConstPtr> QueueBatchContext::RegisterAsyncContexts(const std::vector<ConstPtr>& batches_resolved) {
    // Gather async context information for hazard checks and conserve the QBC's for the async batches
    auto skip_resolved_filter = [&batches_resolved](auto& batch) { return !vvl::Contains(batches_resolved, batch); };
    std::vector<ConstPtr> async_batches = sync_state_.GetLastBatches(skip_resolved_filter);
    std::vector<ConstPtr> async_pending_batches = sync_state_.GetLastPendingBatches(skip_resolved_filter);
    if (!async_pending_batches.empty()) {
        vvl::Append(async_batches, async_pending_batches);
    }
    for (const auto& async_batch : async_batches) {
        const QueueId async_queue = async_batch->GetQueueId();
        ResourceUsageTag sync_tag;
        if (async_queue < queue_sync_tag_.size()) {
            sync_tag = queue_sync_tag_[async_queue];
        } else {
            // If this isn't from a tracked queue, just check the batch itself
            sync_tag = async_batch->tag_range_.begin;
        }

        // The start of the asynchronous access range for a given queue is one more than the highest tagged reference
        access_context_.AddAsyncContext(async_batch->GetCurrentAccessContext(), sync_tag, async_batch->GetQueueId());
        // We need to snapshot the async log information for async hazard reporting
        batch_log_.Import(async_batch->batch_log_);
    }
    return async_batches;
}

QueueId QueueBatchContext::GetQueueId() const {
    QueueId id = queue_state_ ? queue_state_->GetQueueId() : kQueueIdInvalid;
    return id;
}

ResourceUsageTag QueueBatchContext::SetupBatchTags(uint32_t tag_count) {
    tag_range_ = sync_state_.ReserveGlobalTagRange(tag_count);
    access_context_.SetStartTag(tag_range_.begin);

    // Needed for ImportSyncTags to pick up the "from" own sync tag.
    const QueueId this_q = GetQueueId();
    if (this_q < queue_sync_tag_.size()) {
        // If this is a non-queued operation we'll get a "special" value like invalid
        queue_sync_tag_[this_q] = tag_range_.end;
    }
    return tag_range_.begin;
}

std::vector<BatchContextConstPtr> QueueBatchContext::ResolveSubmitWaits(vvl::span<const VkSemaphoreSubmitInfo> wait_infos,
                                                                        std::vector<VkSemaphoreSubmitInfo>& unresolved_waits,
                                                                        SignalsUpdate& signals_update) {
    std::vector<BatchContextConstPtr> resolved_batches;
    for (const auto& wait_info : wait_infos) {
        auto semaphore_state = sync_state_.Get<vvl::Semaphore>(wait_info.semaphore);
        if (!semaphore_state) {
            continue;  // [core validation check]
        }
        // Binary semaphore wait:
        // * There must be a single resovling signal. If no signal is found, it is a validation error.
        // * The resolving signal must not depend on another not yet submitted timeline signal. That's
        //   not allowed by the specification. When this happens OnBinaryWait also reports that signal
        //   not found.
        // Timeline semaphore wait:
        // * No resolving signal is allowed. It is a wait-before-signal scenario.
        // * A single resolving signal. The specification defines that exactly *one* signal resolves the wait.
        //   If there are multiple signals that meet the waiting criteria then implementation may choose
        //   any of them (which one is unspecified). This also means that a single timeline wait cannot
        //   synchronize accesses from multiple queues even if each queue has matching signal.
        std::optional<SignalInfo> resolving_signal;

        if (semaphore_state->type == VK_SEMAPHORE_TYPE_BINARY) {
            resolving_signal = signals_update.OnBinaryWait(wait_info.semaphore);
            if (!resolving_signal) {
                // [core validation check]: binary signal not found or depends on not yet submitted timeline signal
                continue;
            }
        } else {
            // Special case when semaphore initial value satisfies the wait.
            // There is no batch that signals initial value, nothing to resolve here.
            if (wait_info.value <= semaphore_state->initial_value) {
                continue;
            }
            resolving_signal = signals_update.OnTimelineWait(wait_info.semaphore, wait_info.value);

            // Register wait-before-signal
            if (!resolving_signal) {
                if (semaphore_state->Scope() == vvl::Semaphore::Scope::kInternal) {
                    unresolved_waits.emplace_back(wait_info);
                    continue;
                } else {
                    // Do not register wait-before-signal for external semaphore.
                    // We might not be able to track the signal. Just assume that wait is satified.
                    // TODO: current support for external semaphores ensures resources are not
                    // leaked. It is still possible to get false-positives. Improve how to silence
                    // validation when signal cannot be tracked properly.
                    continue;
                }
            }
        }
        if (resolving_signal->batch) {
            ResolveSubmitSemaphoreWait(resolving_signal.value(), wait_info.stageMask);
            ImportTags(*resolving_signal->batch);
            resolved_batches.emplace_back(std::move(resolving_signal->batch));
        }
    }
    return resolved_batches;
}

bool QueueBatchContext::ValidateSubmit(const std::vector<CommandBufferConstPtr>& command_buffers, uint64_t submit_index,
                                       uint32_t batch_index, std::vector<std::string>& current_label_stack,
                                       const ErrorObject& error_obj) {
    bool skip = false;

    BatchAccessLog::BatchRecord batch{queue_state_, submit_index, batch_index};
    uint32_t tag_count = 0;
    for (const auto& cb : command_buffers) {
        if (!cb) continue;
        tag_count += static_cast<uint32_t>(SubState(*cb).access_context.GetTagCount());
    }
    batch.base_tag = SetupBatchTags(tag_count);

    for (size_t index = 0; index < command_buffers.size(); index++) {
        const auto& cb = SubState(*command_buffers[index]);
        // Validate and resolve command buffers that has tagged commands
        const CommandBufferAccessContext& access_context = cb.access_context;
        if (access_context.GetTagCount() > 0) {
            skip |= ReplayState(*this, access_context, error_obj, uint32_t(index), batch.base_tag).ValidateFirstUse();
            // The barriers have already been applied in ValidatFirstUse
            batch_log_.Import(batch, access_context, current_label_stack);
            ResolveSubmittedCommandBuffer(*access_context.GetCurrentAccessContext(), batch.base_tag);
            batch.base_tag += access_context.GetTagCount();
        }
        // Apply debug label commands
        vvl::CommandBuffer::ReplayLabelCommands(cb.base.GetLabelCommands(), current_label_stack);
        batch.cb_index++;
    }
    return skip;
}

QueueBatchContext::PresentResourceRecord::Base_::Record QueueBatchContext::PresentResourceRecord::MakeRecord() const {
    return std::make_unique<PresentResourceRecord>(presented_);
}

VkSwapchainKHR QueueBatchContext::PresentResourceRecord::GetSwapchainHandle() const {
    return presented_.image->create_from_swapchain;
}

QueueBatchContext::AcquireResourceRecord::Base_::Record QueueBatchContext::AcquireResourceRecord::MakeRecord() const {
    return std::make_unique<AcquireResourceRecord>(presented_, acquire_tag_, command_);
}

VkSwapchainKHR QueueBatchContext::AcquireResourceRecord::GetSwapchainHandle() const {
    return presented_.image->create_from_swapchain;
}

std::vector<QueueBatchContext::ConstPtr> SyncValidator::GetLastBatches(
    std::function<bool(const QueueBatchContext::ConstPtr&)> filter) const {
    std::vector<QueueBatchContext::ConstPtr> snapshot;
    for (const auto& queue_sync_state : queue_sync_states_) {
        auto batch = queue_sync_state->LastBatch();
        if (batch && filter(batch)) {
            snapshot.emplace_back(std::move(batch));
        }
    }
    return snapshot;
}

std::vector<QueueBatchContext::Ptr> SyncValidator::GetLastBatches(std::function<bool(const QueueBatchContext::ConstPtr&)> filter) {
    std::vector<QueueBatchContext::Ptr> snapshot;
    for (const auto& queue_sync_state : queue_sync_states_) {
        auto batch = queue_sync_state->LastBatch();
        if (batch && filter(batch)) {
            snapshot.emplace_back(std::move(batch));
        }
    }
    return snapshot;
}

std::vector<QueueBatchContext::ConstPtr> SyncValidator::GetLastPendingBatches(
    std::function<bool(const QueueBatchContext::ConstPtr&)> filter) const {
    std::vector<QueueBatchContext::ConstPtr> snapshot;
    for (const auto& queue_sync_state : queue_sync_states_) {
        auto batch = queue_sync_state->PendingLastBatch();
        if (batch && filter(batch)) {
            snapshot.emplace_back(std::move(batch));
        }
    }
    return snapshot;
}

void SyncValidator::ClearPending() const {
    for (const auto& queue_state : queue_sync_states_) {
        queue_state->ClearPending();
    }
}

// Note that function is const, but updates mutable submit_index to allow Validate to create correct tagging for command invocation
// scope state.
// Given that queue submits are supposed to be externally synchronized for the same queue, this should safe without being
// atomic... but as the ops are per submit, the performance cost is negible for the peace of mind.
uint64_t QueueSyncState::ReserveSubmitId() const { return submit_index_.fetch_add(1); }

const LastSynchronizedPresent& QueueSyncState::GetLastSynchronizedPresent() const {
    static const LastSynchronizedPresent empty;
    return last_batch_ ? last_batch_->last_synchronized_present : empty;
}

void QueueSyncState::SetPendingLastBatch(QueueBatchContext::Ptr&& last) const { pending_last_batch_ = std::move(last); }

// Since we're updating the QueueSync state, this is Record phase and the access log needs to point to the global one
// Batch Contexts saved during signalling have their AccessLog reset when the pending signals are signalled.
// NOTE: By design, QueueBatchContexts that are neither last, nor referenced by a signal are abandoned as unowned, since
//       the contexts Resolve all history from previous all contexts when created
void QueueSyncState::ApplyPendingLastBatch() {
    // Update the queue to point to the last batch from the submit
    if (pending_last_batch_) {
        // Clean up the events data in the previous last batch on queue, as only the subsequent batches have valid use for them
        // and the QueueBatchContext::Setup calls have be copying them along from batch to batch during submit.
        if (last_batch_) {
            last_batch_->ResetEventsContext();
        }
        pending_last_batch_->Trim();
        last_batch_ = std::move(pending_last_batch_);
    }
}

void QueueSyncState::SetPendingUnresolvedBatches(std::vector<UnresolvedBatch>&& unresolved_batches) const {
    pending_unresolved_batches_ = std::move(unresolved_batches);
    update_unresolved_batches_ = true;
}

void QueueSyncState::ApplyPendingUnresolvedBatches() {
    if (update_unresolved_batches_) {
        unresolved_batches_ = std::move(pending_unresolved_batches_);
        pending_unresolved_batches_.clear();
        update_unresolved_batches_ = false;
    }
}

void QueueSyncState::ClearPending() const {
    pending_last_batch_ = nullptr;
    if (update_unresolved_batches_) {
        const_cast<std::vector<UnresolvedBatch>&>(unresolved_batches_) = std::move(pending_unresolved_batches_);
        pending_unresolved_batches_.clear();
        update_unresolved_batches_ = false;
    }
}

void BatchAccessLog::Import(const BatchRecord& batch, const CommandBufferAccessContext& cb_access,
                            const std::vector<std::string>& initial_label_stack) {
    ResourceUsageRange import_range = {batch.base_tag, batch.base_tag + cb_access.GetTagCount()};
    log_map_.insert(std::make_pair(import_range, CBSubmitLog(batch, cb_access, initial_label_stack)));
}

void BatchAccessLog::Import(const BatchAccessLog& other) {
    for (const auto& entry : other.log_map_) {
        log_map_.insert(entry);
    }
}

void BatchAccessLog::Insert(const BatchRecord& batch, const ResourceUsageRange& range,
                            std::shared_ptr<const CommandExecutionContext::AccessLog> log) {
    log_map_.insert(std::make_pair(range, CBSubmitLog(batch, nullptr, std::move(log))));
}

// Trim: Remove any unreferenced AccessLog ranges from a BatchAccessLog
//
// In order to contain memory growth in the AccessLog information regarding prior submitted command buffers,
// the Trim call removes any AccessLog references that do not correspond to any tags in use. The set of referenced tag, used_tags,
// is generated by scanning the AccessContext and EventContext of the containing QueueBatchContext.
//
// Upon return the BatchAccessLog should only contain references to the AccessLog information needed by the
// containing parent QueueBatchContext.
//
// The algorithm used is another example of the "parallel iteration" pattern common within SyncVal.  In this case we are
// traversing the ordered range_map containing the AccessLog references and the ordered set of tags in use.
//
// To efficiently perform the parallel iteration, optimizations within this function include:
//  * when ranges are detected that have no tags referenced, all ranges between the last tag and the current tag are erased
//  * when used tags prior to the current range are found, all tags up to the current range are skipped
//  * when a tag is found within the current range, that range is skipped (and thus kept in the map), and further used tags
//    within the range are skipped.
//
// Note that for each subcase, any "next steps" logic is designed to be handled within the subsequent iteration -- meaning that
// each subcase simply handles the specifics of the current update/skip/erase action needed, and leaves the iterators in a sensible
// state for the top of loop... intentionally eliding special case handling.
void BatchAccessLog::Trim(const ResourceUsageTagSet& used_tags) {
    auto current_tag = used_tags.cbegin();
    const auto end_tag = used_tags.cend();
    auto current_map_range = log_map_.begin();
    const auto end_map = log_map_.end();

    while (current_map_range != end_map) {
        if (current_tag == end_tag) {
            // We're out of tags, the rest of the map isn't referenced, so erase it
            current_map_range = log_map_.erase(current_map_range, end_map);
        } else {
            auto& range = current_map_range->first;
            const ResourceUsageTag tag = *current_tag;
            if (tag < range.begin) {
                // Skip to the next tag potentially in range
                // if this is end_tag, we'll handle that next iteration
                current_tag = used_tags.lower_bound(range.begin);
            } else if (tag >= range.end) {
                // This tag is beyond the current range, delete all ranges between current_map_range,
                // and the next that includes the tag.  Next is not erased.
                auto next_used = log_map_.lower_bound(ResourceUsageRange(tag, tag + 1));
                current_map_range = log_map_.erase(current_map_range, next_used);
            } else {
                // Skip the rest of the tags in this range
                // If this is end, the next iteration will handle
                current_tag = used_tags.lower_bound(range.end);

                // This is a range we will keep, advance to the next. Next iteration handles end condition
                ++current_map_range;
            }
        }
    }
}

BatchAccessLog::AccessRecord BatchAccessLog::GetAccessRecord(ResourceUsageTag tag) const {
    auto found_log = log_map_.find(tag);
    if (found_log != log_map_.cend()) {
        return found_log->second.GetAccessRecord(tag);
    }
    // tag not found
    assert(false);
    return AccessRecord();
}

std::string BatchAccessLog::CBSubmitLog::GetDebugRegionName(const ResourceUsageRecord& record) const {
    const auto& label_commands = (*cbs_)[0]->GetLabelCommands();
    return vvl::CommandBuffer::GetDebugRegionName(label_commands, record.label_command_index, initial_label_stack_);
}

BatchAccessLog::AccessRecord BatchAccessLog::CBSubmitLog::GetAccessRecord(ResourceUsageTag tag) const {
    assert(tag >= batch_.base_tag);
    const size_t index = tag - batch_.base_tag;
    assert(log_);
    assert(index < log_->size());
    const ResourceUsageRecord* record = &(*log_)[index];
    const auto debug_name_provider = (record->label_command_index == vvl::kNoIndex32) ? nullptr : this;
    return AccessRecord{&batch_, record, debug_name_provider};
}

BatchAccessLog::CBSubmitLog::CBSubmitLog(const BatchRecord& batch,
                                         std::shared_ptr<const CommandExecutionContext::CommandBufferSet> cbs,
                                         std::shared_ptr<const CommandExecutionContext::AccessLog> log)
    : batch_(batch), cbs_(cbs), log_(log) {}

BatchAccessLog::CBSubmitLog::CBSubmitLog(const BatchRecord& batch, const CommandBufferAccessContext& cb,
                                         const std::vector<std::string>& initial_label_stack)
    : batch_(batch), cbs_(cb.GetCBReferencesShared()), log_(cb.GetAccessLogShared()), initial_label_stack_(initial_label_stack) {}

PresentedImage::PresentedImage(SyncValidator& sync_state, QueueBatchContext::Ptr batch_, VkSwapchainKHR swapchain,
                               uint32_t image_index_, uint32_t present_index_, ResourceUsageTag tag_)
    : PresentedImageRecord{tag_, image_index_, present_index_, sync_state.Get<vvl::Swapchain>(swapchain), {}},
      batch(std::move(batch_)) {
    SetImage(image_index_);
}

PresentedImage::PresentedImage(std::shared_ptr<vvl::Swapchain>&& swapchain, uint32_t at_index) : PresentedImage() {
    swapchain_state = std::move(swapchain);
    tag = kInvalidTag;
    SetImage(at_index);
}

bool PresentedImage::Invalid() const { return vvl::StateObject::Invalid(image); }

// Export uses move semantics...
void PresentedImage::ExportToSwapchain(SyncValidator&) {  // Include this argument to prove the const cast is safe
    // If the swapchain is dead just ignore the present
    auto swap_lock = swapchain_state.lock();
    if (vvl::StateObject::Invalid(swap_lock)) return;
    auto& sub_state = SubState(*swap_lock);
    sub_state.RecordPresentedImage(std::move(*this));
}

void PresentedImage::SetImage(uint32_t at_index) {
    image_index = at_index;

    auto swap_lock = swapchain_state.lock();
    if (vvl::StateObject::Invalid(swap_lock)) return;

    image = std::static_pointer_cast<const vvl::Image>(swap_lock->GetSwapChainImageShared(image_index));
    if (Invalid()) {
        range_gen = ImageRangeGen();
    } else {
        // For valid images create the type/range_gen to used to scope the semaphore operations
        const auto& sub_state = SubState(*image);
        range_gen = sub_state.MakeImageRangeGen(image->full_range, false);
    }
}

void PresentedImage::UpdateMemoryAccess(SyncAccessIndex usage, ResourceUsageTag tag, AccessContext& access_context,
                                        SyncFlags flags) const {
    ImageRangeGen mutable_range_gen = range_gen;
    access_context.UpdateAccessState(mutable_range_gen, usage, ResourceUsageTagEx{tag}, flags);
}

}  // namespace syncval
