// 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, ObjectBase::ErrorTag tag)
        : ApiObjectBase(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;
    }

    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
