Re: D3DCREATE_FPU_PRESERVE effects

Tech-Archive recommends: Repair Windows Errors & Optimize Windows Performance




The main issue is if someone enables floating-point exceptions or changes the rounding-modes globally. Leaving the FPU in double-precision mode doesn't normally cause a problem.

The default native C++ CRT environment is to use double-precision, round-to-nearest, generate specials not exceptions. The same is true for the C# managed environment. By default Direct3D 9 switches the calling thread's FPU to single-precision mode globally since for most of the history of Direct3D the only software that used it were games and this gives a significant performance increase. They were generally single-threaded applications as well which never relied on the extra precision afforded by double-precision mode, and almost all game structures exclusively use 'float' rather than 'double'. The use of D3DCREATE_FPU_PRESERVE means Direct3D leaves the control word alone.

Note that Direct3D 10 and 11 do not modify the control word globally like this, leaving it up to the application. This behavior has just become too problematic. Furthermore, SSE code doesn't use the FPU control word at all and has explicit double vs. single-precision instructions instead. x64 native code never uses the FPU, and always uses SSE instructions, so the floating-point control word issues are all specific to 32-bit code. Of course, there is a similiar global optimization for SSE code which is to disable DNORMALs using the SSE's control word, and in fact games probably should do that for the same performance increases. Inside a plug-in, you should really just try to live with the plug-ins environment assuming they do not enable floating-point exceptions.

Enabling floating-point exceptions causes a lot of problems, especially on Windows XP, because the FPU control word is carried over into kernel-mode code. Direct3D drivers will assume that they generate specials and are set for round-to-nearest, and the docs are warning you that breaking that assumption could result in BSOD. We had enough difficulty with games trying this and running into trouble that this was part of my Top Issues for Windows Titles techncial article from 2006: http://msdn.microsoft.com/en-us/library/bb206267(VS.85).aspx

---

Manipulation of the Floating-Point Control Word

As a debugging aid, some developers have been enabling exceptions on the floating-point unit (FPU) via manipulations of the
floating-point control word. Doing this is highly problematic and will likely cause the process to crash. Just like the calling convention
requires that the ebx register be preserved, the majority of the system assumes that the FPU is in a default state, will give reasonable
results, and won't generate exceptions. Drivers and other system components will often compute results based on the assumption that
standard error values will appear in the registers for bad conditions, but if exceptions are enabled, these will go unhandled and result
in crashes.

Direct3D will set the floating-point unit to single-precision, round-to-nearest as part of initialization for the calling thread, unless the
D3DCREATE_FPU_PRESERVE flag is used, in which case, the floating-point control word is untouched. Since the control word is
a per-thread setting, ensuring that all of your application threads are set to single-precision mode may optimize performance.
Remember that calling _control_fp is not valid for x64-native coding, which uses SSE exclusively instead, and it is extremely
expensive on the PowerPC-based architecture of the Xbox 360 CPU.

In any libraries where we need to have different rounding rules or other behavior — such as dealing with software vertex shaders or
compilation — we save and restore the control word. If a game needs to make use of non-standard rounding or FPU exceptions, it
should save and restore the floating-point control word, and you should be sure that it does not call any external code that has not
been proven to be safe from these problems, including system APIs.

---

As a plug-in, you should find out what the running environment is w.r.t. the FPU. More than likely, they leave it at the CRT default which should work fine.

--
-Chuck Walbourn
SDE, XNA Developer Connection

This posting is provided "AS IS" with no warrenties, and confers no rights.

.



Relevant Pages

  • Re: D3DCREATE_FPU_PRESERVE effects
    ... Leaving the FPU in double-precision mode ... round-to-nearest, generate specials not exceptions. ... Direct3D leaves the control word alone. ... Manipulation of the Floating-Point Control Word ...
    (microsoft.public.win32.programmer.directx.graphics)
  • Re: Divide by 0 - exception thrown?
    ... You've helped clear up the workings of the FPU in my ... The FPU's control word sets whether it handles exceptions itself (i.e. ... If it generates an interrupt, ...
    (microsoft.public.vc.language)
  • Re: bcopy
    ... Other exceptions include floating-point on a ... machine without an FPU, and arithmetic on ... for tiny machines either omit floating point altogether or provide a 3- ...
    (comp.lang.c)
  • Re: IEEE-FP 0.5.2 - Exception handling
    ... exceptions is far enough along to put it back in, ... uses terminology borrowed from C99, "fp status flags", instead ... X.XX Floating-point status flags ... provides a default fp datum and does not interrupt program flow. ...
    (comp.lang.forth)
  • Re: RfD: IEEE-FP
    ... >>> control the hardware must deal with NaN and Inf. ... > Any floating-point hardware that is IEEE-compatible is already ... hardware because IEEE 754 has essentially won the day. ... the reason is the exceptions. ...
    (comp.lang.forth)