// Copyright 2017 The Dawn & Tint Authors
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this
//    list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice,
//    this list of conditions and the following disclaimer in the documentation
//    and/or other materials provided with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of its
//    contributors may be used to endorse or promote products derived from
//    this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#include "dawn/native/opengl/ShaderModuleGL.h"

#include <sstream>
#include <unordered_map>
#include <utility>

#include "absl/container/flat_hash_map.h"
#include "dawn/common/MatchVariant.h"
#include "dawn/native/Adapter.h"
#include "dawn/native/BindGroupLayoutInternal.h"
#include "dawn/native/CacheRequest.h"
#include "dawn/native/Pipeline.h"
#include "dawn/native/TintUtils.h"
#include "dawn/native/opengl/BindGroupLayoutGL.h"
#include "dawn/native/opengl/BindingPoint.h"
#include "dawn/native/opengl/DeviceGL.h"
#include "dawn/native/opengl/PipelineLayoutGL.h"
#include "dawn/native/opengl/UtilsGL.h"
#include "dawn/platform/DawnPlatform.h"
#include "dawn/platform/tracing/TraceEvent.h"

#include "src/tint/api/common/binding_point.h"

namespace dawn::native {
namespace {

GLenum GLShaderType(SingleShaderStage stage) {
    switch (stage) {
        case SingleShaderStage::Vertex:
            return GL_VERTEX_SHADER;
        case SingleShaderStage::Fragment:
            return GL_FRAGMENT_SHADER;
        case SingleShaderStage::Compute:
            return GL_COMPUTE_SHADER;
    }
    DAWN_UNREACHABLE();
}

tint::glsl::writer::Version::Standard ToTintGLStandard(opengl::OpenGLVersion::Standard standard) {
    switch (standard) {
        case opengl::OpenGLVersion::Standard::Desktop:
            return tint::glsl::writer::Version::Standard::kDesktop;
        case opengl::OpenGLVersion::Standard::ES:
            return tint::glsl::writer::Version::Standard::kES;
    }
    DAWN_UNREACHABLE();
}

using BindingMap = absl::flat_hash_map<tint::BindingPoint, tint::BindingPoint>;

opengl::CombinedSampler* AppendCombinedSampler(opengl::CombinedSamplerInfo* info,
                                               tint::BindingPoint texture,
                                               tint::BindingPoint sampler,
                                               tint::BindingPoint placeholderBindingPoint) {
    info->emplace_back();
    opengl::CombinedSampler* combinedSampler = &info->back();
    combinedSampler->usePlaceholderSampler = sampler == placeholderBindingPoint;
    combinedSampler->samplerLocation.group = BindGroupIndex(sampler.group);
    combinedSampler->samplerLocation.binding = BindingNumber(sampler.binding);
    combinedSampler->textureLocation.group = BindGroupIndex(texture.group);
    combinedSampler->textureLocation.binding = BindingNumber(texture.binding);
    return combinedSampler;
}

using InterstageLocationAndName = std::pair<uint32_t, std::string>;
using SubstituteOverrideConfig = std::unordered_map<tint::OverrideId, double>;

#define GLSL_COMPILATION_REQUEST_MEMBERS(X)                                               \
    X(ShaderModuleBase::ShaderModuleHash, shaderModuleHash)                               \
    X(CacheKey::UnsafeUnkeyedValue<ShaderModuleBase::ScopedUseTintProgram>, inputProgram) \
    X(std::string, entryPointName)                                                        \
    X(SingleShaderStage, stage)                                                           \
    X(SubstituteOverrideConfig, substituteOverrideConfig)                                 \
    X(LimitsForCompilationRequest, limits)                                                \
    X(CacheKey::UnsafeUnkeyedValue<LimitsForCompilationRequest>, adapterSupportedLimits)  \
    X(bool, disableSymbolRenaming)                                                        \
    X(std::vector<InterstageLocationAndName>, interstageVariables)                        \
    X(tint::glsl::writer::Options, tintOptions)                                           \
    X(CacheKey::UnsafeUnkeyedValue<dawn::platform::Platform*>, platform)

DAWN_MAKE_CACHE_REQUEST(GLSLCompilationRequest, GLSL_COMPILATION_REQUEST_MEMBERS);
#undef GLSL_COMPILATION_REQUEST_MEMBERS

#define GLSL_COMPILATION_MEMBERS(X) X(std::string, glsl)

DAWN_SERIALIZABLE(struct, GLSLCompilation, GLSL_COMPILATION_MEMBERS){};
#undef GLSL_COMPILATION_MEMBERS

}  // namespace
}  // namespace dawn::native

namespace dawn::native::opengl {
namespace {

// 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 "usePlaceholderSampler" 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).
CombinedSamplerInfo GenerateCombinedSamplerInfo(const EntryPointMetadata& metadata,
                                                tint::glsl::writer::Bindings& bindings,
                                                BindingMap externalTextureExpansionMap,
                                                bool* needsPlaceholderSampler

) {
    auto samplerAndNonSamplerTextureUses = metadata.samplerAndNonSamplerTexturePairs;

    CombinedSamplerInfo combinedSamplerInfo;
    for (const auto& use : samplerAndNonSamplerTextureUses) {
        // Convert BindingSlot in metadata back to tint::BindingPoint
        tint::BindingPoint samplerBindPoint =
            use.sampler == EntryPointMetadata::nonSamplerBindingPoint
                ? bindings.placeholder_sampler_bind_point
                : ToTint(use.sampler);
        tint::BindingPoint texBindPoint = ToTint(use.texture);

        CombinedSampler* info =
            AppendCombinedSampler(&combinedSamplerInfo, ToTint(use.texture),
                                  use.sampler == EntryPointMetadata::nonSamplerBindingPoint
                                      ? bindings.placeholder_sampler_bind_point
                                      : ToTint(use.sampler),
                                  bindings.placeholder_sampler_bind_point);

        if (info->usePlaceholderSampler) {
            *needsPlaceholderSampler = true;
        }

        // Note, the rest of Dawn is expecting to use the un-modified WGSL binding points when
        // looking up information on the combined samplers. Tint is expecting Dawn to provide
        // the final expected values for those entry points. So, we end up using the original
        // values for the AppendCombinedSampler calls and the remapped binding points when we
        // put things in the tint bindings structure.

        {
            auto texIt = bindings.texture.find(texBindPoint);
            if (texIt != bindings.texture.end()) {
                texBindPoint.group = 0;
                texBindPoint.binding = texIt->second.binding;
            } else {
                // The plane0 texture will be in external_textures, not textures, so we have to set
                // the `sampler_texture_to_name` based on the external_texture value.
                auto exIt = bindings.external_texture.find(texBindPoint);
                if (exIt != bindings.external_texture.end()) {
                    texBindPoint.group = 0;
                    texBindPoint.binding = exIt->second.plane0.binding;
                }
            }
        }
        {
            auto it = bindings.sampler.find(samplerBindPoint);
            if (it != bindings.sampler.end()) {
                samplerBindPoint.group = 0;
                samplerBindPoint.binding = it->second.binding;
            }
        }

        bindings.sampler_texture_to_name.emplace(
            tint::glsl::writer::binding::CombinedTextureSamplerPair{texBindPoint, samplerBindPoint,
                                                                    false},
            info->GetName());

        // If the texture has an associated plane1 texture (ie., it's an external texture),
        // append a new combined sampler with the same sampler and the plane1 texture.
        auto it = externalTextureExpansionMap.find(ToTint(use.texture));
        if (it != externalTextureExpansionMap.end()) {
            CombinedSampler* plane1Info =
                AppendCombinedSampler(&combinedSamplerInfo, it->second,
                                      use.sampler == EntryPointMetadata::nonSamplerBindingPoint
                                          ? bindings.placeholder_sampler_bind_point
                                          : ToTint(use.sampler),
                                      bindings.placeholder_sampler_bind_point);

            tint::BindingPoint plane1TexBindPoint = it->second;
            auto dstIt = bindings.external_texture.find(ToTint(use.texture));
            if (dstIt != bindings.external_texture.end()) {
                plane1TexBindPoint.group = 0;
                plane1TexBindPoint.binding = dstIt->second.plane1.binding;
            }

            bindings.sampler_texture_to_name.emplace(
                tint::glsl::writer::binding::CombinedTextureSamplerPair{plane1TexBindPoint,
                                                                        samplerBindPoint, true},
                plane1Info->GetName());
        }
    }
    return combinedSamplerInfo;
}

bool GenerateTextureBuiltinFromUniformData(const EntryPointMetadata& metadata,
                                           const PipelineLayout* layout,
                                           BindingPointToFunctionAndOffset* bindingPointToData,
                                           tint::glsl::writer::Bindings& bindings) {
    auto textureBuiltinsFromUniformData = metadata.textureQueries;

    if (textureBuiltinsFromUniformData.empty()) {
        return false;
    }

    for (size_t i = 0; i < textureBuiltinsFromUniformData.size(); ++i) {
        const auto& info = textureBuiltinsFromUniformData[i];

        // This is the unmodified binding point from the WGSL shader.
        tint::BindingPoint srcBindingPoint{info.group, info.binding};
        bindings.texture_builtins_from_uniform.ubo_bindingpoint_ordering.emplace_back(
            srcBindingPoint);

        // The remapped binding point is inserted into the Dawn data structure.
        const BindGroupLayoutInternalBase* bgl =
            layout->GetBindGroupLayout(BindGroupIndex{info.group});
        tint::BindingPoint dstBindingPoint = tint::BindingPoint{
            info.group, static_cast<uint32_t>(bgl->GetBindingIndex(BindingNumber{info.binding}))};

        BindPointFunction type = BindPointFunction::kTextureNumLevels;
        switch (info.type) {
            case EntryPointMetadata::TextureMetadataQuery::TextureQueryType::TextureNumLevels:
                type = BindPointFunction::kTextureNumLevels;
                break;
            case EntryPointMetadata::TextureMetadataQuery::TextureQueryType::TextureNumSamples:
                type = BindPointFunction::kTextureNumSamples;
                break;
        }

        // Note, the `sizeof(uint32_t)` has to match up with the data type created by the
        // `TextureBuiltinsFromUniform` when it creates the UBO structure.
        bindingPointToData->emplace(dstBindingPoint,
                                    std::pair{type, static_cast<uint32_t>(i * sizeof(uint32_t))});
    }

    return true;
}

bool GenerateArrayLengthFromuniformData(const BindingInfoArray& moduleBindingInfo,
                                        const PipelineLayout* layout,
                                        tint::glsl::writer::Bindings& bindings) {
    const PipelineLayout::BindingIndexInfo& indexInfo = layout->GetBindingIndexInfo();

    for (BindGroupIndex group : layout->GetBindGroupLayoutsMask()) {
        const BindGroupLayoutInternalBase* bgl = layout->GetBindGroupLayout(group);
        for (const auto& [binding, shaderBindingInfo] : moduleBindingInfo[group]) {
            BindingIndex bindingIndex = bgl->GetBindingIndex(binding);
            const BindingInfo& bindingInfo = bgl->GetBindingInfo(bindingIndex);

            // TODO(crbug.com/408010433): capturing binding directly in lambda is C++20
            // extension in cmake
            uint32_t capturedBindingNumber = static_cast<uint32_t>(binding);

            MatchVariant(
                bindingInfo.bindingLayout,
                [&](const BufferBindingInfo& bufferBinding) {
                    switch (bufferBinding.type) {
                        case wgpu::BufferBindingType::Storage:
                        case kInternalStorageBufferBinding:
                        case wgpu::BufferBindingType::ReadOnlyStorage:
                        case kInternalReadOnlyStorageBufferBinding: {
                            // Use ssbo index as the indices for the buffer size lookups
                            // in the array length from uniform transform.
                            tint::BindingPoint srcBindingPoint = {static_cast<uint32_t>(group),
                                                                  capturedBindingNumber};
                            uint32_t ssboIndex = indexInfo[group][bindingIndex];
                            bindings.array_length_from_uniform.bindpoint_to_size_index.emplace(
                                srcBindingPoint, ssboIndex);
                            break;
                        }
                        default:
                            break;
                    }
                },
                [](const StaticSamplerBindingInfo&) {}, [](const SamplerBindingInfo&) {},
                [](const TextureBindingInfo&) {}, [](const StorageTextureBindingInfo&) {},
                [](const InputAttachmentBindingInfo&) {});
        }
    }

    return bindings.array_length_from_uniform.bindpoint_to_size_index.size() > 0;
}

}  // namespace

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.usePlaceholderSampler, a.samplerLocation, a.textureLocation) <
           std::tie(b.usePlaceholderSampler, a.samplerLocation, b.textureLocation);
}

std::string CombinedSampler::GetName() const {
    std::ostringstream o;
    o << "dawn_combined";
    if (usePlaceholderSampler) {
        o << "_placeholder_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 UnpackedPtr<ShaderModuleDescriptor>& descriptor,
    const std::vector<tint::wgsl::Extension>& internalExtensions,
    ShaderModuleParseResult* parseResult,
    std::unique_ptr<OwnedCompilationMessages>* compilationMessages) {
    Ref<ShaderModule> module = AcquireRef(new ShaderModule(device, descriptor, internalExtensions));
    DAWN_TRY(module->Initialize(parseResult, compilationMessages));
    return module;
}

ShaderModule::ShaderModule(Device* device,
                           const UnpackedPtr<ShaderModuleDescriptor>& descriptor,
                           std::vector<tint::wgsl::Extension> internalExtensions)
    : ShaderModuleBase(device, descriptor, std::move(internalExtensions)) {}

MaybeError ShaderModule::Initialize(
    ShaderModuleParseResult* parseResult,
    std::unique_ptr<OwnedCompilationMessages>* compilationMessages) {
    DAWN_TRY(InitializeBase(parseResult, compilationMessages));

    return {};
}

std::pair<tint::glsl::writer::Bindings, BindingMap> GenerateBindingInfo(
    SingleShaderStage stage,
    const PipelineLayout* layout,
    const BindingInfoArray& moduleBindingInfo,
    GLSLCompilationRequest& req) {
    // Because of the way the rest of the backend uses the binding information, we need to pass
    // through the original WGSL values in the combined shader map. That means, we need to store
    // that data for the external texture, otherwise it ends up getting lost.
    BindingMap externalTextureExpansionMap;

    tint::glsl::writer::Bindings bindings;

    for (BindGroupIndex group : layout->GetBindGroupLayoutsMask()) {
        const BindGroupLayout* bgl = ToBackend(layout->GetBindGroupLayout(group));

        for (const auto& [binding, shaderBindingInfo] : moduleBindingInfo[group]) {
            tint::BindingPoint srcBindingPoint{static_cast<uint32_t>(group),
                                               static_cast<uint32_t>(binding)};

            BindingIndex bindingIndex = bgl->GetBindingIndex(binding);
            auto& bindingIndexInfo = layout->GetBindingIndexInfo()[group];
            uint32_t shaderIndex = bindingIndexInfo[bindingIndex];
            tint::BindingPoint dstBindingPoint{0, shaderIndex};

            auto* const bufferBindingInfo =
                std::get_if<BufferBindingInfo>(&shaderBindingInfo.bindingInfo);

            if (bufferBindingInfo) {
                switch (bufferBindingInfo->type) {
                    case wgpu::BufferBindingType::Uniform:
                        bindings.uniform.emplace(
                            srcBindingPoint,
                            tint::glsl::writer::binding::Uniform{dstBindingPoint.binding});
                        break;
                    case kInternalStorageBufferBinding:
                    case wgpu::BufferBindingType::Storage:
                    case wgpu::BufferBindingType::ReadOnlyStorage:
                    case kInternalReadOnlyStorageBufferBinding:
                        bindings.storage.emplace(
                            srcBindingPoint,
                            tint::glsl::writer::binding::Storage{dstBindingPoint.binding});
                        break;
                    case wgpu::BufferBindingType::BindingNotUsed:
                    case wgpu::BufferBindingType::Undefined:
                        DAWN_UNREACHABLE();
                        break;
                }
            } else if (std::holds_alternative<SamplerBindingInfo>(shaderBindingInfo.bindingInfo)) {
                bindings.sampler.emplace(
                    srcBindingPoint, tint::glsl::writer::binding::Sampler{dstBindingPoint.binding});
            } else if (std::holds_alternative<TextureBindingInfo>(shaderBindingInfo.bindingInfo)) {
                bindings.texture.emplace(
                    srcBindingPoint, tint::glsl::writer::binding::Texture{dstBindingPoint.binding});
            } else if (std::holds_alternative<StorageTextureBindingInfo>(
                           shaderBindingInfo.bindingInfo)) {
                bindings.storage_texture.emplace(
                    srcBindingPoint,
                    tint::glsl::writer::binding::StorageTexture{dstBindingPoint.binding});
            } else if (std::holds_alternative<ExternalTextureBindingInfo>(
                           shaderBindingInfo.bindingInfo)) {
                const auto& etBindingMap = bgl->GetExternalTextureBindingExpansionMap();
                const auto& expansion = etBindingMap.find(binding);
                DAWN_ASSERT(expansion != etBindingMap.end());

                using BindingInfo = tint::glsl::writer::binding::BindingInfo;

                const auto& bindingExpansion = expansion->second;
                const BindingInfo plane0{
                    bindingIndexInfo[bgl->GetBindingIndex(bindingExpansion.plane0)]};
                const BindingInfo plane1{
                    bindingIndexInfo[bgl->GetBindingIndex(bindingExpansion.plane1)]};
                const BindingInfo metadata{
                    bindingIndexInfo[bgl->GetBindingIndex(bindingExpansion.params)]};

                tint::BindingPoint plane1WGSLBindingPoint{
                    static_cast<uint32_t>(group), static_cast<uint32_t>(bindingExpansion.plane1)};
                externalTextureExpansionMap[srcBindingPoint] = plane1WGSLBindingPoint;

                bindings.external_texture.emplace(
                    srcBindingPoint,
                    tint::glsl::writer::binding::ExternalTexture{metadata, plane0, plane1});
            }
        }
    }
    return {bindings, externalTextureExpansionMap};
}

ResultOrError<GLuint> ShaderModule::CompileShader(
    const OpenGLFunctions& gl,
    const ProgrammableStage& programmableStage,
    SingleShaderStage stage,
    bool usesVertexIndex,
    bool usesInstanceIndex,
    bool usesFragDepth,
    VertexAttributeMask bgraSwizzleAttributes,
    CombinedSamplerInfo* combinedSamplers,
    const PipelineLayout* layout,
    bool* needsPlaceholderSampler,
    BindingPointToFunctionAndOffset* bindingPointToTextureBuiltinData,
    bool* needsSSBOLengthUniformBuffer) {
    TRACE_EVENT0(GetDevice()->GetPlatform(), General, "TranslateToGLSL");

    const OpenGLVersion& version = ToBackend(GetDevice())->GetGL().GetVersion();

    GLSLCompilationRequest req = {};

    req.shaderModuleHash = GetHash();
    req.inputProgram = UseTintProgram();

    // 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.
    const EntryPointMetadata& entryPointMetaData = GetEntryPoint(programmableStage.entryPoint);
    const BindingInfoArray& moduleBindingInfo = entryPointMetaData.bindings;

    auto [bindings, externalTextureExpansionMap] =
        GenerateBindingInfo(stage, layout, moduleBindingInfo, req);

    // When textures are accessed without a sampler (e.g., textureLoad()), returned
    // CombinedSamplerInfo should use this sentinel value as sampler binding point.
    bindings.placeholder_sampler_bind_point = {static_cast<uint32_t>(kMaxBindGroupsTyped), 0};

    CombinedSamplerInfo combinedSamplerInfo = GenerateCombinedSamplerInfo(
        entryPointMetaData, bindings, externalTextureExpansionMap, needsPlaceholderSampler);

    bool needsInternalUBO = GenerateTextureBuiltinFromUniformData(
        entryPointMetaData, layout, bindingPointToTextureBuiltinData, bindings);
    if (needsInternalUBO) {
        DAWN_ASSERT(!bindingPointToTextureBuiltinData->empty());
        // Some texture builtin functions are unsupported on GLSL ES. These are emulated with
        // internal uniforms.
        bindings.texture_builtins_from_uniform.ubo_binding = {kMaxBindGroups + 1, 0};

        // Remap the internal ubo binding as well.
        bindings.uniform.emplace(bindings.texture_builtins_from_uniform.ubo_binding,
                                 tint::glsl::writer::binding::Uniform{
                                     layout->GetInternalTextureBuiltinsUniformBinding()});
    }

    req.stage = stage;
    req.entryPointName = programmableStage.entryPoint;
    req.substituteOverrideConfig = BuildSubstituteOverridesTransformConfig(programmableStage);
    req.limits = LimitsForCompilationRequest::Create(GetDevice()->GetLimits().v1);
    req.adapterSupportedLimits =
        LimitsForCompilationRequest::Create(GetDevice()->GetAdapter()->GetLimits().v1);

    if (GetDevice()->IsToggleEnabled(Toggle::GLUseArrayLengthFromUniform)) {
        *needsSSBOLengthUniformBuffer =
            GenerateArrayLengthFromuniformData(moduleBindingInfo, layout, bindings);
        if (*needsSSBOLengthUniformBuffer) {
            req.tintOptions.use_array_length_from_uniform = true;
            bindings.array_length_from_uniform.ubo_binding = {kMaxBindGroups + 2, 0};
            bindings.uniform.emplace(bindings.array_length_from_uniform.ubo_binding,
                                     tint::glsl::writer::binding::Uniform{
                                         layout->GetInternalArrayLengthUniformBinding()});
        }
    }

    req.platform = UnsafeUnkeyedValue(GetDevice()->GetPlatform());

    req.tintOptions.version = tint::glsl::writer::Version(ToTintGLStandard(version.GetStandard()),
                                                          version.GetMajor(), version.GetMinor());

    req.tintOptions.disable_robustness = false;

    if (usesVertexIndex) {
        req.tintOptions.first_vertex_offset = 4 * PipelineLayout::PushConstantLocation::FirstVertex;
    }

    if (usesInstanceIndex) {
        req.tintOptions.first_instance_offset =
            4 * PipelineLayout::PushConstantLocation::FirstInstance;
    }

    if (usesFragDepth) {
        req.tintOptions.depth_range_offsets = {4 * PipelineLayout::PushConstantLocation::MinDepth,
                                               4 * PipelineLayout::PushConstantLocation::MaxDepth};
    }

    if (stage == SingleShaderStage::Vertex) {
        for (VertexAttributeLocation i : bgraSwizzleAttributes) {
            req.tintOptions.bgra_swizzle_locations.insert(static_cast<uint8_t>(i));
        }
    }

    req.tintOptions.strip_all_names = !GetDevice()->IsToggleEnabled(Toggle::DisableSymbolRenaming);

    req.interstageVariables = {};
    for (size_t i = 0; i < entryPointMetaData.interStageVariables.size(); i++) {
        if (entryPointMetaData.usedInterStageVariables[i]) {
            req.interstageVariables.emplace_back(static_cast<uint32_t>(i),
                                                 entryPointMetaData.interStageVariables[i].name);
        }
    }

    req.tintOptions.bindings = std::move(bindings);
    req.tintOptions.disable_polyfill_integer_div_mod =
        GetDevice()->IsToggleEnabled(Toggle::DisablePolyfillsOnIntegerDivisonAndModulo);

    CacheResult<GLSLCompilation> compilationResult;
    DAWN_TRY_LOAD_OR_RUN(
        compilationResult, GetDevice(), std::move(req), GLSLCompilation::FromBlob,
        [](GLSLCompilationRequest r) -> ResultOrError<GLSLCompilation> {
            // Requires Tint Program here right before actual using.
            auto inputProgram = r.inputProgram.UnsafeGetValue()->GetTintProgram();
            const tint::Program* tintInputProgram = &(inputProgram->program);
            // Convert the AST program to an IR module.
            auto ir = tint::wgsl::reader::ProgramToLoweredIR(*tintInputProgram);
            DAWN_INVALID_IF(ir != tint::Success, "An error occurred while generating Tint IR\n%s",
                            ir.Failure().reason);

            auto singleEntryPointResult =
                tint::core::ir::transform::SingleEntryPoint(ir.Get(), r.entryPointName);
            DAWN_INVALID_IF(singleEntryPointResult != tint::Success,
                            "Pipeline single entry point (IR) failed:\n%s",
                            singleEntryPointResult.Failure().reason);

            // this needs to run after SingleEntryPoint transform which removes unused
            // overrides for the current entry point.
            tint::core::ir::transform::SubstituteOverridesConfig cfg;
            cfg.map = std::move(r.substituteOverrideConfig);
            auto substituteOverridesResult =
                tint::core::ir::transform::SubstituteOverrides(ir.Get(), cfg);
            DAWN_INVALID_IF(substituteOverridesResult != tint::Success,
                            "Pipeline override substitution (IR) failed:\n%s",
                            substituteOverridesResult.Failure().reason);

            const std::string remappedEntryPoint = "";
            // Generate GLSL from Tint IR.
            auto result = tint::glsl::writer::Generate(ir.Get(), r.tintOptions, remappedEntryPoint);
            DAWN_INVALID_IF(result != tint::Success, "An error occurred while generating GLSL:\n%s",
                            result.Failure().reason);

            // Workgroup validation has to come after `Generate` because it may require
            // overrides to have been substituted.
            if (r.stage == SingleShaderStage::Compute) {
                // Validate workgroup size after program runs transforms.
                Extent3D _;
                DAWN_TRY_ASSIGN(_,
                                ValidateComputeStageWorkgroupSize(
                                    result->workgroup_info.x, result->workgroup_info.y,
                                    result->workgroup_info.z, result->workgroup_info.storage_size,
                                    /* usesSubgroupMatrix */ false,
                                    /* maxSubgroupSize, GL backend not support */ 0, r.limits,
                                    r.adapterSupportedLimits.UnsafeGetValue()));
            }

            return GLSLCompilation{{std::move(result->glsl)}};
        },
        "OpenGL.CompileShaderToGLSL");

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

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

    GLuint shader = DAWN_GL_TRY(gl, CreateShader(GLShaderType(stage)));
    const char* source = compilationResult->glsl.c_str();
    DAWN_GL_TRY(gl, ShaderSource(shader, 1, &source, nullptr));
    DAWN_GL_TRY(gl, CompileShader(shader));

    GLint compileStatus = GL_FALSE;
    DAWN_GL_TRY(gl, GetShaderiv(shader, GL_COMPILE_STATUS, &compileStatus));
    if (compileStatus == GL_FALSE) {
        GLint infoLogLength = 0;
        DAWN_GL_TRY(gl, GetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLogLength));

        if (infoLogLength > 1) {
            std::vector<char> buffer(infoLogLength);
            DAWN_GL_TRY(gl, GetShaderInfoLog(shader, infoLogLength, nullptr, &buffer[0]));
            DAWN_GL_TRY(gl, DeleteShader(shader));
            return DAWN_VALIDATION_ERROR("%s\nProgram compilation failed:\n%s", source,
                                         buffer.data());
        }
    }

    GetDevice()->GetBlobCache()->EnsureStored(compilationResult);

    *combinedSamplers = std::move(combinedSamplerInfo);
    return shader;
}

}  // namespace dawn::native::opengl
