Commit a42e8b2c by Olli Etuaho Committed by Commit Bot

Support precision emulation on HLSL

Add precision emulation support to HLSL 4.1 output. This makes it possible for developers to test their shaders for precision issues easily on Chrome on Windows without having to use the GL backend. The patch has been verified with Chrome on Windows to reproduce some precision bugs in real-world WebGL content, including old versions of the babylon.js library. The EmulatePrecision AST transformation still relies on writing out raw shader code for the rounding functions, with raw HLSL code added alongside pre-existing GLSL and ESSL code. In some ways it would be nicer to do the EmulatePrecision step as a pure AST transformation, but on the other hand the raw code is much more readable and easier to optimize. To better support multiple output languages in EmulatePrecision, add a RoundingHelperWriter class that has different subclasses for writing the rounding functions in different languages. The unit tests are expanded to cover the HLSL output of precision emulation. The parts of the tests that require the HLSL output are only active on Windows where ANGLE_ENABLE_HLSL define is added to the unit tests. Putting the HLSL tests in an entirely separate file is a worse alternative, since it would require either a lot of code duplication or add a lot of boilerplate to the individual tests. BUG=angleproject:1437 TEST=angle_unittests Change-Id: Ia4ba0374cd415908f16f34752321af1cb93525a5 Reviewed-on: https://chromium-review.googlesource.com/358473Reviewed-by: 's avatarCorentin Wallez <cwallez@chromium.org> Commit-Queue: Olli Etuaho <oetuaho@nvidia.com>
parent fea6e952
......@@ -6,99 +6,203 @@
#include "compiler/translator/EmulatePrecision.h"
#include <memory>
namespace
{
static void writeVectorPrecisionEmulationHelpers(TInfoSinkBase &sink,
const ShShaderOutput outputLanguage,
const unsigned int size)
class RoundingHelperWriter
{
std::stringstream vecTypeStrStr;
if (outputLanguage == SH_ESSL_OUTPUT)
vecTypeStrStr << "highp ";
vecTypeStrStr << "vec" << size;
std::string vecType = vecTypeStrStr.str();
sink <<
vecType << " angle_frm(in " << vecType << " v) {\n"
" v = clamp(v, -65504.0, 65504.0);\n"
" " << vecType << " exponent = floor(log2(abs(v) + 1e-30)) - 10.0;\n"
" bvec" << size << " isNonZero = greaterThanEqual(exponent, vec" << size << "(-25.0));\n"
" v = v * exp2(-exponent);\n"
" v = sign(v) * floor(abs(v));\n"
" return v * exp2(exponent) * vec" << size << "(isNonZero);\n"
"}\n";
sink <<
vecType << " angle_frl(in " << vecType << " v) {\n"
" v = clamp(v, -2.0, 2.0);\n"
" v = v * 256.0;\n"
" v = sign(v) * floor(abs(v));\n"
" return v * 0.00390625;\n"
"}\n";
}
static void writeMatrixPrecisionEmulationHelper(TInfoSinkBase &sink,
const ShShaderOutput outputLanguage,
const unsigned int columns,
const unsigned int rows,
const char *functionName)
public:
static RoundingHelperWriter *createHelperWriter(const ShShaderOutput outputLanguage);
void writeCommonRoundingHelpers(TInfoSinkBase &sink, const int shaderVersion);
void writeCompoundAssignmentHelper(TInfoSinkBase &sink,
const char *lType,
const char *rType,
const char *opStr,
const char *opNameStr);
protected:
RoundingHelperWriter(const ShShaderOutput outputLanguage) : mOutputLanguage(outputLanguage) {}
RoundingHelperWriter() = delete;
const ShShaderOutput mOutputLanguage;
private:
virtual std::string getTypeString(const char *glslType) = 0;
virtual void writeFloatRoundingHelpers(TInfoSinkBase &sink) = 0;
virtual void writeVectorRoundingHelpers(TInfoSinkBase &sink, const unsigned int size) = 0;
virtual void writeMatrixRoundingHelper(TInfoSinkBase &sink,
const unsigned int columns,
const unsigned int rows,
const char *functionName) = 0;
};
class RoundingHelperWriterGLSL : public RoundingHelperWriter
{
std::stringstream matTypeStrStr;
if (outputLanguage == SH_ESSL_OUTPUT)
matTypeStrStr << "highp ";
matTypeStrStr << "mat" << columns;
if (rows != columns)
public:
RoundingHelperWriterGLSL(const ShShaderOutput outputLanguage)
: RoundingHelperWriter(outputLanguage)
{
matTypeStrStr << "x" << rows;
}
std::string matType = matTypeStrStr.str();
private:
std::string getTypeString(const char *glslType) override;
void writeFloatRoundingHelpers(TInfoSinkBase &sink) override;
void writeVectorRoundingHelpers(TInfoSinkBase &sink, const unsigned int size) override;
void writeMatrixRoundingHelper(TInfoSinkBase &sink,
const unsigned int columns,
const unsigned int rows,
const char *functionName) override;
};
class RoundingHelperWriterESSL : public RoundingHelperWriterGLSL
{
public:
RoundingHelperWriterESSL(const ShShaderOutput outputLanguage)
: RoundingHelperWriterGLSL(outputLanguage)
{
}
sink << matType << " " << functionName << "(in " << matType << " m) {\n"
" " << matType << " rounded;\n";
private:
std::string getTypeString(const char *glslType) override;
};
for (unsigned int i = 0; i < columns; ++i)
class RoundingHelperWriterHLSL : public RoundingHelperWriter
{
public:
RoundingHelperWriterHLSL(const ShShaderOutput outputLanguage)
: RoundingHelperWriter(outputLanguage)
{
sink << " rounded[" << i << "] = " << functionName << "(m[" << i << "]);\n";
}
sink << " return rounded;\n"
"}\n";
private:
std::string getTypeString(const char *glslType) override;
void writeFloatRoundingHelpers(TInfoSinkBase &sink) override;
void writeVectorRoundingHelpers(TInfoSinkBase &sink, const unsigned int size) override;
void writeMatrixRoundingHelper(TInfoSinkBase &sink,
const unsigned int columns,
const unsigned int rows,
const char *functionName) override;
};
RoundingHelperWriter *RoundingHelperWriter::createHelperWriter(const ShShaderOutput outputLanguage)
{
switch (outputLanguage)
{
case SH_HLSL_4_1_OUTPUT:
return new RoundingHelperWriterHLSL(outputLanguage);
case SH_ESSL_OUTPUT:
return new RoundingHelperWriterESSL(outputLanguage);
default:
// Other languages not yet supported
ASSERT(outputLanguage == SH_GLSL_COMPATIBILITY_OUTPUT ||
IsGLSL130OrNewer(outputLanguage));
return new RoundingHelperWriterGLSL(outputLanguage);
}
}
static void writeCommonPrecisionEmulationHelpers(TInfoSinkBase &sink,
const int shaderVersion,
const ShShaderOutput outputLanguage)
void RoundingHelperWriter::writeCommonRoundingHelpers(TInfoSinkBase &sink, const int shaderVersion)
{
// Write the angle_frm functions that round floating point numbers to
// half precision, and angle_frl functions that round them to minimum lowp
// precision.
writeFloatRoundingHelpers(sink);
writeVectorRoundingHelpers(sink, 2);
writeVectorRoundingHelpers(sink, 3);
writeVectorRoundingHelpers(sink, 4);
if (shaderVersion > 100)
{
for (unsigned int columns = 2; columns <= 4; ++columns)
{
for (unsigned int rows = 2; rows <= 4; ++rows)
{
writeMatrixRoundingHelper(sink, columns, rows, "angle_frm");
writeMatrixRoundingHelper(sink, columns, rows, "angle_frl");
}
}
}
else
{
for (unsigned int size = 2; size <= 4; ++size)
{
writeMatrixRoundingHelper(sink, size, size, "angle_frm");
writeMatrixRoundingHelper(sink, size, size, "angle_frl");
}
}
}
void RoundingHelperWriter::writeCompoundAssignmentHelper(TInfoSinkBase &sink,
const char *lType,
const char *rType,
const char *opStr,
const char *opNameStr)
{
std::string lTypeStr = getTypeString(lType);
std::string rTypeStr = getTypeString(rType);
// Note that y should be passed through angle_frm at the function call site,
// but x can't be passed through angle_frm there since it is an inout parameter.
// So only pass x and the result through angle_frm here.
// clang-format off
sink <<
lTypeStr << " angle_compound_" << opNameStr << "_frm(inout " << lTypeStr << " x, in " << rTypeStr << " y) {\n"
" x = angle_frm(angle_frm(x) " << opStr << " y);\n"
" return x;\n"
"}\n";
sink <<
lTypeStr << " angle_compound_" << opNameStr << "_frl(inout " << lTypeStr << " x, in " << rTypeStr << " y) {\n"
" x = angle_frl(angle_frm(x) " << opStr << " y);\n"
" return x;\n"
"}\n";
// clang-format on
}
std::string RoundingHelperWriterGLSL::getTypeString(const char *glslType)
{
return glslType;
}
std::string RoundingHelperWriterESSL::getTypeString(const char *glslType)
{
std::stringstream typeStrStr;
typeStrStr << "highp " << glslType;
return typeStrStr.str();
}
void RoundingHelperWriterGLSL::writeFloatRoundingHelpers(TInfoSinkBase &sink)
{
// Unoptimized version of angle_frm for single floats:
//
// int webgl_maxNormalExponent(in int exponentBits) {
// int webgl_maxNormalExponent(in int exponentBits)
// {
// int possibleExponents = int(exp2(float(exponentBits)));
// int exponentBias = possibleExponents / 2 - 1;
// int allExponentBitsOne = possibleExponents - 1;
// return (allExponentBitsOne - 1) - exponentBias;
// }
//
// float angle_frm(in float x) {
// float angle_frm(in float x)
// {
// int mantissaBits = 10;
// int exponentBits = 5;
// float possibleMantissas = exp2(float(mantissaBits));
// float mantissaMax = 2.0 - 1.0 / possibleMantissas;
// int maxNE = webgl_maxNormalExponent(exponentBits);
// float max = exp2(float(maxNE)) * mantissaMax;
// if (x > max) {
// if (x > max)
// {
// return max;
// }
// if (x < -max) {
// if (x < -max)
// {
// return -max;
// }
// float exponent = floor(log2(abs(x)));
// if (abs(x) == 0.0 || exponent < -float(maxNE)) {
// if (abs(x) == 0.0 || exponent < -float(maxNE))
// {
// return 0.0 * sign(x)
// }
// x = x * exp2(-(exponent - float(mantissaBits)));
......@@ -120,83 +224,198 @@ static void writeCommonPrecisionEmulationHelpers(TInfoSinkBase &sink,
// numbers will be flushed to zero either way (2^-15 is the smallest
// normal positive number), this does not introduce any error.
std::string floatType = "float";
if (outputLanguage == SH_ESSL_OUTPUT)
floatType = "highp float";
std::string floatType = getTypeString("float");
// clang-format off
sink <<
floatType << " angle_frm(in " << floatType << " x) {\n"
" x = clamp(x, -65504.0, 65504.0);\n"
" " << floatType << " exponent = floor(log2(abs(x) + 1e-30)) - 10.0;\n"
" bool isNonZero = (exponent >= -25.0);\n"
" x = x * exp2(-exponent);\n"
" x = sign(x) * floor(abs(x));\n"
" return x * exp2(exponent) * float(isNonZero);\n"
"}\n";
floatType << " angle_frm(in " << floatType << " x) {\n"
" x = clamp(x, -65504.0, 65504.0);\n"
" " << floatType << " exponent = floor(log2(abs(x) + 1e-30)) - 10.0;\n"
" bool isNonZero = (exponent >= -25.0);\n"
" x = x * exp2(-exponent);\n"
" x = sign(x) * floor(abs(x));\n"
" return x * exp2(exponent) * float(isNonZero);\n"
"}\n";
sink <<
floatType << " angle_frl(in " << floatType << " x) {\n"
" x = clamp(x, -2.0, 2.0);\n"
" x = x * 256.0;\n"
" x = sign(x) * floor(abs(x));\n"
" return x * 0.00390625;\n"
"}\n";
writeVectorPrecisionEmulationHelpers(sink, outputLanguage, 2);
writeVectorPrecisionEmulationHelpers(sink, outputLanguage, 3);
writeVectorPrecisionEmulationHelpers(sink, outputLanguage, 4);
if (shaderVersion > 100)
floatType << " angle_frl(in " << floatType << " x) {\n"
" x = clamp(x, -2.0, 2.0);\n"
" x = x * 256.0;\n"
" x = sign(x) * floor(abs(x));\n"
" return x * 0.00390625;\n"
"}\n";
// clang-format on
}
void RoundingHelperWriterGLSL::writeVectorRoundingHelpers(TInfoSinkBase &sink,
const unsigned int size)
{
std::stringstream vecTypeStrStr;
vecTypeStrStr << "vec" << size;
std::string vecType = getTypeString(vecTypeStrStr.str().c_str());
// clang-format off
sink <<
vecType << " angle_frm(in " << vecType << " v) {\n"
" v = clamp(v, -65504.0, 65504.0);\n"
" " << vecType << " exponent = floor(log2(abs(v) + 1e-30)) - 10.0;\n"
" bvec" << size << " isNonZero = greaterThanEqual(exponent, vec" << size << "(-25.0));\n"
" v = v * exp2(-exponent);\n"
" v = sign(v) * floor(abs(v));\n"
" return v * exp2(exponent) * vec" << size << "(isNonZero);\n"
"}\n";
sink <<
vecType << " angle_frl(in " << vecType << " v) {\n"
" v = clamp(v, -2.0, 2.0);\n"
" v = v * 256.0;\n"
" v = sign(v) * floor(abs(v));\n"
" return v * 0.00390625;\n"
"}\n";
// clang-format on
}
void RoundingHelperWriterGLSL::writeMatrixRoundingHelper(TInfoSinkBase &sink,
const unsigned int columns,
const unsigned int rows,
const char *functionName)
{
std::stringstream matTypeStrStr;
matTypeStrStr << "mat" << columns;
if (rows != columns)
{
for (unsigned int columns = 2; columns <= 4; ++columns)
{
for (unsigned int rows = 2; rows <= 4; ++rows)
{
writeMatrixPrecisionEmulationHelper(sink, outputLanguage, columns, rows,
"angle_frm");
writeMatrixPrecisionEmulationHelper(sink, outputLanguage, columns, rows,
"angle_frl");
}
}
matTypeStrStr << "x" << rows;
}
else
std::string matType = getTypeString(matTypeStrStr.str().c_str());
sink << matType << " " << functionName << "(in " << matType << " m) {\n"
<< " " << matType << " rounded;\n";
for (unsigned int i = 0; i < columns; ++i)
{
for (unsigned int size = 2; size <= 4; ++size)
{
writeMatrixPrecisionEmulationHelper(sink, outputLanguage, size, size, "angle_frm");
writeMatrixPrecisionEmulationHelper(sink, outputLanguage, size, size, "angle_frl");
}
sink << " rounded[" << i << "] = " << functionName << "(m[" << i << "]);\n";
}
sink << " return rounded;\n"
"}\n";
}
static void writeCompoundAssignmentPrecisionEmulation(
TInfoSinkBase& sink, ShShaderOutput outputLanguage,
const char *lType, const char *rType, const char *opStr, const char *opNameStr)
static const char *GetHLSLTypeStr(const char *floatTypeStr)
{
std::string lTypeStr = lType;
std::string rTypeStr = rType;
if (outputLanguage == SH_ESSL_OUTPUT)
if (strcmp(floatTypeStr, "float") == 0)
{
return "float";
}
if (strcmp(floatTypeStr, "vec2") == 0)
{
return "float2";
}
if (strcmp(floatTypeStr, "vec3") == 0)
{
return "float3";
}
if (strcmp(floatTypeStr, "vec4") == 0)
{
return "float4";
}
if (strcmp(floatTypeStr, "mat2") == 0)
{
return "float2x2";
}
if (strcmp(floatTypeStr, "mat3") == 0)
{
return "float3x3";
}
if (strcmp(floatTypeStr, "mat4") == 0)
{
return "float4x4";
}
if (strcmp(floatTypeStr, "mat2x3") == 0)
{
return "float2x3";
}
if (strcmp(floatTypeStr, "mat2x4") == 0)
{
return "float2x4";
}
if (strcmp(floatTypeStr, "mat3x2") == 0)
{
return "float3x2";
}
if (strcmp(floatTypeStr, "mat3x4") == 0)
{
return "float3x4";
}
if (strcmp(floatTypeStr, "mat4x2") == 0)
{
std::stringstream lTypeStrStr;
lTypeStrStr << "highp " << lType;
lTypeStr = lTypeStrStr.str();
std::stringstream rTypeStrStr;
rTypeStrStr << "highp " << rType;
rTypeStr = rTypeStrStr.str();
return "float4x2";
}
if (strcmp(floatTypeStr, "mat4x3") == 0)
{
return "float4x3";
}
UNREACHABLE();
return nullptr;
}
// Note that y should be passed through angle_frm at the function call site,
// but x can't be passed through angle_frm there since it is an inout parameter.
// So only pass x and the result through angle_frm here.
std::string RoundingHelperWriterHLSL::getTypeString(const char *glslType)
{
return GetHLSLTypeStr(glslType);
}
void RoundingHelperWriterHLSL::writeFloatRoundingHelpers(TInfoSinkBase &sink)
{
// In HLSL scalars are the same as 1-vectors.
writeVectorRoundingHelpers(sink, 1);
}
void RoundingHelperWriterHLSL::writeVectorRoundingHelpers(TInfoSinkBase &sink,
const unsigned int size)
{
std::stringstream vecTypeStrStr;
vecTypeStrStr << "float" << size;
std::string vecType = vecTypeStrStr.str();
// clang-format off
sink <<
lTypeStr << " angle_compound_" << opNameStr << "_frm(inout " << lTypeStr << " x, in " << rTypeStr << " y) {\n"
" x = angle_frm(angle_frm(x) " << opStr << " y);\n"
" return x;\n"
"}\n";
vecType << " angle_frm(" << vecType << " v) {\n"
" v = clamp(v, -65504.0, 65504.0);\n"
" " << vecType << " exponent = floor(log2(abs(v) + 1e-30)) - 10.0;\n"
" bool" << size << " isNonZero = exponent < -25.0;\n"
" v = v * exp2(-exponent);\n"
" v = sign(v) * floor(abs(v));\n"
" return v * exp2(exponent) * (float" << size << ")(isNonZero);\n"
"}\n";
sink <<
lTypeStr << " angle_compound_" << opNameStr << "_frl(inout " << lTypeStr << " x, in " << rTypeStr << " y) {\n"
" x = angle_frl(angle_frm(x) " << opStr << " y);\n"
" return x;\n"
"}\n";
vecType << " angle_frl(" << vecType << " v) {\n"
" v = clamp(v, -2.0, 2.0);\n"
" v = v * 256.0;\n"
" v = sign(v) * floor(abs(v));\n"
" return v * 0.00390625;\n"
"}\n";
// clang-format on
}
void RoundingHelperWriterHLSL::writeMatrixRoundingHelper(TInfoSinkBase &sink,
const unsigned int columns,
const unsigned int rows,
const char *functionName)
{
std::stringstream matTypeStrStr;
matTypeStrStr << "float" << columns << "x" << rows;
std::string matType = matTypeStrStr.str();
sink << matType << " " << functionName << "(" << matType << " m) {\n"
<< " " << matType << " rounded;\n";
for (unsigned int i = 0; i < columns; ++i)
{
sink << " rounded[" << i << "] = " << functionName << "(m[" << i << "]);\n";
}
sink << " return rounded;\n"
"}\n";
}
bool canRoundFloat(const TType &type)
......@@ -474,20 +693,19 @@ void EmulatePrecision::writeEmulationHelpers(TInfoSinkBase &sink,
const int shaderVersion,
const ShShaderOutput outputLanguage)
{
// Other languages not yet supported
ASSERT(outputLanguage == SH_GLSL_COMPATIBILITY_OUTPUT ||
IsGLSL130OrNewer(outputLanguage) ||
outputLanguage == SH_ESSL_OUTPUT);
writeCommonPrecisionEmulationHelpers(sink, shaderVersion, outputLanguage);
std::unique_ptr<RoundingHelperWriter> roundingHelperWriter(
RoundingHelperWriter::createHelperWriter(outputLanguage));
roundingHelperWriter->writeCommonRoundingHelpers(sink, shaderVersion);
EmulationSet::const_iterator it;
for (it = mEmulateCompoundAdd.begin(); it != mEmulateCompoundAdd.end(); it++)
writeCompoundAssignmentPrecisionEmulation(sink, outputLanguage, it->lType, it->rType, "+", "add");
roundingHelperWriter->writeCompoundAssignmentHelper(sink, it->lType, it->rType, "+", "add");
for (it = mEmulateCompoundSub.begin(); it != mEmulateCompoundSub.end(); it++)
writeCompoundAssignmentPrecisionEmulation(sink, outputLanguage, it->lType, it->rType, "-", "sub");
roundingHelperWriter->writeCompoundAssignmentHelper(sink, it->lType, it->rType, "-", "sub");
for (it = mEmulateCompoundDiv.begin(); it != mEmulateCompoundDiv.end(); it++)
writeCompoundAssignmentPrecisionEmulation(sink, outputLanguage, it->lType, it->rType, "/", "div");
roundingHelperWriter->writeCompoundAssignmentHelper(sink, it->lType, it->rType, "/", "div");
for (it = mEmulateCompoundMul.begin(); it != mEmulateCompoundMul.end(); it++)
writeCompoundAssignmentPrecisionEmulation(sink, outputLanguage, it->lType, it->rType, "*", "mul");
roundingHelperWriter->writeCompoundAssignmentHelper(sink, it->lType, it->rType, "*", "mul");
}
......@@ -1677,6 +1677,12 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node)
out << DisambiguateFunctionName(node->getSequence());
out << (lod0 ? "Lod0(" : "(");
}
else if (node->getNameObj().isInternal())
{
// This path is used for internal functions that don't have their definitions in the
// AST, such as precision emulation functions.
out << DecorateFunctionIfNeeded(node->getNameObj()) << "(";
}
else
{
TString name = TFunction::unmangleName(node->getNameObj().getString());
......
......@@ -7,6 +7,7 @@
#include "compiler/translator/TranslatorHLSL.h"
#include "compiler/translator/ArrayReturnValueToOutParameter.h"
#include "compiler/translator/EmulatePrecision.h"
#include "compiler/translator/OutputHLSL.h"
#include "compiler/translator/RemoveDynamicIndexing.h"
#include "compiler/translator/RewriteElseBlocks.h"
......@@ -52,6 +53,18 @@ void TranslatorHLSL::translate(TIntermNode *root, int compileOptions)
sh::RewriteElseBlocks(root, getTemporaryIndex());
}
bool precisionEmulation =
getResources().WEBGL_debug_shader_precision && getPragma().debugShaderPrecision;
if (precisionEmulation)
{
EmulatePrecision emulatePrecision(getSymbolTable(), getShaderVersion());
root->traverse(&emulatePrecision);
emulatePrecision.updateTree();
emulatePrecision.writeEmulationHelpers(getInfoSink().obj, getShaderVersion(),
getOutputType());
}
sh::OutputHLSL outputHLSL(getShaderType(), getShaderVersion(), getExtensionBehavior(),
getSourcePath(), getOutputType(), numRenderTargets, getUniforms(), compileOptions);
......
......@@ -25,6 +25,7 @@ test("angle_unittests") {
if (angle_enable_hlsl) {
sources +=
rebase_path(unittests_gypi.angle_unittests_hlsl_sources, ".", "../..")
defines = [ "ANGLE_ENABLE_HLSL" ]
}
sources += [ "//gpu/angle_unittest_main.cc" ]
......
......@@ -136,6 +136,10 @@
['OS=="win"',
{
# TODO(cwallez): make this angle_enable_hlsl instead (requires gyp file refactoring)
'defines':
[
'ANGLE_ENABLE_HLSL',
],
'sources':
[
'<@(angle_unittests_hlsl_sources)',
......
......@@ -18,8 +18,26 @@ class DebugShaderPrecisionTest : public MatchOutputCodeTest
DebugShaderPrecisionTest() : MatchOutputCodeTest(GL_FRAGMENT_SHADER, 0, SH_ESSL_OUTPUT)
{
addOutputType(SH_GLSL_COMPATIBILITY_OUTPUT);
#if defined(ANGLE_ENABLE_HLSL)
addOutputType(SH_HLSL_4_1_OUTPUT);
#endif
getResources()->WEBGL_debug_shader_precision = 1;
}
protected:
bool foundInAllGLSLCode(const char *str)
{
return foundInCode(SH_GLSL_COMPATIBILITY_OUTPUT, str) && foundInCode(SH_ESSL_OUTPUT, str);
}
bool foundInHLSLCode(const char *stringToFind) const
{
#if defined(ANGLE_ENABLE_HLSL)
return foundInCode(SH_HLSL_4_1_OUTPUT, stringToFind);
#else
return true;
#endif
}
};
class NoDebugShaderPrecisionTest : public MatchOutputCodeTest
......@@ -72,6 +90,22 @@ TEST_F(DebugShaderPrecisionTest, RoundingFunctionsDefined)
ASSERT_TRUE(foundInGLSLCode("mat3 angle_frl(in mat3"));
ASSERT_TRUE(foundInGLSLCode("mat4 angle_frl(in mat4"));
ASSERT_TRUE(foundInHLSLCode("float1 angle_frm(float1"));
ASSERT_TRUE(foundInHLSLCode("float2 angle_frm(float2"));
ASSERT_TRUE(foundInHLSLCode("float3 angle_frm(float3"));
ASSERT_TRUE(foundInHLSLCode("float4 angle_frm(float4"));
ASSERT_TRUE(foundInHLSLCode("float2x2 angle_frm(float2x2"));
ASSERT_TRUE(foundInHLSLCode("float3x3 angle_frm(float3x3"));
ASSERT_TRUE(foundInHLSLCode("float4x4 angle_frm(float4x4"));
ASSERT_TRUE(foundInHLSLCode("float1 angle_frl(float1"));
ASSERT_TRUE(foundInHLSLCode("float2 angle_frl(float2"));
ASSERT_TRUE(foundInHLSLCode("float3 angle_frl(float3"));
ASSERT_TRUE(foundInHLSLCode("float4 angle_frl(float4"));
ASSERT_TRUE(foundInHLSLCode("float2x2 angle_frl(float2x2"));
ASSERT_TRUE(foundInHLSLCode("float3x3 angle_frl(float3x3"));
ASSERT_TRUE(foundInHLSLCode("float4x4 angle_frl(float4x4"));
// Check that ESSL 3.00 rounding functions for non-square matrices are not defined.
ASSERT_TRUE(notFoundInCode("mat2x"));
ASSERT_TRUE(notFoundInCode("mat3x"));
......@@ -117,6 +151,20 @@ TEST_F(DebugShaderPrecisionTest, NonSquareMatrixRoundingFunctionsDefinedES3)
ASSERT_TRUE(foundInGLSLCode("mat3x4 angle_frl(in mat3x4"));
ASSERT_TRUE(foundInGLSLCode("mat4x2 angle_frl(in mat4x2"));
ASSERT_TRUE(foundInGLSLCode("mat4x3 angle_frl(in mat4x3"));
ASSERT_TRUE(foundInHLSLCode("float2x3 angle_frm(float2x3"));
ASSERT_TRUE(foundInHLSLCode("float2x4 angle_frm(float2x4"));
ASSERT_TRUE(foundInHLSLCode("float3x2 angle_frm(float3x2"));
ASSERT_TRUE(foundInHLSLCode("float3x4 angle_frm(float3x4"));
ASSERT_TRUE(foundInHLSLCode("float4x2 angle_frm(float4x2"));
ASSERT_TRUE(foundInHLSLCode("float4x3 angle_frm(float4x3"));
ASSERT_TRUE(foundInHLSLCode("float2x3 angle_frl(float2x3"));
ASSERT_TRUE(foundInHLSLCode("float2x4 angle_frl(float2x4"));
ASSERT_TRUE(foundInHLSLCode("float3x2 angle_frl(float3x2"));
ASSERT_TRUE(foundInHLSLCode("float3x4 angle_frl(float3x4"));
ASSERT_TRUE(foundInHLSLCode("float4x2 angle_frl(float4x2"));
ASSERT_TRUE(foundInHLSLCode("float4x3 angle_frl(float4x3"));
}
TEST_F(DebugShaderPrecisionTest, PragmaDisablesEmulation)
......@@ -203,6 +251,7 @@ TEST_F(DebugShaderPrecisionTest, DeclarationsAndConstants)
ASSERT_TRUE(notFoundInCode("angle_frm(aa"));
}
// Test that expressions that are part of initialization have rounding.
TEST_F(DebugShaderPrecisionTest, InitializerRounding)
{
const std::string &shaderString =
......@@ -214,9 +263,11 @@ TEST_F(DebugShaderPrecisionTest, InitializerRounding)
"}\n";
compile(shaderString);
// An expression that's part of initialization should have rounding
ASSERT_TRUE(foundInCode("angle_frm(u)"));
ASSERT_TRUE(foundInAllGLSLCode("angle_frm(u)"));
ASSERT_TRUE(foundInHLSLCode("angle_frm(_u)"));
}
// Test that compound additions have rounding in the GLSL translations.
TEST_F(DebugShaderPrecisionTest, CompoundAddFunction)
{
const std::string &shaderString =
......@@ -237,7 +288,11 @@ TEST_F(DebugShaderPrecisionTest, CompoundAddFunction)
"vec4 angle_compound_add_frm(inout vec4 x, in vec4 y) {\n"
" x = angle_frm(angle_frm(x) + y);"
));
ASSERT_TRUE(foundInCode("angle_compound_add_frm(v, angle_frm(u2));"));
ASSERT_TRUE(
foundInHLSLCode("float4 angle_compound_add_frm(inout float4 x, in float4 y) {\n"
" x = angle_frm(angle_frm(x) + y);"));
ASSERT_TRUE(foundInAllGLSLCode("angle_compound_add_frm(v, angle_frm(u2));"));
ASSERT_TRUE(foundInHLSLCode("angle_compound_add_frm(_v, angle_frm(_u2));"));
ASSERT_TRUE(notFoundInCode("+="));
}
......@@ -261,7 +316,11 @@ TEST_F(DebugShaderPrecisionTest, CompoundSubFunction)
"vec4 angle_compound_sub_frm(inout vec4 x, in vec4 y) {\n"
" x = angle_frm(angle_frm(x) - y);"
));
ASSERT_TRUE(foundInCode("angle_compound_sub_frm(v, angle_frm(u2));"));
ASSERT_TRUE(
foundInHLSLCode("float4 angle_compound_sub_frm(inout float4 x, in float4 y) {\n"
" x = angle_frm(angle_frm(x) - y);"));
ASSERT_TRUE(foundInAllGLSLCode("angle_compound_sub_frm(v, angle_frm(u2));"));
ASSERT_TRUE(foundInHLSLCode("angle_compound_sub_frm(_v, angle_frm(_u2));"));
ASSERT_TRUE(notFoundInCode("-="));
}
......@@ -285,7 +344,11 @@ TEST_F(DebugShaderPrecisionTest, CompoundDivFunction)
"vec4 angle_compound_div_frm(inout vec4 x, in vec4 y) {\n"
" x = angle_frm(angle_frm(x) / y);"
));
ASSERT_TRUE(foundInCode("angle_compound_div_frm(v, angle_frm(u2));"));
ASSERT_TRUE(
foundInHLSLCode("float4 angle_compound_div_frm(inout float4 x, in float4 y) {\n"
" x = angle_frm(angle_frm(x) / y);"));
ASSERT_TRUE(foundInAllGLSLCode("angle_compound_div_frm(v, angle_frm(u2));"));
ASSERT_TRUE(foundInHLSLCode("angle_compound_div_frm(_v, angle_frm(_u2));"));
ASSERT_TRUE(notFoundInCode("/="));
}
......@@ -309,7 +372,11 @@ TEST_F(DebugShaderPrecisionTest, CompoundMulFunction)
"vec4 angle_compound_mul_frm(inout vec4 x, in vec4 y) {\n"
" x = angle_frm(angle_frm(x) * y);"
));
ASSERT_TRUE(foundInCode("angle_compound_mul_frm(v, angle_frm(u2));"));
ASSERT_TRUE(
foundInHLSLCode("float4 angle_compound_mul_frm(inout float4 x, in float4 y) {\n"
" x = angle_frm(angle_frm(x) * y);"));
ASSERT_TRUE(foundInAllGLSLCode("angle_compound_mul_frm(v, angle_frm(u2));"));
ASSERT_TRUE(foundInHLSLCode("angle_compound_mul_frm(_v, angle_frm(_u2));"));
ASSERT_TRUE(notFoundInCode("*="));
}
......@@ -333,7 +400,11 @@ TEST_F(DebugShaderPrecisionTest, CompoundAddVectorPlusScalarFunction)
"vec4 angle_compound_add_frm(inout vec4 x, in float y) {\n"
" x = angle_frm(angle_frm(x) + y);"
));
ASSERT_TRUE(foundInCode("angle_compound_add_frm(v, angle_frm(u2));"));
ASSERT_TRUE(
foundInHLSLCode("float4 angle_compound_add_frm(inout float4 x, in float y) {\n"
" x = angle_frm(angle_frm(x) + y);"));
ASSERT_TRUE(foundInAllGLSLCode("angle_compound_add_frm(v, angle_frm(u2));"));
ASSERT_TRUE(foundInHLSLCode("angle_compound_add_frm(_v, angle_frm(_u2));"));
ASSERT_TRUE(notFoundInCode("+="));
}
......@@ -357,7 +428,11 @@ TEST_F(DebugShaderPrecisionTest, CompoundMatrixTimesMatrixFunction)
"mat4 angle_compound_mul_frm(inout mat4 x, in mat4 y) {\n"
" x = angle_frm(angle_frm(x) * y);"
));
ASSERT_TRUE(foundInCode("angle_compound_mul_frm(m, angle_frm(u2));"));
ASSERT_TRUE(
foundInHLSLCode("float4x4 angle_compound_mul_frm(inout float4x4 x, in float4x4 y) {\n"
" x = angle_frm(angle_frm(x) * y);"));
ASSERT_TRUE(foundInAllGLSLCode("angle_compound_mul_frm(m, angle_frm(u2));"));
ASSERT_TRUE(foundInHLSLCode("angle_compound_mul_frm(_m, angle_frm(_u2));"));
ASSERT_TRUE(notFoundInCode("*="));
}
......@@ -383,7 +458,11 @@ TEST_F(DebugShaderPrecisionTest, CompoundNonSquareMatrixTimesMatrixFunction)
ASSERT_TRUE(
foundInGLSLCode("mat2x4 angle_compound_mul_frm(inout mat2x4 x, in mat2 y) {\n"
" x = angle_frm(angle_frm(x) * y);"));
ASSERT_TRUE(foundInCode("angle_compound_mul_frm(m, angle_frm(u2));"));
ASSERT_TRUE(
foundInHLSLCode("float2x4 angle_compound_mul_frm(inout float2x4 x, in float2x2 y) {\n"
" x = angle_frm(angle_frm(x) * y);"));
ASSERT_TRUE(foundInAllGLSLCode("angle_compound_mul_frm(m, angle_frm(u2));"));
ASSERT_TRUE(foundInHLSLCode("angle_compound_mul_frm(_m, angle_frm(_u2));"));
ASSERT_TRUE(notFoundInCode("*="));
}
......@@ -407,7 +486,11 @@ TEST_F(DebugShaderPrecisionTest, CompoundMatrixTimesScalarFunction)
"mat4 angle_compound_mul_frm(inout mat4 x, in float y) {\n"
" x = angle_frm(angle_frm(x) * y);"
));
ASSERT_TRUE(foundInCode("angle_compound_mul_frm(m, angle_frm(u2));"));
ASSERT_TRUE(
foundInHLSLCode("float4x4 angle_compound_mul_frm(inout float4x4 x, in float y) {\n"
" x = angle_frm(angle_frm(x) * y);"));
ASSERT_TRUE(foundInAllGLSLCode("angle_compound_mul_frm(m, angle_frm(u2));"));
ASSERT_TRUE(foundInHLSLCode("angle_compound_mul_frm(_m, angle_frm(_u2));"));
ASSERT_TRUE(notFoundInCode("*="));
}
......@@ -430,7 +513,11 @@ TEST_F(DebugShaderPrecisionTest, CompoundVectorTimesMatrixFunction)
ASSERT_TRUE(foundInGLSLCode("vec4 angle_compound_mul_frm(inout vec4 x, in mat4 y) {\n"
" x = angle_frm(angle_frm(x) * y);"
));
ASSERT_TRUE(foundInCode("angle_compound_mul_frm(v, angle_frm(u2));"));
ASSERT_TRUE(
foundInHLSLCode("float4 angle_compound_mul_frm(inout float4 x, in float4x4 y) {\n"
" x = angle_frm(angle_frm(x) * y);"));
ASSERT_TRUE(foundInAllGLSLCode("angle_compound_mul_frm(v, angle_frm(u2));"));
ASSERT_TRUE(foundInHLSLCode("angle_compound_mul_frm(_v, angle_frm(_u2));"));
ASSERT_TRUE(notFoundInCode("*="));
}
......@@ -454,7 +541,11 @@ TEST_F(DebugShaderPrecisionTest, CompoundVectorTimesScalarFunction)
"vec4 angle_compound_mul_frm(inout vec4 x, in float y) {\n"
" x = angle_frm(angle_frm(x) * y);"
));
ASSERT_TRUE(foundInCode("angle_compound_mul_frm(v, angle_frm(u2));"));
ASSERT_TRUE(
foundInHLSLCode("float4 angle_compound_mul_frm(inout float4 x, in float y) {\n"
" x = angle_frm(angle_frm(x) * y);"));
ASSERT_TRUE(foundInAllGLSLCode("angle_compound_mul_frm(v, angle_frm(u2));"));
ASSERT_TRUE(foundInHLSLCode("angle_compound_mul_frm(_v, angle_frm(_u2));"));
ASSERT_TRUE(notFoundInCode("*="));
}
......@@ -477,11 +568,17 @@ TEST_F(DebugShaderPrecisionTest, BinaryMathRounding)
" gl_FragColor = v1 + v2 + v3 + v4;\n"
"}\n";
compile(shaderString);
ASSERT_TRUE(foundInCode("v1 = angle_frm((angle_frm(u1) + angle_frm(u2)))"));
ASSERT_TRUE(foundInCode("v2 = angle_frm((angle_frm(u2) - angle_frm(u3)))"));
ASSERT_TRUE(foundInCode("v3 = angle_frm((angle_frm(u3) * angle_frm(u4)))"));
ASSERT_TRUE(foundInCode("v4 = angle_frm((angle_frm(u4) / angle_frm(u5)))"));
ASSERT_TRUE(foundInCode("v6 = angle_frm((v5 = angle_frm(u5)))"));
ASSERT_TRUE(foundInAllGLSLCode("v1 = angle_frm((angle_frm(u1) + angle_frm(u2)))"));
ASSERT_TRUE(foundInAllGLSLCode("v2 = angle_frm((angle_frm(u2) - angle_frm(u3)))"));
ASSERT_TRUE(foundInAllGLSLCode("v3 = angle_frm((angle_frm(u3) * angle_frm(u4)))"));
ASSERT_TRUE(foundInAllGLSLCode("v4 = angle_frm((angle_frm(u4) / angle_frm(u5)))"));
ASSERT_TRUE(foundInAllGLSLCode("v6 = angle_frm((v5 = angle_frm(u5)))"));
ASSERT_TRUE(foundInHLSLCode("v1 = angle_frm((angle_frm(_u1) + angle_frm(_u2)))"));
ASSERT_TRUE(foundInHLSLCode("v2 = angle_frm((angle_frm(_u2) - angle_frm(_u3)))"));
ASSERT_TRUE(foundInHLSLCode("v3 = angle_frm((angle_frm(_u3) * angle_frm(_u4)))"));
ASSERT_TRUE(foundInHLSLCode("v4 = angle_frm((angle_frm(_u4) / angle_frm(_u5)))"));
ASSERT_TRUE(foundInHLSLCode("v6 = angle_frm((_v5 = angle_frm(_u5)))"));
}
TEST_F(DebugShaderPrecisionTest, BuiltInMathFunctionRounding)
......@@ -551,51 +648,114 @@ TEST_F(DebugShaderPrecisionTest, BuiltInMathFunctionRounding)
"vec4(f1, f2, f3, 0.0) + vec4(vf31, 0.0) + m1[0];\n"
"}\n";
compile(shaderString);
ASSERT_TRUE(foundInCode("v1 = angle_frm(radians(angle_frm(u1)))"));
ASSERT_TRUE(foundInCode("v2 = angle_frm(degrees(angle_frm(u1)))"));
ASSERT_TRUE(foundInCode("v3 = angle_frm(sin(angle_frm(u1)))"));
ASSERT_TRUE(foundInCode("v4 = angle_frm(cos(angle_frm(u1)))"));
ASSERT_TRUE(foundInCode("v5 = angle_frm(tan(angle_frm(u1)))"));
ASSERT_TRUE(foundInCode("v6 = angle_frm(asin(angle_frm(u1)))"));
ASSERT_TRUE(foundInCode("v7 = angle_frm(acos(angle_frm(u1)))"));
ASSERT_TRUE(foundInCode("v8 = angle_frm(atan(angle_frm(u1)))"));
ASSERT_TRUE(foundInCode("v9 = angle_frm(atan(angle_frm(u1), angle_frm(u2)))"));
ASSERT_TRUE(foundInCode("v10 = angle_frm(pow(angle_frm(u1), angle_frm(u2)))"));
ASSERT_TRUE(foundInCode("v11 = angle_frm(exp(angle_frm(u1)))"));
ASSERT_TRUE(foundInCode("v12 = angle_frm(log(angle_frm(u1)))"));
ASSERT_TRUE(foundInCode("v13 = angle_frm(exp2(angle_frm(u1)))"));
ASSERT_TRUE(foundInCode("v14 = angle_frm(log2(angle_frm(u1)))"));
ASSERT_TRUE(foundInCode("v15 = angle_frm(sqrt(angle_frm(u1)))"));
ASSERT_TRUE(foundInCode("v16 = angle_frm(inversesqrt(angle_frm(u1)))"));
ASSERT_TRUE(foundInCode("v17 = angle_frm(abs(angle_frm(u1)))"));
ASSERT_TRUE(foundInCode("v18 = angle_frm(sign(angle_frm(u1)))"));
ASSERT_TRUE(foundInCode("v19 = angle_frm(floor(angle_frm(u1)))"));
ASSERT_TRUE(foundInCode("v20 = angle_frm(ceil(angle_frm(u1)))"));
ASSERT_TRUE(foundInCode("v21 = angle_frm(fract(angle_frm(u1)))"));
ASSERT_TRUE(foundInCode("v22 = angle_frm(mod(angle_frm(u1), angle_frm(uf)))"));
ASSERT_TRUE(foundInCode("v23 = angle_frm(mod(angle_frm(u1), angle_frm(u2)))"));
ASSERT_TRUE(foundInCode("v24 = angle_frm(min(angle_frm(u1), angle_frm(uf)))"));
ASSERT_TRUE(foundInCode("v25 = angle_frm(min(angle_frm(u1), angle_frm(u2)))"));
ASSERT_TRUE(foundInCode("v26 = angle_frm(max(angle_frm(u1), angle_frm(uf)))"));
ASSERT_TRUE(foundInCode("v27 = angle_frm(max(angle_frm(u1), angle_frm(u2)))"));
ASSERT_TRUE(foundInCode("v28 = angle_frm(clamp(angle_frm(u1), angle_frm(u2), angle_frm(u3)))"));
ASSERT_TRUE(foundInCode("v29 = angle_frm(clamp(angle_frm(u1), angle_frm(uf), angle_frm(uf2)))"));
ASSERT_TRUE(foundInCode("v30 = angle_frm(mix(angle_frm(u1), angle_frm(u2), angle_frm(u3)))"));
ASSERT_TRUE(foundInCode("v31 = angle_frm(mix(angle_frm(u1), angle_frm(u2), angle_frm(uf)))"));
ASSERT_TRUE(foundInCode("v32 = angle_frm(step(angle_frm(u1), angle_frm(u2)))"));
ASSERT_TRUE(foundInCode("v33 = angle_frm(step(angle_frm(uf), angle_frm(u1)))"));
ASSERT_TRUE(foundInCode("v34 = angle_frm(smoothstep(angle_frm(u1), angle_frm(u2), angle_frm(u3)))"));
ASSERT_TRUE(foundInCode("v35 = angle_frm(smoothstep(angle_frm(uf), angle_frm(uf2), angle_frm(u1)))"));
ASSERT_TRUE(foundInCode("v36 = angle_frm(normalize(angle_frm(u1)))"));
ASSERT_TRUE(foundInCode("v37 = angle_frm(faceforward(angle_frm(u1), angle_frm(u2), angle_frm(u3)))"));
ASSERT_TRUE(foundInCode("v38 = angle_frm(reflect(angle_frm(u1), angle_frm(u2)))"));
ASSERT_TRUE(foundInCode("v39 = angle_frm(refract(angle_frm(u1), angle_frm(u2), angle_frm(uf)))"));
ASSERT_TRUE(foundInCode("f1 = angle_frm(length(angle_frm(u1)))"));
ASSERT_TRUE(foundInCode("f2 = angle_frm(distance(angle_frm(u1), angle_frm(u2)))"));
ASSERT_TRUE(foundInCode("f3 = angle_frm(dot(angle_frm(u1), angle_frm(u2)))"));
ASSERT_TRUE(foundInCode("vf31 = angle_frm(cross(angle_frm(uf31), angle_frm(uf32)))"));
ASSERT_TRUE(foundInCode("m1 = angle_frm(matrixCompMult(angle_frm(um1), angle_frm(um2)))"));
ASSERT_TRUE(foundInAllGLSLCode("v1 = angle_frm(radians(angle_frm(u1)))"));
ASSERT_TRUE(foundInAllGLSLCode("v2 = angle_frm(degrees(angle_frm(u1)))"));
ASSERT_TRUE(foundInAllGLSLCode("v3 = angle_frm(sin(angle_frm(u1)))"));
ASSERT_TRUE(foundInAllGLSLCode("v4 = angle_frm(cos(angle_frm(u1)))"));
ASSERT_TRUE(foundInAllGLSLCode("v5 = angle_frm(tan(angle_frm(u1)))"));
ASSERT_TRUE(foundInAllGLSLCode("v6 = angle_frm(asin(angle_frm(u1)))"));
ASSERT_TRUE(foundInAllGLSLCode("v7 = angle_frm(acos(angle_frm(u1)))"));
ASSERT_TRUE(foundInAllGLSLCode("v8 = angle_frm(atan(angle_frm(u1)))"));
ASSERT_TRUE(foundInAllGLSLCode("v9 = angle_frm(atan(angle_frm(u1), angle_frm(u2)))"));
ASSERT_TRUE(foundInAllGLSLCode("v10 = angle_frm(pow(angle_frm(u1), angle_frm(u2)))"));
ASSERT_TRUE(foundInAllGLSLCode("v11 = angle_frm(exp(angle_frm(u1)))"));
ASSERT_TRUE(foundInAllGLSLCode("v12 = angle_frm(log(angle_frm(u1)))"));
ASSERT_TRUE(foundInAllGLSLCode("v13 = angle_frm(exp2(angle_frm(u1)))"));
ASSERT_TRUE(foundInAllGLSLCode("v14 = angle_frm(log2(angle_frm(u1)))"));
ASSERT_TRUE(foundInAllGLSLCode("v15 = angle_frm(sqrt(angle_frm(u1)))"));
ASSERT_TRUE(foundInAllGLSLCode("v16 = angle_frm(inversesqrt(angle_frm(u1)))"));
ASSERT_TRUE(foundInAllGLSLCode("v17 = angle_frm(abs(angle_frm(u1)))"));
ASSERT_TRUE(foundInAllGLSLCode("v18 = angle_frm(sign(angle_frm(u1)))"));
ASSERT_TRUE(foundInAllGLSLCode("v19 = angle_frm(floor(angle_frm(u1)))"));
ASSERT_TRUE(foundInAllGLSLCode("v20 = angle_frm(ceil(angle_frm(u1)))"));
ASSERT_TRUE(foundInAllGLSLCode("v21 = angle_frm(fract(angle_frm(u1)))"));
ASSERT_TRUE(foundInAllGLSLCode("v22 = angle_frm(mod(angle_frm(u1), angle_frm(uf)))"));
ASSERT_TRUE(foundInAllGLSLCode("v23 = angle_frm(mod(angle_frm(u1), angle_frm(u2)))"));
ASSERT_TRUE(foundInAllGLSLCode("v24 = angle_frm(min(angle_frm(u1), angle_frm(uf)))"));
ASSERT_TRUE(foundInAllGLSLCode("v25 = angle_frm(min(angle_frm(u1), angle_frm(u2)))"));
ASSERT_TRUE(foundInAllGLSLCode("v26 = angle_frm(max(angle_frm(u1), angle_frm(uf)))"));
ASSERT_TRUE(foundInAllGLSLCode("v27 = angle_frm(max(angle_frm(u1), angle_frm(u2)))"));
ASSERT_TRUE(
foundInAllGLSLCode("v28 = angle_frm(clamp(angle_frm(u1), angle_frm(u2), angle_frm(u3)))"));
ASSERT_TRUE(
foundInAllGLSLCode("v29 = angle_frm(clamp(angle_frm(u1), angle_frm(uf), angle_frm(uf2)))"));
ASSERT_TRUE(
foundInAllGLSLCode("v30 = angle_frm(mix(angle_frm(u1), angle_frm(u2), angle_frm(u3)))"));
ASSERT_TRUE(
foundInAllGLSLCode("v31 = angle_frm(mix(angle_frm(u1), angle_frm(u2), angle_frm(uf)))"));
ASSERT_TRUE(foundInAllGLSLCode("v32 = angle_frm(step(angle_frm(u1), angle_frm(u2)))"));
ASSERT_TRUE(foundInAllGLSLCode("v33 = angle_frm(step(angle_frm(uf), angle_frm(u1)))"));
ASSERT_TRUE(foundInAllGLSLCode(
"v34 = angle_frm(smoothstep(angle_frm(u1), angle_frm(u2), angle_frm(u3)))"));
ASSERT_TRUE(foundInAllGLSLCode(
"v35 = angle_frm(smoothstep(angle_frm(uf), angle_frm(uf2), angle_frm(u1)))"));
ASSERT_TRUE(foundInAllGLSLCode("v36 = angle_frm(normalize(angle_frm(u1)))"));
ASSERT_TRUE(foundInAllGLSLCode(
"v37 = angle_frm(faceforward(angle_frm(u1), angle_frm(u2), angle_frm(u3)))"));
ASSERT_TRUE(foundInAllGLSLCode("v38 = angle_frm(reflect(angle_frm(u1), angle_frm(u2)))"));
ASSERT_TRUE(foundInAllGLSLCode(
"v39 = angle_frm(refract(angle_frm(u1), angle_frm(u2), angle_frm(uf)))"));
ASSERT_TRUE(foundInAllGLSLCode("f1 = angle_frm(length(angle_frm(u1)))"));
ASSERT_TRUE(foundInAllGLSLCode("f2 = angle_frm(distance(angle_frm(u1), angle_frm(u2)))"));
ASSERT_TRUE(foundInAllGLSLCode("f3 = angle_frm(dot(angle_frm(u1), angle_frm(u2)))"));
ASSERT_TRUE(foundInAllGLSLCode("vf31 = angle_frm(cross(angle_frm(uf31), angle_frm(uf32)))"));
ASSERT_TRUE(
foundInAllGLSLCode("m1 = angle_frm(matrixCompMult(angle_frm(um1), angle_frm(um2)))"));
ASSERT_TRUE(foundInHLSLCode("v1 = angle_frm(radians(angle_frm(_u1)))"));
ASSERT_TRUE(foundInHLSLCode("v2 = angle_frm(degrees(angle_frm(_u1)))"));
ASSERT_TRUE(foundInHLSLCode("v3 = angle_frm(sin(angle_frm(_u1)))"));
ASSERT_TRUE(foundInHLSLCode("v4 = angle_frm(cos(angle_frm(_u1)))"));
ASSERT_TRUE(foundInHLSLCode("v5 = angle_frm(tan(angle_frm(_u1)))"));
ASSERT_TRUE(foundInHLSLCode("v6 = angle_frm(asin(angle_frm(_u1)))"));
ASSERT_TRUE(foundInHLSLCode("v7 = angle_frm(acos(angle_frm(_u1)))"));
ASSERT_TRUE(foundInHLSLCode("v8 = angle_frm(atan(angle_frm(_u1)))"));
ASSERT_TRUE(foundInHLSLCode("v9 = angle_frm(webgl_atan_emu(angle_frm(_u1), angle_frm(_u2)))"));
ASSERT_TRUE(foundInHLSLCode("v10 = angle_frm(pow(angle_frm(_u1), angle_frm(_u2)))"));
ASSERT_TRUE(foundInHLSLCode("v11 = angle_frm(exp(angle_frm(_u1)))"));
ASSERT_TRUE(foundInHLSLCode("v12 = angle_frm(log(angle_frm(_u1)))"));
ASSERT_TRUE(foundInHLSLCode("v13 = angle_frm(exp2(angle_frm(_u1)))"));
ASSERT_TRUE(foundInHLSLCode("v14 = angle_frm(log2(angle_frm(_u1)))"));
ASSERT_TRUE(foundInHLSLCode("v15 = angle_frm(sqrt(angle_frm(_u1)))"));
ASSERT_TRUE(foundInHLSLCode("v16 = angle_frm(rsqrt(angle_frm(_u1)))"));
ASSERT_TRUE(foundInHLSLCode("v17 = angle_frm(abs(angle_frm(_u1)))"));
ASSERT_TRUE(foundInHLSLCode("v18 = angle_frm(sign(angle_frm(_u1)))"));
ASSERT_TRUE(foundInHLSLCode("v19 = angle_frm(floor(angle_frm(_u1)))"));
ASSERT_TRUE(foundInHLSLCode("v20 = angle_frm(ceil(angle_frm(_u1)))"));
ASSERT_TRUE(foundInHLSLCode("v21 = angle_frm(frac(angle_frm(_u1)))"));
ASSERT_TRUE(foundInHLSLCode("v22 = angle_frm(webgl_mod_emu(angle_frm(_u1), angle_frm(_uf)))"));
ASSERT_TRUE(foundInHLSLCode("v23 = angle_frm(webgl_mod_emu(angle_frm(_u1), angle_frm(_u2)))"));
ASSERT_TRUE(foundInHLSLCode("v24 = angle_frm(min(angle_frm(_u1), angle_frm(_uf)))"));
ASSERT_TRUE(foundInHLSLCode("v25 = angle_frm(min(angle_frm(_u1), angle_frm(_u2)))"));
ASSERT_TRUE(foundInHLSLCode("v26 = angle_frm(max(angle_frm(_u1), angle_frm(_uf)))"));
ASSERT_TRUE(foundInHLSLCode("v27 = angle_frm(max(angle_frm(_u1), angle_frm(_u2)))"));
ASSERT_TRUE(
foundInHLSLCode("v28 = angle_frm(clamp(angle_frm(_u1), angle_frm(_u2), angle_frm(_u3)))"));
ASSERT_TRUE(
foundInHLSLCode("v29 = angle_frm(clamp(angle_frm(_u1), angle_frm(_uf), angle_frm(_uf2)))"));
ASSERT_TRUE(
foundInHLSLCode("v30 = angle_frm(lerp(angle_frm(_u1), angle_frm(_u2), angle_frm(_u3)))"));
ASSERT_TRUE(
foundInHLSLCode("v31 = angle_frm(lerp(angle_frm(_u1), angle_frm(_u2), angle_frm(_uf)))"));
ASSERT_TRUE(foundInHLSLCode("v32 = angle_frm(step(angle_frm(_u1), angle_frm(_u2)))"));
ASSERT_TRUE(foundInHLSLCode("v33 = angle_frm(step(angle_frm(_uf), angle_frm(_u1)))"));
ASSERT_TRUE(foundInHLSLCode(
"v34 = angle_frm(smoothstep(angle_frm(_u1), angle_frm(_u2), angle_frm(_u3)))"));
ASSERT_TRUE(foundInHLSLCode(
"v35 = angle_frm(smoothstep(angle_frm(_uf), angle_frm(_uf2), angle_frm(_u1)))"));
ASSERT_TRUE(foundInHLSLCode("v36 = angle_frm(normalize(angle_frm(_u1)))"));
ASSERT_TRUE(foundInHLSLCode(
"v37 = angle_frm(webgl_faceforward_emu(angle_frm(_u1), angle_frm(_u2), angle_frm(_u3)))"));
ASSERT_TRUE(foundInHLSLCode("v38 = angle_frm(reflect(angle_frm(_u1), angle_frm(_u2)))"));
ASSERT_TRUE(foundInHLSLCode(
"v39 = angle_frm(refract(angle_frm(_u1), angle_frm(_u2), angle_frm(_uf)))"));
ASSERT_TRUE(foundInHLSLCode("f1 = angle_frm(length(angle_frm(_u1)))"));
ASSERT_TRUE(foundInHLSLCode("f2 = angle_frm(distance(angle_frm(_u1), angle_frm(_u2)))"));
ASSERT_TRUE(foundInHLSLCode("f3 = angle_frm(dot(angle_frm(_u1), angle_frm(_u2)))"));
ASSERT_TRUE(foundInHLSLCode("vf31 = angle_frm(cross(angle_frm(_uf31), angle_frm(_uf32)))"));
ASSERT_TRUE(foundInHLSLCode("m1 = angle_frm((angle_frm(_um1) * angle_frm(_um2)))"));
}
TEST_F(DebugShaderPrecisionTest, BuiltInRelationalFunctionRounding)
......@@ -614,12 +774,19 @@ TEST_F(DebugShaderPrecisionTest, BuiltInRelationalFunctionRounding)
" gl_FragColor = vec4(bv1) + vec4(bv2) + vec4(bv3) + vec4(bv4) + vec4(bv5) + vec4(bv6);\n"
"}\n";
compile(shaderString);
ASSERT_TRUE(foundInCode("bv1 = lessThan(angle_frm(u1), angle_frm(u2))"));
ASSERT_TRUE(foundInCode("bv2 = lessThanEqual(angle_frm(u1), angle_frm(u2))"));
ASSERT_TRUE(foundInCode("bv3 = greaterThan(angle_frm(u1), angle_frm(u2))"));
ASSERT_TRUE(foundInCode("bv4 = greaterThanEqual(angle_frm(u1), angle_frm(u2))"));
ASSERT_TRUE(foundInCode("bv5 = equal(angle_frm(u1), angle_frm(u2))"));
ASSERT_TRUE(foundInCode("bv6 = notEqual(angle_frm(u1), angle_frm(u2))"));
ASSERT_TRUE(foundInAllGLSLCode("bv1 = lessThan(angle_frm(u1), angle_frm(u2))"));
ASSERT_TRUE(foundInAllGLSLCode("bv2 = lessThanEqual(angle_frm(u1), angle_frm(u2))"));
ASSERT_TRUE(foundInAllGLSLCode("bv3 = greaterThan(angle_frm(u1), angle_frm(u2))"));
ASSERT_TRUE(foundInAllGLSLCode("bv4 = greaterThanEqual(angle_frm(u1), angle_frm(u2))"));
ASSERT_TRUE(foundInAllGLSLCode("bv5 = equal(angle_frm(u1), angle_frm(u2))"));
ASSERT_TRUE(foundInAllGLSLCode("bv6 = notEqual(angle_frm(u1), angle_frm(u2))"));
ASSERT_TRUE(foundInHLSLCode("bv1 = (angle_frm(_u1) < angle_frm(_u2))"));
ASSERT_TRUE(foundInHLSLCode("bv2 = (angle_frm(_u1) <= angle_frm(_u2))"));
ASSERT_TRUE(foundInHLSLCode("bv3 = (angle_frm(_u1) > angle_frm(_u2))"));
ASSERT_TRUE(foundInHLSLCode("bv4 = (angle_frm(_u1) >= angle_frm(_u2))"));
ASSERT_TRUE(foundInHLSLCode("bv5 = (angle_frm(_u1) == angle_frm(_u2))"));
ASSERT_TRUE(foundInHLSLCode("bv6 = (angle_frm(_u1) != angle_frm(_u2))"));
}
TEST_F(DebugShaderPrecisionTest, ConstructorRounding)
......@@ -639,8 +806,13 @@ TEST_F(DebugShaderPrecisionTest, ConstructorRounding)
"}\n";
compile(shaderString);
// Note: this is suboptimal for the case taking four floats, but optimizing would be tricky.
ASSERT_TRUE(foundInCode("v1 = angle_frm(vec4(angle_frm(u1), angle_frm(u2), angle_frm(u3), angle_frm(u4)))"));
ASSERT_TRUE(foundInCode("v2 = angle_frm(vec4(uiv))"));
ASSERT_TRUE(foundInAllGLSLCode(
"v1 = angle_frm(vec4(angle_frm(u1), angle_frm(u2), angle_frm(u3), angle_frm(u4)))"));
ASSERT_TRUE(foundInAllGLSLCode("v2 = angle_frm(vec4(uiv))"));
ASSERT_TRUE(foundInHLSLCode(
"v1 = angle_frm(vec4(angle_frm(_u1), angle_frm(_u2), angle_frm(_u3), angle_frm(_u4)))"));
ASSERT_TRUE(foundInHLSLCode("v2 = angle_frm(vec4(_uiv))"));
}
TEST_F(DebugShaderPrecisionTest, StructConstructorNoRounding)
......@@ -654,7 +826,8 @@ TEST_F(DebugShaderPrecisionTest, StructConstructorNoRounding)
" gl_FragColor = s.a;\n"
"}\n";
compile(shaderString);
ASSERT_TRUE(foundInCode("s = S(angle_frm(u))"));
ASSERT_TRUE(foundInAllGLSLCode("s = S(angle_frm(u))"));
ASSERT_TRUE(foundInHLSLCode("s = _S_ctor(angle_frm(_u))"));
ASSERT_TRUE(notFoundInCode("angle_frm(S"));
}
......@@ -668,7 +841,8 @@ TEST_F(DebugShaderPrecisionTest, SwizzleRounding)
" gl_FragColor = v;\n"
"}\n";
compile(shaderString);
ASSERT_TRUE(foundInCode("v = angle_frm(u).xyxy"));
ASSERT_TRUE(foundInAllGLSLCode("v = angle_frm(u).xyxy"));
ASSERT_TRUE(foundInHLSLCode("v = angle_frm(_u).xyxy"));
}
TEST_F(DebugShaderPrecisionTest, BuiltInTexFunctionRounding)
......@@ -683,7 +857,8 @@ TEST_F(DebugShaderPrecisionTest, BuiltInTexFunctionRounding)
" gl_FragColor = v;\n"
"}\n";
compile(shaderString);
ASSERT_TRUE(foundInCode("v = angle_frl(texture2D(s, angle_frm(u)))"));
ASSERT_TRUE(foundInAllGLSLCode("v = angle_frl(texture2D(s, angle_frm(u)))"));
ASSERT_TRUE(foundInHLSLCode("v = angle_frl(gl_texture2D(_s, angle_frm(_u)))"));
}
TEST_F(DebugShaderPrecisionTest, FunctionCallParameterQualifiersFromDefinition)
......@@ -717,11 +892,15 @@ TEST_F(DebugShaderPrecisionTest, FunctionCallParameterQualifiersFromDefinition)
// are nested within function calls would be tricky if to get right
// otherwise.
// Test in parameters
ASSERT_TRUE(foundInCode("v = add(angle_frm(u1), angle_frm(u2))"));
ASSERT_TRUE(foundInAllGLSLCode("v = add(angle_frm(u1), angle_frm(u2))"));
ASSERT_TRUE(foundInHLSLCode("v = _add_float4_float4(angle_frm(_u1), angle_frm(_u2))"));
// Test inout parameter
ASSERT_TRUE(foundInCode("compound_add(v, angle_frm(u3))"));
ASSERT_TRUE(foundInAllGLSLCode("compound_add(v, angle_frm(u3))"));
ASSERT_TRUE(foundInHLSLCode("compound_add_float4_float4(_v, angle_frm(_u3))"));
// Test out parameter
ASSERT_TRUE(foundInCode("add_to_last(angle_frm(u4), angle_frm(u5), v2)"));
ASSERT_TRUE(foundInAllGLSLCode("add_to_last(angle_frm(u4), angle_frm(u5), v2)"));
ASSERT_TRUE(
foundInHLSLCode("add_to_last_float4_float4_float4(angle_frm(_u4), angle_frm(_u5), _v2)"));
}
TEST_F(DebugShaderPrecisionTest, FunctionCallParameterQualifiersFromPrototype)
......@@ -754,11 +933,15 @@ TEST_F(DebugShaderPrecisionTest, FunctionCallParameterQualifiersFromPrototype)
"}\n";
compile(shaderString);
// Test in parameters
ASSERT_TRUE(foundInCode("v = add(angle_frm(u1), angle_frm(u2))"));
ASSERT_TRUE(foundInAllGLSLCode("v = add(angle_frm(u1), angle_frm(u2))"));
ASSERT_TRUE(foundInHLSLCode("v = _add_float4_float4(angle_frm(_u1), angle_frm(_u2))"));
// Test inout parameter
ASSERT_TRUE(foundInCode("compound_add(v, angle_frm(u3))"));
ASSERT_TRUE(foundInAllGLSLCode("compound_add(v, angle_frm(u3))"));
ASSERT_TRUE(foundInHLSLCode("compound_add_float4_float4(_v, angle_frm(_u3))"));
// Test out parameter
ASSERT_TRUE(foundInCode("add_to_last(angle_frm(u4), angle_frm(u5), v2)"));
ASSERT_TRUE(foundInAllGLSLCode("add_to_last(angle_frm(u4), angle_frm(u5), v2)"));
ASSERT_TRUE(
foundInHLSLCode("add_to_last_float4_float4_float4(angle_frm(_u4), angle_frm(_u5), _v2)"));
}
TEST_F(DebugShaderPrecisionTest, NestedFunctionCalls)
......@@ -782,7 +965,11 @@ TEST_F(DebugShaderPrecisionTest, NestedFunctionCalls)
"}\n";
compile(shaderString);
// Test nested calls
ASSERT_TRUE(foundInCode("v2 = add(compound_add(v, angle_frm(u2)), angle_frm(fract(angle_frm(u3))))"));
ASSERT_TRUE(foundInAllGLSLCode(
"v2 = add(compound_add(v, angle_frm(u2)), angle_frm(fract(angle_frm(u3))))"));
ASSERT_TRUE(
foundInHLSLCode("v2 = _add_float4_float4(_compound_add_float4_float4(_v, angle_frm(_u2)), "
"angle_frm(frac(angle_frm(_u3))))"));
}
// Test that code inside an index of a function out parameter gets processed.
......@@ -798,7 +985,8 @@ TEST_F(DebugShaderPrecisionTest, OpInIndexOfFunctionOutParameter)
" gl_FragColor = v[0];\n"
"}\n";
compile(shaderString);
ASSERT_TRUE(foundInCode("angle_frm(exp2(angle_frm(u2)))"));
ASSERT_TRUE(foundInAllGLSLCode("angle_frm(exp2(angle_frm(u2)))"));
ASSERT_TRUE(foundInHLSLCode("angle_frm(exp2(angle_frm(_u2)))"));
}
// Test that code inside an index of an l-value gets processed.
......@@ -814,7 +1002,8 @@ TEST_F(DebugShaderPrecisionTest, OpInIndexOfLValue)
" gl_FragColor = v[0];\n"
"}\n";
compile(shaderString);
ASSERT_TRUE(foundInCode("angle_frm(exp2(angle_frm(u2)))"));
ASSERT_TRUE(foundInAllGLSLCode("angle_frm(exp2(angle_frm(u2)))"));
ASSERT_TRUE(foundInHLSLCode("angle_frm(exp2(angle_frm(_u2)))"));
}
// Test that the out parameter of modf doesn't get rounded
......@@ -831,5 +1020,6 @@ TEST_F(DebugShaderPrecisionTest, ModfOutParameter)
" my_FragColor = vec4(f, o, 0, 1);\n"
"}\n";
compile(shaderString);
ASSERT_TRUE(foundInCode("modf(angle_frm(u), o)"));
ASSERT_TRUE(foundInAllGLSLCode("modf(angle_frm(u), o)"));
ASSERT_TRUE(foundInHLSLCode("modf(angle_frm(_u), _o)"));
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment