blob: 838ac93a09ef81aa5afbe2a90da8342a1db7748b [file] [log] [blame]
//
// Copyright (c) 2014 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.
//
// TypeTracking_test.cpp:
// Test for tracking types resulting from math operations, including their
// precision.
//
#include "angle_gl.h"
#include "gtest/gtest.h"
#include "GLSLANG/ShaderLang.h"
#include "compiler/translator/TranslatorESSL.h"
class TypeTrackingTest : public testing::Test
{
public:
TypeTrackingTest() {}
protected:
virtual void SetUp()
{
ShBuiltInResources resources;
ShInitBuiltInResources(&resources);
mTranslator = new TranslatorESSL(GL_FRAGMENT_SHADER, SH_GLES2_SPEC);
ASSERT_TRUE(mTranslator->Init(resources));
}
virtual void TearDown()
{
delete mTranslator;
}
void compile(const std::string& shaderString)
{
const char *shaderStrings[] = { shaderString.c_str() };
bool compilationSuccess = mTranslator->compile(shaderStrings, 1, SH_INTERMEDIATE_TREE);
TInfoSink &infoSink = mTranslator->getInfoSink();
mInfoLog = infoSink.info.c_str();
if (!compilationSuccess)
FAIL() << "Shader compilation failed " << mInfoLog;
}
bool foundInIntermediateTree(const char* stringToFind)
{
return mInfoLog.find(stringToFind) != std::string::npos;
}
private:
TranslatorESSL *mTranslator;
std::string mInfoLog;
};
TEST_F(TypeTrackingTest, BuiltInFunctionResultPrecision)
{
const std::string &shaderString =
"precision mediump float;\n"
"uniform float f;\n"
"void main() {\n"
" float ff = sin(f);\n"
" gl_FragColor = vec4(ff);\n"
"}\n";
compile(shaderString);
ASSERT_TRUE(foundInIntermediateTree("sine (mediump float)"));
};
TEST_F(TypeTrackingTest, BinaryMathResultPrecision)
{
const std::string &shaderString =
"precision mediump float;\n"
"uniform float f;\n"
"void main() {\n"
" float ff = f * 0.5;\n"
" gl_FragColor = vec4(ff);\n"
"}\n";
compile(shaderString);
ASSERT_TRUE(foundInIntermediateTree("multiply (mediump float)"));
};
TEST_F(TypeTrackingTest, BuiltInVecFunctionResultTypeAndPrecision)
{
const std::string &shaderString =
"precision mediump float;\n"
"uniform vec2 a;\n"
"void main() {\n"
" float b = length(a);\n"
" float c = dot(a, vec2(0.5));\n"
" float d = distance(vec2(0.5), a);\n"
" gl_FragColor = vec4(b, c, d, 1.0);\n"
"}\n";
compile(shaderString);
ASSERT_TRUE(foundInIntermediateTree("length (mediump float)"));
ASSERT_TRUE(foundInIntermediateTree("dot-product (mediump float)"));
ASSERT_TRUE(foundInIntermediateTree("distance (mediump float)"));
};
TEST_F(TypeTrackingTest, BuiltInFunctionChoosesHigherPrecision)
{
const std::string &shaderString =
"precision lowp float;\n"
"uniform mediump vec2 a;\n"
"uniform lowp vec2 b;\n"
"void main() {\n"
" float c = dot(a, b);\n"
" float d = distance(b, a);\n"
" gl_FragColor = vec4(c, d, 0.0, 1.0);\n"
"}\n";
compile(shaderString);
ASSERT_TRUE(foundInIntermediateTree("dot-product (mediump float)"));
ASSERT_TRUE(foundInIntermediateTree("distance (mediump float)"));
};
TEST_F(TypeTrackingTest, BuiltInBoolFunctionResultType)
{
const std::string &shaderString =
"uniform bvec4 bees;\n"
"void main() {\n"
" bool b = any(bees);\n"
" bool c = all(bees);\n"
" bvec4 d = not(bees);\n"
" gl_FragColor = vec4(b ? 1.0 : 0.0, c ? 1.0 : 0.0, d.x ? 1.0 : 0.0, 1.0);\n"
"}\n";
compile(shaderString);
ASSERT_TRUE(foundInIntermediateTree("any (bool)"));
ASSERT_TRUE(foundInIntermediateTree("all (bool)"));
ASSERT_TRUE(foundInIntermediateTree("Negate conditional (4-component vector of bool)"));
};
TEST_F(TypeTrackingTest, BuiltInVecToBoolFunctionResultType)
{
const std::string &shaderString =
"precision mediump float;\n"
"uniform vec2 apples;\n"
"uniform vec2 oranges;\n"
"uniform ivec2 foo;\n"
"uniform ivec2 bar;\n"
"void main() {\n"
" bvec2 a = lessThan(apples, oranges);\n"
" bvec2 b = greaterThan(foo, bar);\n"
" gl_FragColor = vec4(any(a) ? 1.0 : 0.0, any(b) ? 1.0 : 0.0, 0.0, 1.0);\n"
"}\n";
compile(shaderString);
ASSERT_TRUE(foundInIntermediateTree("Less Than (2-component vector of bool)"));
ASSERT_TRUE(foundInIntermediateTree("Greater Than (2-component vector of bool)"));
};
TEST_F(TypeTrackingTest, Texture2DResultTypeAndPrecision)
{
// ESSL spec section 4.5.3: sampler2D and samplerCube are lowp by default
// ESSL spec section 8: For the texture functions, the precision of the return type matches the precision of the sampler type.
const std::string &shaderString =
"precision mediump float;\n"
"uniform sampler2D s;\n"
"uniform vec2 a;\n"
"void main() {\n"
" vec4 c = texture2D(s, a);\n"
" gl_FragColor = c;\n"
"}\n";
compile(shaderString);
ASSERT_TRUE(foundInIntermediateTree("texture2D(s21;vf2; (lowp 4-component vector of float)"));
};
TEST_F(TypeTrackingTest, TextureCubeResultTypeAndPrecision)
{
// ESSL spec section 4.5.3: sampler2D and samplerCube are lowp by default
// ESSL spec section 8: For the texture functions, the precision of the return type matches the precision of the sampler type.
const std::string &shaderString =
"precision mediump float;\n"
"uniform samplerCube sc;\n"
"uniform vec3 a;\n"
"void main() {\n"
" vec4 c = textureCube(sc, a);\n"
" gl_FragColor = c;\n"
"}\n";
compile(shaderString);
ASSERT_TRUE(foundInIntermediateTree("textureCube(sC1;vf3; (lowp 4-component vector of float)"));
};
TEST_F(TypeTrackingTest, TextureSizeResultTypeAndPrecision)
{
// ESSL 3.0 spec section 8: textureSize has predefined precision highp
const std::string &shaderString =
"#version 300 es\n"
"precision mediump float;\n"
"out vec4 my_FragColor;\n"
"uniform sampler2D s;\n"
"void main() {\n"
" ivec2 size = textureSize(s, 0);\n"
" if (size.x > 100) {\n"
" my_FragColor = vec4(0.0, 1.0, 0.0, 1.0);\n"
" } else {\n"
" my_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n"
" }\n"
"}\n";
compile(shaderString);
ASSERT_TRUE(foundInIntermediateTree("textureSize(s21;i1; (highp 2-component vector of int)"));
};