Implement missing vector operations.
Bug swiftshader:15
Change-Id: I2116fa6ad368c801e921becd89259b02b4ca68ce
Reviewed-on: https://swiftshader-review.googlesource.com/8251
Reviewed-by: Nicolas Capens <capn@google.com>
Reviewed-by: Alexis Hétu <sugoi@google.com>
Tested-by: Nicolas Capens <capn@google.com>
diff --git a/src/Reactor/Main.cpp b/src/Reactor/Main.cpp
index 558110d..3adb638 100644
--- a/src/Reactor/Main.cpp
+++ b/src/Reactor/Main.cpp
@@ -182,6 +182,49 @@
delete routine;
}
+TEST(SubzeroReactorTest, Concatenate)
+{
+ Routine *routine = nullptr;
+
+ {
+ Function<Int(Pointer<Byte>)> function;
+ {
+ Pointer<Byte> out = function.Arg<0>();
+
+ *Pointer<Int4>(out + 16 * 0) = Int4(Int2(0x04030201, 0x08070605), Int2(0x0C0B0A09, 0x100F0E0D));
+ *Pointer<Short8>(out + 16 * 1) = Short8(Short4(0x0201, 0x0403, 0x0605, 0x0807), Short4(0x0A09, 0x0C0B, 0x0E0D, 0x100F));
+
+ Return(0);
+ }
+
+ routine = function(L"one");
+
+ if(routine)
+ {
+ int8_t ref[16 * 5] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
+
+ int8_t out[16 * 5] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1};
+
+ int (*callable)(void*) = (int(*)(void*))routine->getEntry();
+ callable(out);
+
+ for(int row = 0; row < 2; row++)
+ {
+ for(int col = 0; col < 16; col++)
+ {
+ int i = row * 16 + col;
+
+ EXPECT_EQ(out[i], ref[i]) << "Row " << row << " column " << col << " not equal to reference.";
+ }
+ }
+ }
+ }
+
+ delete routine;
+}
+
TEST(SubzeroReactorTest, Swizzle)
{
Routine *routine = nullptr;
diff --git a/src/Reactor/SubzeroReactor.cpp b/src/Reactor/SubzeroReactor.cpp
index 973180c..07ea893 100644
--- a/src/Reactor/SubzeroReactor.cpp
+++ b/src/Reactor/SubzeroReactor.cpp
@@ -2904,7 +2904,7 @@
Short2::Short2(RValue<Short4> cast)
{
- assert(false && "UNIMPLEMENTED");
+ storeValue(Nucleus::createBitCast(cast.value, getType()));
}
Type *Short2::getType()
@@ -2914,7 +2914,7 @@
UShort2::UShort2(RValue<UShort4> cast)
{
- assert(false && "UNIMPLEMENTED");
+ storeValue(Nucleus::createBitCast(cast.value, getType()));
}
Type *UShort2::getType()
@@ -3637,7 +3637,10 @@
Short8::Short8(RValue<Short4> lo, RValue<Short4> hi)
{
- assert(false && "UNIMPLEMENTED");
+ int shuffle[8] = {0, 1, 2, 3, 8, 9, 10, 11}; // Real type is v8i16
+ Value *packed = Nucleus::createShuffleVector(lo.value, hi.value, shuffle);
+
+ storeValue(packed);
}
RValue<Short8> operator+(RValue<Short8> lhs, RValue<Short8> rhs)
@@ -3700,7 +3703,10 @@
UShort8::UShort8(RValue<UShort4> lo, RValue<UShort4> hi)
{
- assert(false && "UNIMPLEMENTED");
+ int shuffle[8] = {0, 1, 2, 3, 8, 9, 10, 11}; // Real type is v8i16
+ Value *packed = Nucleus::createShuffleVector(lo.value, hi.value, shuffle);
+
+ storeValue(packed);
}
RValue<UShort8> UShort8::operator=(RValue<UShort8> rhs)
@@ -4230,7 +4236,18 @@
UInt::UInt(RValue<Float> cast)
{
- assert(false && "UNIMPLEMENTED");
+ // Smallest positive value representable in UInt, but not in Int
+ const unsigned int ustart = 0x80000000u;
+ const float ustartf = float(ustart);
+
+ // If the value is negative, store 0, otherwise store the result of the conversion
+ storeValue((~(As<Int>(cast) >> 31) &
+ // Check if the value can be represented as an Int
+ IfThenElse(cast >= ustartf,
+ // If the value is too large, subtract ustart and re-add it after conversion.
+ As<Int>(As<UInt>(Int(cast - Float(ustartf))) + UInt(ustart)),
+ // Otherwise, just convert normally
+ Int(cast))).value);
}
UInt::UInt()
@@ -4731,12 +4748,15 @@
RValue<Short4> UnpackLow(RValue<Int2> x, RValue<Int2> y)
{
- assert(false && "UNIMPLEMENTED"); return RValue<Short4>(V(nullptr));
+ int shuffle[4] = {0, 4, 1, 5}; // Real type is v4i32
+ return As<Short4>(Nucleus::createShuffleVector(x.value, y.value, shuffle));
}
RValue<Short4> UnpackHigh(RValue<Int2> x, RValue<Int2> y)
{
- assert(false && "UNIMPLEMENTED"); return RValue<Short4>(V(nullptr));
+ int shuffle[16] = {0, 4, 1, 5}; // Real type is v4i32
+ auto lowHigh = RValue<Int4>(Nucleus::createShuffleVector(x.value, y.value, shuffle));
+ return As<Short4>(Swizzle(lowHigh, 0xEE));
}
RValue<Int> Extract(RValue<Int2> val, int i)
@@ -5077,7 +5097,10 @@
Int4::Int4(RValue<Int2> lo, RValue<Int2> hi)
{
- assert(false && "UNIMPLEMENTED");
+ int shuffle[4] = {0, 1, 4, 5}; // Real type is v4i32
+ Value *packed = Nucleus::createShuffleVector(lo.value, hi.value, shuffle);
+
+ storeValue(packed);
}
Int4::Int4(RValue<Int> rhs)
@@ -5369,7 +5392,18 @@
{
// xyzw.parent = this;
- assert(false && "UNIMPLEMENTED");
+ // Smallest positive value representable in UInt, but not in Int
+ const unsigned int ustart = 0x80000000u;
+ const float ustartf = float(ustart);
+
+ // Check if the value can be represented as an Int
+ Int4 uiValue = CmpNLT(cast, Float4(ustartf));
+ // If the value is too large, subtract ustart and re-add it after conversion.
+ uiValue = (uiValue & As<Int4>(As<UInt4>(Int4(cast - Float4(ustartf))) + UInt4(ustart))) |
+ // Otherwise, just convert normally
+ (~uiValue & Int4(cast));
+ // If the value is negative, store 0, otherwise store the result of the conversion
+ storeValue((~(As<Int4>(cast) >> 31) & uiValue).value);
}
UInt4::UInt4()
@@ -5453,7 +5487,10 @@
UInt4::UInt4(RValue<UInt2> lo, RValue<UInt2> hi)
{
- assert(false && "UNIMPLEMENTED");
+ int shuffle[4] = {0, 1, 4, 5}; // Real type is v4i32
+ Value *packed = Nucleus::createShuffleVector(lo.value, hi.value, shuffle);
+
+ storeValue(packed);
}
RValue<UInt4> UInt4::operator=(RValue<UInt4> rhs)