Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix blurry fonts in GLFW backend when using -ffast-math #6529

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

deggua
Copy link

@deggua deggua commented Jun 18, 2023

Issue: Fonts look blurry when using the GLFW backend with -ffast-math/-Ofast//fp:fast due to a reciprocal divide optimization introducing error in the scale calculation.

Solution: Compute the scale with higher precision.

Before:
imgui_before

After:
imgui_after

I'm not sure this is the best solution in general, but it's a lot more portable than anything else I could think of (inline asm, compiler specific optimization #pragmas/attributes).

@ocornut
Copy link
Owner

ocornut commented Jun 18, 2023

That seems surprising.
What is the value of both variables?
I would be surprised that sorts of side-effect wouldn’t exist in many other places.

@deggua
Copy link
Author

deggua commented Jun 18, 2023

w = 1920
display_w = 1920
h = 1080
display_h = 1080

Here's some analysis of the assembly for a program which causes blurry text output
imgui_Ofast_asm

The VRCPPS instruction causes too much error compared to a normal VDIVPS or DIVSS

Here's the analysis if I use the following function to perform the divide (which also solves the blurryness)

static inline float divss(float x, float y)
{
    asm(
        "divss %[y], %[x]"
        : [x] "+x" (x)
        : [y] "x" (y)
        :
    );

    return x;
}

imgui_divss_asm

And here it is with the code in the PR (divide using double)
imgui_double_asm

There isn't a reciprocal approximation instruction for double so the compiler is forced to use the normal VDIVPD instruction to perform the calculation which produces the correct result. I could see this PR still breaking with -ffast-math if Intel/AMD ever add a VRCPPD instruction (unlikely) and compilers use it, but there would still be less error in that case.

@deggua
Copy link
Author

deggua commented Jun 18, 2023

I would imagine -ffast-math could produce other issues, either in other backends or in standard UI code. This was just the most visible problem I found. I haven't played with imgui in my project enough to find any other precision related issues, the demo window seems to work fine otherwise as far as I can tell.

@ocornut
Copy link
Owner

ocornut commented Jun 19, 2023

I would imagine -ffast-math could produce other issues, either in other backends or in standard UI code. This was just the most visible problem I found. I haven't played with imgui in my project enough to find any other precision related issues, the demo window seems to work fine otherwise as far as I can tell.

This is indeed a very-visible thing as it indirectly affects the projection matrix.

My issue is that am 100% confident many other things would be affected, and I am not exactly looking forward to having to debug and fix obscure bugs that are related to this. Switching to double - even occasionally - in some low-level computation may not be a desirable solution and I can generally envision debugging fast-math related issues to be extremely time consuming.

So I think it is a great "feature" that the projection matrix gets broken so visibly in order to deter people from using that.

My suggestion would be:

  • We don't merge this.
  • If you have a strong need to use fast-math in your project, then fix that 1 computation by doing it in your code after the call to ImGui_ImplGlfw_NewFrame().
  • Use Dear ImGui this way. If after several months of extensive use you don't notice other problems we can consider to apply this here. If you find more problem, note them here or add the fix to your branch and we can reevaluate this depending on their nature.
@deggua
Copy link
Author

deggua commented Jun 19, 2023

That is fair, I don't think it's feasible to find every spot that might be broken by -ffast-math approximations. Maybe it would be better to document somewhere that -ffast-math is incompatible with imgui (or at least may produce artifacts). In my project I can compile imgui's translation units with -O2 instead of -Ofast, but this doesn't offer a solution to people who use a unity build. There weren't any search results for -Ofast breaking imgui, which is part of why I made this PR, to document it somewhere for anyone that runs into this.

For anyone reading this in the future, I found which file produced the visual bug by selectively turning -ffast-math on for a single translation unit at a time until I found which file was the culprit. Then you can use something like __attribute__((optnone)) to disable optimizations on a single function to determine which function is causing the problem.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment