blob: a22b3f6cce95157aad2826a508798f4aebffb76a [file] [log] [blame]
//
// Copyright 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.
//
// ConstantFoldingTest.h:
// Utilities for constant folding tests.
//
#ifndef TESTS_TEST_UTILS_CONSTANTFOLDINGTEST_H_
#define TESTS_TEST_UTILS_CONSTANTFOLDINGTEST_H_
#include <vector>
#include "common/mathutil.h"
#include "compiler/translator/tree_util/FindMain.h"
#include "compiler/translator/tree_util/FindSymbolNode.h"
#include "compiler/translator/tree_util/IntermTraverse.h"
#include "tests/test_utils/ShaderCompileTreeTest.h"
namespace sh
{
class TranslatorESSL;
template <typename T>
class ConstantFinder : public TIntermTraverser
{
public:
ConstantFinder(const std::vector<T> &constantVector)
: TIntermTraverser(true, false, false),
mConstantVector(constantVector),
mFaultTolerance(T()),
mFound(false)
{}
ConstantFinder(const std::vector<T> &constantVector, const T &faultTolerance)
: TIntermTraverser(true, false, false),
mConstantVector(constantVector),
mFaultTolerance(faultTolerance),
mFound(false)
{}
ConstantFinder(const T &value)
: TIntermTraverser(true, false, false), mFaultTolerance(T()), mFound(false)
{
mConstantVector.push_back(value);
}
void visitConstantUnion(TIntermConstantUnion *node)
{
if (node->getType().getObjectSize() == mConstantVector.size())
{
bool found = true;
for (size_t i = 0; i < mConstantVector.size(); i++)
{
if (!isEqual(node->getConstantValue()[i], mConstantVector[i]))
{
found = false;
break;
}
}
if (found)
{
mFound = found;
}
}
}
bool found() const { return mFound; }
private:
bool isEqual(const TConstantUnion &node, const float &value) const
{
if (node.getType() != EbtFloat)
{
return false;
}
if (value == std::numeric_limits<float>::infinity())
{
return gl::isInf(node.getFConst()) && node.getFConst() > 0;
}
else if (value == -std::numeric_limits<float>::infinity())
{
return gl::isInf(node.getFConst()) && node.getFConst() < 0;
}
else if (gl::isNaN(value))
{
// All NaNs are treated as equal.
return gl::isNaN(node.getFConst());
}
return mFaultTolerance >= fabsf(node.getFConst() - value);
}
bool isEqual(const TConstantUnion &node, const int &value) const
{
if (node.getType() != EbtInt)
{
return false;
}
ASSERT(mFaultTolerance < std::numeric_limits<int>::max());
// abs() returns 0 at least on some platforms when the minimum int value is passed in (it
// doesn't have a positive counterpart).
return mFaultTolerance >= abs(node.getIConst() - value) &&
(node.getIConst() - value) != std::numeric_limits<int>::min();
}
bool isEqual(const TConstantUnion &node, const unsigned int &value) const
{
if (node.getType() != EbtUInt)
{
return false;
}
ASSERT(mFaultTolerance < static_cast<unsigned int>(std::numeric_limits<int>::max()));
return static_cast<int>(mFaultTolerance) >=
abs(static_cast<int>(node.getUConst() - value)) &&
static_cast<int>(node.getUConst() - value) != std::numeric_limits<int>::min();
}
bool isEqual(const TConstantUnion &node, const bool &value) const
{
if (node.getType() != EbtBool)
{
return false;
}
return node.getBConst() == value;
}
std::vector<T> mConstantVector;
T mFaultTolerance;
bool mFound;
};
class ConstantFoldingTest : public ShaderCompileTreeTest
{
public:
ConstantFoldingTest() {}
protected:
::GLenum getShaderType() const override { return GL_FRAGMENT_SHADER; }
ShShaderSpec getShaderSpec() const override { return SH_GLES3_1_SPEC; }
template <typename T>
bool constantFoundInAST(T constant)
{
ConstantFinder<T> finder(constant);
mASTRoot->traverse(&finder);
return finder.found();
}
template <typename T>
bool constantVectorFoundInAST(const std::vector<T> &constantVector)
{
ConstantFinder<T> finder(constantVector);
mASTRoot->traverse(&finder);
return finder.found();
}
template <typename T>
bool constantColumnMajorMatrixFoundInAST(const std::vector<T> &constantMatrix)
{
return constantVectorFoundInAST(constantMatrix);
}
template <typename T>
bool constantVectorNearFoundInAST(const std::vector<T> &constantVector, const T &faultTolerance)
{
ConstantFinder<T> finder(constantVector, faultTolerance);
mASTRoot->traverse(&finder);
return finder.found();
}
bool symbolFoundInAST(const char *symbolName)
{
return FindSymbolNode(mASTRoot, ImmutableString(symbolName)) != nullptr;
}
bool symbolFoundInMain(const char *symbolName)
{
return FindSymbolNode(FindMain(mASTRoot), ImmutableString(symbolName)) != nullptr;
}
};
class ConstantFoldingExpressionTest : public ConstantFoldingTest
{
public:
ConstantFoldingExpressionTest() {}
void evaluateFloat(const std::string &floatExpression);
void evaluateInt(const std::string &intExpression);
void evaluateUint(const std::string &uintExpression);
};
} // namespace sh
#endif // TESTS_TEST_UTILS_CONSTANTFOLDINGTEST_H_