//
// Copyright 2015 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//

// ShaderGL.cpp: Implements the class methods for ShaderGL.

#include "libANGLE/renderer/gl/ShaderGL.h"

#include "common/debug.h"
#include "libANGLE/Compiler.h"
#include "libANGLE/Context.h"
#include "libANGLE/renderer/gl/FunctionsGL.h"
#include "libANGLE/renderer/gl/RendererGL.h"
#include "libANGLE/trace.h"
#include "platform/FeaturesGL.h"

#include <iostream>

namespace rx
{

using CompileAndCheckShaderInWorkerFunctor = std::function<bool(const char *source)>;
class TranslateTaskGL : public angle::Closure
{
  public:
    TranslateTaskGL(ShHandle handle,
                    ShCompileOptions options,
                    const std::string &source,
                    CompileAndCheckShaderInWorkerFunctor &&compileAndCheckShaderInWorkerFunctor)
        : mHandle(handle),
          mOptions(options),
          mSource(source),
          mCompileAndCheckShaderInWorkerFunctor(std::move(compileAndCheckShaderInWorkerFunctor)),
          mResult(false),
          mWorkerAvailable(true)
    {}

    void operator()() override
    {
        ANGLE_TRACE_EVENT1("gpu.angle", "TranslateTaskGL::run", "source", mSource);
        const char *source = mSource.c_str();
        mResult            = sh::Compile(mHandle, &source, 1, mOptions);
        if (mResult)
        {
            mWorkerAvailable =
                mCompileAndCheckShaderInWorkerFunctor(sh::GetObjectCode(mHandle).c_str());
        }
    }

    bool getResult() { return mResult; }

    bool workerAvailable() { return mWorkerAvailable; }

    ShHandle getHandle() { return mHandle; }

  private:
    ShHandle mHandle;
    ShCompileOptions mOptions;
    std::string mSource;
    CompileAndCheckShaderInWorkerFunctor mCompileAndCheckShaderInWorkerFunctor;
    bool mResult;
    bool mWorkerAvailable;
};

using PostTranslateFunctor         = std::function<bool(std::string *infoLog)>;
using CompileAndCheckShaderFunctor = std::function<void(const char *source)>;
class WaitableCompileEventWorkerContext final : public WaitableCompileEvent
{
  public:
    WaitableCompileEventWorkerContext(std::shared_ptr<angle::WaitableEvent> waitableEvent,
                                      CompileAndCheckShaderFunctor &&compileAndCheckShaderFunctor,
                                      PostTranslateFunctor &&postTranslateFunctor,
                                      std::shared_ptr<TranslateTaskGL> translateTask)
        : WaitableCompileEvent(waitableEvent),
          mCompileAndCheckShaderFunctor(std::move(compileAndCheckShaderFunctor)),
          mPostTranslateFunctor(std::move(postTranslateFunctor)),
          mTranslateTask(translateTask)
    {}

    bool getResult() override { return mTranslateTask->getResult(); }

    bool postTranslate(std::string *infoLog) override
    {
        if (!mTranslateTask->workerAvailable())
        {
            ShHandle handle = mTranslateTask->getHandle();
            mCompileAndCheckShaderFunctor(sh::GetObjectCode(handle).c_str());
        }
        return mPostTranslateFunctor(infoLog);
    }

  private:
    CompileAndCheckShaderFunctor mCompileAndCheckShaderFunctor;
    PostTranslateFunctor mPostTranslateFunctor;
    std::shared_ptr<TranslateTaskGL> mTranslateTask;
};

using PeekCompletionFunctor = std::function<bool()>;
using CheckShaderFunctor    = std::function<void()>;

class WaitableCompileEventNativeParallel final : public WaitableCompileEvent
{
  public:
    WaitableCompileEventNativeParallel(PostTranslateFunctor &&postTranslateFunctor,
                                       bool result,
                                       CheckShaderFunctor &&checkShaderFunctor,
                                       PeekCompletionFunctor &&peekCompletionFunctor)
        : WaitableCompileEvent(std::shared_ptr<angle::WaitableEventDone>()),
          mPostTranslateFunctor(std::move(postTranslateFunctor)),
          mResult(result),
          mCheckShaderFunctor(std::move(checkShaderFunctor)),
          mPeekCompletionFunctor(std::move(peekCompletionFunctor))
    {}

    void wait() override { mCheckShaderFunctor(); }

    bool isReady() override { return mPeekCompletionFunctor(); }

    bool getResult() override { return mResult; }

    bool postTranslate(std::string *infoLog) override { return mPostTranslateFunctor(infoLog); }

  private:
    PostTranslateFunctor mPostTranslateFunctor;
    bool mResult;
    CheckShaderFunctor mCheckShaderFunctor;
    PeekCompletionFunctor mPeekCompletionFunctor;
};

class WaitableCompileEventDone final : public WaitableCompileEvent
{
  public:
    WaitableCompileEventDone(PostTranslateFunctor &&postTranslateFunctor, bool result)
        : WaitableCompileEvent(std::make_shared<angle::WaitableEventDone>()),
          mPostTranslateFunctor(std::move(postTranslateFunctor)),
          mResult(result)
    {}

    bool getResult() override { return mResult; }

    bool postTranslate(std::string *infoLog) override { return mPostTranslateFunctor(infoLog); }

  private:
    PostTranslateFunctor mPostTranslateFunctor;
    bool mResult;
};

ShaderGL::ShaderGL(const gl::ShaderState &data,
                   GLuint shaderID,
                   MultiviewImplementationTypeGL multiviewImplementationType,
                   const std::shared_ptr<RendererGL> &renderer)
    : ShaderImpl(data),
      mShaderID(shaderID),
      mMultiviewImplementationType(multiviewImplementationType),
      mRenderer(renderer),
      mCompileStatus(GL_FALSE)
{}

ShaderGL::~ShaderGL()
{
    ASSERT(mShaderID == 0);
}

void ShaderGL::destroy()
{
    mRenderer->getFunctions()->deleteShader(mShaderID);
    mShaderID = 0;
}

void ShaderGL::compileAndCheckShader(const char *source)
{
    compileShader(source);
    checkShader();
}

void ShaderGL::compileShader(const char *source)
{
    const FunctionsGL *functions = mRenderer->getFunctions();
    functions->shaderSource(mShaderID, 1, &source, nullptr);
    functions->compileShader(mShaderID);
}

void ShaderGL::checkShader()
{
    const FunctionsGL *functions = mRenderer->getFunctions();

    // Check for compile errors from the native driver
    mCompileStatus = GL_FALSE;
    functions->getShaderiv(mShaderID, GL_COMPILE_STATUS, &mCompileStatus);
    if (mCompileStatus == GL_FALSE)
    {
        // Compilation failed, put the error into the info log
        GLint infoLogLength = 0;
        functions->getShaderiv(mShaderID, GL_INFO_LOG_LENGTH, &infoLogLength);

        // Info log length includes the null terminator, so 1 means that the info log is an empty
        // string.
        if (infoLogLength > 1)
        {
            std::vector<char> buf(infoLogLength);
            functions->getShaderInfoLog(mShaderID, infoLogLength, nullptr, &buf[0]);

            mInfoLog += &buf[0];
            WARN() << std::endl << mInfoLog;
        }
        else
        {
            WARN() << std::endl << "Shader compilation failed with no info log.";
        }
    }
}

bool ShaderGL::peekCompletion()
{
    const FunctionsGL *functions = mRenderer->getFunctions();
    GLint status                 = GL_FALSE;
    functions->getShaderiv(mShaderID, GL_COMPLETION_STATUS, &status);
    return status == GL_TRUE;
}

bool ShaderGL::compileAndCheckShaderInWorker(const char *source)
{
    std::string workerInfoLog;
    ScopedWorkerContextGL worker(mRenderer.get(), &workerInfoLog);
    if (worker())
    {
        compileAndCheckShader(source);
        return true;
    }
    else
    {
#if !defined(NDEBUG)
        mInfoLog += "bindWorkerContext failed.\n" + workerInfoLog;
#endif
        return false;
    }
}

std::shared_ptr<WaitableCompileEvent> ShaderGL::compile(const gl::Context *context,
                                                        gl::ShCompilerInstance *compilerInstance,
                                                        ShCompileOptions options)
{
    mInfoLog.clear();

    ShCompileOptions additionalOptions = SH_INIT_GL_POSITION;

    bool isWebGL = context->isWebGL();
    if (isWebGL && mState.getShaderType() != gl::ShaderType::Compute)
    {
        additionalOptions |= SH_INIT_OUTPUT_VARIABLES;
    }

    if (isWebGL && !context->getState().getEnableFeature(GL_TEXTURE_RECTANGLE_ANGLE))
    {
        additionalOptions |= SH_DISABLE_ARB_TEXTURE_RECTANGLE;
    }

    const angle::FeaturesGL &features = GetFeaturesGL(context);

    if (features.initFragmentOutputVariables.enabled)
    {
        additionalOptions |= SH_INIT_FRAGMENT_OUTPUT_VARIABLES;
    }

    if (features.doWhileGLSLCausesGPUHang.enabled)
    {
        additionalOptions |= SH_REWRITE_DO_WHILE_LOOPS;
    }

    if (features.emulateAbsIntFunction.enabled)
    {
        additionalOptions |= SH_EMULATE_ABS_INT_FUNCTION;
    }

    if (features.addAndTrueToLoopCondition.enabled)
    {
        additionalOptions |= SH_ADD_AND_TRUE_TO_LOOP_CONDITION;
    }

    if (features.emulateIsnanFloat.enabled)
    {
        additionalOptions |= SH_EMULATE_ISNAN_FLOAT_FUNCTION;
    }

    if (features.emulateAtan2Float.enabled)
    {
        additionalOptions |= SH_EMULATE_ATAN2_FLOAT_FUNCTION;
    }

    if (features.useUnusedBlocksWithStandardOrSharedLayout.enabled)
    {
        additionalOptions |= SH_USE_UNUSED_STANDARD_SHARED_BLOCKS;
    }

    if (features.removeInvariantAndCentroidForESSL3.enabled)
    {
        additionalOptions |= SH_REMOVE_INVARIANT_AND_CENTROID_FOR_ESSL3;
    }

    if (features.rewriteFloatUnaryMinusOperator.enabled)
    {
        additionalOptions |= SH_REWRITE_FLOAT_UNARY_MINUS_OPERATOR;
    }

    if (!features.dontInitializeUninitializedLocals.enabled)
    {
        additionalOptions |= SH_INITIALIZE_UNINITIALIZED_LOCALS;
    }

    if (features.clampPointSize.enabled)
    {
        additionalOptions |= SH_CLAMP_POINT_SIZE;
    }

    if (features.dontUseLoopsToInitializeVariables.enabled)
    {
        additionalOptions |= SH_DONT_USE_LOOPS_TO_INITIALIZE_VARIABLES;
    }

    if (features.clampFragDepth.enabled)
    {
        additionalOptions |= SH_CLAMP_FRAG_DEPTH;
    }

    if (features.rewriteRepeatedAssignToSwizzled.enabled)
    {
        additionalOptions |= SH_REWRITE_REPEATED_ASSIGN_TO_SWIZZLED;
    }

    if (mMultiviewImplementationType == MultiviewImplementationTypeGL::NV_VIEWPORT_ARRAY2)
    {
        additionalOptions |= SH_INITIALIZE_BUILTINS_FOR_INSTANCED_MULTIVIEW;
        additionalOptions |= SH_SELECT_VIEW_IN_NV_GLSL_VERTEX_SHADER;
    }

    if (features.clampArrayAccess.enabled || isWebGL)
    {
        additionalOptions |= SH_CLAMP_INDIRECT_ARRAY_BOUNDS;
    }

    if (features.addBaseVertexToVertexID.enabled)
    {
        additionalOptions |= SH_ADD_BASE_VERTEX_TO_VERTEX_ID;
    }

    if (features.unfoldShortCircuits.enabled)
    {
        additionalOptions |= SH_UNFOLD_SHORT_CIRCUIT;
    }

    if (features.removeDynamicIndexingOfSwizzledVector.enabled)
    {
        additionalOptions |= SH_REMOVE_DYNAMIC_INDEXING_OF_SWIZZLED_VECTOR;
    }

    if (features.preAddTexelFetchOffsets.enabled)
    {
        additionalOptions |= SH_REWRITE_TEXELFETCHOFFSET_TO_TEXELFETCH;
    }

    if (features.regenerateStructNames.enabled)
    {
        additionalOptions |= SH_REGENERATE_STRUCT_NAMES;
    }

    if (features.rewriteRowMajorMatrices.enabled)
    {
        additionalOptions |= SH_REWRITE_ROW_MAJOR_MATRICES;
    }

    options |= additionalOptions;

    auto workerThreadPool = context->getShaderCompileThreadPool();

    const std::string &source = mState.getSource();

    auto postTranslateFunctor = [this](std::string *infoLog) {
        if (mCompileStatus == GL_FALSE)
        {
            *infoLog = mInfoLog;
            return false;
        }
        return true;
    };

    if (mRenderer->hasNativeParallelCompile())
    {
        ShHandle handle = compilerInstance->getHandle();
        const char *str = source.c_str();
        bool result     = sh::Compile(handle, &str, 1, options);
        if (result)
        {
            compileShader(sh::GetObjectCode(handle).c_str());
            auto checkShaderFunctor    = [this]() { checkShader(); };
            auto peekCompletionFunctor = [this]() { return peekCompletion(); };
            return std::make_shared<WaitableCompileEventNativeParallel>(
                std::move(postTranslateFunctor), result, std::move(checkShaderFunctor),
                std::move(peekCompletionFunctor));
        }
        else
        {
            return std::make_shared<WaitableCompileEventDone>([](std::string *) { return true; },
                                                              result);
        }
    }
    else if (workerThreadPool->isAsync())
    {
        auto compileAndCheckShaderInWorkerFunctor = [this](const char *source) {
            return compileAndCheckShaderInWorker(source);
        };
        auto translateTask =
            std::make_shared<TranslateTaskGL>(compilerInstance->getHandle(), options, source,
                                              std::move(compileAndCheckShaderInWorkerFunctor));

        auto compileAndCheckShaderFunctor = [this](const char *source) {
            compileAndCheckShader(source);
        };
        return std::make_shared<WaitableCompileEventWorkerContext>(
            angle::WorkerThreadPool::PostWorkerTask(workerThreadPool, translateTask),
            std::move(compileAndCheckShaderFunctor), std::move(postTranslateFunctor),
            translateTask);
    }
    else
    {
        ShHandle handle = compilerInstance->getHandle();
        const char *str = source.c_str();
        bool result     = sh::Compile(handle, &str, 1, options);
        if (result)
        {
            compileAndCheckShader(sh::GetObjectCode(handle).c_str());
        }
        return std::make_shared<WaitableCompileEventDone>(std::move(postTranslateFunctor), result);
    }
}

std::string ShaderGL::getDebugInfo() const
{
    return mState.getTranslatedSource();
}

GLuint ShaderGL::getShaderID() const
{
    return mShaderID;
}

}  // namespace rx
