Commit 74da73fe by Olli Etuaho Committed by Commit Bot

Add ESSL 3.10 ldexp/frexp builtins

This adds new built-ins found in ESSL 3.10 section 8.3 Common Functions. This includes constant folding support for ldexp and support for both GLSL and HLSL output. In HLSL these functions need to be emulated. BUG=angleproject:1730 TEST=angle_unittests Change-Id: I1330e69978b0cf53efbc3416150194764414e96c Reviewed-on: https://chromium-review.googlesource.com/435342Reviewed-by: 's avatarCorentin Wallez <cwallez@chromium.org> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Commit-Queue: Olli Etuaho <oetuaho@nvidia.com>
parent 7e24bfd3
......@@ -614,6 +614,22 @@ struct IndexRange
size_t vertexIndexCount;
};
// Combine a floating-point value representing a mantissa (x) and an integer exponent (exp) into a
// floating-point value. As in GLSL ldexp() built-in.
inline float Ldexp(float x, int exp)
{
if (exp > 128)
{
return std::numeric_limits<float>::infinity();
}
if (exp < -126)
{
return 0.0f;
}
double result = static_cast<double>(x) * std::pow(2.0, static_cast<double>(exp));
return static_cast<float>(result);
}
// First, both normalized floating-point values are converted into 16-bit integer values.
// Then, the results are packed into the returned 32-bit unsigned integer.
// The first float value will be written to the least significant bits of the output;
......
......@@ -310,4 +310,13 @@ TEST(MathUtilTest, FindMSB)
EXPECT_EQ(31, gl::FindMSB(0x80000000u));
}
// Test Ldexp, which combines mantissa and exponent into a floating-point number.
TEST(MathUtilTest, Ldexp)
{
EXPECT_EQ(2.5f, Ldexp(0.625f, 2));
EXPECT_EQ(-5.0f, Ldexp(-0.625f, 3));
EXPECT_EQ(std::numeric_limits<float>::infinity(), Ldexp(0.625f, 129));
EXPECT_EQ(0.0f, Ldexp(1.0f, -129));
}
} // anonymous namespace
......@@ -126,6 +126,68 @@ void InitBuiltInFunctionEmulatorForHLSL(BuiltInFunctionEmulator *emu)
"}\n"
"\n");
emu->addEmulatedFunction(EOpFrexp, float1, int1,
"float webgl_frexp_emu(float x, out int exp)\n"
"{\n"
" float fexp;\n"
" float mantissa = frexp(abs(x), fexp) * sign(x);\n"
" exp = int(fexp);\n"
" return mantissa;\n"
"}\n"
"\n");
emu->addEmulatedFunction(EOpFrexp, float2, int2,
"float2 webgl_frexp_emu(float2 x, out int2 exp)\n"
"{\n"
" float2 fexp;\n"
" float2 mantissa = frexp(abs(x), fexp) * sign(x);\n"
" exp = int2(fexp);\n"
" return mantissa;\n"
"}\n"
"\n");
emu->addEmulatedFunction(EOpFrexp, float3, int3,
"float3 webgl_frexp_emu(float3 x, out int3 exp)\n"
"{\n"
" float3 fexp;\n"
" float3 mantissa = frexp(abs(x), fexp) * sign(x);\n"
" exp = int3(fexp);\n"
" return mantissa;\n"
"}\n"
"\n");
emu->addEmulatedFunction(EOpFrexp, float4, int4,
"float4 webgl_frexp_emu(float4 x, out int4 exp)\n"
"{\n"
" float4 fexp;\n"
" float4 mantissa = frexp(abs(x), fexp) * sign(x);\n"
" exp = int4(fexp);\n"
" return mantissa;\n"
"}\n"
"\n");
emu->addEmulatedFunction(EOpLdexp, float1, int1,
"float webgl_ldexp_emu(float x, int exp)\n"
"{\n"
" return ldexp(x, float(exp));\n"
"}\n"
"\n");
emu->addEmulatedFunction(EOpLdexp, float2, int2,
"float2 webgl_ldexp_emu(float2 x, int2 exp)\n"
"{\n"
" return ldexp(x, float2(exp));\n"
"}\n"
"\n");
emu->addEmulatedFunction(EOpLdexp, float3, int3,
"float3 webgl_ldexp_emu(float3 x, int3 exp)\n"
"{\n"
" return ldexp(x, float3(exp));\n"
"}\n"
"\n");
emu->addEmulatedFunction(EOpLdexp, float4, int4,
"float4 webgl_ldexp_emu(float4 x, int4 exp)\n"
"{\n"
" return ldexp(x, float4(exp));\n"
"}\n"
"\n");
emu->addEmulatedFunction(EOpFaceForward, float1, float1, float1,
"float webgl_faceforward_emu(float N, float I, float Nref)\n"
"{\n"
......
......@@ -111,6 +111,7 @@ void InsertBuiltInFunctions(sh::GLenum type,
symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpSmoothStep, genType, float1, float1, genType);
const TType *outGenType = TCache::getType(EbtGenType, EvqOut);
const TType *outGenIType = TCache::getType(EbtGenIType, EvqOut);
symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpModf, genType, genType, outGenType);
......@@ -121,6 +122,9 @@ void InsertBuiltInFunctions(sh::GLenum type,
symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpIntBitsToFloat, genType, genIType);
symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpUintBitsToFloat, genType, genUType);
symbolTable.insertBuiltInOp(ESSL3_1_BUILTINS, EOpFrexp, genType, genType, outGenIType);
symbolTable.insertBuiltInOp(ESSL3_1_BUILTINS, EOpLdexp, genType, genType, genIType);
symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpPackSnorm2x16, uint1, float2);
symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpPackUnorm2x16, uint1, float2);
symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpPackHalf2x16, uint1, float2);
......@@ -234,7 +238,6 @@ void InsertBuiltInFunctions(sh::GLenum type,
// Integer functions
//
const TType *outGenUType = TCache::getType(EbtGenUType, EvqOut);
const TType *outGenIType = TCache::getType(EbtGenIType, EvqOut);
symbolTable.insertBuiltInOp(ESSL3_1_BUILTINS, EOpBitfieldExtract, genIType, genIType, int1,
int1);
......
......@@ -3012,6 +3012,25 @@ TConstantUnion *TIntermConstantUnion::FoldAggregateBuiltIn(TIntermAggregate *agg
break;
}
case EOpLdexp:
{
resultArray = new TConstantUnion[maxObjectSize];
for (size_t i = 0; i < maxObjectSize; i++)
{
float x = unionArrays[0][i].getFConst();
int exp = unionArrays[1][i].getIConst();
if (exp > 128)
{
UndefinedConstantFoldingError(loc, op, basicType, diagnostics, &resultArray[i]);
}
else
{
resultArray[i].setFConst(gl::Ldexp(x, exp));
}
}
break;
}
case EOpFaceForward:
{
ASSERT(basicType == EbtFloat);
......
......@@ -273,6 +273,7 @@ TIntermTyped *TIntermediate::foldAggregateBuiltIn(TIntermAggregate *aggregate,
case EOpMix:
case EOpStep:
case EOpSmoothStep:
case EOpLdexp:
case EOpMulMatrixComponentWise:
case EOpOuterProduct:
case EOpEqualComponentWise:
......
......@@ -197,6 +197,11 @@ const char *GetOperatorString(TOperator op)
case EOpUintBitsToFloat:
return "uintBitsToFloat";
case EOpFrexp:
return "frexp";
case EOpLdexp:
return "ldexp";
case EOpPackSnorm2x16:
return "packSnorm2x16";
case EOpPackUnorm2x16:
......
......@@ -143,6 +143,9 @@ enum TOperator
EOpIntBitsToFloat,
EOpUintBitsToFloat,
EOpFrexp,
EOpLdexp,
EOpPackSnorm2x16,
EOpPackUnorm2x16,
EOpPackHalf2x16,
......
......@@ -937,6 +937,8 @@ bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate *node)
case EOpMix:
case EOpStep:
case EOpSmoothStep:
case EOpFrexp:
case EOpLdexp:
case EOpDistance:
case EOpDot:
case EOpCross:
......
......@@ -1993,6 +1993,11 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node)
case EOpSmoothStep:
outputTriplet(out, visit, "smoothstep(", ", ", ")");
break;
case EOpFrexp:
case EOpLdexp:
ASSERT(node->getUseEmulatedFunction());
writeEmulatedFunctionTriplet(out, visit, node->getOp());
break;
case EOpDistance:
outputTriplet(out, visit, "distance(", ", ", ")");
break;
......
......@@ -1409,3 +1409,11 @@ TEST_F(ConstantFoldingExpressionTest, FoldUnpackUnorm4x8)
evaluateFloat(floatString);
ASSERT_TRUE(constantFoundInAST(123.0f / 255.0f));
}
// Test that ldexp is folded correctly.
TEST_F(ConstantFoldingExpressionTest, FoldLdexp)
{
const std::string &floatString = "ldexp(0.625, 1)";
evaluateFloat(floatString);
ASSERT_TRUE(constantFoundInAST(1.25f));
}
......@@ -368,77 +368,29 @@
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.floatbitstouint.vec4_lowp_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.floatbitstouint.vec4_mediump_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.floatbitstouint.vec4_highp_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.frexp.float_lowp_vertex = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.frexp.float_lowp_fragment = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.frexp.float_lowp_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.frexp.float_mediump_vertex = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.frexp.float_mediump_fragment = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.frexp.float_mediump_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.frexp.float_highp_vertex = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.frexp.float_highp_fragment = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.frexp.float_highp_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.frexp.vec2_lowp_vertex = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.frexp.vec2_lowp_fragment = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.frexp.vec2_lowp_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.frexp.vec2_mediump_vertex = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.frexp.vec2_mediump_fragment = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.frexp.vec2_mediump_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.frexp.vec2_highp_vertex = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.frexp.vec2_highp_fragment = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.frexp.vec2_highp_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.frexp.vec3_lowp_vertex = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.frexp.vec3_lowp_fragment = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.frexp.vec3_lowp_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.frexp.vec3_mediump_vertex = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.frexp.vec3_mediump_fragment = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.frexp.vec3_mediump_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.frexp.vec3_highp_vertex = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.frexp.vec3_highp_fragment = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.frexp.vec3_highp_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.frexp.vec4_lowp_vertex = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.frexp.vec4_lowp_fragment = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.frexp.vec4_lowp_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.frexp.vec4_mediump_vertex = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.frexp.vec4_mediump_fragment = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.frexp.vec4_mediump_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.frexp.vec4_highp_vertex = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.frexp.vec4_highp_fragment = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.frexp.vec4_highp_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.ldexp.float_lowp_vertex = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.ldexp.float_lowp_fragment = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.ldexp.float_lowp_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.ldexp.float_mediump_vertex = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.ldexp.float_mediump_fragment = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.ldexp.float_mediump_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.ldexp.float_highp_vertex = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.ldexp.float_highp_fragment = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.ldexp.float_highp_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.ldexp.vec2_lowp_vertex = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.ldexp.vec2_lowp_fragment = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.ldexp.vec2_lowp_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.ldexp.vec2_mediump_vertex = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.ldexp.vec2_mediump_fragment = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.ldexp.vec2_mediump_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.ldexp.vec2_highp_vertex = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.ldexp.vec2_highp_fragment = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.ldexp.vec2_highp_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.ldexp.vec3_lowp_vertex = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.ldexp.vec3_lowp_fragment = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.ldexp.vec3_lowp_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.ldexp.vec3_mediump_vertex = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.ldexp.vec3_mediump_fragment = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.ldexp.vec3_mediump_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.ldexp.vec3_highp_vertex = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.ldexp.vec3_highp_fragment = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.ldexp.vec3_highp_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.ldexp.vec4_lowp_vertex = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.ldexp.vec4_lowp_fragment = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.ldexp.vec4_lowp_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.ldexp.vec4_mediump_vertex = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.ldexp.vec4_mediump_fragment = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.ldexp.vec4_mediump_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.ldexp.vec4_highp_vertex = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.ldexp.vec4_highp_fragment = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.ldexp.vec4_highp_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.intbitstofloat.int_highp_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.common.intbitstofloat.ivec2_highp_compute = FAIL
......
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