blob: 07923f991423f4ec1ff8cbe81fb822c2b526d149 [file] [log] [blame]
//
// 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.
//
// RecordConstantPrecision_test.cpp:
// Test for recording constant variable precision when it affects consuming expression.
//
#include "GLSLANG/ShaderLang.h"
#include "angle_gl.h"
#include "gtest/gtest.h"
#include "tests/test_utils/compiler_test.h"
using namespace sh;
class RecordConstantPrecisionTest : public MatchOutputCodeTest
{
public:
RecordConstantPrecisionTest() : MatchOutputCodeTest(GL_FRAGMENT_SHADER, SH_ESSL_OUTPUT) {}
};
// The constant's precision must be specified if its precision is higher than the other operands,
// since it increases the precision of the consuming expression.
TEST_F(RecordConstantPrecisionTest, HigherPrecisionConstantAsParameter)
{
const std::string &shaderString = R"(
uniform mediump float u;
void main()
{
const highp float a = 4096.5;
mediump float b = fract(a + u);
gl_FragColor = vec4(b);
})";
compile(shaderString);
ASSERT_TRUE(foundInCode("const highp float s"));
ASSERT_FALSE(foundInCode("fract(4096.5"));
ASSERT_FALSE(foundInCode("fract((4096.5"));
}
// The constant's precision does not need to be specified if its precision is equal to the other
// operands, as it does not increase the precision of the consuming expression. For simplicity
// however, the constant's precision is specified anyway.
TEST_F(RecordConstantPrecisionTest, EqualPrecisionConstantAsParameter)
{
const std::string &shaderString = R"(
uniform mediump float u;
void main()
{
const mediump float a = 4096.5;
mediump float b = fract(a + u);
gl_FragColor = vec4(b);
})";
compile(shaderString);
ASSERT_TRUE(foundInCode("const mediump float s"));
ASSERT_FALSE(foundInCode("fract((4096.5"));
}
// The constant's precision must be specified if its precision is higher than the other operands,
// since it increases the precision of the consuming expression. This applies also when the
// constant is part of a constant expression that can be folded.
TEST_F(RecordConstantPrecisionTest, FoldedBinaryConstantPrecisionIsHigher)
{
const std::string &shaderString = R"(
uniform mediump float u;
void main()
{
const highp float a = 4095.5;
mediump float b = fract((a + 1.0) + u);
gl_FragColor = vec4(b);
})";
compile(shaderString);
ASSERT_TRUE(foundInCode("const highp float s"));
ASSERT_FALSE(foundInCode("fract(4096.5"));
ASSERT_FALSE(foundInCode("fract((4096.5"));
}
// The constant's precision must be specified if its precision is higher than the other operands,
// since it increases the precision of the consuming expression. This applies also when the
// constant is part of a constant expression that can be folded.
TEST_F(RecordConstantPrecisionTest, FoldedUnaryConstantPrecisionIsHigher)
{
const std::string &shaderString = R"(
uniform mediump float u;
void main()
{
const highp float a = 0.5;
mediump float b = sin(fract(a) + u);
gl_FragColor = vec4(b);
})";
compile(shaderString);
ASSERT_TRUE(foundInCode("const highp float s"));
ASSERT_FALSE(foundInCode("sin(0.5"));
ASSERT_FALSE(foundInCode("sin((0.5"));
}
// The constant's precision must be specified if its precision is higher than the other operands,
// since it increases the precision of the consuming expression. This applies also when the
// constant is part of a constructor expression. Note that lowp constants never need their
// precision specified.
TEST_F(RecordConstantPrecisionTest, HigherPrecisionConstantInConstructor)
{
const std::string &shaderString = R"(
uniform mediump float u;
void main()
{
const highp float a = 4096.5;
const lowp float b = 1.0;
lowp vec4 result = vec4(b, a, b, u);
gl_FragColor = result;
})";
compile(shaderString);
ASSERT_TRUE(foundInCode("const highp float s"));
ASSERT_FALSE(foundInCode("const lowp float s"));
ASSERT_TRUE(foundInCode("vec4(1.0, s"));
}
// The constant's precision does not need to be specified if its used to initialize a variable.
TEST_F(RecordConstantPrecisionTest, HigherPrecisionConstantInAssignment)
{
const std::string &shaderString = R"(
uniform mediump float u;
void main()
{
const highp float a = 4096.5;
mediump float b = a;
mediump float c;
c = a;
gl_FragColor = vec4(b, b, c, c);
})";
compile(shaderString);
ASSERT_FALSE(foundInCode("const highp float s"));
ASSERT_TRUE(foundInCode("b = 4096.5"));
ASSERT_TRUE(foundInCode("c = 4096.5"));
}
// The constant's precision does not need to be specified if its used as an index.
TEST_F(RecordConstantPrecisionTest, HigherPrecisionConstantInIndex)
{
const std::string &shaderString = R"(
uniform mediump float u;
void main()
{
const highp int a = 33000;
mediump float b[34000];
gl_FragColor = vec4(b[a]);
})";
compile(shaderString);
ASSERT_FALSE(foundInCode("const highp int s"));
ASSERT_TRUE(foundInCode("b[33000]"));
}