// 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.

#ifndef DAWNNATIVE_SHADERMODULE_H_
#define DAWNNATIVE_SHADERMODULE_H_

#include "common/Constants.h"
#include "common/ityp_array.h"
#include "dawn_native/BindingInfo.h"
#include "dawn_native/CachedObject.h"
#include "dawn_native/CompilationMessages.h"
#include "dawn_native/Error.h"
#include "dawn_native/Format.h"
#include "dawn_native/Forward.h"
#include "dawn_native/IntegerTypes.h"
#include "dawn_native/ObjectBase.h"
#include "dawn_native/PerStage.h"
#include "dawn_native/VertexFormat.h"
#include "dawn_native/dawn_platform.h"

#include <bitset>
#include <map>
#include <unordered_map>
#include <unordered_set>
#include <vector>

namespace tint {

    class Program;

    namespace transform {
        class DataMap;
        class Transform;
        class VertexPulling;
    }  // namespace transform

}  // namespace tint

namespace dawn_native {

    struct EntryPointMetadata;

    // Base component type of an inter-stage variable
    enum class InterStageComponentType {
        Sint,
        Uint,
        Float,
    };

    enum class InterpolationType {
        Perspective,
        Linear,
        Flat,
    };

    enum class InterpolationSampling {
        None,
        Center,
        Centroid,
        Sample,
    };

    using PipelineLayoutEntryPointPair = std::pair<PipelineLayoutBase*, std::string>;
    struct PipelineLayoutEntryPointPairHashFunc {
        size_t operator()(const PipelineLayoutEntryPointPair& pair) const;
    };

    // A map from name to EntryPointMetadata.
    using EntryPointMetadataTable =
        std::unordered_map<std::string, std::unique_ptr<EntryPointMetadata>>;

    // Source for a tint program
    class TintSource;

    struct ShaderModuleParseResult {
        ShaderModuleParseResult();
        ~ShaderModuleParseResult();
        ShaderModuleParseResult(ShaderModuleParseResult&& rhs);
        ShaderModuleParseResult& operator=(ShaderModuleParseResult&& rhs);

        bool HasParsedShader() const;

        std::unique_ptr<tint::Program> tintProgram;
        std::unique_ptr<TintSource> tintSource;
    };

    MaybeError ValidateShaderModuleDescriptor(DeviceBase* device,
                                              const ShaderModuleDescriptor* descriptor,
                                              ShaderModuleParseResult* parseResult,
                                              OwnedCompilationMessages* outMessages);
    MaybeError ValidateCompatibilityWithPipelineLayout(DeviceBase* device,
                                                       const EntryPointMetadata& entryPoint,
                                                       const PipelineLayoutBase* layout);

    RequiredBufferSizes ComputeRequiredBufferSizesForLayout(const EntryPointMetadata& entryPoint,
                                                            const PipelineLayoutBase* layout);
    ResultOrError<tint::Program> RunTransforms(tint::transform::Transform* transform,
                                               const tint::Program* program,
                                               const tint::transform::DataMap& inputs,
                                               tint::transform::DataMap* outputs,
                                               OwnedCompilationMessages* messages);

    /// Creates and adds the tint::transform::VertexPulling::Config to transformInputs.
    void AddVertexPullingTransformConfig(const RenderPipelineBase& renderPipeline,
                                         const std::string& entryPoint,
                                         BindGroupIndex pullingBufferBindingSet,
                                         tint::transform::DataMap* transformInputs);

    // Mirrors wgpu::SamplerBindingLayout but instead stores a single boolean
    // for isComparison instead of a wgpu::SamplerBindingType enum.
    struct ShaderSamplerBindingInfo {
        bool isComparison;
    };

    // Mirrors wgpu::TextureBindingLayout but instead has a set of compatible sampleTypes
    // instead of a single enum.
    struct ShaderTextureBindingInfo {
        SampleTypeBit compatibleSampleTypes;
        wgpu::TextureViewDimension viewDimension;
        bool multisampled;
    };

    // Per-binding shader metadata contains some SPIRV specific information in addition to
    // most of the frontend per-binding information.
    struct ShaderBindingInfo {
        // The SPIRV ID of the resource.
        uint32_t id;
        uint32_t base_type_id;

        BindingNumber binding;
        BindingInfoType bindingType;

        BufferBindingLayout buffer;
        ShaderSamplerBindingInfo sampler;
        ShaderTextureBindingInfo texture;
        StorageTextureBindingLayout storageTexture;
    };

    using BindingGroupInfoMap = std::map<BindingNumber, ShaderBindingInfo>;
    using BindingInfoArray = ityp::array<BindGroupIndex, BindingGroupInfoMap, kMaxBindGroups>;

    // The WebGPU overridable constants only support these scalar types
    union OverridableConstantScalar {
        // Use int32_t for boolean to initialize the full 32bit
        int32_t b;
        float f32;
        int32_t i32;
        uint32_t u32;
    };

    // Contains all the reflection data for a valid (ShaderModule, entryPoint, stage). They are
    // stored in the ShaderModuleBase and destroyed only when the shader program is destroyed so
    // pointers to EntryPointMetadata are safe to store as long as you also keep a Ref to the
    // ShaderModuleBase.
    struct EntryPointMetadata {
        // bindings[G][B] is the reflection data for the binding defined with
        // [[group=G, binding=B]] in WGSL / SPIRV.
        BindingInfoArray bindings;

        struct SamplerTexturePair {
            BindingSlot sampler;
            BindingSlot texture;
        };
        std::vector<SamplerTexturePair> samplerTexturePairs;

        // The set of vertex attributes this entryPoint uses.
        ityp::array<VertexAttributeLocation, VertexFormatBaseType, kMaxVertexAttributes>
            vertexInputBaseTypes;
        ityp::bitset<VertexAttributeLocation, kMaxVertexAttributes> usedVertexInputs;

        // An array to record the basic types (float, int and uint) of the fragment shader outputs.
        struct FragmentOutputVariableInfo {
            wgpu::TextureComponentType baseType;
            uint8_t componentCount;
        };
        ityp::array<ColorAttachmentIndex, FragmentOutputVariableInfo, kMaxColorAttachments>
            fragmentOutputVariables;
        ityp::bitset<ColorAttachmentIndex, kMaxColorAttachments> fragmentOutputsWritten;

        struct InterStageVariableInfo {
            InterStageComponentType baseType;
            uint32_t componentCount;
            InterpolationType interpolationType;
            InterpolationSampling interpolationSampling;
        };
        // Now that we only support vertex and fragment stages, there can't be both inter-stage
        // inputs and outputs in one shader stage.
        std::bitset<kMaxInterStageShaderVariables> usedInterStageVariables;
        std::array<InterStageVariableInfo, kMaxInterStageShaderVariables> interStageVariables;

        // The local workgroup size declared for a compute entry point (or 0s otehrwise).
        Origin3D localWorkgroupSize;

        // The shader stage for this binding.
        SingleShaderStage stage;

        struct OverridableConstant {
            uint32_t id;
            // Match tint::inspector::OverridableConstant::Type
            // Bool is defined as a macro on linux X11 and cannot compile
            enum class Type { Boolean, Float32, Uint32, Int32 } type;

            // If the constant doesn't not have an initializer in the shader
            // Then it is required for the pipeline stage to have a constant record to initialize a
            // value
            bool isInitialized;

            // Store the default initialized value in shader
            // This is used by metal backend as the function_constant does not have dafault values
            // Initialized when isInitialized == true
            OverridableConstantScalar defaultValue;
        };

        using OverridableConstantsMap = std::unordered_map<std::string, OverridableConstant>;

        // Map identifier to overridable constant
        // Identifier is unique: either the variable name or the numeric ID if specified
        OverridableConstantsMap overridableConstants;

        // Overridable constants that are not initialized in shaders
        // They need value initialization from pipeline stage or it is a validation error
        std::unordered_set<std::string> uninitializedOverridableConstants;

        // Store constants with shader initialized values as well
        // This is used by metal backend to set values with default initializers that are not
        // overridden
        std::unordered_set<std::string> initializedOverridableConstants;

        bool usesNumWorkgroups = false;
    };

    class ShaderModuleBase : public ApiObjectBase, public CachedObject {
      public:
        ShaderModuleBase(DeviceBase* device,
                         const ShaderModuleDescriptor* descriptor,
                         ApiObjectBase::UntrackedByDeviceTag tag);
        ShaderModuleBase(DeviceBase* device, const ShaderModuleDescriptor* descriptor);
        ~ShaderModuleBase() override;

        static Ref<ShaderModuleBase> MakeError(DeviceBase* device);

        ObjectType GetType() const override;

        // Return true iff the program has an entrypoint called `entryPoint`.
        bool HasEntryPoint(const std::string& entryPoint) const;

        // Return the metadata for the given `entryPoint`. HasEntryPoint with the same argument
        // must be true.
        const EntryPointMetadata& GetEntryPoint(const std::string& entryPoint) const;

        // Functions necessary for the unordered_set<ShaderModuleBase*>-based cache.
        size_t ComputeContentHash() override;

        struct EqualityFunc {
            bool operator()(const ShaderModuleBase* a, const ShaderModuleBase* b) const;
        };

        const tint::Program* GetTintProgram() const;

        void APIGetCompilationInfo(wgpu::CompilationInfoCallback callback, void* userdata);

        void InjectCompilationMessages(
            std::unique_ptr<OwnedCompilationMessages> compilationMessages);

        OwnedCompilationMessages* GetCompilationMessages() const;

      protected:
        // Constructor used only for mocking and testing.
        ShaderModuleBase(DeviceBase* device);
        void DestroyImpl() override;

        MaybeError InitializeBase(ShaderModuleParseResult* parseResult);

      private:
        ShaderModuleBase(DeviceBase* device, ObjectBase::ErrorTag tag);

        // The original data in the descriptor for caching.
        enum class Type { Undefined, Spirv, Wgsl };
        Type mType;
        std::vector<uint32_t> mOriginalSpirv;
        std::string mWgsl;

        EntryPointMetadataTable mEntryPoints;
        std::unique_ptr<tint::Program> mTintProgram;
        std::unique_ptr<TintSource> mTintSource;  // Keep the tint::Source::File alive

        std::unique_ptr<OwnedCompilationMessages> mCompilationMessages;
    };

}  // namespace dawn_native

#endif  // DAWNNATIVE_SHADERMODULE_H_
