// 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/metal/ShaderModuleMTL.h"

#include "dawn_native/BindGroupLayout.h"
#include "dawn_native/TintUtils.h"
#include "dawn_native/metal/DeviceMTL.h"
#include "dawn_native/metal/PipelineLayoutMTL.h"
#include "dawn_native/metal/RenderPipelineMTL.h"

#include <tint/tint.h>

#include <sstream>

namespace dawn_native { namespace metal {

    // static
    ResultOrError<Ref<ShaderModule>> ShaderModule::Create(Device* device,
                                                          const ShaderModuleDescriptor* descriptor,
                                                          ShaderModuleParseResult* parseResult) {
        Ref<ShaderModule> module = AcquireRef(new ShaderModule(device, descriptor));
        DAWN_TRY(module->Initialize(parseResult));
        return module;
    }

    ShaderModule::ShaderModule(Device* device, const ShaderModuleDescriptor* descriptor)
        : ShaderModuleBase(device, descriptor) {
    }

    MaybeError ShaderModule::Initialize(ShaderModuleParseResult* parseResult) {
        ScopedTintICEHandler scopedICEHandler(GetDevice());
        return InitializeBase(parseResult);
    }

    ResultOrError<std::string> ShaderModule::TranslateToMSL(const char* entryPointName,
                                                            SingleShaderStage stage,
                                                            const PipelineLayout* layout,
                                                            uint32_t sampleMask,
                                                            const RenderPipeline* renderPipeline,
                                                            const VertexState* vertexState,
                                                            std::string* remappedEntryPointName,
                                                            bool* needsStorageBufferLength,
                                                            bool* hasInvariantAttribute) {
        ScopedTintICEHandler scopedICEHandler(GetDevice());

        std::ostringstream errorStream;
        errorStream << "Tint MSL failure:" << std::endl;

        // Remap BindingNumber to BindingIndex in WGSL shader
        using BindingRemapper = tint::transform::BindingRemapper;
        using BindingPoint = tint::transform::BindingPoint;
        BindingRemapper::BindingPoints bindingPoints;
        BindingRemapper::AccessControls accessControls;

        for (BindGroupIndex group : IterateBitSet(layout->GetBindGroupLayoutsMask())) {
            const BindGroupLayoutBase::BindingMap& bindingMap =
                layout->GetBindGroupLayout(group)->GetBindingMap();
            for (const auto& it : bindingMap) {
                BindingNumber bindingNumber = it.first;
                BindingIndex bindingIndex = it.second;

                const BindingInfo& bindingInfo =
                    layout->GetBindGroupLayout(group)->GetBindingInfo(bindingIndex);

                if (!(bindingInfo.visibility & StageBit(stage))) {
                    continue;
                }

                uint32_t shaderIndex = layout->GetBindingIndexInfo(stage)[group][bindingIndex];

                BindingPoint srcBindingPoint{static_cast<uint32_t>(group),
                                             static_cast<uint32_t>(bindingNumber)};
                BindingPoint dstBindingPoint{0, shaderIndex};
                if (srcBindingPoint != dstBindingPoint) {
                    bindingPoints.emplace(srcBindingPoint, dstBindingPoint);
                }
            }
        }

        tint::transform::Manager transformManager;
        tint::transform::DataMap transformInputs;

        // We only remap bindings for the target entry point, so we need to strip all other entry
        // points to avoid generating invalid bindings for them.
        transformManager.Add<tint::transform::SingleEntryPoint>();
        transformInputs.Add<tint::transform::SingleEntryPoint::Config>(entryPointName);

        if (stage == SingleShaderStage::Vertex &&
            GetDevice()->IsToggleEnabled(Toggle::MetalEnableVertexPulling)) {
            transformManager.Add<tint::transform::VertexPulling>();
            AddVertexPullingTransformConfig(*vertexState, entryPointName, kPullingBufferBindingSet,
                                            &transformInputs);

            for (VertexBufferSlot slot :
                 IterateBitSet(renderPipeline->GetVertexBufferSlotsUsed())) {
                uint32_t metalIndex = renderPipeline->GetMtlVertexBufferIndex(slot);

                // Tell Tint to map (kPullingBufferBindingSet, slot) to this MSL buffer index.
                BindingPoint srcBindingPoint{static_cast<uint32_t>(kPullingBufferBindingSet),
                                             static_cast<uint8_t>(slot)};
                BindingPoint dstBindingPoint{0, metalIndex};
                if (srcBindingPoint != dstBindingPoint) {
                    bindingPoints.emplace(srcBindingPoint, dstBindingPoint);
                }
            }
        }
        if (GetDevice()->IsRobustnessEnabled()) {
            transformManager.Add<tint::transform::BoundArrayAccessors>();
        }
        transformManager.Add<tint::transform::BindingRemapper>();
        transformManager.Add<tint::transform::Renamer>();

        if (GetDevice()->IsToggleEnabled(Toggle::DisableSymbolRenaming)) {
            // We still need to rename MSL reserved keywords
            transformInputs.Add<tint::transform::Renamer::Config>(
                tint::transform::Renamer::Target::kMslKeywords);
        }

        transformInputs.Add<BindingRemapper::Remappings>(std::move(bindingPoints),
                                                         std::move(accessControls),
                                                         /* mayCollide */ true);

        tint::Program program;
        tint::transform::DataMap transformOutputs;
        DAWN_TRY_ASSIGN(program, RunTransforms(&transformManager, GetTintProgram(), transformInputs,
                                               &transformOutputs, nullptr));

        if (auto* data = transformOutputs.Get<tint::transform::Renamer::Data>()) {
            auto it = data->remappings.find(entryPointName);
            if (it != data->remappings.end()) {
                *remappedEntryPointName = it->second;
            } else {
                if (GetDevice()->IsToggleEnabled(Toggle::DisableSymbolRenaming)) {
                    *remappedEntryPointName = entryPointName;
                } else {
                    return DAWN_VALIDATION_ERROR("Could not find remapped name for entry point.");
                }
            }
        } else {
            return DAWN_VALIDATION_ERROR("Transform output missing renamer data.");
        }

        tint::writer::msl::Options options;
        options.buffer_size_ubo_index = kBufferLengthBufferSlot;
        options.fixed_sample_mask = sampleMask;
        options.disable_workgroup_init = GetDevice()->IsToggleEnabled(Toggle::DisableWorkgroupInit);
        options.emit_vertex_point_size =
            stage == SingleShaderStage::Vertex &&
            renderPipeline->GetPrimitiveTopology() == wgpu::PrimitiveTopology::PointList;
        auto result = tint::writer::msl::Generate(&program, options);
        if (!result.success) {
            errorStream << "Generator: " << result.error << std::endl;
            return DAWN_VALIDATION_ERROR(errorStream.str().c_str());
        }

        *needsStorageBufferLength = result.needs_storage_buffer_sizes;
        *hasInvariantAttribute = result.has_invariant_attribute;

        return std::move(result.msl);
    }

    MaybeError ShaderModule::CreateFunction(const char* entryPointName,
                                            SingleShaderStage stage,
                                            const PipelineLayout* layout,
                                            ShaderModule::MetalFunctionData* out,
                                            uint32_t sampleMask,
                                            const RenderPipeline* renderPipeline,
                                            const VertexState* vertexState) {
        ASSERT(!IsError());
        ASSERT(out);

        // Vertex stages must specify a renderPipeline and vertexState
        if (stage == SingleShaderStage::Vertex) {
            ASSERT(renderPipeline != nullptr);
            ASSERT(vertexState != nullptr);
        }

        std::string remappedEntryPointName;
        std::string msl;
        bool hasInvariantAttribute = false;
        DAWN_TRY_ASSIGN(msl,
                        TranslateToMSL(entryPointName, stage, layout, sampleMask, renderPipeline,
                                       vertexState, &remappedEntryPointName,
                                       &out->needsStorageBufferLength, &hasInvariantAttribute));

        // Metal uses Clang to compile the shader as C++14. Disable everything in the -Wall
        // category. -Wunused-variable in particular comes up a lot in generated code, and some
        // (old?) Metal drivers accidentally treat it as a MTLLibraryErrorCompileError instead
        // of a warning.
        msl = R"(
#ifdef __clang__
#pragma clang diagnostic ignored "-Wall"
#endif
)" + msl;

        if (GetDevice()->IsToggleEnabled(Toggle::DumpShaders)) {
            std::ostringstream dumpedMsg;
            dumpedMsg << "/* Dumped generated MSL */" << std::endl << msl;
            GetDevice()->EmitLog(WGPULoggingType_Info, dumpedMsg.str().c_str());
        }

        NSRef<NSString> mslSource = AcquireNSRef([[NSString alloc] initWithUTF8String:msl.c_str()]);

        NSRef<MTLCompileOptions> compileOptions = AcquireNSRef([[MTLCompileOptions alloc] init]);
        if (hasInvariantAttribute) {
            if (@available(macOS 11.0, iOS 13.0, *)) {
                (*compileOptions).preserveInvariance = true;
            }
        }
        auto mtlDevice = ToBackend(GetDevice())->GetMTLDevice();
        NSError* error = nullptr;
        NSPRef<id<MTLLibrary>> library =
            AcquireNSPRef([mtlDevice newLibraryWithSource:mslSource.Get()
                                                  options:compileOptions.Get()
                                                    error:&error]);
        if (error != nullptr) {
            if (error.code != MTLLibraryErrorCompileWarning) {
                return DAWN_VALIDATION_ERROR(std::string("Unable to create library object: ") +
                                             [error.localizedDescription UTF8String]);
            }
        }
        ASSERT(library != nil);

        NSRef<NSString> name =
            AcquireNSRef([[NSString alloc] initWithUTF8String:remappedEntryPointName.c_str()]);
        out->function = AcquireNSPRef([*library newFunctionWithName:name.Get()]);

        if (GetDevice()->IsToggleEnabled(Toggle::MetalEnableVertexPulling) &&
            GetEntryPoint(entryPointName).usedVertexInputs.any()) {
            out->needsStorageBufferLength = true;
        }

        return {};
    }
}}  // namespace dawn_native::metal
