How to disable DirectX in JUCE 8?

You can still do pixel data manipulation, but instead of calling getPixel/setPixel on the image object directly, you create a BitmapData object from the image, and as long as that object is in scope, the data will remain in RAM. Once it goes out of scope, the image will be copied back to the GPU.

1 Like

In an ideal world, everything would be perfect. But the reality is that the JUCE developers have limited bandwidth.

You won’t accept that reality, but use it yourself to justify your refusal to test.

My experience with D2D is overall good:

  1. I had to change a few things in the code, mainly use of images and setBufferedToImage.
  2. Performance got much better after that.

However, I big problem I’ve had was that the runtime flag wasn’t working correctly (this is about a month ago), and didn’t disable Direct2D image processing. So that forced me to take a couple days and stop everything to stabilize our Windows builds.

If the runtime flag would 100% disable Direct2D, I’d be pretty much 100% happy and could then do the code transition on my own time. I think the JUCE team should work on that part?

This is a gentle reminder to everyone to keep things professional, and to avoid direct criticisms of other users. If in doubt, please refer to the code-of-conduct document in the JUCE repo.

It would be good to know exactly what problems you encountered, so that we can address them individually. Disabling D2D globally is quite a drastic approach, and likely overkill, because it means you won’t benefit from any of the new D2D features - most significantly, performance improvements.

If you want to use a software graphics context to render to an image, you can explicitly pass SoftwareImageType{} when constructing the image, or use SoftwareImageType{}.convert() to convert an existing image. While this will be a bit more time consuming to migrate, it also means that you can restrict your use of software images to places where they’re really necessary, and keep the rest of the images using D2D, which should improve runtime performance.

I did report all my issues in a number of relevant threads. See here:

The main issue was that performance became horrible and there was no way of disabling D2D to achieve stable builds. It took a couple of days and help from people on the forum to find out all the instances where my performance could be affected.

This should be made into an explicit argument that fails builds. Even with hundreds of compile time errors, this would have been easier to fix on my end than the current runtime bug that took a long time to track down.

I have the same problem, but it does not seem affect all fonts to the same extend.

1 Like

I found the reason for my window opening slowdown. I was painting to an image with juce::Image::PixelFormat::RGB pixels. I didn’t need transparency and drawing a RGB image was much faster on Windows using the software renderer.

However using the Direct2D renderer it appears the RGB picture gets converted to ARGB before drawing (in flushImage())
 and this is extremely slow as it seems to access pixels.

It is so slow (seconds for a large image!), that it should be considered broken.

AFAIK macOS always uses ARGB in its CoreGraphics images regardless of the format specified. @matt, maybe this could be done in D2D as well? Otherwise maybe it would be good to add an assert and make people move away from juce::Image::PixelFormat::RGB.

Anyway
 with ARGB things are now fast and that has me motivated to look into the font rendering configuration.

1 Like

OK, thanks, that’s useful information.

Direct2D doesn’t support RGB bitmap formats directly.

https://learn.microsoft.com/en-us/windows/win32/direct2d/supported-pixel-formats-and-alpha-modes#supported-formats-for-id2d1devicecontext

Essentially we use ARGB with premultiplied alpha or ARGB with “ignore alpha” set. I suspect the slowdown you’re reporting is more due to the image flush than the format conversion, though.

Is this an image you are generating on the fly?

Matt

1 Like

Yes these are some background images for displays I draw when my editor is drawn for the first time or the size changed
 similar to CachedImageComponent but only for a background. Switching to ARGB made it very fast, so I do think the slowness is in the conversion
 which happens in the main juce::Image class and goes pixel by pixel it seems. I saw pixel operations show up in the profiler as well.

We used to create a background image as well, but with D2D being so insanely fast to draw giant rects etc. we stopped using background images. Now everything is drawn in realtime, even if there a big overlaps, etc.

1 Like

I found that what bothers me about the font scaling is just Direct2D font hinting in general (it just hints too much and IMHO kills the glyph shapes at smaller sizes).
If I strip fonts of all hinting information the results look much more pleasing to me - and much more similar to the results on macOS - which is known for ignoring hinting information. I believe the render @Toddler-Boy showed was achieved without any hinting, maybe the Inter font contains no hinting info or it was stripped on the way into Juce. The font I struggled the most with had plenty of hinting data. I shrunk to 2/3 its size when I stripped all of it
!

If I enable subpixel aliasing by changing line 90 in juce_Direct2DResources_windows.cpp to
result->SetTextAntialiasMode (D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE);

The results are what I am truly looking for. I achieved similar things in the past by using a custom subpixel-antialias font renderer in Juce6.

Now what would be very nice was to have options. Personally I would like to have the option to disable hinting in the Direct2D font renderer. I failed to work out how this can be done, SetTextRenderingParams() seems to be the method that could do it, but it’s just super hard to set up the param struct it wants (from DirectWrite). :confused:

It would be great if the renderer used cleartype antialiasing if it is enabled on a system. 200% scaling systems don’t really need it, but there are tons of windows systems that use 150% or 125% scaling and on these, subpixel font rendering would be awesome to have and Direct2D can provide it mostly for free.

4 Likes

Just FYI: we didn’t do anything with the font. I just straight-up downloaded it from Google Fonts. There are no modifications whatsoever.

Interesting; maybe that should be the default. Sounds like there’s a tradeoff here between performance & visual quality; the Microsoft docs recommend D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE for improved performance.

Setting the text rendering params is fussy indeed. I don’t think you’ll be able to do it without modifying JUCE; you’d need access to the Direct2D device context.

Matt

1 Like

sized

I put together this gif showing Arial Bold 10pt at 200% desktop scaling, with a few different antialiasing modes.

It looks like the glyph shapes are broadly similar between the two D2D rendering modes. Compared to the software renderer, D2D seems to hint quite aggressively. Text in this font rendered with D2D looks a bit less blurry. It also seems like the hinting attempts to separate details that might get lost at small sizes. e.g. in the software renderer, the dot on the i and j is almost joined to the rest of the glyph, and the inside stroke of the Q gets lost.

Some characters do look quite different depending on the renderer (S, a, 4), but I think this is because D2D’s font rendering is actually using the font’s hinting and size information, while the software renderer just uses the glyph shapes at some “default” size and scales them to the requested size. I see the same glyph shapes in the DemoRunner D2D as in Firefox for Arial Bold at 10px match, although Firefox seems to use ClearType instead of grayscale antialiasing.

I’m not sure exactly where to go from here. We can’t replicate the software renderer results using any of the built-in D2D rendering modes. We could probably get close by rendering glyphs to paths instead, but ignoring the hinting suggested by the type designer feels like a step in the wrong direction, and we’d also lose out on any performance benefits from rendering glyphs directly through D2D.

Given that it’s already possible to replicate the old behaviour by switching to the software renderer, and that replicating the same behaviour in D2D would introduce runtime overhead and maintenance cost, I don’t think it makes sense to try to match the software renderer style exactly in D2D.

This issue has been discussed a bit on the forum previously:

I agree with Anthony’s conclusions from that post. If you really disagree with the type designer about how the font is hinted at small sizes, then either stick with the software renderer, or remove the hinting info from the font.

I’m fairly sure that using the software renderer as suggested can be done currently, without requiring a flag to globally disable D2D. If you run into problems with this approach, please let us know, and we’ll try to help.

@reuk , thank you for looking into it. Did you also try stripping the font of hinting info? (FontForge Menu / Hints / Remove Insert Tables) It would be interesting to see a gif with the same font with hinting info and without.

To me and the fonts I’m using this makes all the difference.

sized

Here’s the same test including a version of the same font with hints removed, rendered using the JUCE default, i.e. Direct2D with grayscale antialiasing.

Do you agree that’s much closer to the software renderer? (take a look at ‘S’)
Imho with ClearType antialiasing at native res it’s even better.
If yes, all we’d need was a way to disable the hinting to get this look for any font. I will try again - using those DirectWrite settings I mentioned and SetTextRendingParams()

2 Likes

I don’t know whether it’s actually that straightforward to completely remove hinting info in this way. I don’t see a DirectWrite or D2D option to disable hinting completely. The closest I see is DWRITE_RENDERING_MODE_OUTLINE, which “bypasses the rasterizer and uses outlines directly”, but even with this enabled the glyph shapes are still closer to the “new” shapes than the old software renderer shapes. My next idea would be to pass a much larger font size when drawing the font, and then apply a transform to scale it back down to the correct size - but even that might not work.

As I said above, I think replicating the software renderer behaviour in D2D is going to introduce performance and maintenance overheads, and I’m not sure that the end result (ignoring the work of the type designer) is worth it, especially given that there’s already an alternative workaround.

Can cleartype already be enabled in JUCE 8.0.1?
Or is it something that will be added in a future version?

1 Like