Commit 9250cb24 by Olli Etuaho Committed by Commit Bot

Add ESSL 3.10 integer math built-ins

This adds built-ins found in ESSL 3.10 section 8.8 Integer functions. This includes constant folding support for functions that may be constant folded, and support for both GLSL and HLSL output. In HLSL several of the functions need to be emulated. The precision qualification for the return value of some of these functions is determined by special rules, that are now part of type promotion for TIntermUnary nodes and determining the type of TIntermAggregate nodes. BUG=angleproject:1730 TEST=angle_unittests TEST=dEQP-GLES31.functional.shaders.builtin_functions.integer.* Change-Id: Ib0056c17671c42b6496c2f0ef059b99f8f25c122 Reviewed-on: https://chromium-review.googlesource.com/431310 Commit-Queue: Olli Etuaho <oetuaho@nvidia.com> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org>
parent 2add15ef
......@@ -97,21 +97,6 @@ typename BitSetIterator<N>::Iterator &BitSetIterator<N>::Iterator::operator++()
return *this;
}
inline unsigned long ScanForward(unsigned long bits)
{
ASSERT(bits != 0);
#if defined(ANGLE_PLATFORM_WINDOWS)
unsigned long firstBitIndex = 0ul;
unsigned char ret = _BitScanForward(&firstBitIndex, bits);
ASSERT(ret != 0);
return firstBitIndex;
#elif defined(ANGLE_PLATFORM_POSIX)
return static_cast<unsigned long>(__builtin_ctzl(bits));
#else
#error Please implement bit-scan-forward for your platform!
#endif
}
template <size_t N>
bool BitSetIterator<N>::Iterator::operator==(const Iterator &other) const
{
......@@ -134,7 +119,7 @@ unsigned long BitSetIterator<N>::Iterator::getNextBit()
unsigned long wordBits = (mBits & wordMask).to_ulong();
if (wordBits != 0ul)
{
return ScanForward(wordBits) + mOffset;
return gl::ScanForward(wordBits) + mOffset;
}
mBits >>= BitsPerWord;
......
......@@ -695,6 +695,91 @@ inline void unpackHalf2x16(uint32_t u, float *f1, float *f2)
*f2 = float16ToFloat32(mostSignificantBits);
}
// Reverse the order of the bits.
inline uint32_t BitfieldReverse(uint32_t value)
{
// TODO(oetuaho@nvidia.com): Optimize this if needed. There don't seem to be compiler intrinsics
// for this, and right now it's not used in performance-critical paths.
uint32_t result = 0u;
for (size_t j = 0u; j < 32u; ++j)
{
result |= (((value >> j) & 1u) << (31u - j));
}
return result;
}
// Count the 1 bits.
inline int BitCount(unsigned int bits)
{
#if defined(ANGLE_PLATFORM_WINDOWS)
return static_cast<int>(__popcnt(bits));
#elif defined(ANGLE_PLATFORM_POSIX)
return __builtin_popcount(bits);
#else
#error Please implement bit count for your platform!
#endif
}
// Return the index of the least significant bit set. Indexing is such that bit 0 is the least
// significant bit.
inline unsigned long ScanForward(unsigned long bits)
{
ASSERT(bits != 0u);
#if defined(ANGLE_PLATFORM_WINDOWS)
unsigned long firstBitIndex = 0ul;
unsigned char ret = _BitScanForward(&firstBitIndex, bits);
ASSERT(ret != 0u);
return firstBitIndex;
#elif defined(ANGLE_PLATFORM_POSIX)
return static_cast<unsigned long>(__builtin_ctzl(bits));
#else
#error Please implement bit-scan-forward for your platform!
#endif
}
// Return the index of the most significant bit set. Indexing is such that bit 0 is the least
// significant bit.
inline unsigned long ScanReverse(unsigned long bits)
{
ASSERT(bits != 0u);
#if defined(ANGLE_PLATFORM_WINDOWS)
unsigned long lastBitIndex = 0ul;
unsigned char ret = _BitScanReverse(&lastBitIndex, bits);
ASSERT(ret != 0u);
return lastBitIndex;
#elif defined(ANGLE_PLATFORM_POSIX)
return static_cast<unsigned long>(sizeof(unsigned long) * CHAR_BIT - 1 - __builtin_clzl(bits));
#else
#error Please implement bit-scan-reverse for your platform!
#endif
}
// Returns -1 on 0, otherwise the index of the least significant 1 bit as in GLSL.
inline int FindLSB(uint32_t bits)
{
if (bits == 0u)
{
return -1;
}
else
{
return static_cast<int>(ScanForward(bits));
}
}
// Returns -1 on 0, otherwise the index of the most significant 1 bit as in GLSL.
inline int FindMSB(uint32_t bits)
{
if (bits == 0u)
{
return -1;
}
else
{
return static_cast<int>(ScanReverse(bits));
}
}
// Returns whether the argument is Not a Number.
// IEEE 754 single precision NaN representation: Exponent(8 bits) - 255, Mantissa(23 bits) - non-zero.
inline bool isNaN(float f)
......
......@@ -207,4 +207,57 @@ TEST(MathUtilTest, CheckedRoundUpInvalid)
ASSERT_FALSE(checkedLimit.IsValid());
}
// Test BitfieldReverse which reverses the order of the bits in an integer.
TEST(MathUtilTest, BitfieldReverse)
{
EXPECT_EQ(0u, gl::BitfieldReverse(0u));
EXPECT_EQ(0x80000000u, gl::BitfieldReverse(1u));
EXPECT_EQ(0x1u, gl::BitfieldReverse(0x80000000u));
uint32_t bits = (1u << 4u) | (1u << 7u);
uint32_t reversed = (1u << (31u - 4u)) | (1u << (31u - 7u));
EXPECT_EQ(reversed, gl::BitfieldReverse(bits));
}
// Test BitCount, which counts 1 bits in an integer.
TEST(MathUtilTest, BitCount)
{
EXPECT_EQ(0, gl::BitCount(0u));
EXPECT_EQ(32, gl::BitCount(0xFFFFFFFFu));
EXPECT_EQ(10, gl::BitCount(0x17103121u));
}
// Test ScanForward, which scans for the least significant 1 bit from a non-zero integer.
TEST(MathUtilTest, ScanForward)
{
EXPECT_EQ(0ul, gl::ScanForward(1ul));
EXPECT_EQ(16ul, gl::ScanForward(0x80010000ul));
EXPECT_EQ(31ul, gl::ScanForward(0x80000000ul));
}
// Test ScanReverse, which scans for the most significant 1 bit from a non-zero integer.
TEST(MathUtilTest, ScanReverse)
{
EXPECT_EQ(0ul, gl::ScanReverse(1ul));
EXPECT_EQ(16ul, gl::ScanReverse(0x00010030ul));
EXPECT_EQ(31ul, gl::ScanReverse(0x80000000ul));
}
// Test FindLSB, which finds the least significant 1 bit.
TEST(MathUtilTest, FindLSB)
{
EXPECT_EQ(-1, gl::FindLSB(0u));
EXPECT_EQ(0, gl::FindLSB(1u));
EXPECT_EQ(16, gl::FindLSB(0x80010000u));
EXPECT_EQ(31, gl::FindLSB(0x80000000u));
}
// Test FindMSB, which finds the most significant 1 bit.
TEST(MathUtilTest, FindMSB)
{
EXPECT_EQ(-1, gl::FindMSB(0u));
EXPECT_EQ(0, gl::FindMSB(1u));
EXPECT_EQ(16, gl::FindMSB(0x00010030u));
EXPECT_EQ(31, gl::FindMSB(0x80000000u));
}
} // anonymous namespace
......@@ -74,6 +74,14 @@ void InitBuiltInFunctionEmulatorForHLSL(BuiltInFunctionEmulator *emu)
TType *float2 = new TType(EbtFloat, 2);
TType *float3 = new TType(EbtFloat, 3);
TType *float4 = new TType(EbtFloat, 4);
TType *int1 = new TType(EbtInt);
TType *int2 = new TType(EbtInt, 2);
TType *int3 = new TType(EbtInt, 3);
TType *int4 = new TType(EbtInt, 4);
TType *uint1 = new TType(EbtUInt);
TType *uint2 = new TType(EbtUInt, 2);
TType *uint3 = new TType(EbtUInt, 3);
TType *uint4 = new TType(EbtUInt, 4);
emu->addEmulatedFunction(EOpMod, float1, float1,
"float webgl_mod_emu(float x, float y)\n"
......@@ -315,8 +323,6 @@ void InitBuiltInFunctionEmulatorForHLSL(BuiltInFunctionEmulator *emu)
" return (y << 16) | x;\n"
"}\n");
TType *uint1 = new TType(EbtUInt);
emu->addEmulatedFunction(EOpUnpackSnorm2x16, uint1,
"float webgl_fromSnorm(in uint x) {\n"
" int xi = asint(x & 0x7fffu) - asint(x & 0x8000u);\n"
......@@ -538,6 +544,388 @@ void InitBuiltInFunctionEmulatorForHLSL(BuiltInFunctionEmulator *emu)
"{\n"
" return a ? y : x;\n"
"}\n");
emu->addEmulatedFunction(
EOpBitfieldExtract, uint1, int1, int1,
"uint webgl_bitfieldExtract_emu(uint value, int offset, int bits)\n"
"{\n"
" if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n"
" {\n"
" return 0u;\n"
" }\n"
" uint maskMsb = (1u << (bits - 1));\n"
" uint mask = ((maskMsb - 1u) | maskMsb) << offset;\n"
" return (value & mask) >> offset;\n"
"}\n");
emu->addEmulatedFunction(
EOpBitfieldExtract, uint2, int1, int1,
"uint2 webgl_bitfieldExtract_emu(uint2 value, int offset, int bits)\n"
"{\n"
" if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n"
" {\n"
" return uint2(0u, 0u);\n"
" }\n"
" uint maskMsb = (1u << (bits - 1));\n"
" uint mask = ((maskMsb - 1u) | maskMsb) << offset;\n"
" return (value & mask) >> offset;\n"
"}\n");
emu->addEmulatedFunction(
EOpBitfieldExtract, uint3, int1, int1,
"uint3 webgl_bitfieldExtract_emu(uint3 value, int offset, int bits)\n"
"{\n"
" if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n"
" {\n"
" return uint3(0u, 0u, 0u);\n"
" }\n"
" uint maskMsb = (1u << (bits - 1));\n"
" uint mask = ((maskMsb - 1u) | maskMsb) << offset;\n"
" return (value & mask) >> offset;\n"
"}\n");
emu->addEmulatedFunction(
EOpBitfieldExtract, uint4, int1, int1,
"uint4 webgl_bitfieldExtract_emu(uint4 value, int offset, int bits)\n"
"{\n"
" if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n"
" {\n"
" return uint4(0u, 0u, 0u, 0u);\n"
" }\n"
" uint maskMsb = (1u << (bits - 1));\n"
" uint mask = ((maskMsb - 1u) | maskMsb) << offset;\n"
" return (value & mask) >> offset;\n"
"}\n");
emu->addEmulatedFunction(
EOpBitfieldExtract, int1, int1, int1,
"int webgl_bitfieldExtract_emu(int value, int offset, int bits)\n"
"{\n"
" if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n"
" {\n"
" return 0;\n"
" }\n"
" uint maskMsb = (1u << (bits - 1));\n"
" uint mask = ((maskMsb - 1u) | maskMsb) << offset;\n"
" uint resultUnsigned = (asuint(value) & mask) >> offset;\n"
" if (bits != 32 && (resultUnsigned & maskMsb) != 0)\n"
" {\n"
" uint higherBitsMask = ((1u << (32 - bits)) - 1u) << bits;\n"
" resultUnsigned |= higherBitsMask;\n"
" }\n"
" return asint(resultUnsigned);\n"
"}\n");
emu->addEmulatedFunction(
EOpBitfieldExtract, int2, int1, int1,
"int2 webgl_bitfieldExtract_emu(int2 value, int offset, int bits)\n"
"{\n"
" if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n"
" {\n"
" return int2(0, 0);\n"
" }\n"
" uint maskMsb = (1u << (bits - 1));\n"
" uint mask = ((maskMsb - 1u) | maskMsb) << offset;\n"
" uint2 resultUnsigned = (asuint(value) & mask) >> offset;\n"
" if (bits != 32)\n"
" {\n"
" uint higherBitsMask = ((1u << (32 - bits)) - 1u) << bits;\n"
" resultUnsigned |= ((resultUnsigned & maskMsb) >> (bits - 1)) * higherBitsMask;\n"
" }\n"
" return asint(resultUnsigned);\n"
"}\n");
emu->addEmulatedFunction(
EOpBitfieldExtract, int3, int1, int1,
"int3 webgl_bitfieldExtract_emu(int3 value, int offset, int bits)\n"
"{\n"
" if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n"
" {\n"
" return int3(0, 0, 0);\n"
" }\n"
" uint maskMsb = (1u << (bits - 1));\n"
" uint mask = ((maskMsb - 1u) | maskMsb) << offset;\n"
" uint3 resultUnsigned = (asuint(value) & mask) >> offset;\n"
" if (bits != 32)\n"
" {\n"
" uint higherBitsMask = ((1u << (32 - bits)) - 1u) << bits;\n"
" resultUnsigned |= ((resultUnsigned & maskMsb) >> (bits - 1)) * higherBitsMask;\n"
" }\n"
" return asint(resultUnsigned);\n"
"}\n");
emu->addEmulatedFunction(
EOpBitfieldExtract, int4, int1, int1,
"int4 webgl_bitfieldExtract_emu(int4 value, int offset, int bits)\n"
"{\n"
" if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n"
" {\n"
" return int4(0, 0, 0, 0);\n"
" }\n"
" uint maskMsb = (1u << (bits - 1));\n"
" uint mask = ((maskMsb - 1u) | maskMsb) << offset;\n"
" uint4 resultUnsigned = (asuint(value) & mask) >> offset;\n"
" if (bits != 32)\n"
" {\n"
" uint higherBitsMask = ((1u << (32 - bits)) - 1u) << bits;\n"
" resultUnsigned |= ((resultUnsigned & maskMsb) >> (bits - 1)) * higherBitsMask;\n"
" }\n"
" return asint(resultUnsigned);\n"
"}\n");
emu->addEmulatedFunction(
EOpBitfieldInsert, uint1, uint1, int1, int1,
"uint webgl_bitfieldInsert_emu(uint base, uint insert, int offset, int bits)\n"
"{\n"
" if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n"
" {\n"
" return base;\n"
" }\n"
" uint maskMsb = (1u << (bits - 1));\n"
" uint insertMask = ((maskMsb - 1u) | maskMsb) << offset;\n"
" uint baseMask = ~insertMask;\n"
" return (base & baseMask) | ((insert << offset) & insertMask);\n"
"}\n");
emu->addEmulatedFunction(
EOpBitfieldInsert, uint2, uint2, int1, int1,
"uint2 webgl_bitfieldInsert_emu(uint2 base, uint2 insert, int offset, int bits)\n"
"{\n"
" if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n"
" {\n"
" return base;\n"
" }\n"
" uint maskMsb = (1u << (bits - 1));\n"
" uint insertMask = ((maskMsb - 1u) | maskMsb) << offset;\n"
" uint baseMask = ~insertMask;\n"
" return (base & baseMask) | ((insert << offset) & insertMask);\n"
"}\n");
emu->addEmulatedFunction(
EOpBitfieldInsert, uint3, uint3, int1, int1,
"uint3 webgl_bitfieldInsert_emu(uint3 base, uint3 insert, int offset, int bits)\n"
"{\n"
" if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n"
" {\n"
" return base;\n"
" }\n"
" uint maskMsb = (1u << (bits - 1));\n"
" uint insertMask = ((maskMsb - 1u) | maskMsb) << offset;\n"
" uint baseMask = ~insertMask;\n"
" return (base & baseMask) | ((insert << offset) & insertMask);\n"
"}\n");
emu->addEmulatedFunction(
EOpBitfieldInsert, uint4, uint4, int1, int1,
"uint4 webgl_bitfieldInsert_emu(uint4 base, uint4 insert, int offset, int bits)\n"
"{\n"
" if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n"
" {\n"
" return base;\n"
" }\n"
" uint maskMsb = (1u << (bits - 1));\n"
" uint insertMask = ((maskMsb - 1u) | maskMsb) << offset;\n"
" uint baseMask = ~insertMask;\n"
" return (base & baseMask) | ((insert << offset) & insertMask);\n"
"}\n");
emu->addEmulatedFunction(
EOpBitfieldInsert, int1, int1, int1, int1,
"int webgl_bitfieldInsert_emu(int base, int insert, int offset, int bits)\n"
"{\n"
" if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n"
" {\n"
" return base;\n"
" }\n"
" uint maskMsb = (1u << (bits - 1));\n"
" uint insertMask = ((maskMsb - 1u) | maskMsb) << offset;\n"
" uint baseMask = ~insertMask;\n"
" uint resultUnsigned = (asuint(base) & baseMask) | ((asuint(insert) << offset) & "
"insertMask);\n"
" return asint(resultUnsigned);\n"
"}\n");
emu->addEmulatedFunction(
EOpBitfieldInsert, int2, int2, int1, int1,
"int2 webgl_bitfieldInsert_emu(int2 base, int2 insert, int offset, int bits)\n"
"{\n"
" if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n"
" {\n"
" return base;\n"
" }\n"
" uint maskMsb = (1u << (bits - 1));\n"
" uint insertMask = ((maskMsb - 1u) | maskMsb) << offset;\n"
" uint baseMask = ~insertMask;\n"
" uint2 resultUnsigned = (asuint(base) & baseMask) | ((asuint(insert) << offset) & "
"insertMask);\n"
" return asint(resultUnsigned);\n"
"}\n");
emu->addEmulatedFunction(
EOpBitfieldInsert, int3, int3, int1, int1,
"int3 webgl_bitfieldInsert_emu(int3 base, int3 insert, int offset, int bits)\n"
"{\n"
" if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n"
" {\n"
" return base;\n"
" }\n"
" uint maskMsb = (1u << (bits - 1));\n"
" uint insertMask = ((maskMsb - 1u) | maskMsb) << offset;\n"
" uint baseMask = ~insertMask;\n"
" uint3 resultUnsigned = (asuint(base) & baseMask) | ((asuint(insert) << offset) & "
"insertMask);\n"
" return asint(resultUnsigned);\n"
"}\n");
emu->addEmulatedFunction(
EOpBitfieldInsert, int4, int4, int1, int1,
"int4 webgl_bitfieldInsert_emu(int4 base, int4 insert, int offset, int bits)\n"
"{\n"
" if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n"
" {\n"
" return base;\n"
" }\n"
" uint maskMsb = (1u << (bits - 1));\n"
" uint insertMask = ((maskMsb - 1u) | maskMsb) << offset;\n"
" uint baseMask = ~insertMask;\n"
" uint4 resultUnsigned = (asuint(base) & baseMask) | ((asuint(insert) << offset) & "
"insertMask);\n"
" return asint(resultUnsigned);\n"
"}\n");
emu->addEmulatedFunction(EOpUaddCarry, uint1, uint1, uint1,
"uint webgl_uaddCarry_emu(uint x, uint y, out uint carry)\n"
"{\n"
" carry = uint(x > (0xffffffffu - y));\n"
" return x + y;\n"
"}\n");
emu->addEmulatedFunction(EOpUaddCarry, uint2, uint2, uint2,
"uint2 webgl_uaddCarry_emu(uint2 x, uint2 y, out uint2 carry)\n"
"{\n"
" carry = uint2(x > (0xffffffffu - y));\n"
" return x + y;\n"
"}\n");
emu->addEmulatedFunction(EOpUaddCarry, uint3, uint3, uint3,
"uint3 webgl_uaddCarry_emu(uint3 x, uint3 y, out uint3 carry)\n"
"{\n"
" carry = uint3(x > (0xffffffffu - y));\n"
" return x + y;\n"
"}\n");
emu->addEmulatedFunction(EOpUaddCarry, uint4, uint4, uint4,
"uint4 webgl_uaddCarry_emu(uint4 x, uint4 y, out uint4 carry)\n"
"{\n"
" carry = uint4(x > (0xffffffffu - y));\n"
" return x + y;\n"
"}\n");
emu->addEmulatedFunction(EOpUsubBorrow, uint1, uint1, uint1,
"uint webgl_usubBorrow_emu(uint x, uint y, out uint borrow)\n"
"{\n"
" borrow = uint(x < y);\n"
" return x - y;\n"
"}\n");
emu->addEmulatedFunction(EOpUsubBorrow, uint2, uint2, uint2,
"uint2 webgl_usubBorrow_emu(uint2 x, uint2 y, out uint2 borrow)\n"
"{\n"
" borrow = uint2(x < y);\n"
" return x - y;\n"
"}\n");
emu->addEmulatedFunction(EOpUsubBorrow, uint3, uint3, uint3,
"uint3 webgl_usubBorrow_emu(uint3 x, uint3 y, out uint3 borrow)\n"
"{\n"
" borrow = uint3(x < y);\n"
" return x - y;\n"
"}\n");
emu->addEmulatedFunction(EOpUsubBorrow, uint4, uint4, uint4,
"uint4 webgl_usubBorrow_emu(uint4 x, uint4 y, out uint4 borrow)\n"
"{\n"
" borrow = uint4(x < y);\n"
" return x - y;\n"
"}\n");
// (a + b2^16) * (c + d2^16) = ac + (ad + bc) * 2^16 + bd * 2^32
// Also note that below, a * d + ((a * c) >> 16) is guaranteed not to overflow, because:
// a <= 0xffff, d <= 0xffff, ((a * c) >> 16) <= 0xffff and 0xffff * 0xffff + 0xffff = 0xffff0000
BuiltInFunctionEmulator::FunctionId umulExtendedUint1 = emu->addEmulatedFunction(
EOpUmulExtended, uint1, uint1, uint1, uint1,
"void webgl_umulExtended_emu(uint x, uint y, out uint msb, out uint lsb)\n"
"{\n"
" lsb = x * y;\n"
" uint a = (x & 0xffffu);\n"
" uint b = (x >> 16);\n"
" uint c = (y & 0xffffu);\n"
" uint d = (y >> 16);\n"
" uint ad = a * d + ((a * c) >> 16);\n"
" uint bc = b * c;\n"
" uint carry = uint(ad > (0xffffffffu - bc));\n"
" msb = ((ad + bc) >> 16) + (carry << 16) + b * d;\n"
"}\n");
emu->addEmulatedFunctionWithDependency(
umulExtendedUint1, EOpUmulExtended, uint2, uint2, uint2, uint2,
"void webgl_umulExtended_emu(uint2 x, uint2 y, out uint2 msb, out uint2 lsb)\n"
"{\n"
" webgl_umulExtended_emu(x.x, y.x, msb.x, lsb.x);\n"
" webgl_umulExtended_emu(x.y, y.y, msb.y, lsb.y);\n"
"}\n");
emu->addEmulatedFunctionWithDependency(
umulExtendedUint1, EOpUmulExtended, uint3, uint3, uint3, uint3,
"void webgl_umulExtended_emu(uint3 x, uint3 y, out uint3 msb, out uint3 lsb)\n"
"{\n"
" webgl_umulExtended_emu(x.x, y.x, msb.x, lsb.x);\n"
" webgl_umulExtended_emu(x.y, y.y, msb.y, lsb.y);\n"
" webgl_umulExtended_emu(x.z, y.z, msb.z, lsb.z);\n"
"}\n");
emu->addEmulatedFunctionWithDependency(
umulExtendedUint1, EOpUmulExtended, uint4, uint4, uint4, uint4,
"void webgl_umulExtended_emu(uint4 x, uint4 y, out uint4 msb, out uint4 lsb)\n"
"{\n"
" webgl_umulExtended_emu(x.x, y.x, msb.x, lsb.x);\n"
" webgl_umulExtended_emu(x.y, y.y, msb.y, lsb.y);\n"
" webgl_umulExtended_emu(x.z, y.z, msb.z, lsb.z);\n"
" webgl_umulExtended_emu(x.w, y.w, msb.w, lsb.w);\n"
"}\n");
// The imul emulation does two's complement negation on the lsb and msb manually in case the
// result needs to be negative.
// TODO(oetuaho): Note that this code doesn't take one edge case into account, where x or y is
// -2^31. abs(-2^31) is undefined.
BuiltInFunctionEmulator::FunctionId imulExtendedInt1 = emu->addEmulatedFunctionWithDependency(
umulExtendedUint1, EOpImulExtended, int1, int1, int1, int1,
"void webgl_imulExtended_emu(int x, int y, out int msb, out int lsb)\n"
"{\n"
" uint unsignedMsb;\n"
" uint unsignedLsb;\n"
" bool negative = (x < 0) != (y < 0);\n"
" webgl_umulExtended_emu(uint(abs(x)), uint(abs(y)), unsignedMsb, unsignedLsb);\n"
" lsb = asint(unsignedLsb);\n"
" msb = asint(unsignedMsb);\n"
" if (negative)\n"
" {\n"
" lsb = ~lsb;\n"
" msb = ~msb;\n"
" if (lsb == 0xffffffff)\n"
" {\n"
" lsb = 0;\n"
" msb += 1;\n"
" }\n"
" else\n"
" {\n"
" lsb += 1;\n"
" }\n"
" }\n"
"}\n");
emu->addEmulatedFunctionWithDependency(
imulExtendedInt1, EOpImulExtended, int2, int2, int2, int2,
"void webgl_imulExtended_emu(int2 x, int2 y, out int2 msb, out int2 lsb)\n"
"{\n"
" webgl_imulExtended_emu(x.x, y.x, msb.x, lsb.x);\n"
" webgl_imulExtended_emu(x.y, y.y, msb.y, lsb.y);\n"
"}\n");
emu->addEmulatedFunctionWithDependency(
imulExtendedInt1, EOpImulExtended, int3, int3, int3, int3,
"void webgl_imulExtended_emu(int3 x, int3 y, out int3 msb, out int3 lsb)\n"
"{\n"
" webgl_imulExtended_emu(x.x, y.x, msb.x, lsb.x);\n"
" webgl_imulExtended_emu(x.y, y.y, msb.y, lsb.y);\n"
" webgl_imulExtended_emu(x.z, y.z, msb.z, lsb.z);\n"
"}\n");
emu->addEmulatedFunctionWithDependency(
imulExtendedInt1, EOpImulExtended, int4, int4, int4, int4,
"void webgl_imulExtended_emu(int4 x, int4 y, out int4 msb, out int4 lsb)\n"
"{\n"
" webgl_imulExtended_emu(x.x, y.x, msb.x, lsb.x);\n"
" webgl_imulExtended_emu(x.y, y.y, msb.y, lsb.y);\n"
" webgl_imulExtended_emu(x.z, y.z, msb.z, lsb.z);\n"
" webgl_imulExtended_emu(x.w, y.w, msb.w, lsb.w);\n"
"}\n");
}
} // namespace sh
......@@ -110,15 +110,9 @@ void InsertBuiltInFunctions(sh::GLenum type,
symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpSmoothStep, genType, genType, genType, genType);
symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpSmoothStep, genType, float1, float1, genType);
const TType *outFloat1 = TCache::getType(EbtFloat, EvqOut);
const TType *outFloat2 = TCache::getType(EbtFloat, EvqOut, 2);
const TType *outFloat3 = TCache::getType(EbtFloat, EvqOut, 3);
const TType *outFloat4 = TCache::getType(EbtFloat, EvqOut, 4);
const TType *outGenType = TCache::getType(EbtGenType, EvqOut);
symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpModf, float1, float1, outFloat1);
symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpModf, float2, float2, outFloat2);
symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpModf, float3, float3, outFloat3);
symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpModf, float4, float4, outFloat4);
symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpModf, genType, genType, outGenType);
symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpIsNan, genBType, genType);
symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpIsInf, genBType, genType);
......@@ -231,6 +225,37 @@ void InsertBuiltInFunctions(sh::GLenum type,
symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpAll, bool1, bvec);
symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpLogicalNotComponentWise, bvec, bvec);
//
// 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);
symbolTable.insertBuiltInOp(ESSL3_1_BUILTINS, EOpBitfieldExtract, genUType, genUType, int1,
int1);
symbolTable.insertBuiltInOp(ESSL3_1_BUILTINS, EOpBitfieldInsert, genIType, genIType, genIType,
int1, int1);
symbolTable.insertBuiltInOp(ESSL3_1_BUILTINS, EOpBitfieldInsert, genUType, genUType, genUType,
int1, int1);
symbolTable.insertBuiltInOp(ESSL3_1_BUILTINS, EOpBitfieldReverse, genIType, genIType);
symbolTable.insertBuiltInOp(ESSL3_1_BUILTINS, EOpBitfieldReverse, genUType, genUType);
symbolTable.insertBuiltInOp(ESSL3_1_BUILTINS, EOpBitCount, genIType, genIType);
symbolTable.insertBuiltInOp(ESSL3_1_BUILTINS, EOpBitCount, genIType, genUType);
symbolTable.insertBuiltInOp(ESSL3_1_BUILTINS, EOpFindLSB, genIType, genIType);
symbolTable.insertBuiltInOp(ESSL3_1_BUILTINS, EOpFindLSB, genIType, genUType);
symbolTable.insertBuiltInOp(ESSL3_1_BUILTINS, EOpFindMSB, genIType, genIType);
symbolTable.insertBuiltInOp(ESSL3_1_BUILTINS, EOpFindMSB, genIType, genUType);
symbolTable.insertBuiltInOp(ESSL3_1_BUILTINS, EOpUaddCarry, genUType, genUType, genUType,
outGenUType);
symbolTable.insertBuiltInOp(ESSL3_1_BUILTINS, EOpUsubBorrow, genUType, genUType, genUType,
outGenUType);
symbolTable.insertBuiltInOp(ESSL3_1_BUILTINS, EOpUmulExtended, voidType, genUType, genUType,
outGenUType, outGenUType);
symbolTable.insertBuiltInOp(ESSL3_1_BUILTINS, EOpImulExtended, voidType, genIType, genIType,
outGenIType, outGenIType);
const TType *sampler2D = TCache::getType(EbtSampler2D);
const TType *samplerCube = TCache::getType(EbtSamplerCube);
......
......@@ -306,10 +306,41 @@ void TIntermAggregate::setPrecisionFromChildren()
mType.setPrecision(precision);
}
void TIntermAggregate::setPrecisionForBuiltInOp()
{
ASSERT(!isConstructor());
ASSERT(mOp != EOpFunctionCall);
if (!setPrecisionForSpecialBuiltInOp())
{
setPrecisionFromChildren();
}
}
bool TIntermAggregate::setPrecisionForSpecialBuiltInOp()
{
switch (mOp)
{
case EOpBitfieldExtract:
mType.setPrecision(mSequence[0]->getAsTyped()->getPrecision());
return true;
case EOpBitfieldInsert:
mType.setPrecision(GetHigherPrecision(mSequence[0]->getAsTyped()->getPrecision(),
mSequence[1]->getAsTyped()->getPrecision()));
return true;
case EOpUaddCarry:
case EOpUsubBorrow:
mType.setPrecision(EbpHigh);
return true;
default:
return false;
}
}
void TIntermAggregate::setBuiltInFunctionPrecision()
{
// All built-ins returning bool should be handled as ops, not functions.
ASSERT(getBasicType() != EbtBool);
ASSERT(getOp() == EOpFunctionCall);
TPrecision precision = EbpUndefined;
TIntermSequence::iterator childIter = mSequence.begin();
......@@ -764,6 +795,18 @@ void TIntermUnary::promote()
case EOpIsNan:
setType(TType(EbtBool, EbpUndefined, resultQualifier, operandPrimarySize));
break;
case EOpBitfieldReverse:
setType(TType(mOperand->getBasicType(), EbpHigh, resultQualifier, operandPrimarySize));
break;
case EOpBitCount:
setType(TType(EbtInt, EbpLow, resultQualifier, operandPrimarySize));
break;
case EOpFindLSB:
setType(TType(EbtInt, EbpLow, resultQualifier, operandPrimarySize));
break;
case EOpFindMSB:
setType(TType(EbtInt, EbpLow, resultQualifier, operandPrimarySize));
break;
default:
setType(mOperand->getType());
mType.setQualifier(resultQualifier);
......@@ -2151,7 +2194,82 @@ TConstantUnion *TIntermConstantUnion::foldUnaryComponentWise(TOperator op,
diagnostics, &resultArray[i]);
break;
}
case EOpBitfieldReverse:
{
uint32_t value;
if (getType().getBasicType() == EbtInt)
{
value = static_cast<uint32_t>(operandArray[i].getIConst());
}
else
{
ASSERT(getType().getBasicType() == EbtUInt);
value = operandArray[i].getUConst();
}
uint32_t result = gl::BitfieldReverse(value);
if (getType().getBasicType() == EbtInt)
{
resultArray[i].setIConst(static_cast<int32_t>(result));
}
else
{
resultArray[i].setUConst(result);
}
break;
}
case EOpBitCount:
{
uint32_t value;
if (getType().getBasicType() == EbtInt)
{
value = static_cast<uint32_t>(operandArray[i].getIConst());
}
else
{
ASSERT(getType().getBasicType() == EbtUInt);
value = operandArray[i].getUConst();
}
int result = gl::BitCount(value);
resultArray[i].setIConst(result);
break;
}
case EOpFindLSB:
{
uint32_t value;
if (getType().getBasicType() == EbtInt)
{
value = static_cast<uint32_t>(operandArray[i].getIConst());
}
else
{
ASSERT(getType().getBasicType() == EbtUInt);
value = operandArray[i].getUConst();
}
resultArray[i].setIConst(gl::FindLSB(value));
break;
}
case EOpFindMSB:
{
uint32_t value;
if (getType().getBasicType() == EbtInt)
{
int intValue = operandArray[i].getIConst();
value = static_cast<uint32_t>(intValue);
if (intValue < 0)
{
// Look for zero instead of one in value. This also handles the intValue ==
// -1 special case, where the return value needs to be -1.
value = ~value;
}
}
else
{
ASSERT(getType().getBasicType() == EbtUInt);
value = operandArray[i].getUConst();
}
resultArray[i].setIConst(gl::FindMSB(value));
break;
}
case EOpDFdx:
case EOpDFdy:
case EOpFwidth:
......@@ -2834,6 +2952,110 @@ TConstantUnion *TIntermConstantUnion::FoldAggregateBuiltIn(TIntermAggregate *agg
}
break;
}
case EOpBitfieldExtract:
{
resultArray = new TConstantUnion[maxObjectSize];
for (size_t i = 0; i < maxObjectSize; ++i)
{
int offset = unionArrays[1][0].getIConst();
int bits = unionArrays[2][0].getIConst();
if (bits == 0)
{
if (aggregate->getBasicType() == EbtInt)
{
resultArray[i].setIConst(0);
}
else
{
ASSERT(aggregate->getBasicType() == EbtUInt);
resultArray[i].setUConst(0);
}
}
else if (offset < 0 || bits < 0 || offset >= 32 || bits > 32 || offset + bits > 32)
{
UndefinedConstantFoldingError(loc, op, aggregate->getBasicType(), diagnostics,
&resultArray[i]);
}
else
{
// bits can be 32 here, so we need to avoid bit shift overflow.
uint32_t maskMsb = 1u << (bits - 1);
uint32_t mask = ((maskMsb - 1u) | maskMsb) << offset;
if (aggregate->getBasicType() == EbtInt)
{
uint32_t value = static_cast<uint32_t>(unionArrays[0][i].getIConst());
uint32_t resultUnsigned = (value & mask) >> offset;
if ((resultUnsigned & maskMsb) != 0)
{
// The most significant bits (from bits+1 to the most significant bit)
// should be set to 1.
uint32_t higherBitsMask = ((1u << (32 - bits)) - 1u) << bits;
resultUnsigned |= higherBitsMask;
}
resultArray[i].setIConst(static_cast<int32_t>(resultUnsigned));
}
else
{
ASSERT(aggregate->getBasicType() == EbtUInt);
uint32_t value = unionArrays[0][i].getUConst();
resultArray[i].setUConst((value & mask) >> offset);
}
}
}
break;
}
case EOpBitfieldInsert:
{
resultArray = new TConstantUnion[maxObjectSize];
for (size_t i = 0; i < maxObjectSize; ++i)
{
int offset = unionArrays[2][0].getIConst();
int bits = unionArrays[3][0].getIConst();
if (bits == 0)
{
if (aggregate->getBasicType() == EbtInt)
{
int32_t base = unionArrays[0][i].getIConst();
resultArray[i].setIConst(base);
}
else
{
ASSERT(aggregate->getBasicType() == EbtUInt);
uint32_t base = unionArrays[0][i].getUConst();
resultArray[i].setUConst(base);
}
}
else if (offset < 0 || bits < 0 || offset >= 32 || bits > 32 || offset + bits > 32)
{
UndefinedConstantFoldingError(loc, op, aggregate->getBasicType(), diagnostics,
&resultArray[i]);
}
else
{
// bits can be 32 here, so we need to avoid bit shift overflow.
uint32_t maskMsb = 1u << (bits - 1);
uint32_t insertMask = ((maskMsb - 1u) | maskMsb) << offset;
uint32_t baseMask = ~insertMask;
if (aggregate->getBasicType() == EbtInt)
{
uint32_t base = static_cast<uint32_t>(unionArrays[0][i].getIConst());
uint32_t insert = static_cast<uint32_t>(unionArrays[1][i].getIConst());
uint32_t resultUnsigned =
(base & baseMask) | ((insert << offset) & insertMask);
resultArray[i].setIConst(static_cast<int32_t>(resultUnsigned));
}
else
{
ASSERT(aggregate->getBasicType() == EbtUInt);
uint32_t base = unionArrays[0][i].getUConst();
uint32_t insert = unionArrays[1][i].getUConst();
resultArray[i].setUConst((base & baseMask) |
((insert << offset) & insertMask));
}
}
}
break;
}
default:
UNREACHABLE();
......
......@@ -618,7 +618,12 @@ class TIntermAggregate : public TIntermOperator, public TIntermAggregateBase
bool getUseEmulatedFunction() { return mUseEmulatedFunction; }
bool areChildrenConstQualified();
void setPrecisionForBuiltInOp();
void setPrecisionFromChildren();
// Used for built-in functions under EOpFunctionCall.
void setBuiltInFunctionPrecision();
// Returns true if changing parameter precision may affect the return value.
......@@ -641,6 +646,9 @@ class TIntermAggregate : public TIntermOperator, public TIntermAggregateBase
private:
TIntermAggregate(const TIntermAggregate &node); // note: not deleted, just private!
// Returns true if precision was set according to special rules for this built-in.
bool setPrecisionForSpecialBuiltInOp();
};
// A list of statements. Either the root node which contains declarations and function definitions,
......
......@@ -378,6 +378,8 @@ TIntermTyped *TIntermediate::foldAggregateBuiltIn(TIntermAggregate *aggregate,
case EOpFaceForward:
case EOpReflect:
case EOpRefract:
case EOpBitfieldExtract:
case EOpBitfieldInsert:
return aggregate->fold(diagnostics);
default:
// TODO: Add support for folding array constructors
......
......@@ -252,6 +252,27 @@ const char *GetOperatorString(TOperator op)
case EOpLogicalNotComponentWise:
return "not";
case EOpBitfieldExtract:
return "bitfieldExtract";
case EOpBitfieldInsert:
return "bitfieldInsert";
case EOpBitfieldReverse:
return "bitfieldReverse";
case EOpBitCount:
return "bitCount";
case EOpFindLSB:
return "findLSB";
case EOpFindMSB:
return "findMSB";
case EOpUaddCarry:
return "uaddCarry";
case EOpUsubBorrow:
return "usubBorrow";
case EOpUmulExtended:
return "umulExtended";
case EOpImulExtended:
return "imulExtended";
case EOpKill:
return "kill";
case EOpReturn:
......
......@@ -160,6 +160,17 @@ enum TOperator
EOpAll,
EOpLogicalNotComponentWise,
EOpBitfieldExtract,
EOpBitfieldInsert,
EOpBitfieldReverse,
EOpBitCount,
EOpFindLSB,
EOpFindMSB,
EOpUaddCarry,
EOpUsubBorrow,
EOpUmulExtended,
EOpImulExtended,
//
// Branch
//
......
......@@ -725,6 +725,10 @@ bool TOutputGLSLBase::visitUnary(Visit visit, TIntermUnary *node)
case EOpAny:
case EOpAll:
case EOpLogicalNotComponentWise:
case EOpBitfieldReverse:
case EOpBitCount:
case EOpFindLSB:
case EOpFindMSB:
writeBuiltInFunctionTriplet(visit, node->getOp(), node->getUseEmulatedFunction());
return true;
default:
......@@ -935,6 +939,12 @@ bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate *node)
case EOpRefract:
case EOpMulMatrixComponentWise:
case EOpOuterProduct:
case EOpBitfieldExtract:
case EOpBitfieldInsert:
case EOpUaddCarry:
case EOpUsubBorrow:
case EOpUmulExtended:
case EOpImulExtended:
case EOpBarrier:
case EOpMemoryBarrier:
case EOpMemoryBarrierAtomicCounter:
......
......@@ -1473,6 +1473,22 @@ bool OutputHLSL::visitUnary(Visit visit, TIntermUnary *node)
case EOpLogicalNotComponentWise:
outputTriplet(out, visit, "(!", "", ")");
break;
case EOpBitfieldReverse:
outputTriplet(out, visit, "reversebits(", "", ")");
break;
case EOpBitCount:
outputTriplet(out, visit, "countbits(", "", ")");
break;
case EOpFindLSB:
// Note that it's unclear from the HLSL docs what this returns for 0, but this is tested
// in GLSLTest and results are consistent with GL.
outputTriplet(out, visit, "firstbitlow(", "", ")");
break;
case EOpFindMSB:
// Note that it's unclear from the HLSL docs what this returns for 0 or -1, but this is
// tested in GLSLTest and results are consistent with GL.
outputTriplet(out, visit, "firstbithigh(", "", ")");
break;
default:
UNREACHABLE();
}
......@@ -1997,6 +2013,15 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node)
case EOpMulMatrixComponentWise:
outputTriplet(out, visit, "(", " * ", ")");
break;
case EOpBitfieldExtract:
case EOpBitfieldInsert:
case EOpUaddCarry:
case EOpUsubBorrow:
case EOpUmulExtended:
case EOpImulExtended:
ASSERT(node->getUseEmulatedFunction());
writeEmulatedFunctionTriplet(out, visit, node->getOp());
break;
default:
UNREACHABLE();
}
......
......@@ -4432,7 +4432,7 @@ TIntermTyped *TParseContext::addFunctionCallOrMethod(TFunction *fnCall,
TIntermAggregate *aggregate =
intermediate.setAggregateOperator(paramNode, op, loc);
aggregate->setType(fnCandidate->getReturnType());
aggregate->setPrecisionFromChildren();
aggregate->setPrecisionForBuiltInOp();
if (aggregate->areChildrenConstQualified())
{
aggregate->getTypePointer()->setQualifier(EvqConst);
......
......@@ -223,13 +223,14 @@ const TType *SpecificType(const TType *type, int size)
switch (type->getBasicType())
{
case EbtGenType:
return TCache::getType(EbtFloat, static_cast<unsigned char>(size));
return TCache::getType(EbtFloat, type->getQualifier(),
static_cast<unsigned char>(size));
case EbtGenIType:
return TCache::getType(EbtInt, static_cast<unsigned char>(size));
return TCache::getType(EbtInt, type->getQualifier(), static_cast<unsigned char>(size));
case EbtGenUType:
return TCache::getType(EbtUInt, static_cast<unsigned char>(size));
return TCache::getType(EbtUInt, type->getQualifier(), static_cast<unsigned char>(size));
case EbtGenBType:
return TCache::getType(EbtBool, static_cast<unsigned char>(size));
return TCache::getType(EbtBool, type->getQualifier(), static_cast<unsigned char>(size));
default:
return type;
}
......@@ -364,18 +365,19 @@ void TSymbolTable::insertBuiltIn(ESymbolLevel level,
insertBuiltIn(level, rvalue, name, unsignedImage, ptype2, ptype3, ptype4, ptype5);
}
}
else if (IsGenType(rvalue) || IsGenType(ptype1) || IsGenType(ptype2) || IsGenType(ptype3))
else if (IsGenType(rvalue) || IsGenType(ptype1) || IsGenType(ptype2) || IsGenType(ptype3) ||
IsGenType(ptype4))
{
ASSERT(!ptype4 && !ptype5);
ASSERT(!ptype5);
insertUnmangledBuiltInName(name, level);
insertBuiltIn(level, op, ext, SpecificType(rvalue, 1), name, SpecificType(ptype1, 1),
SpecificType(ptype2, 1), SpecificType(ptype3, 1));
SpecificType(ptype2, 1), SpecificType(ptype3, 1), SpecificType(ptype4, 1));
insertBuiltIn(level, op, ext, SpecificType(rvalue, 2), name, SpecificType(ptype1, 2),
SpecificType(ptype2, 2), SpecificType(ptype3, 2));
SpecificType(ptype2, 2), SpecificType(ptype3, 2), SpecificType(ptype4, 2));
insertBuiltIn(level, op, ext, SpecificType(rvalue, 3), name, SpecificType(ptype1, 3),
SpecificType(ptype2, 3), SpecificType(ptype3, 3));
SpecificType(ptype2, 3), SpecificType(ptype3, 3), SpecificType(ptype4, 3));
insertBuiltIn(level, op, ext, SpecificType(rvalue, 4), name, SpecificType(ptype1, 4),
SpecificType(ptype2, 4), SpecificType(ptype3, 4));
SpecificType(ptype2, 4), SpecificType(ptype3, 4), SpecificType(ptype4, 4));
}
else if (IsVecType(rvalue) || IsVecType(ptype1) || IsVecType(ptype2) || IsVecType(ptype3))
{
......
......@@ -1244,3 +1244,112 @@ TEST_F(ConstantFoldingExpressionTest, FoldDivideByInfinity)
evaluateFloat(floatString);
ASSERT_TRUE(constantFoundInAST(0.0f));
}
// Test that unsigned bitfieldExtract is folded correctly.
TEST_F(ConstantFoldingExpressionTest, FoldUnsignedBitfieldExtract)
{
const std::string &uintString = "bitfieldExtract(0x00110000u, 16, 5)";
evaluateUint(uintString);
ASSERT_TRUE(constantFoundInAST(0x11u));
}
// Test that unsigned bitfieldExtract to extract 32 bits is folded correctly.
TEST_F(ConstantFoldingExpressionTest, FoldUnsignedBitfieldExtract32Bits)
{
const std::string &uintString = "bitfieldExtract(0xff0000ffu, 0, 32)";
evaluateUint(uintString);
ASSERT_TRUE(constantFoundInAST(0xff0000ffu));
}
// Test that signed bitfieldExtract is folded correctly. The higher bits should be set to 1 if the
// most significant bit of the extracted value is 1.
TEST_F(ConstantFoldingExpressionTest, FoldSignedBitfieldExtract)
{
const std::string &intString = "bitfieldExtract(0x00110000, 16, 5)";
evaluateInt(intString);
// 0xfffffff1 == -15
ASSERT_TRUE(constantFoundInAST(-15));
}
// Test that bitfieldInsert is folded correctly.
TEST_F(ConstantFoldingExpressionTest, FoldBitfieldInsert)
{
const std::string &uintString = "bitfieldInsert(0x04501701u, 0x11u, 8, 5)";
evaluateUint(uintString);
ASSERT_TRUE(constantFoundInAST(0x04501101u));
}
// Test that bitfieldInsert to insert 32 bits is folded correctly.
TEST_F(ConstantFoldingExpressionTest, FoldBitfieldInsert32Bits)
{
const std::string &uintString = "bitfieldInsert(0xff0000ffu, 0x11u, 0, 32)";
evaluateUint(uintString);
ASSERT_TRUE(constantFoundInAST(0x11u));
}
// Test that bitfieldReverse is folded correctly.
TEST_F(ConstantFoldingExpressionTest, FoldBitfieldReverse)
{
const std::string &uintString = "bitfieldReverse((1u << 4u) | (1u << 7u))";
evaluateUint(uintString);
uint32_t flag1 = 1u << (31u - 4u);
uint32_t flag2 = 1u << (31u - 7u);
ASSERT_TRUE(constantFoundInAST(flag1 | flag2));
}
// Test that bitCount is folded correctly.
TEST_F(ConstantFoldingExpressionTest, FoldBitCount)
{
const std::string &intString = "bitCount(0x17103121u)";
evaluateInt(intString);
ASSERT_TRUE(constantFoundInAST(10));
}
// Test that findLSB is folded correctly.
TEST_F(ConstantFoldingExpressionTest, FoldFindLSB)
{
const std::string &intString = "findLSB(0x80010000u)";
evaluateInt(intString);
ASSERT_TRUE(constantFoundInAST(16));
}
// Test that findLSB is folded correctly when the operand is zero.
TEST_F(ConstantFoldingExpressionTest, FoldFindLSBZero)
{
const std::string &intString = "findLSB(0u)";
evaluateInt(intString);
ASSERT_TRUE(constantFoundInAST(-1));
}
// Test that findMSB is folded correctly.
TEST_F(ConstantFoldingExpressionTest, FoldFindMSB)
{
const std::string &intString = "findMSB(0x01000008u)";
evaluateInt(intString);
ASSERT_TRUE(constantFoundInAST(24));
}
// Test that findMSB is folded correctly when the operand is zero.
TEST_F(ConstantFoldingExpressionTest, FoldFindMSBZero)
{
const std::string &intString = "findMSB(0u)";
evaluateInt(intString);
ASSERT_TRUE(constantFoundInAST(-1));
}
// Test that findMSB is folded correctly for a negative integer.
// It is supposed to return the index of the most significant bit set to 0.
TEST_F(ConstantFoldingExpressionTest, FoldFindMSBNegativeInt)
{
const std::string &intString = "findMSB(-8)";
evaluateInt(intString);
ASSERT_TRUE(constantFoundInAST(2));
}
// Test that findMSB is folded correctly for -1.
TEST_F(ConstantFoldingExpressionTest, FoldFindMSBMinusOne)
{
const std::string &intString = "findMSB(-1)";
evaluateInt(intString);
ASSERT_TRUE(constantFoundInAST(-1));
}
......@@ -27,7 +27,7 @@ class TypeTrackingTest : public testing::Test
InitBuiltInResources(&resources);
resources.FragmentPrecisionHigh = 1;
mTranslator = new TranslatorESSL(GL_FRAGMENT_SHADER, SH_GLES3_SPEC);
mTranslator = new TranslatorESSL(GL_FRAGMENT_SHADER, SH_GLES3_1_SPEC);
ASSERT_TRUE(mTranslator->Init(resources));
}
......@@ -454,3 +454,192 @@ TEST_F(TypeTrackingTest, BuiltInIntBitsToFloatResultTypeAndPrecision)
ASSERT_TRUE(foundInIntermediateTree("intBitsToFloat (highp float)"));
ASSERT_TRUE(foundInIntermediateTree("uintBitsToFloat (highp float)"));
}
// Test that bitfieldExtract returns a precision consistent with its "value" parameter.
TEST_F(TypeTrackingTest, BuiltInBitfieldExtractResultTypeAndPrecision)
{
const std::string &shaderString =
"#version 310 es\n"
"precision mediump float;\n"
"uniform mediump int i;\n"
"uniform highp uint u;\n"
"uniform lowp int offset;\n"
"uniform highp int bits;\n"
"out vec4 my_FragColor;\n"
"void main() {\n"
" lowp int i2 = bitfieldExtract(i, offset, bits);\n"
" lowp uint u2 = bitfieldExtract(u, offset, bits);\n"
" my_FragColor = vec4(i2, u2, 0.0, 1.0); \n"
"}\n";
compile(shaderString);
ASSERT_FALSE(foundErrorInIntermediateTree());
ASSERT_TRUE(foundInIntermediateTree("bitfieldExtract (mediump int)"));
ASSERT_TRUE(foundInIntermediateTree("bitfieldExtract (highp uint)"));
}
// Test that signed bitfieldInsert returns a precision consistent with its "base/insert" parameters.
TEST_F(TypeTrackingTest, BuiltInBitfieldInsertResultTypeAndPrecision)
{
const std::string &shaderString =
"#version 310 es\n"
"precision mediump float;\n"
"uniform lowp int iBase;\n"
"uniform mediump int iInsert;\n"
"uniform highp uint uBase;\n"
"uniform mediump uint uInsert;\n"
"uniform highp int offset;\n"
"uniform highp int bits;\n"
"out vec4 my_FragColor;\n"
"void main() {\n"
" lowp int i = bitfieldInsert(iBase, iInsert, offset, bits);\n"
" lowp uint u = bitfieldInsert(uBase, uInsert, offset, bits);\n"
" my_FragColor = vec4(i, u, 0.0, 1.0); \n"
"}\n";
compile(shaderString);
ASSERT_FALSE(foundErrorInIntermediateTree());
ASSERT_TRUE(foundInIntermediateTree("bitfieldInsert (mediump int)"));
ASSERT_TRUE(foundInIntermediateTree("bitfieldInsert (highp uint)"));
}
// Test that signed bitfieldInsert returns a precision consistent with its "base/insert" parameters.
// Another variation on parameter precisions.
TEST_F(TypeTrackingTest, BuiltInBitfieldInsertResultTypeAndPrecision2)
{
const std::string &shaderString =
"#version 310 es\n"
"precision mediump float;\n"
"uniform highp int iBase;\n"
"uniform mediump int iInsert;\n"
"uniform lowp uint uBase;\n"
"uniform mediump uint uInsert;\n"
"uniform lowp int offset;\n"
"uniform lowp int bits;\n"
"out vec4 my_FragColor;\n"
"void main() {\n"
" lowp int i = bitfieldInsert(iBase, iInsert, offset, bits);\n"
" lowp uint u = bitfieldInsert(uBase, uInsert, offset, bits);\n"
" my_FragColor = vec4(i, u, 0.0, 1.0); \n"
"}\n";
compile(shaderString);
ASSERT_FALSE(foundErrorInIntermediateTree());
ASSERT_TRUE(foundInIntermediateTree("bitfieldInsert (highp int)"));
ASSERT_TRUE(foundInIntermediateTree("bitfieldInsert (mediump uint)"));
}
// Test that bitfieldReverse always results in highp precision.
TEST_F(TypeTrackingTest, BuiltInBitfieldReversePrecision)
{
const std::string &shaderString =
"#version 310 es\n"
"precision mediump float;\n"
"uniform lowp uint u;\n"
"uniform mediump int i;\n"
"out vec4 my_FragColor;\n"
"void main() {\n"
" lowp uint u2 = bitfieldReverse(u);\n"
" lowp int i2 = bitfieldReverse(i);\n"
" my_FragColor = vec4(u2, i2, 0.0, 1.0); \n"
"}\n";
compile(shaderString);
ASSERT_FALSE(foundErrorInIntermediateTree());
ASSERT_TRUE(foundInIntermediateTree("bitfieldReverse (highp uint)"));
ASSERT_TRUE(foundInIntermediateTree("bitfieldReverse (highp int)"));
}
// Test that bitCount always results in lowp precision integer.
TEST_F(TypeTrackingTest, BuiltInBitCountTypeAndPrecision)
{
const std::string &shaderString =
"#version 310 es\n"
"precision mediump float;\n"
"uniform highp uint u;\n"
"uniform mediump int i;\n"
"out vec4 my_FragColor;\n"
"void main() {\n"
" highp int count1 = bitCount(u);\n"
" highp int count2 = bitCount(i);\n"
" my_FragColor = vec4(count1, count2, 0.0, 1.0); \n"
"}\n";
compile(shaderString);
ASSERT_FALSE(foundErrorInIntermediateTree());
ASSERT_TRUE(foundInIntermediateTree("bitCount (lowp int)"));
ASSERT_FALSE(foundInIntermediateTree("bitCount (lowp uint)"));
}
// Test that findLSB always results in a lowp precision integer.
TEST_F(TypeTrackingTest, BuiltInFindLSBTypeAndPrecision)
{
const std::string &shaderString =
"#version 310 es\n"
"precision mediump float;\n"
"uniform highp uint u;\n"
"uniform mediump int i;\n"
"out vec4 my_FragColor;\n"
"void main() {\n"
" highp int index1 = findLSB(u);\n"
" highp int index2 = findLSB(i);\n"
" my_FragColor = vec4(index1, index2, 0.0, 1.0); \n"
"}\n";
compile(shaderString);
ASSERT_FALSE(foundErrorInIntermediateTree());
ASSERT_TRUE(foundInIntermediateTree("findLSB (lowp int)"));
ASSERT_FALSE(foundInIntermediateTree("findLSB (lowp uint)"));
}
// Test that findMSB always results in a lowp precision integer.
TEST_F(TypeTrackingTest, BuiltInFindMSBTypeAndPrecision)
{
const std::string &shaderString =
"#version 310 es\n"
"precision mediump float;\n"
"uniform highp uint u;\n"
"uniform mediump int i;\n"
"out vec4 my_FragColor;\n"
"void main() {\n"
" highp int index1 = findMSB(u);\n"
" highp int index2 = findMSB(i);\n"
" my_FragColor = vec4(index1, index2, 0.0, 1.0); \n"
"}\n";
compile(shaderString);
ASSERT_FALSE(foundErrorInIntermediateTree());
ASSERT_TRUE(foundInIntermediateTree("findMSB (lowp int)"));
ASSERT_FALSE(foundInIntermediateTree("findMSB (lowp uint)"));
}
// Test that uaddCarry always results in highp precision.
TEST_F(TypeTrackingTest, BuiltInUaddCarryPrecision)
{
const std::string &shaderString =
"#version 310 es\n"
"precision mediump float;\n"
"uniform mediump uvec2 x;\n"
"uniform mediump uvec2 y;\n"
"out vec4 my_FragColor;\n"
"void main() {\n"
" lowp uvec2 carry;\n"
" mediump uvec2 result = uaddCarry(x, y, carry);\n"
" my_FragColor = vec4(result.x, carry.y, 0.0, 1.0); \n"
"}\n";
compile(shaderString);
ASSERT_FALSE(foundErrorInIntermediateTree());
ASSERT_TRUE(foundInIntermediateTree("uaddCarry (highp 2-component vector of uint)"));
}
// Test that usubBorrow always results in highp precision.
TEST_F(TypeTrackingTest, BuiltInUsubBorrowPrecision)
{
const std::string &shaderString =
"#version 310 es\n"
"precision mediump float;\n"
"uniform mediump uvec2 x;\n"
"uniform mediump uvec2 y;\n"
"out vec4 my_FragColor;\n"
"void main() {\n"
" lowp uvec2 borrow;\n"
" mediump uvec2 result = usubBorrow(x, y, borrow);\n"
" my_FragColor = vec4(result.x, borrow.y, 0.0, 1.0); \n"
"}\n";
compile(shaderString);
ASSERT_FALSE(foundErrorInIntermediateTree());
ASSERT_TRUE(foundInIntermediateTree("usubBorrow (highp 2-component vector of uint)"));
}
\ No newline at end of file
......@@ -480,16 +480,182 @@
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.pack_unpack.unpackunorm2x16_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.pack_unpack.packhalf2x16_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.pack_unpack.unpackhalf2x16_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.uaddcarry.* = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.usubborrow.* = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.umulextended.* = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.imulextended.* = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitfieldextract.* = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitfieldinsert.* = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitfieldreverse.* = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitcount.* = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.findlsb.* = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.findmsb.* = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.uaddcarry.uint_lowp_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.uaddcarry.uint_mediump_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.uaddcarry.uint_highp_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.uaddcarry.uvec2_lowp_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.uaddcarry.uvec2_mediump_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.uaddcarry.uvec2_highp_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.uaddcarry.uvec3_lowp_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.uaddcarry.uvec3_mediump_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.uaddcarry.uvec3_highp_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.uaddcarry.uvec4_lowp_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.uaddcarry.uvec4_mediump_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.uaddcarry.uvec4_highp_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.usubborrow.uint_lowp_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.usubborrow.uint_mediump_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.usubborrow.uint_highp_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.usubborrow.uvec2_lowp_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.usubborrow.uvec2_mediump_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.usubborrow.uvec2_highp_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.usubborrow.uvec3_lowp_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.usubborrow.uvec3_mediump_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.usubborrow.uvec3_highp_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.usubborrow.uvec4_lowp_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.usubborrow.uvec4_mediump_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.usubborrow.uvec4_highp_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.umulextended.uint_highp_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.umulextended.uvec2_highp_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.umulextended.uvec3_highp_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.umulextended.uvec4_highp_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.imulextended.int_highp_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.imulextended.ivec2_highp_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.imulextended.ivec3_highp_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.imulextended.ivec4_highp_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitfieldextract.int_lowp_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitfieldextract.int_mediump_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitfieldextract.int_highp_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitfieldextract.ivec2_lowp_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitfieldextract.ivec2_mediump_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitfieldextract.ivec2_highp_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitfieldextract.ivec3_lowp_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitfieldextract.ivec3_mediump_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitfieldextract.ivec3_highp_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitfieldextract.ivec4_lowp_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitfieldextract.ivec4_mediump_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitfieldextract.ivec4_highp_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitfieldextract.uint_lowp_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitfieldextract.uint_mediump_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitfieldextract.uint_highp_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitfieldextract.uvec2_lowp_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitfieldextract.uvec2_mediump_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitfieldextract.uvec2_highp_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitfieldextract.uvec3_lowp_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitfieldextract.uvec3_mediump_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitfieldextract.uvec3_highp_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitfieldextract.uvec4_lowp_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitfieldextract.uvec4_mediump_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitfieldextract.uvec4_highp_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitfieldinsert.int_lowp_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitfieldinsert.int_mediump_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitfieldinsert.int_highp_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitfieldinsert.ivec2_lowp_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitfieldinsert.ivec2_mediump_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitfieldinsert.ivec2_highp_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitfieldinsert.ivec3_lowp_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitfieldinsert.ivec3_mediump_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitfieldinsert.ivec3_highp_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitfieldinsert.ivec4_lowp_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitfieldinsert.ivec4_mediump_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitfieldinsert.ivec4_highp_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitfieldinsert.uint_lowp_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitfieldinsert.uint_mediump_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitfieldinsert.uint_highp_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitfieldinsert.uvec2_lowp_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitfieldinsert.uvec2_mediump_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitfieldinsert.uvec2_highp_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitfieldinsert.uvec3_lowp_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitfieldinsert.uvec3_mediump_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitfieldinsert.uvec3_highp_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitfieldinsert.uvec4_lowp_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitfieldinsert.uvec4_mediump_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitfieldinsert.uvec4_highp_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitfieldreverse.int_lowp_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitfieldreverse.int_mediump_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitfieldreverse.int_highp_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitfieldreverse.ivec2_lowp_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitfieldreverse.ivec2_mediump_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitfieldreverse.ivec2_highp_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitfieldreverse.ivec3_lowp_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitfieldreverse.ivec3_mediump_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitfieldreverse.ivec3_highp_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitfieldreverse.ivec4_lowp_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitfieldreverse.ivec4_mediump_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitfieldreverse.ivec4_highp_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitfieldreverse.uint_lowp_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitfieldreverse.uint_mediump_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitfieldreverse.uint_highp_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitfieldreverse.uvec2_lowp_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitfieldreverse.uvec2_mediump_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitfieldreverse.uvec2_highp_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitfieldreverse.uvec3_lowp_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitfieldreverse.uvec3_mediump_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitfieldreverse.uvec3_highp_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitfieldreverse.uvec4_lowp_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitfieldreverse.uvec4_mediump_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitfieldreverse.uvec4_highp_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitcount.int_lowp_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitcount.int_mediump_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitcount.int_highp_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitcount.ivec2_lowp_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitcount.ivec2_mediump_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitcount.ivec2_highp_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitcount.ivec3_lowp_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitcount.ivec3_mediump_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitcount.ivec3_highp_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitcount.ivec4_lowp_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitcount.ivec4_mediump_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitcount.ivec4_highp_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitcount.uint_lowp_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitcount.uint_mediump_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitcount.uint_highp_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitcount.uvec2_lowp_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitcount.uvec2_mediump_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitcount.uvec2_highp_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitcount.uvec3_lowp_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitcount.uvec3_mediump_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitcount.uvec3_highp_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitcount.uvec4_lowp_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitcount.uvec4_mediump_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.bitcount.uvec4_highp_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.findlsb.int_lowp_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.findlsb.int_mediump_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.findlsb.int_highp_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.findlsb.ivec2_lowp_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.findlsb.ivec2_mediump_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.findlsb.ivec2_highp_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.findlsb.ivec3_lowp_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.findlsb.ivec3_mediump_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.findlsb.ivec3_highp_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.findlsb.ivec4_lowp_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.findlsb.ivec4_mediump_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.findlsb.ivec4_highp_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.findlsb.uint_lowp_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.findlsb.uint_mediump_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.findlsb.uint_highp_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.findlsb.uvec2_lowp_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.findlsb.uvec2_mediump_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.findlsb.uvec2_highp_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.findlsb.uvec3_lowp_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.findlsb.uvec3_mediump_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.findlsb.uvec3_highp_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.findlsb.uvec4_lowp_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.findlsb.uvec4_mediump_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.findlsb.uvec4_highp_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.findmsb.int_lowp_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.findmsb.int_mediump_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.findmsb.int_highp_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.findmsb.ivec2_lowp_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.findmsb.ivec2_mediump_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.findmsb.ivec2_highp_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.findmsb.ivec3_lowp_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.findmsb.ivec3_mediump_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.findmsb.ivec3_highp_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.findmsb.ivec4_lowp_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.findmsb.ivec4_mediump_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.findmsb.ivec4_highp_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.findmsb.uint_lowp_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.findmsb.uint_mediump_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.findmsb.uint_highp_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.findmsb.uvec2_lowp_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.findmsb.uvec2_mediump_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.findmsb.uvec2_highp_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.findmsb.uvec3_lowp_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.findmsb.uvec3_mediump_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.findmsb.uvec3_highp_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.findmsb.uvec4_lowp_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.findmsb.uvec4_mediump_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.integer.findmsb.uvec4_highp_compute = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.add.lowp_compute.scalar = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.add.lowp_compute.vec2 = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.builtin_functions.precision.add.lowp_compute.vec3 = FAIL
......
......@@ -458,6 +458,22 @@ class GLSLTest_ES3 : public GLSLTest
}
};
class GLSLTest_ES31 : public GLSLTest
{
void SetUp() override
{
ANGLETest::SetUp();
mSimpleVSSource =
"#version 310 es\n"
"in vec4 inputAttribute;"
"void main()"
"{"
" gl_Position = inputAttribute;"
"}";
}
};
TEST_P(GLSLTest, NamelessScopedStructs)
{
const std::string fragmentShaderSource = SHADER_SOURCE
......@@ -2591,6 +2607,30 @@ TEST_P(WebGLGLSLTest, MaxVaryingVec3ArrayAndMaxPlusOneFloatArray)
} // anonymous namespace
// Test that FindLSB and FindMSB return correct values in their corner cases.
TEST_P(GLSLTest_ES31, FindMSBAndFindLSBCornerCases)
{
const std::string &fragmentShader =
"#version 310 es\n"
"precision mediump float;\n"
"out vec4 my_FragColor;\n"
"uniform int u_zero;\n"
"void main() {\n"
" if (findLSB(u_zero) == -1 && findMSB(u_zero) == -1 && findMSB(u_zero - 1) == -1)\n"
" {\n"
" my_FragColor = vec4(0.0, 1.0, 0.0, 1.0);\n"
" }\n"
" else\n"
" {\n"
" my_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n"
" }\n"
"}\n";
ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
drawQuad(program.get(), "inputAttribute", 0.5f);
EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
}
// Use this to select which configurations (e.g. which renderer, which GLES major version) these tests should be run against.
ANGLE_INSTANTIATE_TEST(GLSLTest,
ES2_D3D9(),
......@@ -2605,3 +2645,5 @@ ANGLE_INSTANTIATE_TEST(GLSLTest,
ANGLE_INSTANTIATE_TEST(GLSLTest_ES3, ES3_D3D11(), ES3_OPENGL(), ES3_OPENGLES());
ANGLE_INSTANTIATE_TEST(WebGLGLSLTest, ES2_D3D11(), ES2_OPENGL(), ES2_OPENGLES());
ANGLE_INSTANTIATE_TEST(GLSLTest_ES31, ES31_D3D11(), ES31_OPENGL(), ES31_OPENGLES());
......@@ -27,3 +27,29 @@ void ConstantFoldingExpressionTest::evaluateFloat(const std::string &floatExpres
<< "}\n";
compileAssumeSuccess(shaderStream.str());
}
void ConstantFoldingExpressionTest::evaluateInt(const std::string &intExpression)
{
std::stringstream shaderStream;
shaderStream << "#version 310 es\n"
"precision mediump int;\n"
"out int my_FragColor;\n"
"void main()\n"
"{\n"
<< " my_FragColor = " << intExpression << ";\n"
<< "}\n";
compileAssumeSuccess(shaderStream.str());
}
void ConstantFoldingExpressionTest::evaluateUint(const std::string &uintExpression)
{
std::stringstream shaderStream;
shaderStream << "#version 310 es\n"
"precision mediump int;\n"
"out uint my_FragColor;\n"
"void main()\n"
"{\n"
<< " my_FragColor = " << uintExpression << ";\n"
<< "}\n";
compileAssumeSuccess(shaderStream.str());
}
......@@ -138,7 +138,7 @@ class ConstantFoldingTest : public ShaderCompileTreeTest
protected:
::GLenum getShaderType() const override { return GL_FRAGMENT_SHADER; }
ShShaderSpec getShaderSpec() const override { return SH_GLES3_SPEC; }
ShShaderSpec getShaderSpec() const override { return SH_GLES3_1_SPEC; }
template <typename T>
bool constantFoundInAST(T constant)
......@@ -177,6 +177,8 @@ class ConstantFoldingExpressionTest : public ConstantFoldingTest
ConstantFoldingExpressionTest() {}
void evaluateFloat(const std::string &floatExpression);
void evaluateInt(const std::string &intExpression);
void evaluateUint(const std::string &uintExpression);
};
} // namespace sh
......
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