summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoland Scheidegger <sroland@vmware.com>2018-05-07 21:04:27 +0200
committerRoland Scheidegger <sroland@vmware.com>2018-05-14 03:14:00 +0200
commitcf3fb42fb5eb6130693a4be0a7b5ea06b184ce2d (patch)
tree976915fb72eaf8f699b88db45f25a2dfe9662636
parent5978d54a09e6ad151c0bd365de0e2c82bbf493d1 (diff)
llvmpipe: Fix random number generation for unit tests
We were never producing negative numbers for signed types. Also fix only producing half the valid range for uint32, and properly clamp signed values. Because this now also properly tests snorm with actually negative values, need to increase eps for such conversions. I believe these cannot actually be hit in ordinary operation (e.g. if a snorm texture is sampled and output to snorm RT, it will still go through snorm->float and float->snorm conversion), so don't bother to do anything to fix the bad accuracy (might be quite complex). Basically, the issue is for something like snorm16->snorm8 that in the end this will just use a 8 bit arithmetic right shift. But the math behind it says we should actually do a division by 32767 / 127, which is ~258, not 256. So the result can be one bit off (values have too large magnitude), and furthermore, the shift has incorrect rounding (always rounds down). For positive numbers, these errors have different direction, but for negative ones they have the same, hence for some values the error will be 2 bit in the end. Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=106232
-rw-r--r--src/gallium/drivers/llvmpipe/lp_test_conv.c8
-rw-r--r--src/gallium/drivers/llvmpipe/lp_test_main.c13
2 files changed, 19 insertions, 2 deletions
diff --git a/src/gallium/drivers/llvmpipe/lp_test_conv.c b/src/gallium/drivers/llvmpipe/lp_test_conv.c
index 6e58a03151..a4f313a0bb 100644
--- a/src/gallium/drivers/llvmpipe/lp_test_conv.c
+++ b/src/gallium/drivers/llvmpipe/lp_test_conv.c
@@ -211,6 +211,14 @@ test_one(unsigned verbose,
assert(src_type.length * num_srcs == dst_type.length * num_dsts);
eps = MAX2(lp_const_eps(src_type), lp_const_eps(dst_type));
+ if (dst_type.norm && dst_type.sign && src_type.sign && !src_type.floating) {
+ /*
+ * This is quite inaccurate due to shift being used.
+ * I don't think it's possible to hit such conversions with
+ * llvmpipe though.
+ */
+ eps *= 2;
+ }
context = LLVMContextCreate();
gallivm = gallivm_create("test_module", context);
diff --git a/src/gallium/drivers/llvmpipe/lp_test_main.c b/src/gallium/drivers/llvmpipe/lp_test_main.c
index 518ca274e7..5ec0dd347b 100644
--- a/src/gallium/drivers/llvmpipe/lp_test_main.c
+++ b/src/gallium/drivers/llvmpipe/lp_test_main.c
@@ -147,6 +147,7 @@ write_elem(struct lp_type type, void *dst, unsigned index, double value)
if(type.sign) {
long long lvalue = (long long)value;
lvalue = MIN2(lvalue, ((long long)1 << (type.width - 1)) - 1);
+ lvalue = MAX2(lvalue, -((long long)1 << (type.width - 1)));
switch(type.width) {
case 8:
*((int8_t *)dst + index) = (int8_t)lvalue;
@@ -200,16 +201,24 @@ random_elem(struct lp_type type, void *dst, unsigned index)
}
else {
unsigned long long mask;
- if (type.fixed)
+ if (type.fixed)
mask = ((unsigned long long)1 << (type.width / 2)) - 1;
else if (type.sign)
mask = ((unsigned long long)1 << (type.width - 1)) - 1;
else
mask = ((unsigned long long)1 << type.width) - 1;
value += (double)(mask & rand());
+ if (!type.fixed && !type.sign && type.width == 32) {
+ /*
+ * rand only returns half the possible range
+ * XXX 64bit values...
+ */
+ if(rand() & 1)
+ value += (double)0x80000000;
+ }
}
}
- if(!type.sign)
+ if(type.sign)
if(rand() & 1)
value = -value;
write_elem(type, dst, index, value);