Commit ec1aeb84 by Ben Clayton

SpirvShader: Add relational ops for ordered and unordered floats

Bug: b/127282157 Change-Id: Id2c5b29d744f6f7ddcbb853db0a95228425d7f83 Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/26108Tested-by: 's avatarBen Clayton <bclayton@google.com> Reviewed-by: 's avatarNicolas Capens <nicolascapens@google.com> Kokoro-Presubmit: kokoro <noreply+kokoro@google.com>
parent 76e9bc06
...@@ -250,6 +250,18 @@ namespace sw ...@@ -250,6 +250,18 @@ namespace sw
case spv::OpFAdd: case spv::OpFAdd:
case spv::OpFSub: case spv::OpFSub:
case spv::OpFDiv: case spv::OpFDiv:
case spv::OpFOrdEqual:
case spv::OpFUnordEqual:
case spv::OpFOrdNotEqual:
case spv::OpFUnordNotEqual:
case spv::OpFOrdLessThan:
case spv::OpFUnordLessThan:
case spv::OpFOrdGreaterThan:
case spv::OpFUnordGreaterThan:
case spv::OpFOrdLessThanEqual:
case spv::OpFUnordLessThanEqual:
case spv::OpFOrdGreaterThanEqual:
case spv::OpFUnordGreaterThanEqual:
case spv::OpUMod: case spv::OpUMod:
case spv::OpIEqual: case spv::OpIEqual:
case spv::OpINotEqual: case spv::OpINotEqual:
...@@ -953,6 +965,18 @@ namespace sw ...@@ -953,6 +965,18 @@ namespace sw
case spv::OpFAdd: case spv::OpFAdd:
case spv::OpFSub: case spv::OpFSub:
case spv::OpFDiv: case spv::OpFDiv:
case spv::OpFOrdEqual:
case spv::OpFUnordEqual:
case spv::OpFOrdNotEqual:
case spv::OpFUnordNotEqual:
case spv::OpFOrdLessThan:
case spv::OpFUnordLessThan:
case spv::OpFOrdGreaterThan:
case spv::OpFUnordGreaterThan:
case spv::OpFOrdLessThanEqual:
case spv::OpFUnordLessThanEqual:
case spv::OpFOrdGreaterThanEqual:
case spv::OpFUnordGreaterThanEqual:
case spv::OpUMod: case spv::OpUMod:
case spv::OpIEqual: case spv::OpIEqual:
case spv::OpINotEqual: case spv::OpINotEqual:
...@@ -1354,6 +1378,42 @@ namespace sw ...@@ -1354,6 +1378,42 @@ namespace sw
case spv::OpFDiv: case spv::OpFDiv:
dst.emplace(i, lhs / rhs); dst.emplace(i, lhs / rhs);
break; break;
case spv::OpFOrdEqual:
dst.emplace(i, As<SIMD::Float>(CmpEQ(lhs, rhs)));
break;
case spv::OpFUnordEqual:
dst.emplace(i, As<SIMD::Float>(CmpUEQ(lhs, rhs)));
break;
case spv::OpFOrdNotEqual:
dst.emplace(i, As<SIMD::Float>(CmpNEQ(lhs, rhs)));
break;
case spv::OpFUnordNotEqual:
dst.emplace(i, As<SIMD::Float>(CmpUNEQ(lhs, rhs)));
break;
case spv::OpFOrdLessThan:
dst.emplace(i, As<SIMD::Float>(CmpLT(lhs, rhs)));
break;
case spv::OpFUnordLessThan:
dst.emplace(i, As<SIMD::Float>(CmpULT(lhs, rhs)));
break;
case spv::OpFOrdGreaterThan:
dst.emplace(i, As<SIMD::Float>(CmpGT(lhs, rhs)));
break;
case spv::OpFUnordGreaterThan:
dst.emplace(i, As<SIMD::Float>(CmpUGT(lhs, rhs)));
break;
case spv::OpFOrdLessThanEqual:
dst.emplace(i, As<SIMD::Float>(CmpLE(lhs, rhs)));
break;
case spv::OpFUnordLessThanEqual:
dst.emplace(i, As<SIMD::Float>(CmpULE(lhs, rhs)));
break;
case spv::OpFOrdGreaterThanEqual:
dst.emplace(i, As<SIMD::Float>(CmpGE(lhs, rhs)));
break;
case spv::OpFUnordGreaterThanEqual:
dst.emplace(i, As<SIMD::Float>(CmpUGE(lhs, rhs)));
break;
case spv::OpShiftRightLogical: case spv::OpShiftRightLogical:
dst.emplace(i, As<SIMD::Float>(As<SIMD::UInt>(lhs) >> As<SIMD::UInt>(rhs))); dst.emplace(i, As<SIMD::Float>(As<SIMD::UInt>(lhs) >> As<SIMD::UInt>(rhs)));
break; break;
......
...@@ -6809,6 +6809,36 @@ namespace rr ...@@ -6809,6 +6809,36 @@ namespace rr
return RValue<Int4>(Nucleus::createSExt(Nucleus::createFCmpOGT(x.value, y.value), Int4::getType())); return RValue<Int4>(Nucleus::createSExt(Nucleus::createFCmpOGT(x.value, y.value), Int4::getType()));
} }
RValue<Int4> CmpUEQ(RValue<Float4> x, RValue<Float4> y)
{
return RValue<Int4>(Nucleus::createSExt(Nucleus::createFCmpUEQ(x.value, y.value), Int4::getType()));
}
RValue<Int4> CmpULT(RValue<Float4> x, RValue<Float4> y)
{
return RValue<Int4>(Nucleus::createSExt(Nucleus::createFCmpULT(x.value, y.value), Int4::getType()));
}
RValue<Int4> CmpULE(RValue<Float4> x, RValue<Float4> y)
{
return RValue<Int4>(Nucleus::createSExt(Nucleus::createFCmpULE(x.value, y.value), Int4::getType()));
}
RValue<Int4> CmpUNEQ(RValue<Float4> x, RValue<Float4> y)
{
return RValue<Int4>(Nucleus::createSExt(Nucleus::createFCmpUNE(x.value, y.value), Int4::getType()));
}
RValue<Int4> CmpUNLT(RValue<Float4> x, RValue<Float4> y)
{
return RValue<Int4>(Nucleus::createSExt(Nucleus::createFCmpUGE(x.value, y.value), Int4::getType()));
}
RValue<Int4> CmpUNLE(RValue<Float4> x, RValue<Float4> y)
{
return RValue<Int4>(Nucleus::createSExt(Nucleus::createFCmpUGT(x.value, y.value), Int4::getType()));
}
RValue<Int4> IsInf(RValue<Float4> x) RValue<Int4> IsInf(RValue<Float4> x)
{ {
return CmpEQ(As<Int4>(x) & Int4(0x7FFFFFFF), Int4(0x7F800000)); return CmpEQ(As<Int4>(x) & Int4(0x7FFFFFFF), Int4(0x7F800000));
......
...@@ -2138,12 +2138,27 @@ namespace rr ...@@ -2138,12 +2138,27 @@ namespace rr
RValue<Float4> UnpackHigh(RValue<Float4> x, RValue<Float4> y); RValue<Float4> UnpackHigh(RValue<Float4> x, RValue<Float4> y);
RValue<Float4> Mask(Float4 &lhs, RValue<Float4> rhs, unsigned char select); RValue<Float4> Mask(Float4 &lhs, RValue<Float4> rhs, unsigned char select);
RValue<Int> SignMask(RValue<Float4> x); RValue<Int> SignMask(RValue<Float4> x);
// Ordered comparison functions
RValue<Int4> CmpEQ(RValue<Float4> x, RValue<Float4> y); RValue<Int4> CmpEQ(RValue<Float4> x, RValue<Float4> y);
RValue<Int4> CmpLT(RValue<Float4> x, RValue<Float4> y); RValue<Int4> CmpLT(RValue<Float4> x, RValue<Float4> y);
RValue<Int4> CmpLE(RValue<Float4> x, RValue<Float4> y); RValue<Int4> CmpLE(RValue<Float4> x, RValue<Float4> y);
RValue<Int4> CmpNEQ(RValue<Float4> x, RValue<Float4> y); RValue<Int4> CmpNEQ(RValue<Float4> x, RValue<Float4> y);
RValue<Int4> CmpNLT(RValue<Float4> x, RValue<Float4> y); RValue<Int4> CmpNLT(RValue<Float4> x, RValue<Float4> y);
RValue<Int4> CmpNLE(RValue<Float4> x, RValue<Float4> y); RValue<Int4> CmpNLE(RValue<Float4> x, RValue<Float4> y);
inline RValue<Int4> CmpGT(RValue<Float4> x, RValue<Float4> y) { return CmpNLE(x, y); }
inline RValue<Int4> CmpGE(RValue<Float4> x, RValue<Float4> y) { return CmpNLT(x, y); }
// Unordered comparison functions
RValue<Int4> CmpUEQ(RValue<Float4> x, RValue<Float4> y);
RValue<Int4> CmpULT(RValue<Float4> x, RValue<Float4> y);
RValue<Int4> CmpULE(RValue<Float4> x, RValue<Float4> y);
RValue<Int4> CmpUNEQ(RValue<Float4> x, RValue<Float4> y);
RValue<Int4> CmpUNLT(RValue<Float4> x, RValue<Float4> y);
RValue<Int4> CmpUNLE(RValue<Float4> x, RValue<Float4> y);
inline RValue<Int4> CmpUGT(RValue<Float4> x, RValue<Float4> y) { return CmpUNLE(x, y); }
inline RValue<Int4> CmpUGE(RValue<Float4> x, RValue<Float4> y) { return CmpUNLT(x, y); }
RValue<Int4> IsInf(RValue<Float4> x); RValue<Int4> IsInf(RValue<Float4> x);
RValue<Int4> IsNan(RValue<Float4> x); RValue<Int4> IsNan(RValue<Float4> x);
RValue<Float4> Round(RValue<Float4> x); RValue<Float4> Round(RValue<Float4> x);
......
...@@ -6387,38 +6387,38 @@ namespace rr ...@@ -6387,38 +6387,38 @@ namespace rr
return T(Ice::IceType_v4i32); return T(Ice::IceType_v4i32);
} }
Half::Half(RValue<Float> cast) Half::Half(RValue<Float> cast)
{ {
UInt fp32i = As<UInt>(cast); UInt fp32i = As<UInt>(cast);
UInt abs = fp32i & 0x7FFFFFFF; UInt abs = fp32i & 0x7FFFFFFF;
UShort fp16i((fp32i & 0x80000000) >> 16); // sign UShort fp16i((fp32i & 0x80000000) >> 16); // sign
If(abs > 0x47FFEFFF) // Infinity If(abs > 0x47FFEFFF) // Infinity
{ {
fp16i |= UShort(0x7FFF); fp16i |= UShort(0x7FFF);
} }
Else Else
{ {
If(abs < 0x38800000) // Denormal If(abs < 0x38800000) // Denormal
{ {
Int mantissa = (abs & 0x007FFFFF) | 0x00800000; Int mantissa = (abs & 0x007FFFFF) | 0x00800000;
Int e = 113 - (abs >> 23); Int e = 113 - (abs >> 23);
abs = IfThenElse(e < 24, mantissa >> e, Int(0)); abs = IfThenElse(e < 24, mantissa >> e, Int(0));
fp16i |= UShort((abs + 0x00000FFF + ((abs >> 13) & 1)) >> 13); fp16i |= UShort((abs + 0x00000FFF + ((abs >> 13) & 1)) >> 13);
} }
Else Else
{ {
fp16i |= UShort((abs + 0xC8000000 + 0x00000FFF + ((abs >> 13) & 1)) >> 13); fp16i |= UShort((abs + 0xC8000000 + 0x00000FFF + ((abs >> 13) & 1)) >> 13);
} }
} }
storeValue(fp16i.loadValue()); storeValue(fp16i.loadValue());
} }
Type *Half::getType() Type *Half::getType()
{ {
return T(Ice::IceType_i16); return T(Ice::IceType_i16);
} }
Float::Float(RValue<Int> cast) Float::Float(RValue<Int> cast)
{ {
...@@ -6435,34 +6435,34 @@ namespace rr ...@@ -6435,34 +6435,34 @@ namespace rr
storeValue(result.value); storeValue(result.value);
} }
Float::Float(RValue<Half> cast) Float::Float(RValue<Half> cast)
{ {
Int fp16i(As<UShort>(cast)); Int fp16i(As<UShort>(cast));
Int s = (fp16i >> 15) & 0x00000001; Int s = (fp16i >> 15) & 0x00000001;
Int e = (fp16i >> 10) & 0x0000001F; Int e = (fp16i >> 10) & 0x0000001F;
Int m = fp16i & 0x000003FF; Int m = fp16i & 0x000003FF;
UInt fp32i(s << 31); UInt fp32i(s << 31);
If(e == 0) If(e == 0)
{ {
If(m != 0) If(m != 0)
{ {
While((m & 0x00000400) == 0) While((m & 0x00000400) == 0)
{ {
m <<= 1; m <<= 1;
e -= 1; e -= 1;
} }
fp32i |= As<UInt>(((e + (127 - 15) + 1) << 23) | ((m & ~0x00000400) << 13)); fp32i |= As<UInt>(((e + (127 - 15) + 1) << 23) | ((m & ~0x00000400) << 13));
} }
} }
Else Else
{ {
fp32i |= As<UInt>(((e + (127 - 15)) << 23) | (m << 13)); fp32i |= As<UInt>(((e + (127 - 15)) << 23) | (m << 13));
} }
storeValue(As<Float>(fp32i).value); storeValue(As<Float>(fp32i).value);
} }
Float::Float(float x) Float::Float(float x)
...@@ -7049,6 +7049,36 @@ namespace rr ...@@ -7049,6 +7049,36 @@ namespace rr
return RValue<Int4>(Nucleus::createFCmpOGT(x.value, y.value)); return RValue<Int4>(Nucleus::createFCmpOGT(x.value, y.value));
} }
RValue<Int4> CmpUEQ(RValue<Float4> x, RValue<Float4> y)
{
return RValue<Int4>(Nucleus::createFCmpUEQ(x.value, y.value));
}
RValue<Int4> CmpULT(RValue<Float4> x, RValue<Float4> y)
{
return RValue<Int4>(Nucleus::createFCmpULT(x.value, y.value));
}
RValue<Int4> CmpULE(RValue<Float4> x, RValue<Float4> y)
{
return RValue<Int4>(Nucleus::createFCmpULE(x.value, y.value));
}
RValue<Int4> CmpUNEQ(RValue<Float4> x, RValue<Float4> y)
{
return RValue<Int4>(Nucleus::createFCmpUNE(x.value, y.value));
}
RValue<Int4> CmpUNLT(RValue<Float4> x, RValue<Float4> y)
{
return RValue<Int4>(Nucleus::createFCmpUGE(x.value, y.value));
}
RValue<Int4> CmpUNLE(RValue<Float4> x, RValue<Float4> y)
{
return RValue<Int4>(Nucleus::createFCmpUGT(x.value, y.value));
}
RValue<Int4> IsInf(RValue<Float4> x) RValue<Int4> IsInf(RValue<Float4> x)
{ {
return CmpEQ(As<Int4>(x) & Int4(0x7FFFFFFF), Int4(0x7F800000)); return CmpEQ(As<Int4>(x) & Int4(0x7FFFFFFF), Int4(0x7F800000));
......
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