Commit 764d1426 by Alexis Hetu Committed by Alexis Hétu

Fixed Float4 -> UInt4 conversion

It appears the Nucleus::createFPToUI function is broken and does not yield the correct values for one pixel out of 4 when the f2u operation is used. By manually rewriting the conversion using signed int conversion and some arithmetic, the issue is solved. This fixes at least 130 failures and also fixes many other tests which were passing only due to the threshold being too lenient, but which were showing obvious visual artefacts. This affects, to the very least: dEQP.functional.fbo.blit.conversion dEQP.functional.shaders.functions.datatypes dEQP.functional.shaders.operator.binary_operator ... and any other test using the f2u operation. Change-Id: If38dad6b6ae8198f40e863d0847fa5080a2997e3 Reviewed-on: https://swiftshader-review.googlesource.com/7354Tested-by: 's avatarAlexis Hétu <sugoi@google.com> Reviewed-by: 's avatarNicolas Capens <capn@google.com>
parent 8e7675dd
......@@ -475,10 +475,10 @@ namespace sw
return builder->CreateSExt(V, destType);
}
Value *Nucleus::createFPToUI(Value *V, Type *destType)
{
return builder->CreateFPToUI(V, destType);
}
// Value *Nucleus::createFPToUI(Value *V, Type *destType)
// {
// return builder->CreateFPToUI(V, destType);
// }
Value *Nucleus::createFPToSI(Value *V, Type *destType)
{
......@@ -4293,9 +4293,21 @@ namespace sw
UInt::UInt(RValue<Float> cast)
{
Value *integer = Nucleus::createFPToUI(cast.value, UInt::getType());
// Note: createFPToUI is broken, must perform conversion using createFPtoSI
// Value *integer = Nucleus::createFPToUI(cast.value, UInt::getType());
storeValue(integer);
// 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()
......@@ -5798,9 +5810,21 @@ namespace sw
{
// xyzw.parent = this;
Value *xyzw = Nucleus::createFPToUI(cast.value, UInt4::getType());
storeValue(xyzw);
// Note: createFPToUI is broken, must perform conversion using createFPtoSI
// Value *xyzw = Nucleus::createFPToUI(cast.value, UInt4::getType());
// 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()
......
......@@ -134,7 +134,7 @@ namespace sw
static llvm::Value *createTrunc(llvm::Value *V, llvm::Type *destType);
static llvm::Value *createZExt(llvm::Value *V, llvm::Type *destType);
static llvm::Value *createSExt(llvm::Value *V, llvm::Type *destType);
static llvm::Value *createFPToUI(llvm::Value *V, llvm::Type *destType);
// static llvm::Value *createFPToUI(llvm::Value *V, llvm::Type *destType);
static llvm::Value *createFPToSI(llvm::Value *V, llvm::Type *destType);
static llvm::Value *createUIToFP(llvm::Value *V, llvm::Type *destType);
static llvm::Value *createSIToFP(llvm::Value *V, llvm::Type *destType);
......
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