// Copyright 2017 The Dawn 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 "dawn_native/Pipeline.h"

#include "dawn_native/BindGroupLayout.h"
#include "dawn_native/Device.h"
#include "dawn_native/ObjectContentHasher.h"
#include "dawn_native/PipelineLayout.h"
#include "dawn_native/ShaderModule.h"

namespace dawn_native {

    MaybeError ValidateProgrammableStage(DeviceBase* device,
                                         const ShaderModuleBase* module,
                                         const std::string& entryPoint,
                                         const PipelineLayoutBase* layout,
                                         SingleShaderStage stage) {
        DAWN_TRY(device->ValidateObject(module));

        if (!module->HasEntryPoint(entryPoint)) {
            return DAWN_VALIDATION_ERROR("Entry point doesn't exist in the module");
        }

        const EntryPointMetadata& metadata = module->GetEntryPoint(entryPoint);

        if (metadata.stage != stage) {
            return DAWN_VALIDATION_ERROR("Entry point isn't for the correct stage");
        }

        if (layout != nullptr) {
            DAWN_TRY(ValidateCompatibilityWithPipelineLayout(device, metadata, layout));
        }

        return {};
    }

    // PipelineBase

    PipelineBase::PipelineBase(DeviceBase* device,
                               PipelineLayoutBase* layout,
                               std::vector<StageAndDescriptor> stages)
        : CachedObject(device, kLabelNotImplemented), mLayout(layout) {
        ASSERT(!stages.empty());

        for (const StageAndDescriptor& stage : stages) {
            // Extract argument for this stage.
            SingleShaderStage shaderStage = stage.shaderStage;
            ShaderModuleBase* module = stage.module;
            const char* entryPointName = stage.entryPoint.c_str();

            const EntryPointMetadata& metadata = module->GetEntryPoint(entryPointName);
            ASSERT(metadata.stage == shaderStage);

            // Record them internally.
            bool isFirstStage = mStageMask == wgpu::ShaderStage::None;
            mStageMask |= StageBit(shaderStage);
            mStages[shaderStage] = {module, entryPointName, &metadata};

            // Compute the max() of all minBufferSizes across all stages.
            RequiredBufferSizes stageMinBufferSizes =
                ComputeRequiredBufferSizesForLayout(metadata, layout);

            if (isFirstStage) {
                mMinBufferSizes = std::move(stageMinBufferSizes);
            } else {
                for (BindGroupIndex group(0); group < mMinBufferSizes.size(); ++group) {
                    ASSERT(stageMinBufferSizes[group].size() == mMinBufferSizes[group].size());

                    for (size_t i = 0; i < stageMinBufferSizes[group].size(); ++i) {
                        mMinBufferSizes[group][i] =
                            std::max(mMinBufferSizes[group][i], stageMinBufferSizes[group][i]);
                    }
                }
            }
        }
    }

    PipelineBase::PipelineBase(DeviceBase* device, ObjectBase::ErrorTag tag)
        : CachedObject(device, tag) {
    }

    PipelineLayoutBase* PipelineBase::GetLayout() {
        ASSERT(!IsError());
        return mLayout.Get();
    }

    const PipelineLayoutBase* PipelineBase::GetLayout() const {
        ASSERT(!IsError());
        return mLayout.Get();
    }

    const RequiredBufferSizes& PipelineBase::GetMinBufferSizes() const {
        ASSERT(!IsError());
        return mMinBufferSizes;
    }

    const ProgrammableStage& PipelineBase::GetStage(SingleShaderStage stage) const {
        ASSERT(!IsError());
        return mStages[stage];
    }

    const PerStage<ProgrammableStage>& PipelineBase::GetAllStages() const {
        return mStages;
    }

    MaybeError PipelineBase::ValidateGetBindGroupLayout(uint32_t groupIndex) {
        DAWN_TRY(GetDevice()->ValidateIsAlive());
        DAWN_TRY(GetDevice()->ValidateObject(this));
        DAWN_TRY(GetDevice()->ValidateObject(mLayout.Get()));
        if (groupIndex >= kMaxBindGroups) {
            return DAWN_VALIDATION_ERROR("Bind group layout index out of bounds");
        }
        return {};
    }

    ResultOrError<Ref<BindGroupLayoutBase>> PipelineBase::GetBindGroupLayout(
        uint32_t groupIndexIn) {
        DAWN_TRY(ValidateGetBindGroupLayout(groupIndexIn));

        BindGroupIndex groupIndex(groupIndexIn);
        if (!mLayout->GetBindGroupLayoutsMask()[groupIndex]) {
            return Ref<BindGroupLayoutBase>(GetDevice()->GetEmptyBindGroupLayout());
        } else {
            return Ref<BindGroupLayoutBase>(mLayout->GetBindGroupLayout(groupIndex));
        }
    }

    BindGroupLayoutBase* PipelineBase::APIGetBindGroupLayout(uint32_t groupIndexIn) {
        Ref<BindGroupLayoutBase> result;
        if (GetDevice()->ConsumedError(GetBindGroupLayout(groupIndexIn), &result)) {
            return BindGroupLayoutBase::MakeError(GetDevice());
        }
        return result.Detach();
    }

    size_t PipelineBase::ComputeContentHash() {
        ObjectContentHasher recorder;
        recorder.Record(mLayout->GetContentHash());

        recorder.Record(mStageMask);
        for (SingleShaderStage stage : IterateStages(mStageMask)) {
            recorder.Record(mStages[stage].module->GetContentHash());
            recorder.Record(mStages[stage].entryPoint);
        }

        return recorder.GetContentHash();
    }

    // static
    bool PipelineBase::EqualForCache(const PipelineBase* a, const PipelineBase* b) {
        // The layout is deduplicated so it can be compared by pointer.
        if (a->mLayout.Get() != b->mLayout.Get() || a->mStageMask != b->mStageMask) {
            return false;
        }

        for (SingleShaderStage stage : IterateStages(a->mStageMask)) {
            // The module is deduplicated so it can be compared by pointer.
            if (a->mStages[stage].module.Get() != b->mStages[stage].module.Get() ||
                a->mStages[stage].entryPoint != b->mStages[stage].entryPoint) {
                return false;
            }
        }

        return true;
    }

}  // namespace dawn_native
