// Copyright 2017 The NXT Authors
//
// 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 "backend/CommandBufferStateTracker.h"

#include "backend/BindGroup.h"
#include "backend/BindGroupLayout.h"
#include "backend/Buffer.h"
#include "backend/ComputePipeline.h"
#include "backend/Forward.h"
#include "backend/Framebuffer.h"
#include "backend/InputState.h"
#include "backend/PipelineLayout.h"
#include "backend/RenderPass.h"
#include "backend/RenderPipeline.h"
#include "backend/Texture.h"
#include "common/Assert.h"
#include "common/BitSetIterator.h"

namespace backend {
    CommandBufferStateTracker::CommandBufferStateTracker(CommandBufferBuilder* mBuilder)
        : mBuilder(mBuilder) {
    }

    bool CommandBufferStateTracker::HaveRenderPass() const {
        return mCurrentRenderPass != nullptr;
    }

    bool CommandBufferStateTracker::HaveRenderSubpass() const {
        return mAspects[VALIDATION_ASPECT_RENDER_SUBPASS];
    }

    bool CommandBufferStateTracker::ValidateCanCopy() const {
        if (mCurrentRenderPass) {
            mBuilder->HandleError("Copy cannot occur during a render pass");
            return false;
        }
        return true;
    }

    bool CommandBufferStateTracker::ValidateCanUseBufferAs(BufferBase* buffer,
                                                           nxt::BufferUsageBit usage) const {
        if (!BufferHasGuaranteedUsageBit(buffer, usage)) {
            mBuilder->HandleError("Buffer is not in the necessary usage");
            return false;
        }
        return true;
    }

    bool CommandBufferStateTracker::ValidateCanUseTextureAs(TextureBase* texture,
                                                            nxt::TextureUsageBit usage) const {
        if (!TextureHasGuaranteedUsageBit(texture, usage)) {
            mBuilder->HandleError("Texture is not in the necessary usage");
            return false;
        }
        return true;
    }

    bool CommandBufferStateTracker::ValidateCanDispatch() {
        constexpr ValidationAspects requiredAspects =
            1 << VALIDATION_ASPECT_COMPUTE_PIPELINE |  // implicitly requires COMPUTE_PASS
            1 << VALIDATION_ASPECT_BIND_GROUPS;
        if ((requiredAspects & ~mAspects).none()) {
            // Fast return-true path if everything is good
            return true;
        }

        if (!mAspects[VALIDATION_ASPECT_COMPUTE_PIPELINE]) {
            mBuilder->HandleError("No active compute pipeline");
            return false;
        }
        // Compute the lazily computed mAspects
        if (!RecomputeHaveAspectBindGroups()) {
            mBuilder->HandleError("Bind group state not valid");
            return false;
        }
        return true;
    }

    bool CommandBufferStateTracker::ValidateCanDrawArrays() {
        // TODO(kainino@chromium.org): Check for a current render pass
        constexpr ValidationAspects requiredAspects =
            1 << VALIDATION_ASPECT_RENDER_PIPELINE |  // implicitly requires RENDER_SUBPASS
            1 << VALIDATION_ASPECT_BIND_GROUPS | 1 << VALIDATION_ASPECT_VERTEX_BUFFERS;
        if ((requiredAspects & ~mAspects).none()) {
            // Fast return-true path if everything is good
            return true;
        }

        return RevalidateCanDraw();
    }

    bool CommandBufferStateTracker::ValidateCanDrawElements() {
        // TODO(kainino@chromium.org): Check for a current render pass
        constexpr ValidationAspects requiredAspects =
            1 << VALIDATION_ASPECT_RENDER_PIPELINE | 1 << VALIDATION_ASPECT_BIND_GROUPS |
            1 << VALIDATION_ASPECT_VERTEX_BUFFERS | 1 << VALIDATION_ASPECT_INDEX_BUFFER;
        if ((requiredAspects & ~mAspects).none()) {
            // Fast return-true path if everything is good
            return true;
        }

        if (!mAspects[VALIDATION_ASPECT_INDEX_BUFFER]) {
            mBuilder->HandleError("Cannot DrawElements without index buffer set");
            return false;
        }
        return RevalidateCanDraw();
    }

    bool CommandBufferStateTracker::ValidateEndCommandBuffer() const {
        if (mCurrentRenderPass != nullptr) {
            mBuilder->HandleError("Can't end command buffer with an active render pass");
            return false;
        }
        if (mAspects[VALIDATION_ASPECT_COMPUTE_PASS]) {
            mBuilder->HandleError("Can't end command buffer with an active compute pass");
            return false;
        }
        return true;
    }

    bool CommandBufferStateTracker::ValidateSetPushConstants(nxt::ShaderStageBit stages) {
        if (mAspects[VALIDATION_ASPECT_COMPUTE_PASS]) {
            if (stages & ~nxt::ShaderStageBit::Compute) {
                mBuilder->HandleError(
                    "SetPushConstants stage must be compute or 0 in compute passes");
                return false;
            }
        } else if (mAspects[VALIDATION_ASPECT_RENDER_SUBPASS]) {
            if (stages & ~(nxt::ShaderStageBit::Vertex | nxt::ShaderStageBit::Fragment)) {
                mBuilder->HandleError(
                    "SetPushConstants stage must be a subset if (vertex|fragment) in subpasses");
                return false;
            }
        } else {
            mBuilder->HandleError(
                "PushConstants must be set in either compute passes or subpasses");
            return false;
        }
        return true;
    }

    bool CommandBufferStateTracker::BeginComputePass() {
        if (mCurrentRenderPass != nullptr) {
            mBuilder->HandleError("Cannot begin a compute pass while a render pass is active");
            return false;
        }
        mAspects.set(VALIDATION_ASPECT_COMPUTE_PASS);
        return true;
    }

    bool CommandBufferStateTracker::EndComputePass() {
        if (!mAspects[VALIDATION_ASPECT_COMPUTE_PASS]) {
            mBuilder->HandleError("Can't end a compute pass without beginning one");
            return false;
        }
        mAspects.reset(VALIDATION_ASPECT_COMPUTE_PASS);
        UnsetPipeline();
        return true;
    }

    bool CommandBufferStateTracker::BeginSubpass() {
        if (mCurrentRenderPass == nullptr) {
            mBuilder->HandleError("Can't begin a subpass without an active render pass");
            return false;
        }
        if (mAspects[VALIDATION_ASPECT_RENDER_SUBPASS]) {
            mBuilder->HandleError("Can't begin a subpass without ending the previous subpass");
            return false;
        }
        if (mCurrentSubpass >= mCurrentRenderPass->GetSubpassCount()) {
            mBuilder->HandleError("Can't begin a subpass beyond the last subpass");
            return false;
        }

        auto& subpassInfo = mCurrentRenderPass->GetSubpassInfo(mCurrentSubpass);
        for (auto location : IterateBitSet(subpassInfo.colorAttachmentsSet)) {
            auto attachmentSlot = subpassInfo.colorAttachments[location];
            auto* tv = mCurrentFramebuffer->GetTextureView(attachmentSlot);
            auto* texture = tv->GetTexture();
            if (!EnsureTextureUsage(texture, nxt::TextureUsageBit::OutputAttachment)) {
                mBuilder->HandleError("Unable to ensure texture has OutputAttachment usage");
                return false;
            }
            mTexturesAttached.insert(texture);
        }

        mAspects.set(VALIDATION_ASPECT_RENDER_SUBPASS);
        return true;
    }

    bool CommandBufferStateTracker::EndSubpass() {
        if (!mAspects[VALIDATION_ASPECT_RENDER_SUBPASS]) {
            mBuilder->HandleError("Can't end a subpass without beginning one");
            return false;
        }
        ASSERT(mCurrentRenderPass != nullptr);

        auto& subpassInfo = mCurrentRenderPass->GetSubpassInfo(mCurrentSubpass);
        for (auto location : IterateBitSet(subpassInfo.colorAttachmentsSet)) {
            auto attachmentSlot = subpassInfo.colorAttachments[location];
            auto* tv = mCurrentFramebuffer->GetTextureView(attachmentSlot);
            auto* texture = tv->GetTexture();
            if (texture->IsFrozen()) {
                continue;
            }
        }
        // Everything in mTexturesAttached should be for the current render subpass.
        mTexturesAttached.clear();

        mCurrentSubpass += 1;
        mInputsSet.reset();
        mAspects.reset(VALIDATION_ASPECT_RENDER_SUBPASS);
        UnsetPipeline();
        return true;
    }

    bool CommandBufferStateTracker::BeginRenderPass(RenderPassBase* renderPass,
                                                    FramebufferBase* framebuffer) {
        if (mAspects[VALIDATION_ASPECT_COMPUTE_PASS]) {
            mBuilder->HandleError("Cannot begin a render pass while a compute pass is active");
            return false;
        }
        if (mCurrentRenderPass != nullptr) {
            mBuilder->HandleError("A render pass is already active");
            return false;
        }
        ASSERT(!mAspects[VALIDATION_ASPECT_RENDER_SUBPASS]);
        if (!framebuffer->GetRenderPass()->IsCompatibleWith(renderPass)) {
            mBuilder->HandleError("Framebuffer is incompatible with this render pass");
            return false;
        }

        mCurrentRenderPass = renderPass;
        mCurrentFramebuffer = framebuffer;
        mCurrentSubpass = 0;

        return true;
    }

    bool CommandBufferStateTracker::EndRenderPass() {
        if (mCurrentRenderPass == nullptr) {
            mBuilder->HandleError("No render pass is currently active");
            return false;
        }
        if (mAspects[VALIDATION_ASPECT_RENDER_SUBPASS]) {
            mBuilder->HandleError("Can't end a render pass while a subpass is active");
            return false;
        }
        if (mCurrentSubpass < mCurrentRenderPass->GetSubpassCount() - 1) {
            mBuilder->HandleError("Can't end a render pass before the last subpass");
            return false;
        }
        mCurrentRenderPass = nullptr;
        mCurrentFramebuffer = nullptr;

        return true;
    }

    bool CommandBufferStateTracker::SetComputePipeline(ComputePipelineBase* pipeline) {
        if (!mAspects[VALIDATION_ASPECT_COMPUTE_PASS]) {
            mBuilder->HandleError("A compute pass must be active when a compute pipeline is set");
            return false;
        }
        if (mCurrentRenderPass) {
            mBuilder->HandleError("Can't use a compute pipeline while a render pass is active");
            return false;
        }

        mAspects.set(VALIDATION_ASPECT_COMPUTE_PIPELINE);
        SetPipelineCommon(pipeline);
        return true;
    }

    bool CommandBufferStateTracker::SetRenderPipeline(RenderPipelineBase* pipeline) {
        if (!mAspects[VALIDATION_ASPECT_RENDER_SUBPASS]) {
            mBuilder->HandleError("A render subpass must be active when a render pipeline is set");
            return false;
        }
        if (!pipeline->GetRenderPass()->IsCompatibleWith(mCurrentRenderPass)) {
            mBuilder->HandleError("Pipeline is incompatible with this render pass");
            return false;
        }

        mAspects.set(VALIDATION_ASPECT_RENDER_PIPELINE);
        mLastRenderPipeline = pipeline;
        SetPipelineCommon(pipeline);
        return true;
    }

    bool CommandBufferStateTracker::SetBindGroup(uint32_t index, BindGroupBase* bindgroup) {
        if (!ValidateBindGroupUsages(bindgroup)) {
            return false;
        }
        mBindgroupsSet.set(index);
        mBindgroups[index] = bindgroup;

        return true;
    }

    bool CommandBufferStateTracker::SetIndexBuffer(BufferBase* buffer) {
        if (!HavePipeline()) {
            mBuilder->HandleError("Can't set the index buffer without a pipeline");
            return false;
        }

        auto usage = nxt::BufferUsageBit::Index;
        if (!BufferHasGuaranteedUsageBit(buffer, usage)) {
            mBuilder->HandleError("Buffer needs the index usage bit to be guaranteed");
            return false;
        }

        mAspects.set(VALIDATION_ASPECT_INDEX_BUFFER);
        return true;
    }

    bool CommandBufferStateTracker::SetVertexBuffer(uint32_t index, BufferBase* buffer) {
        if (!HavePipeline()) {
            mBuilder->HandleError("Can't set vertex buffers without a pipeline");
            return false;
        }

        auto usage = nxt::BufferUsageBit::Vertex;
        if (!BufferHasGuaranteedUsageBit(buffer, usage)) {
            mBuilder->HandleError("Buffer needs vertex usage bit to be guaranteed");
            return false;
        }

        mInputsSet.set(index);
        return true;
    }

    bool CommandBufferStateTracker::TransitionBufferUsage(BufferBase* buffer,
                                                          nxt::BufferUsageBit usage) {
        if (!buffer->IsTransitionPossible(usage)) {
            if (buffer->IsFrozen()) {
                mBuilder->HandleError("Buffer transition not possible (usage is frozen)");
            } else if (!BufferBase::IsUsagePossible(buffer->GetAllowedUsage(), usage)) {
                mBuilder->HandleError("Buffer transition not possible (usage not allowed)");
            } else {
                mBuilder->HandleError("Buffer transition not possible");
            }
            return false;
        }

        mMostRecentBufferUsages[buffer] = usage;
        mBuffersTransitioned.insert(buffer);
        return true;
    }

    bool CommandBufferStateTracker::TransitionTextureUsage(TextureBase* texture,
                                                           nxt::TextureUsageBit usage) {
        if (!IsExplicitTextureTransitionPossible(texture, usage)) {
            if (texture->IsFrozen()) {
                mBuilder->HandleError("Texture transition not possible (usage is frozen)");
            } else if (!TextureBase::IsUsagePossible(texture->GetAllowedUsage(), usage)) {
                mBuilder->HandleError("Texture transition not possible (usage not allowed)");
            } else if (mTexturesAttached.find(texture) != mTexturesAttached.end()) {
                mBuilder->HandleError(
                    "Texture transition not possible (texture is in use as a framebuffer "
                    "attachment)");
            } else {
                mBuilder->HandleError("Texture transition not possible");
            }
            return false;
        }

        mMostRecentTextureUsages[texture] = usage;
        mTexturesTransitioned.insert(texture);
        return true;
    }

    bool CommandBufferStateTracker::EnsureTextureUsage(TextureBase* texture,
                                                       nxt::TextureUsageBit usage) {
        if (texture->HasFrozenUsage(usage)) {
            return true;
        }
        if (!IsInternalTextureTransitionPossible(texture, usage)) {
            return false;
        }
        mMostRecentTextureUsages[texture] = usage;
        mTexturesTransitioned.insert(texture);
        return true;
    }

    bool CommandBufferStateTracker::BufferHasGuaranteedUsageBit(BufferBase* buffer,
                                                                nxt::BufferUsageBit usage) const {
        ASSERT(usage != nxt::BufferUsageBit::None && nxt::HasZeroOrOneBits(usage));
        if (buffer->HasFrozenUsage(usage)) {
            return true;
        }
        auto it = mMostRecentBufferUsages.find(buffer);
        return it != mMostRecentBufferUsages.end() && (it->second & usage);
    }

    bool CommandBufferStateTracker::TextureHasGuaranteedUsageBit(TextureBase* texture,
                                                                 nxt::TextureUsageBit usage) const {
        ASSERT(usage != nxt::TextureUsageBit::None && nxt::HasZeroOrOneBits(usage));
        if (texture->HasFrozenUsage(usage)) {
            return true;
        }
        auto it = mMostRecentTextureUsages.find(texture);
        return it != mMostRecentTextureUsages.end() && (it->second & usage);
    }

    bool CommandBufferStateTracker::IsInternalTextureTransitionPossible(
        TextureBase* texture,
        nxt::TextureUsageBit usage) const {
        ASSERT(usage != nxt::TextureUsageBit::None && nxt::HasZeroOrOneBits(usage));
        if (mTexturesAttached.find(texture) != mTexturesAttached.end()) {
            return false;
        }
        return texture->IsTransitionPossible(usage);
    }

    bool CommandBufferStateTracker::IsExplicitTextureTransitionPossible(
        TextureBase* texture,
        nxt::TextureUsageBit usage) const {
        const nxt::TextureUsageBit attachmentUsages = nxt::TextureUsageBit::OutputAttachment;
        if (usage & attachmentUsages) {
            return false;
        }
        return IsInternalTextureTransitionPossible(texture, usage);
    }

    bool CommandBufferStateTracker::RecomputeHaveAspectBindGroups() {
        if (mAspects[VALIDATION_ASPECT_BIND_GROUPS]) {
            return true;
        }
        // Assumes we have a pipeline already
        if (!mBindgroupsSet.all()) {
            return false;
        }
        for (size_t i = 0; i < mBindgroups.size(); ++i) {
            if (auto* bindgroup = mBindgroups[i]) {
                // TODO(kainino@chromium.org): bind group compatibility
                if (bindgroup->GetLayout() != mLastPipeline->GetLayout()->GetBindGroupLayout(i)) {
                    return false;
                }
            }
        }
        mAspects.set(VALIDATION_ASPECT_BIND_GROUPS);
        return true;
    }

    bool CommandBufferStateTracker::RecomputeHaveAspectVertexBuffers() {
        if (mAspects[VALIDATION_ASPECT_VERTEX_BUFFERS]) {
            return true;
        }
        // Assumes we have a pipeline already
        auto requiredInputs = mLastRenderPipeline->GetInputState()->GetInputsSetMask();
        if ((mInputsSet & requiredInputs) == requiredInputs) {
            mAspects.set(VALIDATION_ASPECT_VERTEX_BUFFERS);
            return true;
        }
        return false;
    }

    bool CommandBufferStateTracker::HavePipeline() const {
        constexpr ValidationAspects pipelineAspects =
            1 << VALIDATION_ASPECT_COMPUTE_PIPELINE | 1 << VALIDATION_ASPECT_RENDER_PIPELINE;
        return (mAspects & pipelineAspects).any();
    }

    bool CommandBufferStateTracker::ValidateBindGroupUsages(BindGroupBase* group) const {
        const auto& layoutInfo = group->GetLayout()->GetBindingInfo();
        for (size_t i = 0; i < kMaxBindingsPerGroup; ++i) {
            if (!layoutInfo.mask[i]) {
                continue;
            }

            nxt::BindingType type = layoutInfo.types[i];
            switch (type) {
                case nxt::BindingType::UniformBuffer:
                case nxt::BindingType::StorageBuffer: {
                    nxt::BufferUsageBit requiredUsage = nxt::BufferUsageBit::None;
                    switch (type) {
                        case nxt::BindingType::UniformBuffer:
                            requiredUsage = nxt::BufferUsageBit::Uniform;
                            break;

                        case nxt::BindingType::StorageBuffer:
                            requiredUsage = nxt::BufferUsageBit::Storage;
                            break;

                        default:
                            UNREACHABLE();
                    }

                    auto buffer = group->GetBindingAsBufferView(i)->GetBuffer();
                    if (!BufferHasGuaranteedUsageBit(buffer, requiredUsage)) {
                        mBuilder->HandleError("Can't guarantee buffer usage needed by bind group");
                        return false;
                    }
                } break;
                case nxt::BindingType::SampledTexture: {
                    auto requiredUsage = nxt::TextureUsageBit::Sampled;

                    auto texture = group->GetBindingAsTextureView(i)->GetTexture();
                    if (!TextureHasGuaranteedUsageBit(texture, requiredUsage)) {
                        mBuilder->HandleError("Can't guarantee texture usage needed by bind group");
                        return false;
                    }
                } break;
                case nxt::BindingType::Sampler:
                    continue;
            }
        }
        return true;
    }

    bool CommandBufferStateTracker::RevalidateCanDraw() {
        if (!mAspects[VALIDATION_ASPECT_RENDER_PIPELINE]) {
            mBuilder->HandleError("No active render pipeline");
            return false;
        }
        // Compute the lazily computed mAspects
        if (!RecomputeHaveAspectBindGroups()) {
            mBuilder->HandleError("Bind group state not valid");
            return false;
        }
        if (!RecomputeHaveAspectVertexBuffers()) {
            mBuilder->HandleError("Some vertex buffers are not set");
            return false;
        }
        return true;
    }

    void CommandBufferStateTracker::SetPipelineCommon(PipelineBase* pipeline) {
        PipelineLayoutBase* layout = pipeline->GetLayout();

        mAspects.reset(VALIDATION_ASPECT_BIND_GROUPS);
        mAspects.reset(VALIDATION_ASPECT_VERTEX_BUFFERS);
        // Reset bindgroups but mark unused bindgroups as valid
        mBindgroupsSet = ~layout->GetBindGroupsLayoutMask();

        // Only bindgroups that were not the same layout in the last pipeline need to be set again.
        if (mLastPipeline) {
            mBindgroupsSet |= layout->InheritedGroupsMask(mLastPipeline->GetLayout());
        }

        mLastPipeline = pipeline;
    }

    void CommandBufferStateTracker::UnsetPipeline() {
        constexpr ValidationAspects pipelineDependentAspects =
            1 << VALIDATION_ASPECT_RENDER_PIPELINE | 1 << VALIDATION_ASPECT_COMPUTE_PIPELINE |
            1 << VALIDATION_ASPECT_BIND_GROUPS | 1 << VALIDATION_ASPECT_VERTEX_BUFFERS |
            1 << VALIDATION_ASPECT_INDEX_BUFFER;
        mAspects &= ~pipelineDependentAspects;
        mBindgroups.fill(nullptr);
    }
}  // namespace backend
