Commit 61b81acf by Olli Etuaho Committed by Commit Bot

Support non-square matrices in precision emulation

In case the shader version is greater than ESSL 1.00, the precision emulation needs to output rounding functions for non-square matrix types. Writing emulated compound assignment functions for non-square matrices already had most of the code in place before this change. New compound assignment operators like >>= don't need floating point precision emulation in ESSL 3.00, since all of them only operate on integers. BUG=angleproject:1434 TEST=angle_unittests Change-Id: I4678f511edf4f9f744fe23bb8d7dab4387f07f20 Reviewed-on: https://chromium-review.googlesource.com/358472Reviewed-by: 's avatarCorentin Wallez <cwallez@chromium.org> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Commit-Queue: Olli Etuaho <oetuaho@nvidia.com>
parent 5695fc99
......@@ -9,8 +9,9 @@
namespace
{
static void writeVectorPrecisionEmulationHelpers(
TInfoSinkBase& sink, ShShaderOutput outputLanguage, unsigned int size)
static void writeVectorPrecisionEmulationHelpers(TInfoSinkBase &sink,
const ShShaderOutput outputLanguage,
const unsigned int size)
{
std::stringstream vecTypeStrStr;
if (outputLanguage == SH_ESSL_OUTPUT)
......@@ -37,19 +38,27 @@ static void writeVectorPrecisionEmulationHelpers(
"}\n";
}
static void writeMatrixPrecisionEmulationHelper(
TInfoSinkBase& sink, ShShaderOutput outputLanguage, unsigned int size, const char *functionName)
static void writeMatrixPrecisionEmulationHelper(TInfoSinkBase &sink,
const ShShaderOutput outputLanguage,
const unsigned int columns,
const unsigned int rows,
const char *functionName)
{
std::stringstream matTypeStrStr;
if (outputLanguage == SH_ESSL_OUTPUT)
matTypeStrStr << "highp ";
matTypeStrStr << "mat" << size;
matTypeStrStr << "mat" << columns;
if (rows != columns)
{
matTypeStrStr << "x" << rows;
}
std::string matType = matTypeStrStr.str();
sink << matType << " " << functionName << "(in " << matType << " m) {\n"
" " << matType << " rounded;\n";
for (unsigned int i = 0; i < size; ++i)
for (unsigned int i = 0; i < columns; ++i)
{
sink << " rounded[" << i << "] = " << functionName << "(m[" << i << "]);\n";
}
......@@ -58,7 +67,9 @@ static void writeMatrixPrecisionEmulationHelper(
"}\n";
}
static void writeCommonPrecisionEmulationHelpers(TInfoSinkBase& sink, ShShaderOutput outputLanguage)
static void writeCommonPrecisionEmulationHelpers(TInfoSinkBase &sink,
const int shaderVersion,
const ShShaderOutput outputLanguage)
{
// Write the angle_frm functions that round floating point numbers to
// half precision, and angle_frl functions that round them to minimum lowp
......@@ -134,10 +145,26 @@ static void writeCommonPrecisionEmulationHelpers(TInfoSinkBase& sink, ShShaderOu
writeVectorPrecisionEmulationHelpers(sink, outputLanguage, 2);
writeVectorPrecisionEmulationHelpers(sink, outputLanguage, 3);
writeVectorPrecisionEmulationHelpers(sink, outputLanguage, 4);
if (shaderVersion > 100)
{
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");
}
}
}
else
{
for (unsigned int size = 2; size <= 4; ++size)
{
writeMatrixPrecisionEmulationHelper(sink, outputLanguage, size, "angle_frm");
writeMatrixPrecisionEmulationHelper(sink, outputLanguage, size, "angle_frl");
writeMatrixPrecisionEmulationHelper(sink, outputLanguage, size, size, "angle_frm");
writeMatrixPrecisionEmulationHelper(sink, outputLanguage, size, size, "angle_frl");
}
}
}
......@@ -174,7 +201,7 @@ static void writeCompoundAssignmentPrecisionEmulation(
bool canRoundFloat(const TType &type)
{
return type.getBasicType() == EbtFloat && !type.isNonSquareMatrix() && !type.isArray() &&
return type.getBasicType() == EbtFloat && !type.isArray() &&
(type.getPrecision() == EbpLow || type.getPrecision() == EbpMedium);
}
......@@ -443,13 +470,15 @@ bool EmulatePrecision::visitUnary(Visit visit, TIntermUnary *node)
return true;
}
void EmulatePrecision::writeEmulationHelpers(TInfoSinkBase& sink, ShShaderOutput outputLanguage)
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, outputLanguage);
writeCommonPrecisionEmulationHelpers(sink, shaderVersion, outputLanguage);
EmulationSet::const_iterator it;
for (it = mEmulateCompoundAdd.begin(); it != mEmulateCompoundAdd.end(); it++)
......
......@@ -28,7 +28,9 @@ class EmulatePrecision : public TLValueTrackingTraverser
bool visitUnary(Visit visit, TIntermUnary *node) override;
bool visitAggregate(Visit visit, TIntermAggregate *node) override;
void writeEmulationHelpers(TInfoSinkBase& sink, ShShaderOutput outputLanguage);
void writeEmulationHelpers(TInfoSinkBase &sink,
const int shaderVersion,
const ShShaderOutput outputLanguage);
private:
struct TypePair
......
......@@ -46,7 +46,7 @@ void TranslatorESSL::translate(TIntermNode *root, int) {
EmulatePrecision emulatePrecision(getSymbolTable(), shaderVer);
root->traverse(&emulatePrecision);
emulatePrecision.updateTree();
emulatePrecision.writeEmulationHelpers(sink, SH_ESSL_OUTPUT);
emulatePrecision.writeEmulationHelpers(sink, shaderVer, SH_ESSL_OUTPUT);
}
RecordConstantPrecision(root, getTemporaryIndex());
......
......@@ -49,7 +49,7 @@ void TranslatorGLSL::translate(TIntermNode *root, int compileOptions)
EmulatePrecision emulatePrecision(getSymbolTable(), getShaderVersion());
root->traverse(&emulatePrecision);
emulatePrecision.updateTree();
emulatePrecision.writeEmulationHelpers(sink, getOutputType());
emulatePrecision.writeEmulationHelpers(sink, getShaderVersion(), getOutputType());
}
// Write emulated built-in functions if needed.
......
......@@ -71,6 +71,52 @@ TEST_F(DebugShaderPrecisionTest, RoundingFunctionsDefined)
ASSERT_TRUE(foundInGLSLCode("mat2 angle_frl(in mat2"));
ASSERT_TRUE(foundInGLSLCode("mat3 angle_frl(in mat3"));
ASSERT_TRUE(foundInGLSLCode("mat4 angle_frl(in mat4"));
// Check that ESSL 3.00 rounding functions for non-square matrices are not defined.
ASSERT_TRUE(notFoundInCode("mat2x"));
ASSERT_TRUE(notFoundInCode("mat3x"));
ASSERT_TRUE(notFoundInCode("mat4x"));
}
// Test that all ESSL 3.00 shaders get rounding function definitions for non-square matrices.
TEST_F(DebugShaderPrecisionTest, NonSquareMatrixRoundingFunctionsDefinedES3)
{
const std::string &shaderString =
"#version 300 es\n"
"precision mediump float;\n"
"uniform float u;\n"
"out vec4 my_FragColor;\n"
"void main() {\n"
" my_FragColor = vec4(u);\n"
"}\n";
compile(shaderString);
ASSERT_TRUE(foundInESSLCode("highp mat2x3 angle_frm(in highp mat2x3"));
ASSERT_TRUE(foundInESSLCode("highp mat2x4 angle_frm(in highp mat2x4"));
ASSERT_TRUE(foundInESSLCode("highp mat3x2 angle_frm(in highp mat3x2"));
ASSERT_TRUE(foundInESSLCode("highp mat3x4 angle_frm(in highp mat3x4"));
ASSERT_TRUE(foundInESSLCode("highp mat4x2 angle_frm(in highp mat4x2"));
ASSERT_TRUE(foundInESSLCode("highp mat4x3 angle_frm(in highp mat4x3"));
ASSERT_TRUE(foundInESSLCode("highp mat2x3 angle_frl(in highp mat2x3"));
ASSERT_TRUE(foundInESSLCode("highp mat2x4 angle_frl(in highp mat2x4"));
ASSERT_TRUE(foundInESSLCode("highp mat3x2 angle_frl(in highp mat3x2"));
ASSERT_TRUE(foundInESSLCode("highp mat3x4 angle_frl(in highp mat3x4"));
ASSERT_TRUE(foundInESSLCode("highp mat4x2 angle_frl(in highp mat4x2"));
ASSERT_TRUE(foundInESSLCode("highp mat4x3 angle_frl(in highp mat4x3"));
ASSERT_TRUE(foundInGLSLCode("mat2x3 angle_frm(in mat2x3"));
ASSERT_TRUE(foundInGLSLCode("mat2x4 angle_frm(in mat2x4"));
ASSERT_TRUE(foundInGLSLCode("mat3x2 angle_frm(in mat3x2"));
ASSERT_TRUE(foundInGLSLCode("mat3x4 angle_frm(in mat3x4"));
ASSERT_TRUE(foundInGLSLCode("mat4x2 angle_frm(in mat4x2"));
ASSERT_TRUE(foundInGLSLCode("mat4x3 angle_frm(in mat4x3"));
ASSERT_TRUE(foundInGLSLCode("mat2x3 angle_frl(in mat2x3"));
ASSERT_TRUE(foundInGLSLCode("mat2x4 angle_frl(in mat2x4"));
ASSERT_TRUE(foundInGLSLCode("mat3x2 angle_frl(in mat3x2"));
ASSERT_TRUE(foundInGLSLCode("mat3x4 angle_frl(in mat3x4"));
ASSERT_TRUE(foundInGLSLCode("mat4x2 angle_frl(in mat4x2"));
ASSERT_TRUE(foundInGLSLCode("mat4x3 angle_frl(in mat4x3"));
}
TEST_F(DebugShaderPrecisionTest, PragmaDisablesEmulation)
......@@ -315,6 +361,32 @@ TEST_F(DebugShaderPrecisionTest, CompoundMatrixTimesMatrixFunction)
ASSERT_TRUE(notFoundInCode("*="));
}
// Test that compound multiplying a non-square matrix with another matrix gets translated into an
// angle_compound_mul function call.
TEST_F(DebugShaderPrecisionTest, CompoundNonSquareMatrixTimesMatrixFunction)
{
const std::string &shaderString =
"#version 300 es\n"
"precision mediump float;\n"
"uniform mat2x4 u;\n"
"uniform mat2 u2;\n"
"out vec4 my_FragColor;\n"
"void main() {\n"
" mat2x4 m = u;\n"
" m *= u2;\n"
" my_FragColor = m[0];\n"
"}\n";
compile(shaderString);
ASSERT_TRUE(foundInESSLCode(
"highp mat2x4 angle_compound_mul_frm(inout highp mat2x4 x, in highp mat2 y) {\n"
" x = angle_frm(angle_frm(x) * y);"));
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(notFoundInCode("*="));
}
TEST_F(DebugShaderPrecisionTest, CompoundMatrixTimesScalarFunction)
{
const std::string &shaderString =
......
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