Hi,
I have a small hint to the D3DXFloat32To16Array function. It seems that some values are handled in some other way.
A small test: D3DXFLOAT16 res; union p { float f; DWORD d; } x;
x.d = 0x33000800; D3DXFloat32To16Array(&res, &x.f, 1); ok(res.value == 1, "Failed %f %x\n", x.f, res.value);
This fails with the current implementation. It's not the only value, there are a couple of them which are of by one. This could be easily seen by loading both d3dx36.dll (wine and native) and comparing the values directly.
Cheers Rico
Am 18.02.2011 02:18, schrieb Misha Koshelev:
Fixes bug 25769. Extensively vetted by Stefan Dosinger. Passes winetestbot: https://testbot.winehq.org/JobDetails.pl?Key=9366
Thank you Misha
dlls/d3dx9_36/d3dx9_36.spec | 4 +- dlls/d3dx9_36/math.c | 105 +++++++++++++++++++++++++++++++++++++++++++ dlls/d3dx9_36/tests/math.c | 69 ++++++++++++++++++++++++++++ include/d3dx9math.h | 18 +++++++ include/d3dx9math.inl | 31 +++++++++++++ 5 files changed, 225 insertions(+), 2 deletions(-)
2011/2/20 Rico Schüller kgbricola@web.de:
Hi,
I have a small hint to the D3DXFloat32To16Array function. It seems that some values are handled in some other way.
A small test: D3DXFLOAT16 res; union p { float f; DWORD d; } x;
x.d = 0x33000800; D3DXFloat32To16Array(&res, &x.f, 1); ok(res.value == 1, "Failed %f %x\n", x.f, res.value);
This fails with the current implementation. It's not the only value, there are a couple of them which are of by one. This could be easily seen by loading both d3dx36.dll (wine and native) and comparing the values directly.
Cheers Rico
Thanks Rico.
Still trying to investigate this further.
Perhaps, if you have any more hints as to how you arrived at this magical value, much appreciated.
Namely, at first my hunch was that this value (2.9806e-08 with the following bitwise representation): 0 01100110 00000000000010000000000 was simply being truncated to the smallest denormalized value representable by a half precision float: 0 000.00 00.0000.0001 6×10-8 (Smallest denormalized value) but this is clearly not true for other values that are too small (they are returned as 0.0f).
Thank you Misha
Am 21.02.2011 20:19, schrieb Misha Koshelev:
Thanks Rico.
Still trying to investigate this further.
Perhaps, if you have any more hints as to how you arrived at this magical value, much appreciated.
I got to this value by running the attached test patch applied after yours. You probably may modify the for loop. I've chosen the increment because of time/usage. You may try with 0xff or a lower value instead of 0xfff, but be warned running at 1 will take a while to see a failed test.
You need a copy of native d3dx9_36.dll renamed to d3dx9_36_2.dll in the path. The test should show the difference between native and wine's implementation. I haven't run the test on windows, yet.
Namely, at first my hunch was that this value (2.9806e-08 with the following bitwise representation): 0 01100110 00000000000010000000000 was simply being truncated to the smallest denormalized value representable by a half precision float: 0 000.00 00.0000.0001 6×10-8 (Smallest denormalized value) but this is clearly not true for other values that are too small (they are returned as 0.0f).
I haven't had the time to investigate this completely, yet. But probably there are a couple of values produced by the patch which should give a hint to what bits are truncated/rounded.
Cheers Rico
2011/2/21 Rico Schüller kgbricola@web.de:
Am 21.02.2011 20:19, schrieb Misha Koshelev:
Thanks Rico.
Still trying to investigate this further.
Perhaps, if you have any more hints as to how you arrived at this magical value, much appreciated.
I got to this value by running the attached test patch applied after yours. You probably may modify the for loop. I've chosen the increment because of time/usage. You may try with 0xff or a lower value instead of 0xfff, but be warned running at 1 will take a while to see a failed test.
You need a copy of native d3dx9_36.dll renamed to d3dx9_36_2.dll in the path. The test should show the difference between native and wine's implementation. I haven't run the test on windows, yet.
Namely, at first my hunch was that this value (2.9806e-08 with the following bitwise representation): 0 01100110 00000000000010000000000 was simply being truncated to the smallest denormalized value representable by a half precision float: 0 000.00 00.0000.0001 6×10-8 (Smallest denormalized value) but this is clearly not true for other values that are too small (they are returned as 0.0f).
I haven't had the time to investigate this completely, yet. But probably there are a couple of values produced by the patch which should give a hint to what bits are truncated/rounded.
Cheers Rico
Thank you. I'm pretty stumped. I've gotten a little farther by making the following changes to the rounding code (handling the special case of mantissa = 2048 = 2^11 = maximal value; "overflow" from rounding).
if (tmp - mantissa > 0.5f) mantissa++; /* round to nearest, away from zero */ if (mantissa == 2048) { mantissa = 1024; exp++; }
This seems to handle all the cases that are, to my understanding, within the representable range (I may be somewhat incorrect, please see attached test results, that include output of exp, unrounded mantissa = tmp, and mantissa). Note, that _most_ of these results fall in the case of fabs(in) > 65520, so I have commented out this line in the test version of the converted (see attached patch).
Any hints appreciated.
Thank you Misha