//
// Copyright (c) 2016 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.
//
// Implementation of texelFetchOffset translation issue workaround.
// See header for more info.

#include "compiler/translator/RewriteTexelFetchOffset.h"

#include "common/angleutils.h"
#include "compiler/translator/IntermNode.h"
#include "compiler/translator/SymbolTable.h"

namespace sh
{

namespace
{

class Traverser : public TIntermTraverser
{
  public:
    static void Apply(TIntermNode *root, const TSymbolTable &symbolTable, int shaderVersion);

  private:
    Traverser(const TSymbolTable &symbolTable, int shaderVersion);
    bool visitAggregate(Visit visit, TIntermAggregate *node) override;
    void nextIteration();

    const TSymbolTable *symbolTable;
    const int shaderVersion;
    bool mFound = false;
};

Traverser::Traverser(const TSymbolTable &symbolTable, int shaderVersion)
    : TIntermTraverser(true, false, false), symbolTable(&symbolTable), shaderVersion(shaderVersion)
{
}

// static
void Traverser::Apply(TIntermNode *root, const TSymbolTable &symbolTable, int shaderVersion)
{
    Traverser traverser(symbolTable, shaderVersion);
    do
    {
        traverser.nextIteration();
        root->traverse(&traverser);
        if (traverser.mFound)
        {
            traverser.updateTree();
        }
    } while (traverser.mFound);
}

void Traverser::nextIteration()
{
    mFound = false;
}

bool Traverser::visitAggregate(Visit visit, TIntermAggregate *node)
{
    if (mFound)
    {
        return false;
    }

    // Decide if the node represents the call of texelFetchOffset.
    if (node->getOp() != EOpCallBuiltInFunction)
    {
        return true;
    }

    if (node->getFunctionSymbolInfo()->getName() != "texelFetchOffset")
    {
        return true;
    }

    // Potential problem case detected, apply workaround.
    const TIntermSequence *sequence = node->getSequence();
    ASSERT(sequence->size() == 4u);

    // Decide if the sampler is a 2DArray sampler. In that case position is ivec3 and offset is
    // ivec2.
    bool is2DArray = sequence->at(1)->getAsTyped()->getNominalSize() == 3 &&
                     sequence->at(3)->getAsTyped()->getNominalSize() == 2;

    // Create new node that represents the call of function texelFetch.
    // Its argument list will be: texelFetch(sampler, Position+offset, lod).

    TIntermSequence *texelFetchArguments = new TIntermSequence();

    // sampler
    texelFetchArguments->push_back(sequence->at(0));

    // Position
    TIntermTyped *texCoordNode = sequence->at(1)->getAsTyped();
    ASSERT(texCoordNode);

    // offset
    TIntermTyped *offsetNode = nullptr;
    ASSERT(sequence->at(3)->getAsTyped());
    if (is2DArray)
    {
        // For 2DArray samplers, Position is ivec3 and offset is ivec2;
        // So offset must be converted into an ivec3 before being added to Position.
        TIntermSequence *constructOffsetIvecArguments = new TIntermSequence();
        constructOffsetIvecArguments->push_back(sequence->at(3)->getAsTyped());

        TIntermTyped *zeroNode = TIntermTyped::CreateZero(TType(EbtInt));
        constructOffsetIvecArguments->push_back(zeroNode);

        offsetNode = TIntermAggregate::CreateConstructor(texCoordNode->getType(),
                                                         constructOffsetIvecArguments);
        offsetNode->setLine(texCoordNode->getLine());
    }
    else
    {
        offsetNode = sequence->at(3)->getAsTyped();
    }

    // Position+offset
    TIntermBinary *add = new TIntermBinary(EOpAdd, texCoordNode, offsetNode);
    add->setLine(texCoordNode->getLine());
    texelFetchArguments->push_back(add);

    // lod
    texelFetchArguments->push_back(sequence->at(2));

    ASSERT(texelFetchArguments->size() == 3u);

    // Get the symbol of the texel fetch function to use.
    TString mangledName = TFunction::GetMangledNameFromCall("texelFetch", *texelFetchArguments);
    TSymbol *texelFetchSymbol = symbolTable->findBuiltIn(mangledName, shaderVersion);
    ASSERT(texelFetchSymbol && texelFetchSymbol->isFunction());

    TIntermAggregate *texelFetchNode = TIntermAggregate::CreateBuiltInFunctionCall(
        *static_cast<const TFunction *>(texelFetchSymbol), texelFetchArguments);
    texelFetchNode->setLine(node->getLine());

    // Replace the old node by this new node.
    queueReplacement(node, texelFetchNode, OriginalNode::IS_DROPPED);
    mFound = true;
    return false;
}

}  // anonymous namespace

void RewriteTexelFetchOffset(TIntermNode *root, const TSymbolTable &symbolTable, int shaderVersion)
{
    // texelFetchOffset is only valid in GLSL 3.0 and later.
    if (shaderVersion < 300)
        return;

    Traverser::Apply(root, symbolTable, shaderVersion);
}

}  // namespace sh