// 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 "common/Assert.h"
#include "common/Platform.h"
#include "dawn_native/opengl/DeviceGL.h"

#include <spirv_glsl.hpp>

#include <sstream>

namespace dawn_native { namespace opengl {

    std::string GetBindingName(uint32_t group, uint32_t binding) {
        std::ostringstream o;
        o << "dawn_binding_" << group << "_" << binding;
        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.samplerLocation, a.textureLocation) <
               std::tie(b.samplerLocation, b.textureLocation);
    }

    std::string CombinedSampler::GetName() const {
        std::ostringstream o;
        o << "dawn_combined";
        o << "_" << samplerLocation.group << "_" << samplerLocation.binding;
        o << "_with_" << textureLocation.group << "_" << textureLocation.binding;
        return o.str();
    }

    // static
    ResultOrError<ShaderModule*> ShaderModule::Create(Device* device,
                                                      const ShaderModuleDescriptor* descriptor) {
        std::unique_ptr<ShaderModule> module(new ShaderModule(device, descriptor));
        if (!module)
            return DAWN_VALIDATION_ERROR("Unable to create ShaderModule");
        DAWN_TRY(module->Initialize(descriptor));
        return module.release();
    }

    const char* ShaderModule::GetSource() const {
        return mGlslSource.c_str();
    }

    const ShaderModule::CombinedSamplerInfo& ShaderModule::GetCombinedSamplerInfo() const {
        return mCombinedInfo;
    }

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

    MaybeError ShaderModule::Initialize(const ShaderModuleDescriptor* descriptor) {
        std::unique_ptr<spirv_cross::CompilerGLSL> compiler_impl;
        spirv_cross::CompilerGLSL* compiler;

        if (GetDevice()->IsToggleEnabled(Toggle::UseSpvc)) {
            // If these options are changed, the values in DawnSPIRVCrossGLSLFastFuzzer.cpp need to
            // be updated.
            shaderc_spvc::CompileOptions options;

            // The range of Z-coordinate in the clipping volume of OpenGL is [-w, w], while it is
            // [0, w] in D3D12, Metal and Vulkan, so we should normalize it in shaders in all
            // backends. See the documentation of
            // spirv_cross::CompilerGLSL::Options::vertex::fixup_clipspace for more details.
            options.SetFlipVertY(true);
            options.SetFixupClipspace(true);

            // TODO(cwallez@chromium.org): discover the backing context version and use that.
#if defined(DAWN_PLATFORM_APPLE)
            options.SetGLSLLanguageVersion(410);
#else
            options.SetGLSLLanguageVersion(440);
#endif
            shaderc_spvc_status status =
                mSpvcContext.InitializeForGlsl(descriptor->code, descriptor->codeSize, options);
            if (status != shaderc_spvc_status_success)
                return DAWN_VALIDATION_ERROR("Unable to initialize instance of spvc");

            compiler = reinterpret_cast<spirv_cross::CompilerGLSL*>(mSpvcContext.GetCompiler());
        } else {
            // If these options are changed, the values in DawnSPIRVCrossGLSLFastFuzzer.cpp need to
            // be updated.
            spirv_cross::CompilerGLSL::Options options;

            // The range of Z-coordinate in the clipping volume of OpenGL is [-w, w], while it is
            // [0, w] in D3D12, Metal and Vulkan, so we should normalize it in shaders in all
            // backends. See the documentation of
            // spirv_cross::CompilerGLSL::Options::vertex::fixup_clipspace for more details.
            options.vertex.flip_vert_y = true;
            options.vertex.fixup_clipspace = true;

            // TODO(cwallez@chromium.org): discover the backing context version and use that.
#if defined(DAWN_PLATFORM_APPLE)
        options.version = 410;
#else
        options.version = 440;
#endif

        compiler_impl =
            std::make_unique<spirv_cross::CompilerGLSL>(descriptor->code, descriptor->codeSize);
        compiler = compiler_impl.get();
        compiler->set_common_options(options);
        }

        ExtractSpirvInfo(*compiler);

        const auto& bindingInfo = GetBindingInfo();

        // Extract bindings names so that it can be used to get its location in program.
        // Now translate the separate sampler / textures into combined ones and store their info.
        // We need to do this before removing the set and binding decorations.
        compiler->build_combined_image_samplers();

        for (const auto& combined : compiler->get_combined_image_samplers()) {
            mCombinedInfo.emplace_back();

            auto& info = mCombinedInfo.back();
            info.samplerLocation.group =
                compiler->get_decoration(combined.sampler_id, spv::DecorationDescriptorSet);
            info.samplerLocation.binding =
                compiler->get_decoration(combined.sampler_id, spv::DecorationBinding);
            info.textureLocation.group =
                compiler->get_decoration(combined.image_id, spv::DecorationDescriptorSet);
            info.textureLocation.binding =
                compiler->get_decoration(combined.image_id, spv::DecorationBinding);
            compiler->set_name(combined.combined_id, info.GetName());
        }

        // Change binding names to be "dawn_binding_<group>_<binding>".
        // Also unsets the SPIRV "Binding" decoration as it outputs "layout(binding=)" which
        // isn't supported on OSX's OpenGL.
        for (uint32_t group = 0; group < kMaxBindGroups; ++group) {
            for (uint32_t binding = 0; binding < kMaxBindingsPerGroup; ++binding) {
                const auto& info = bindingInfo[group][binding];
                if (info.used) {
                    compiler->set_name(info.base_type_id, GetBindingName(group, binding));
                    compiler->unset_decoration(info.id, spv::DecorationBinding);
                    compiler->unset_decoration(info.id, spv::DecorationDescriptorSet);
                }
            }
        }

        if (GetDevice()->IsToggleEnabled(Toggle::UseSpvc)) {
            shaderc_spvc::CompilationResult result;
            shaderc_spvc_status status = mSpvcContext.CompileShader(&result);
            if (status != shaderc_spvc_status_success)
                return DAWN_VALIDATION_ERROR("Unable to compile shader using spvc");
            mGlslSource = result.GetStringOutput();
        } else {
            mGlslSource = compiler->compile();
        }
        return {};
    }

}}  // namespace dawn_native::opengl
