// 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/ObjectBase.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,
                                         uint32_t constantCount,
                                         const ConstantEntry* constants,
                                         const PipelineLayoutBase* layout,
                                         SingleShaderStage stage) {
        DAWN_TRY(device->ValidateObject(module));

        DAWN_INVALID_IF(!module->HasEntryPoint(entryPoint),
                        "Entry point \"%s\" doesn't exist in the shader module %s.", entryPoint,
                        module);

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

        DAWN_INVALID_IF(metadata.stage != stage,
                        "The stage (%s) of the entry point \"%s\" isn't the expected one (%s).",
                        metadata.stage, entryPoint, stage);

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

        if (constantCount > 0u && device->IsToggleEnabled(Toggle::DisallowUnsafeAPIs)) {
            return DAWN_VALIDATION_ERROR(
                "Pipeline overridable constants are disallowed because they are partially "
                "implemented.");
        }

        // Validate if overridable constants exist in shader module
        // pipelineBase is not yet constructed at this moment so iterate constants from descriptor
        size_t numUninitializedConstants = metadata.uninitializedOverridableConstants.size();
        // Keep a initialized constants sets to handle duplicate initialization cases
        // Only storing that of uninialized constants is needed
        std::unordered_set<std::string> stageInitializedConstantIdentifiers;
        for (uint32_t i = 0; i < constantCount; i++) {
            DAWN_INVALID_IF(metadata.overridableConstants.count(constants[i].key) == 0,
                            "Pipeline overridable constant \"%s\" not found in shader module %s.",
                            constants[i].key, module);

            if (metadata.uninitializedOverridableConstants.count(constants[i].key) > 0 &&
                stageInitializedConstantIdentifiers.count(constants[i].key) == 0) {
                numUninitializedConstants--;
                stageInitializedConstantIdentifiers.insert(constants[i].key);
            }
        }

        // Validate if any overridable constant is left uninitialized
        if (DAWN_UNLIKELY(numUninitializedConstants > 0)) {
            std::string uninitializedConstantsArray;
            bool isFirst = true;
            for (std::string identifier : metadata.uninitializedOverridableConstants) {
                if (stageInitializedConstantIdentifiers.count(identifier) > 0) {
                    continue;
                }

                if (isFirst) {
                    isFirst = false;
                } else {
                    uninitializedConstantsArray.append(", ");
                }
                uninitializedConstantsArray.append(identifier);
            }

            return DAWN_FORMAT_VALIDATION_ERROR(
                "There are uninitialized pipeline overridable constants in shader module %s, their "
                "identifiers:[%s]",
                module, uninitializedConstantsArray);
        }

        return {};
    }

    // PipelineBase

    PipelineBase::PipelineBase(DeviceBase* device,
                               PipelineLayoutBase* layout,
                               const char* label,
                               std::vector<StageAndDescriptor> stages)
        : ApiObjectBase(device, label), 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,
                                    std::vector<PipelineConstantEntry>()};
            auto& constants = mStages[shaderStage].constants;
            for (uint32_t i = 0; i < stage.constantCount; i++) {
                constants.emplace_back(stage.constants[i].key, stage.constants[i].value);
            }

            // 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) : ApiObjectBase(device, kLabelNotImplemented) {
    }

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

    PipelineBase::~PipelineBase() = default;

    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;
    }

    wgpu::ShaderStage PipelineBase::GetStageMask() const {
        return mStageMask;
    }

    MaybeError PipelineBase::ValidateGetBindGroupLayout(uint32_t groupIndex) {
        DAWN_TRY(GetDevice()->ValidateIsAlive());
        DAWN_TRY(GetDevice()->ValidateObject(this));
        DAWN_TRY(GetDevice()->ValidateObject(mLayout.Get()));
        DAWN_INVALID_IF(
            groupIndex >= kMaxBindGroups,
            "Bind group layout index (%u) exceeds the maximum number of bind groups (%u).",
            groupIndex, kMaxBindGroups);
        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,
                                       "Validating GetBindGroupLayout (%u) on %s", groupIndexIn,
                                       this)) {
            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
