// 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/Enumerator.h"
#include "dawn/common/MatchVariant.h"
#include "dawn/native/Adapter.h"
#include "dawn/native/BindGroupLayoutInternal.h"
#include "dawn/native/CacheRequest.h"
#include "dawn/native/ImmediateConstantsLayout.h"
#include "dawn/native/Pipeline.h"
#include "dawn/native/TintUtils.h"
#include "dawn/native/opengl/BindGroupLayoutGL.h"
#include "dawn/native/opengl/DeviceGL.h"
#include "dawn/native/opengl/PipelineGL.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 "tint/tint.h"

namespace dawn::native::opengl {
namespace {
using InterstageLocationAndName = std::pair<uint32_t, std::string>;

#define GLSL_COMPILATION_REQUEST_MEMBERS(X)                                          \
    X(ShaderModuleBase::ShaderModuleHash, shaderModuleHash)                          \
    X(UnsafeUnserializedValue<ShaderModuleBase::ScopedUseTintProgram>, inputProgram) \
    X(SingleShaderStage, stage)                                                      \
    X(LimitsForCompilationRequest, limits)                                           \
    X(UnsafeUnserializedValue<LimitsForCompilationRequest>, adapterSupportedLimits)  \
    X(bool, disableSymbolRenaming)                                                   \
    X(std::vector<InterstageLocationAndName>, interstageVariables)                   \
    X(tint::glsl::writer::Options, tintOptions)                                      \
    X(UnsafeUnserializedValue<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)            \
    X(Extent3D, workgroupSize)
DAWN_SERIALIZABLE(struct, GLSLCompilation, GLSL_COMPILATION_MEMBERS) {
    static ResultOrError<GLSLCompilation> FromValidatedBlob(Blob blob);
};
#undef GLSL_COMPILATION_MEMBERS

// Separated from the class definition above to fix a clang-format over-indentation.
// static
ResultOrError<GLSLCompilation> GLSLCompilation::FromValidatedBlob(Blob blob) {
    GLSLCompilation result;
    DAWN_TRY_ASSIGN(result, FromBlob(std::move(blob)));
    DAWN_INVALID_IF(result.glsl.empty(), "Cached GLSLCompilation result has no GLSL");
    return result;
}

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 OpenGLVersion::Standard::Desktop:
            return tint::glsl::writer::Version::Standard::kDesktop;
        case OpenGLVersion::Standard::ES:
            return tint::glsl::writer::Version::Standard::kES;
    }
    DAWN_UNREACHABLE();
}

// Returns information about the texture/sampler pairs used by the entry point. This is necessary
// because GL uses combined texture/sampler bindings while WGSL allows mixing and matching textures
// and samplers in the shader. GL also uses a placeholder sampler to use with textures when they
// aren't combined with a sampler in the WGSL.
//
// Another subtlety is that Dawn uses pre-remapping BindingPoints when referring to bindings while
// the Tint GLSL writer uses post-remapping BindingPoints.
void GenerateCombinedSamplerInfo(
    const EntryPointMetadata& metadata,
    const tint::Bindings& bindings,
    const PipelineLayout* layout,
    std::vector<CombinedSampler>* combinedSamplers,
    tint::glsl::writer::CombinedTextureSamplerInfo* samplerTextureToName,
    tint::BindingPoint* placeholder_sampler_bind_point) {
    // Helper to avoid duplicated logic for when a CombinedSampler is determined. It takes a bunch
    // of information for both the texture and the sampler and translate to what Dawn/Tint need.
    struct CombinedBindingInfo {
        // Dawn takes BindGroupIndex + BindingIndex.
        BindGroupIndex group;
        BindingIndex index;
        BindingIndex shaderArraySize = BindingIndex(1);

        // Tint takes the post-remapping binding point.
        tint::BindingPoint remappedBinding;
    };
    auto AddCombinedSampler = [&](CombinedBindingInfo texture,
                                  std::optional<CombinedBindingInfo> sampler,
                                  bool isPlane1 = false) {
        // Reflect to the pipeline the combination with BindGroupIndex + BindingIndex in that BGL.
        CombinedSampler combinedSampler = {{
            .samplerLocation = std::nullopt,
            .textureLocation = {{
                .group = texture.group,
                .index = texture.index,
                .shaderArraySize = texture.shaderArraySize,
            }},
        }};
        if (sampler.has_value()) {
            combinedSampler.samplerLocation = {{{
                .group = sampler->group,
                .index = sampler->index,
                .shaderArraySize = sampler->shaderArraySize,
            }}};
        }
        combinedSamplers->push_back(combinedSampler);

        // Let Tint know to generate a new GLSL sampler for this combination.
        tint::BindingPoint samplerRemapped = *placeholder_sampler_bind_point;
        if (sampler.has_value()) {
            samplerRemapped = {0, sampler->remappedBinding.binding};
        }
        samplerTextureToName->emplace(
            tint::glsl::writer::CombinedTextureSamplerPair{
                {0, texture.remappedBinding.binding}, samplerRemapped, isPlane1},
            combinedSampler.GetName());
    };

    for (const auto& use : metadata.samplerAndNonSamplerTexturePairs) {
        // Replace uses of the placeholder sampler with its actual binding point.
        std::optional<CombinedBindingInfo> sampler = std::nullopt;
        if (use.sampler != EntryPointMetadata::nonSamplerBindingPoint) {
            const BindGroupLayoutInternalBase* bgl = layout->GetBindGroupLayout(use.sampler.group);
            sampler = {
                .group = use.sampler.group,
                .index = bgl->AsBindingIndex(bgl->GetBindingMap().at(use.sampler.binding)),
                .remappedBinding = bindings.sampler.at(ToTint(use.sampler)),
            };
        }

        // Tint reflection returns information about uses of both regular textures and sampled
        // textures so we need to differentiate both cases here.
        const BindGroupLayoutInternalBase* bgl = layout->GetBindGroupLayout(use.texture.group);
        APIBindingIndex textureAPIIndex = bgl->GetBindingMap().at(use.texture.binding);
        const auto& bindingInfo = bgl->GetAPIBindingInfo(textureAPIIndex);

        // The easy case is when a regular texture is being handled.
        if (std::holds_alternative<TextureBindingInfo>(bindingInfo.bindingLayout)) {
            CombinedBindingInfo texture = {
                .group = use.texture.group,
                .index = bgl->AsBindingIndex(textureAPIIndex),
                .shaderArraySize =
                    metadata.bindings.at(use.texture.group).at(use.texture.binding).arraySize,
                .remappedBinding = bindings.texture.at(ToTint(use.texture)),
            };
            AddCombinedSampler(texture, sampler);
            continue;
        }

        // This is an external texture, add planes individually.
        const auto& bindingLayout = std::get<ExternalTextureBindingInfo>(bindingInfo.bindingLayout);

        auto& tint_data = bindings.external_texture.at(ToTint(use.texture));
        DAWN_ASSERT(std::holds_alternative<tint::ExternalMultiplanarTexture>(tint_data));

        tint::ExternalMultiplanarTexture mp_data =
            std::get<tint::ExternalMultiplanarTexture>(tint_data);

        CombinedBindingInfo plane0 = {
            .group = use.texture.group,
            .index = bindingLayout.plane0,
            .remappedBinding = mp_data.plane0,
        };
        AddCombinedSampler(plane0, sampler, false);

        CombinedBindingInfo plane1 = {
            .group = use.texture.group,
            .index = bindingLayout.plane1,
            .remappedBinding = mp_data.plane1,
        };
        AddCombinedSampler(plane1, sampler, true);
    }
}

// Returns whether the stage uses any texture builtin metadata.
void GenerateTextureBuiltinFromUniformData(
    const EntryPointMetadata& metadata,
    const PipelineLayout* layout,
    const tint::Bindings& bindings,
    EmulatedTextureBuiltinRegistrar* emulatedTextureBuiltins,
    tint::glsl::writer::TextureBuiltinsFromUniformOptions* textureBuiltinsFromUniform) {
    // Tell Tint where the uniform containing the builtin data will be (in post-remapping space),
    // only when this shader stage uses some builtin metadata.
    if (!metadata.textureQueries.empty()) {
        textureBuiltinsFromUniform->ubo_binding = {
            .group = 0,
            .binding = uint32_t(layout->GetInternalTextureBuiltinsUniformBinding()),
        };
    }

    for (auto [i, query] : Enumerate(metadata.textureQueries)) {
        BindGroupIndex group = BindGroupIndex(query.group);
        const auto* bgl = layout->GetBindGroupLayout(group);
        BindingIndex binding =
            bgl->AsBindingIndex(bgl->GetAPIBindingIndex(BindingNumber{query.binding}));

        // Register that the query needs to be emulated and get the offset in the UBO where the data
        // will be passed.
        TextureQuery textureQuery;
        switch (query.type) {
            case EntryPointMetadata::TextureMetadataQuery::TextureQueryType::TextureNumLevels:
                textureQuery = TextureQuery::NumLevels;
                break;
            case EntryPointMetadata::TextureMetadataQuery::TextureQueryType::TextureNumSamples:
                textureQuery = TextureQuery::NumSamples;
                break;
        }
        uint32_t offset = emulatedTextureBuiltins->Register(group, binding, textureQuery);

        // Tint uses post-remapping binding points for textureBuiltinFromUniform options.
        tint::BindingPoint wgslBindPoint = {.group = query.group, .binding = query.binding};

        tint::BindingPoint remappedBinding;
        if (bindings.texture.contains(wgslBindPoint)) {
            remappedBinding = bindings.texture.at(wgslBindPoint);
        } else {
            remappedBinding = bindings.storage_texture.at(wgslBindPoint);
        }
        textureBuiltinsFromUniform->ubo_contents.push_back({
            .offset = offset,
            .count = 1,
            .binding = remappedBinding,
        });
    }
}

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

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

        for (BindingIndex binding : bgl->GetBufferIndices()) {
            const BindingInfo& bindingInfo = bgl->GetBindingInfo(binding);

            switch (std::get<BufferBindingInfo>(bindingInfo.bindingLayout).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 = {uint32_t(group),
                                                          uint32_t(bindingInfo.binding)};
                    FlatBindingIndex ssboIndex = indexInfo[group][binding];
                    options.bindpoint_to_size_index.emplace(srcBindingPoint, uint32_t(ssboIndex));
                    break;
                }
                default:
                    break;
            }
        }
    }

    return options.bindpoint_to_size_index.size() > 0;
}

}  // namespace

bool operator<(const CombinedSamplerElement& a, const CombinedSamplerElement& b) {
    return std::tie(a.group, a.index, a.shaderArraySize) <
           std::tie(b.group, b.index, b.shaderArraySize);
}

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";
    if (!samplerLocation) {
        o << "_placeholder_sampler";
    } else {
        o << "_" << static_cast<uint32_t>(samplerLocation->group) << "_"
          << static_cast<uint32_t>(samplerLocation->index);
    }
    o << "_with_" << static_cast<uint32_t>(textureLocation.group) << "_"
      << static_cast<uint32_t>(textureLocation.index);
    return o.str();
}

// static
ResultOrError<Ref<ShaderModule>> ShaderModule::Create(
    Device* device,
    const UnpackedPtr<ShaderModuleDescriptor>& descriptor,
    const std::vector<tint::wgsl::Extension>& internalExtensions) {
    Ref<ShaderModule> shader = AcquireRef(new ShaderModule(device, descriptor, internalExtensions));
    shader->Initialize();
    return shader;
}

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

ResultOrError<GLuint> ShaderModule::CompileShader(
    const OpenGLFunctions& gl,
    const ProgrammableStage& programmableStage,
    SingleShaderStage stage,
    const ImmediateConstantMask& pipelineImmediateMask,
    VertexAttributeMask bgraSwizzleAttributes,
    std::vector<CombinedSampler>* combinedSamplersOut,
    const PipelineLayout* layout,
    EmulatedTextureBuiltinRegistrar* emulatedTextureBuiltins,
    bool* needsSSBOLengthUniformBuffer,
    Extent3D* workgroupSize) {
    TRACE_EVENT0(GetDevice()->GetPlatform(), General, "TranslateToGLSL");

    const OpenGLVersion& version = gl.GetVersion();

    GLSLCompilationRequest req = {};

    req.shaderModuleHash = GetHash();
    req.inputProgram = UnsafeUnserializedValue(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;

    tint::Bindings bindings =
        GenerateBindingRemapping(layout, stage, [&](BindGroupIndex group, BindingIndex index) {
            return tint::BindingPoint{
                .group = 0,
                .binding = uint32_t(layout->GetBindingIndexInfo()[group][index]),
            };
        });

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

    // Compute the metadata necessary for translating to GL's combined textures and samplers, both
    // for Dawn and for the Tint translation to GLSL.
    {
        std::vector<CombinedSampler> combinedSamplers;
        GenerateCombinedSamplerInfo(entryPointMetaData, bindings, layout, &combinedSamplers,
                                    &(req.tintOptions.sampler_texture_to_name),
                                    &(req.tintOptions.placeholder_sampler_bind_point));
        *combinedSamplersOut = std::move(combinedSamplers);
    }

    // Compute the metadata necessary to emulate some of the texture "getter" builtins not present
    // in GLSL, both for Dawn and for the Tint translation to GLSL.
    GenerateTextureBuiltinFromUniformData(entryPointMetaData, layout, bindings,
                                          emulatedTextureBuiltins,
                                          &(req.tintOptions.texture_builtins_from_uniform));

    req.stage = stage;
    req.limits = LimitsForCompilationRequest::Create(GetDevice()->GetLimits().v1);
    req.adapterSupportedLimits = UnsafeUnserializedValue(
        LimitsForCompilationRequest::Create(GetDevice()->GetAdapter()->GetLimits().v1));

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

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

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

    req.tintOptions.substitute_overrides_config = {
        .map = BuildSubstituteOverridesTransformConfig(programmableStage),
    };

    req.tintOptions.disable_robustness = !GetDevice()->IsRobustnessEnabled();
    req.tintOptions.disable_workgroup_init =
        GetDevice()->IsToggleEnabled(Toggle::DisableWorkgroupInit);

    // If the size or alignment of the vertex and fragment stage immediate variables differ (e.g.,
    // the vertex shader immediates contain a vec4 and the fragment shader do not), the generated
    // structs may have differing alignment or size, and GLSL will give an error at link time. Count
    // the actual used slots, round up to the widest possible alignment (4 u32s), multiply by the
    // element byte size and pass that to Tint.
    auto immediateCount = RoundUp(pipelineImmediateMask.count(), 4u);

    req.tintOptions.minimum_immediate_size = immediateCount * kImmediateConstantElementByteSize;
    if (HasImmediateConstants(&RenderImmediateConstants::firstVertex, pipelineImmediateMask)) {
        req.tintOptions.first_vertex_offset = GetImmediateByteOffsetInPipelineIfAny(
            &RenderImmediateConstants::firstVertex, pipelineImmediateMask);
    }

    if (HasImmediateConstants(&RenderImmediateConstants::firstInstance, pipelineImmediateMask)) {
        req.tintOptions.first_instance_offset = GetImmediateByteOffsetInPipelineIfAny(
            &RenderImmediateConstants::firstInstance, pipelineImmediateMask);
    }

    if (HasImmediateConstants(&RenderImmediateConstants::clampFragDepth, pipelineImmediateMask)) {
        uint32_t offsetStartBytes = GetImmediateByteOffsetInPipeline(
            &RenderImmediateConstants::clampFragDepth, pipelineImmediateMask);
        req.tintOptions.depth_range_offsets = {
            offsetStartBytes, offsetStartBytes + kImmediateConstantElementByteSize};
    }

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

    req.tintOptions.disable_integer_range_analysis =
        !GetDevice()->IsToggleEnabled(Toggle::EnableIntegerRangeAnalysisInRobustness);

    req.tintOptions.use_uniform_buffers =
        !GetDevice()->IsToggleEnabled(Toggle::DecomposeUniformBuffers);

    CacheResult<GLSLCompilation> compilationResult;
    DAWN_TRY_LOAD_OR_RUN(
        compilationResult, GetDevice(), std::move(req), GLSLCompilation::FromValidatedBlob,
        [](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.
            tint::Result<tint::core::ir::Module> ir;
            {
                SCOPED_DAWN_HISTOGRAM_TIMER_MICROS(r.platform.UnsafeGetValue(),
                                                   "ShaderModuleProgramToIR");
                ir = tint::wgsl::reader::ProgramToLoweredIR(*tintInputProgram);
                DAWN_INVALID_IF(ir != tint::Success,
                                "An error occurred while generating Tint IR\n%s",
                                ir.Failure().reason);
            }

            tint::Result<tint::glsl::writer::Output> result;
            {
                SCOPED_DAWN_HISTOGRAM_TIMER_MICROS(r.platform.UnsafeGetValue(),
                                                   "ShaderModuleGenerateGLSL");
                // Generate GLSL from Tint IR.
                result = tint::glsl::writer::Generate(ir.Get(), r.tintOptions);
                DAWN_INVALID_IF(result != tint::Success,
                                "An error occurred while generating GLSL:\n%s",
                                result.Failure().reason);
            }

            GLSLCompilation compResult{{.glsl = std::move(result->glsl)}};
            // 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.
                // Subgroups are not supported on OpenGL backend.
                Extent3D workgroupSize;
                DAWN_TRY_ASSIGN(workgroupSize, ValidateComputeStageWorkgroupSize(
                                                   result->workgroup_info,
                                                   /*usesSubgroupMatrix=*/false,
                                                   /*maxSubgroupSize=*/0, r.limits,
                                                   r.adapterSupportedLimits.UnsafeGetValue()));
                compResult.workgroupSize = workgroupSize;
            }

            return compResult;
        },
        "OpenGL.CompileShaderToGLSL");

    *workgroupSize = compilationResult->workgroupSize;

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

        GetDevice()->EmitLog(wgpu::LoggingType::Info, dumpedMsg.str().c_str());
    }

    GLuint shader = DAWN_GL_TRY(gl, CreateShader(GLShaderType(stage)));
    const char* source = compilationResult->glsl.c_str();
    {
        SCOPED_DAWN_HISTOGRAM_TIMER_MICROS(GetDevice()->GetPlatform(), "GLSL.CompileShader");

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

    return shader;
}

}  // namespace dawn::native::opengl
