// 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/opengl/ShaderModuleGL.h"

#include "dawn/native/BindGroupLayout.h"
#include "dawn/native/TintUtils.h"
#include "dawn/native/opengl/DeviceGL.h"
#include "dawn/native/opengl/PipelineLayoutGL.h"
#include "dawn/platform/DawnPlatform.h"
#include "dawn/platform/tracing/TraceEvent.h"

#include <tint/tint.h>

#include <sstream>

namespace dawn::native::opengl {

    std::string GetBindingName(BindGroupIndex group, BindingNumber bindingNumber) {
        std::ostringstream o;
        o << "dawn_binding_" << static_cast<uint32_t>(group) << "_"
          << static_cast<uint32_t>(bindingNumber);
        return o.str();
    }

    bool operator<(const BindingLocation& a, const BindingLocation& b) {
        return std::tie(a.group, a.binding) < std::tie(b.group, b.binding);
    }

    bool operator<(const CombinedSampler& a, const CombinedSampler& b) {
        return std::tie(a.useDummySampler, a.samplerLocation, a.textureLocation) <
               std::tie(b.useDummySampler, a.samplerLocation, b.textureLocation);
    }

    std::string CombinedSampler::GetName() const {
        std::ostringstream o;
        o << "dawn_combined";
        if (useDummySampler) {
            o << "_dummy_sampler";
        } else {
            o << "_" << static_cast<uint32_t>(samplerLocation.group) << "_"
              << static_cast<uint32_t>(samplerLocation.binding);
        }
        o << "_with_" << static_cast<uint32_t>(textureLocation.group) << "_"
          << static_cast<uint32_t>(textureLocation.binding);
        return o.str();
    }

    // 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());

        DAWN_TRY(InitializeBase(parseResult));

        return {};
    }

    ResultOrError<std::string> ShaderModule::TranslateToGLSL(const char* entryPointName,
                                                             SingleShaderStage stage,
                                                             CombinedSamplerInfo* combinedSamplers,
                                                             const PipelineLayout* layout,
                                                             bool* needsDummySampler) const {
        TRACE_EVENT0(GetDevice()->GetPlatform(), General, "TranslateToGLSL");
        tint::transform::Manager transformManager;
        tint::transform::DataMap transformInputs;

        AddExternalTextureTransform(layout, &transformManager, &transformInputs);

        tint::Program program;
        DAWN_TRY_ASSIGN(program, RunTransforms(&transformManager, GetTintProgram(), transformInputs,
                                               nullptr, nullptr));
        const OpenGLVersion& version = ToBackend(GetDevice())->gl.GetVersion();

        tint::writer::glsl::Options tintOptions;
        using Version = tint::writer::glsl::Version;
        tintOptions.version =
            Version(version.IsDesktop() ? Version::Standard::kDesktop : Version::Standard::kES,
                    version.GetMajor(), version.GetMinor());

        using tint::transform::BindingPoint;
        // When textures are accessed without a sampler (e.g., textureLoad()),
        // GetSamplerTextureUses() will return this sentinel value.
        BindingPoint placeholderBindingPoint{static_cast<uint32_t>(kMaxBindGroupsTyped), 0};

        tint::inspector::Inspector inspector(&program);
        // Find all the sampler/texture pairs for this entry point, and create
        // CombinedSamplers for them. CombinedSampler records the binding points
        // of the original texture and sampler, and generates a unique name. The
        // corresponding uniforms will be retrieved by these generated names
        // in PipelineGL. Any texture-only references will have
        // "useDummySampler" set to true, and only the texture binding point
        // will be used in naming them. In addition, Dawn will bind a
        // non-filtering sampler for them (see PipelineGL).
        auto uses = inspector.GetSamplerTextureUses(entryPointName, placeholderBindingPoint);
        for (const auto& use : uses) {
            combinedSamplers->emplace_back();

            CombinedSampler* info = &combinedSamplers->back();
            if (use.sampler_binding_point == placeholderBindingPoint) {
                info->useDummySampler = true;
                *needsDummySampler = true;
            } else {
                info->useDummySampler = false;
            }
            info->samplerLocation.group = BindGroupIndex(use.sampler_binding_point.group);
            info->samplerLocation.binding = BindingNumber(use.sampler_binding_point.binding);
            info->textureLocation.group = BindGroupIndex(use.texture_binding_point.group);
            info->textureLocation.binding = BindingNumber(use.texture_binding_point.binding);
            tintOptions.binding_map[use] = info->GetName();
        }
        if (*needsDummySampler) {
            tintOptions.placeholder_binding_point = placeholderBindingPoint;
        }

        // Since (non-Vulkan) GLSL does not support descriptor sets, generate a
        // mapping from the original group/binding pair to a binding-only
        // value. This mapping will be used by Tint to remap all global
        // variables to the 1D space.
        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()[group][bindingIndex];
                BindingPoint srcBindingPoint{static_cast<uint32_t>(group),
                                             static_cast<uint32_t>(bindingNumber)};
                BindingPoint dstBindingPoint{0, shaderIndex};
                tintOptions.binding_points.emplace(srcBindingPoint, dstBindingPoint);
            }
            tintOptions.allow_collisions = true;
        }
        auto result = tint::writer::glsl::Generate(&program, tintOptions, entryPointName);
        DAWN_INVALID_IF(!result.success, "An error occured while generating GLSL: %s.",
                        result.error);
        std::string glsl = std::move(result.glsl);

        if (GetDevice()->IsToggleEnabled(Toggle::DumpShaders)) {
            std::ostringstream dumpedMsg;
            dumpedMsg << "/* Dumped generated GLSL */" << std::endl << glsl;

            GetDevice()->EmitLog(WGPULoggingType_Info, dumpedMsg.str().c_str());
        }

        return glsl;
    }

}  // namespace dawn::native::opengl
