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 @@ ...@@ -9,8 +9,9 @@
namespace namespace
{ {
static void writeVectorPrecisionEmulationHelpers( static void writeVectorPrecisionEmulationHelpers(TInfoSinkBase &sink,
TInfoSinkBase& sink, ShShaderOutput outputLanguage, unsigned int size) const ShShaderOutput outputLanguage,
const unsigned int size)
{ {
std::stringstream vecTypeStrStr; std::stringstream vecTypeStrStr;
if (outputLanguage == SH_ESSL_OUTPUT) if (outputLanguage == SH_ESSL_OUTPUT)
...@@ -37,19 +38,27 @@ static void writeVectorPrecisionEmulationHelpers( ...@@ -37,19 +38,27 @@ static void writeVectorPrecisionEmulationHelpers(
"}\n"; "}\n";
} }
static void writeMatrixPrecisionEmulationHelper( static void writeMatrixPrecisionEmulationHelper(TInfoSinkBase &sink,
TInfoSinkBase& sink, ShShaderOutput outputLanguage, unsigned int size, const char *functionName) const ShShaderOutput outputLanguage,
const unsigned int columns,
const unsigned int rows,
const char *functionName)
{ {
std::stringstream matTypeStrStr; std::stringstream matTypeStrStr;
if (outputLanguage == SH_ESSL_OUTPUT) if (outputLanguage == SH_ESSL_OUTPUT)
matTypeStrStr << "highp "; matTypeStrStr << "highp ";
matTypeStrStr << "mat" << size; matTypeStrStr << "mat" << columns;
if (rows != columns)
{
matTypeStrStr << "x" << rows;
}
std::string matType = matTypeStrStr.str(); std::string matType = matTypeStrStr.str();
sink << matType << " " << functionName << "(in " << matType << " m) {\n" sink << matType << " " << functionName << "(in " << matType << " m) {\n"
" " << matType << " rounded;\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"; sink << " rounded[" << i << "] = " << functionName << "(m[" << i << "]);\n";
} }
...@@ -58,7 +67,9 @@ static void writeMatrixPrecisionEmulationHelper( ...@@ -58,7 +67,9 @@ static void writeMatrixPrecisionEmulationHelper(
"}\n"; "}\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 // Write the angle_frm functions that round floating point numbers to
// half precision, and angle_frl functions that round them to minimum lowp // half precision, and angle_frl functions that round them to minimum lowp
...@@ -134,10 +145,26 @@ static void writeCommonPrecisionEmulationHelpers(TInfoSinkBase& sink, ShShaderOu ...@@ -134,10 +145,26 @@ static void writeCommonPrecisionEmulationHelpers(TInfoSinkBase& sink, ShShaderOu
writeVectorPrecisionEmulationHelpers(sink, outputLanguage, 2); writeVectorPrecisionEmulationHelpers(sink, outputLanguage, 2);
writeVectorPrecisionEmulationHelpers(sink, outputLanguage, 3); writeVectorPrecisionEmulationHelpers(sink, outputLanguage, 3);
writeVectorPrecisionEmulationHelpers(sink, outputLanguage, 4); writeVectorPrecisionEmulationHelpers(sink, outputLanguage, 4);
for (unsigned int size = 2; size <= 4; ++size) 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
{ {
writeMatrixPrecisionEmulationHelper(sink, outputLanguage, size, "angle_frm"); for (unsigned int size = 2; size <= 4; ++size)
writeMatrixPrecisionEmulationHelper(sink, outputLanguage, size, "angle_frl"); {
writeMatrixPrecisionEmulationHelper(sink, outputLanguage, size, size, "angle_frm");
writeMatrixPrecisionEmulationHelper(sink, outputLanguage, size, size, "angle_frl");
}
} }
} }
...@@ -174,8 +201,8 @@ static void writeCompoundAssignmentPrecisionEmulation( ...@@ -174,8 +201,8 @@ static void writeCompoundAssignmentPrecisionEmulation(
bool canRoundFloat(const TType &type) 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); (type.getPrecision() == EbpLow || type.getPrecision() == EbpMedium);
} }
TIntermAggregate *createInternalFunctionCallNode(TString name, TIntermNode *child) TIntermAggregate *createInternalFunctionCallNode(TString name, TIntermNode *child)
...@@ -443,13 +470,15 @@ bool EmulatePrecision::visitUnary(Visit visit, TIntermUnary *node) ...@@ -443,13 +470,15 @@ bool EmulatePrecision::visitUnary(Visit visit, TIntermUnary *node)
return true; 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 // Other languages not yet supported
ASSERT(outputLanguage == SH_GLSL_COMPATIBILITY_OUTPUT || ASSERT(outputLanguage == SH_GLSL_COMPATIBILITY_OUTPUT ||
IsGLSL130OrNewer(outputLanguage) || IsGLSL130OrNewer(outputLanguage) ||
outputLanguage == SH_ESSL_OUTPUT); outputLanguage == SH_ESSL_OUTPUT);
writeCommonPrecisionEmulationHelpers(sink, outputLanguage); writeCommonPrecisionEmulationHelpers(sink, shaderVersion, outputLanguage);
EmulationSet::const_iterator it; EmulationSet::const_iterator it;
for (it = mEmulateCompoundAdd.begin(); it != mEmulateCompoundAdd.end(); it++) for (it = mEmulateCompoundAdd.begin(); it != mEmulateCompoundAdd.end(); it++)
......
...@@ -28,7 +28,9 @@ class EmulatePrecision : public TLValueTrackingTraverser ...@@ -28,7 +28,9 @@ class EmulatePrecision : public TLValueTrackingTraverser
bool visitUnary(Visit visit, TIntermUnary *node) override; bool visitUnary(Visit visit, TIntermUnary *node) override;
bool visitAggregate(Visit visit, TIntermAggregate *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: private:
struct TypePair struct TypePair
......
...@@ -46,7 +46,7 @@ void TranslatorESSL::translate(TIntermNode *root, int) { ...@@ -46,7 +46,7 @@ void TranslatorESSL::translate(TIntermNode *root, int) {
EmulatePrecision emulatePrecision(getSymbolTable(), shaderVer); EmulatePrecision emulatePrecision(getSymbolTable(), shaderVer);
root->traverse(&emulatePrecision); root->traverse(&emulatePrecision);
emulatePrecision.updateTree(); emulatePrecision.updateTree();
emulatePrecision.writeEmulationHelpers(sink, SH_ESSL_OUTPUT); emulatePrecision.writeEmulationHelpers(sink, shaderVer, SH_ESSL_OUTPUT);
} }
RecordConstantPrecision(root, getTemporaryIndex()); RecordConstantPrecision(root, getTemporaryIndex());
......
...@@ -49,7 +49,7 @@ void TranslatorGLSL::translate(TIntermNode *root, int compileOptions) ...@@ -49,7 +49,7 @@ void TranslatorGLSL::translate(TIntermNode *root, int compileOptions)
EmulatePrecision emulatePrecision(getSymbolTable(), getShaderVersion()); EmulatePrecision emulatePrecision(getSymbolTable(), getShaderVersion());
root->traverse(&emulatePrecision); root->traverse(&emulatePrecision);
emulatePrecision.updateTree(); emulatePrecision.updateTree();
emulatePrecision.writeEmulationHelpers(sink, getOutputType()); emulatePrecision.writeEmulationHelpers(sink, getShaderVersion(), getOutputType());
} }
// Write emulated built-in functions if needed. // Write emulated built-in functions if needed.
......
...@@ -71,6 +71,52 @@ TEST_F(DebugShaderPrecisionTest, RoundingFunctionsDefined) ...@@ -71,6 +71,52 @@ TEST_F(DebugShaderPrecisionTest, RoundingFunctionsDefined)
ASSERT_TRUE(foundInGLSLCode("mat2 angle_frl(in mat2")); ASSERT_TRUE(foundInGLSLCode("mat2 angle_frl(in mat2"));
ASSERT_TRUE(foundInGLSLCode("mat3 angle_frl(in mat3")); ASSERT_TRUE(foundInGLSLCode("mat3 angle_frl(in mat3"));
ASSERT_TRUE(foundInGLSLCode("mat4 angle_frl(in mat4")); 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) TEST_F(DebugShaderPrecisionTest, PragmaDisablesEmulation)
...@@ -315,6 +361,32 @@ TEST_F(DebugShaderPrecisionTest, CompoundMatrixTimesMatrixFunction) ...@@ -315,6 +361,32 @@ TEST_F(DebugShaderPrecisionTest, CompoundMatrixTimesMatrixFunction)
ASSERT_TRUE(notFoundInCode("*=")); 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) TEST_F(DebugShaderPrecisionTest, CompoundMatrixTimesScalarFunction)
{ {
const std::string &shaderString = 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