Commit 734e2571 by Alexis Hetu Committed by Alexis Hétu

Added support for half float in the Blitter

Implemented Float <-> Half conversion. The conversion is copied from Half.cpp and is the same as the C++ code, converted to Reactor code. The conversion is NOT optimized. Optimizing this code path will be done later, this cl only cares about correctness. Passes all conversion tests to and from half float in the following patterns: [dEQP-VK.api.copy_and_blit.core.blit_image] .all_formats.color.[supported format].r16_sfloat.* .all_formats.color.[supported format].r16g16_sfloat.* .all_formats.color.[supported format].r16g16b16a16_sfloat.* .all_formats.color.r16_sfloat.* .all_formats.color.r16g16_sfloat.* .all_formats.color.r16g16b16a16_sfloat.* Bug b/119620767 Change-Id: Icd725dcd2ddd8c54e6657a2c3210da270210a149 Reviewed-on: https://swiftshader-review.googlesource.com/c/23329Tested-by: 's avatarAlexis Hétu <sugoi@google.com> Reviewed-by: 's avatarChris Forbes <chrisforbes@google.com>
parent 457bd9b1
...@@ -319,6 +319,15 @@ namespace sw ...@@ -319,6 +319,15 @@ namespace sw
case VK_FORMAT_R32_SFLOAT: case VK_FORMAT_R32_SFLOAT:
c.x = *Pointer<Float>(element); c.x = *Pointer<Float>(element);
break; break;
case VK_FORMAT_R16G16B16A16_SFLOAT:
c.w = Float(*Pointer<Half>(element + 6));
case VK_FORMAT_R16G16B16_SFLOAT:
c.z = Float(*Pointer<Half>(element + 4));
case VK_FORMAT_R16G16_SFLOAT:
c.y = Float(*Pointer<Half>(element + 2));
case VK_FORMAT_R16_SFLOAT:
c.x = Float(*Pointer<Half>(element));
break;
case VK_FORMAT_R5G6B5_UNORM_PACK16: case VK_FORMAT_R5G6B5_UNORM_PACK16:
c.x = Float(Int((*Pointer<UShort>(element) & UShort(0xF800)) >> UShort(11))); c.x = Float(Int((*Pointer<UShort>(element) & UShort(0xF800)) >> UShort(11)));
c.y = Float(Int((*Pointer<UShort>(element) & UShort(0x07E0)) >> UShort(5))); c.y = Float(Int((*Pointer<UShort>(element) & UShort(0x07E0)) >> UShort(5)));
...@@ -449,6 +458,15 @@ namespace sw ...@@ -449,6 +458,15 @@ namespace sw
case VK_FORMAT_R32_SFLOAT: case VK_FORMAT_R32_SFLOAT:
if(writeR) { *Pointer<Float>(element) = c.x; } if(writeR) { *Pointer<Float>(element) = c.x; }
break; break;
case VK_FORMAT_R16G16B16A16_SFLOAT:
if(writeA) { *Pointer<Half>(element + 6) = Half(c.w); }
case VK_FORMAT_R16G16B16_SFLOAT:
if(writeB) { *Pointer<Half>(element + 4) = Half(c.z); }
case VK_FORMAT_R16G16_SFLOAT:
if(writeG) { *Pointer<Half>(element + 2) = Half(c.y); }
case VK_FORMAT_R16_SFLOAT:
if(writeR) { *Pointer<Half>(element) = Half(c.x); }
break;
case VK_FORMAT_A8B8G8R8_SINT_PACK32: case VK_FORMAT_A8B8G8R8_SINT_PACK32:
case VK_FORMAT_R8G8B8A8_SINT: case VK_FORMAT_R8G8B8A8_SINT:
case VK_FORMAT_A8B8G8R8_SNORM_PACK32: case VK_FORMAT_A8B8G8R8_SNORM_PACK32:
...@@ -869,6 +887,10 @@ namespace sw ...@@ -869,6 +887,10 @@ namespace sw
case VK_FORMAT_R32G32B32A32_SFLOAT: case VK_FORMAT_R32G32B32A32_SFLOAT:
case VK_FORMAT_R32G32_SFLOAT: case VK_FORMAT_R32G32_SFLOAT:
case VK_FORMAT_R32_SFLOAT: case VK_FORMAT_R32_SFLOAT:
case VK_FORMAT_R16G16B16A16_SFLOAT:
case VK_FORMAT_R16G16B16_SFLOAT:
case VK_FORMAT_R16G16_SFLOAT:
case VK_FORMAT_R16_SFLOAT:
case VK_FORMAT_A2B10G10R10_UINT_PACK32: case VK_FORMAT_A2B10G10R10_UINT_PACK32:
scale = vector(1.0f, 1.0f, 1.0f, 1.0f); scale = vector(1.0f, 1.0f, 1.0f, 1.0f);
break; break;
......
...@@ -6086,6 +6086,39 @@ namespace rr ...@@ -6086,6 +6086,39 @@ namespace rr
return T(llvm::VectorType::get(T(UInt::getType()), 4)); return T(llvm::VectorType::get(T(UInt::getType()), 4));
} }
Half::Half(RValue<Float> cast)
{
UInt fp32i = As<UInt>(cast);
UInt abs = fp32i & 0x7FFFFFFF;
UShort fp16i((fp32i & 0x80000000) >> 16); // sign
If(abs > 0x47FFEFFF) // Infinity
{
fp16i |= UShort(0x7FFF);
}
Else
{
If(abs < 0x38800000) // Denormal
{
Int mantissa = (abs & 0x007FFFFF) | 0x00800000;
Int e = 113 - (abs >> 23);
abs = IfThenElse(e < 24, mantissa >> e, Int(0));
fp16i |= UShort((abs + 0x00000FFF + ((abs >> 13) & 1)) >> 13);
}
Else
{
fp16i |= UShort((abs + 0xC8000000 + 0x00000FFF + ((abs >> 13) & 1)) >> 13);
}
}
storeValue(fp16i.loadValue());
}
Type *Half::getType()
{
return T(llvm::Type::getInt16Ty(*::context));
}
Float::Float(RValue<Int> cast) Float::Float(RValue<Int> cast)
{ {
Value *integer = Nucleus::createSIToFP(cast.value, Float::getType()); Value *integer = Nucleus::createSIToFP(cast.value, Float::getType());
...@@ -6101,6 +6134,36 @@ namespace rr ...@@ -6101,6 +6134,36 @@ namespace rr
storeValue(result.value); storeValue(result.value);
} }
Float::Float(RValue<Half> cast)
{
Int fp16i(As<UShort>(cast));
Int s = (fp16i >> 15) & 0x00000001;
Int e = (fp16i >> 10) & 0x0000001F;
Int m = fp16i & 0x000003FF;
UInt fp32i(s << 31);
If(e == 0)
{
If(m != 0)
{
While((m & 0x00000400) == 0)
{
m <<= 1;
e -= 1;
}
fp32i |= As<UInt>(((e + (127 - 15) + 1) << 23) | ((m & ~0x00000400) << 13));
}
}
Else
{
fp32i |= As<UInt>(((e + (127 - 15)) << 23) | (m << 13));
}
storeValue(As<Float>(fp32i).value);
}
Float::Float(float x) Float::Float(float x)
{ {
storeValue(Nucleus::createConstantFloat(x)); storeValue(Nucleus::createConstantFloat(x));
......
...@@ -49,6 +49,7 @@ namespace rr ...@@ -49,6 +49,7 @@ namespace rr
class Int4; class Int4;
class UInt4; class UInt4;
class Long; class Long;
class Half;
class Float; class Float;
class Float2; class Float2;
class Float4; class Float4;
...@@ -1923,11 +1924,20 @@ namespace rr ...@@ -1923,11 +1924,20 @@ namespace rr
RValue<UInt4> Min(RValue<UInt4> x, RValue<UInt4> y); RValue<UInt4> Min(RValue<UInt4> x, RValue<UInt4> y);
// RValue<UInt4> RoundInt(RValue<Float4> cast); // RValue<UInt4> RoundInt(RValue<Float4> cast);
class Half : public LValue<Half>
{
public:
explicit Half(RValue<Float> cast);
static Type *getType();
};
class Float : public LValue<Float> class Float : public LValue<Float>
{ {
public: public:
explicit Float(RValue<Int> cast); explicit Float(RValue<Int> cast);
explicit Float(RValue<UInt> cast); explicit Float(RValue<UInt> cast);
explicit Float(RValue<Half> cast);
Float() = default; Float() = default;
Float(float x); Float(float x);
......
...@@ -6389,6 +6389,39 @@ namespace rr ...@@ -6389,6 +6389,39 @@ namespace rr
return T(Ice::IceType_v4i32); return T(Ice::IceType_v4i32);
} }
Half::Half(RValue<Float> cast)
{
UInt fp32i = As<UInt>(cast);
UInt abs = fp32i & 0x7FFFFFFF;
UShort fp16i((fp32i & 0x80000000) >> 16); // sign
If(abs > 0x47FFEFFF) // Infinity
{
fp16i |= UShort(0x7FFF);
}
Else
{
If(abs < 0x38800000) // Denormal
{
Int mantissa = (abs & 0x007FFFFF) | 0x00800000;
Int e = 113 - (abs >> 23);
abs = IfThenElse(e < 24, mantissa >> e, Int(0));
fp16i |= UShort((abs + 0x00000FFF + ((abs >> 13) & 1)) >> 13);
}
Else
{
fp16i |= UShort((abs + 0xC8000000 + 0x00000FFF + ((abs >> 13) & 1)) >> 13);
}
}
storeValue(fp16i.loadValue());
}
Type *Half::getType()
{
return T(Ice::IceType_i16);
}
Float::Float(RValue<Int> cast) Float::Float(RValue<Int> cast)
{ {
Value *integer = Nucleus::createSIToFP(cast.value, Float::getType()); Value *integer = Nucleus::createSIToFP(cast.value, Float::getType());
...@@ -6404,6 +6437,36 @@ namespace rr ...@@ -6404,6 +6437,36 @@ namespace rr
storeValue(result.value); storeValue(result.value);
} }
Float::Float(RValue<Half> cast)
{
Int fp16i(As<UShort>(cast));
Int s = (fp16i >> 15) & 0x00000001;
Int e = (fp16i >> 10) & 0x0000001F;
Int m = fp16i & 0x000003FF;
UInt fp32i(s << 31);
If(e == 0)
{
If(m != 0)
{
While((m & 0x00000400) == 0)
{
m <<= 1;
e -= 1;
}
fp32i |= As<UInt>(((e + (127 - 15) + 1) << 23) | ((m & ~0x00000400) << 13));
}
}
Else
{
fp32i |= As<UInt>(((e + (127 - 15)) << 23) | (m << 13));
}
storeValue(As<Float>(fp32i).value);
}
Float::Float(float x) Float::Float(float x)
{ {
storeValue(Nucleus::createConstantFloat(x)); storeValue(Nucleus::createConstantFloat(x));
......
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