Right, this might be it.
I see the toggle in projucer, but can’t see it mentioned in the JUCE cmake API?
Right, this might be it.
I see the toggle in projucer, but can’t see it mentioned in the JUCE cmake API?
Cause it is not a JUCE thing (but it has been discussed here multiple times). I copy the following lines from pamplejuce.
# Static runtime please
# See https://github.com/sudara/pamplejuce/issues/111
if (WIN32)
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>" CACHE INTERNAL "")
endif ()
Yeah im sorry haha, i saw a few threads about the subject.
However i’m still not clear, can i change it to Release without a problem? i.e.
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Release>:Release>")
I havent seen anyone do that
I don’t think you need to change anything. From cmake documentation, the code:
selects for all following targets a multi-threaded statically-linked runtime library with or without debug information depending on the configuration.
This does not work, if you load the image from a file:
image = ImageFileFormat::loadFrom(buffer, info.fileSize);
Managing a cache for gradients is going to be a nightmare. Each component in my plug-ins can use multiple different gradients for each component. The gradient parameters are dependent on the current theme configuration as well as the component’s current rect. Is it seriously necessary to create a complicated caching mechanism for all these gradients?
Probably not; I recommend you try it and see if it’s an issue.
I took a look at your website and your demo videos - looks like you might be using gradients for the animated graphs in the middle? (I dig the ghost effect BTW). How often are the graphs repainted?
Matt
I’m running into this as well. I have many meters, animating objects, etc, that create a gradient on a timer. Caching all possible states of the gradient is impossible.
I would not mind switching to a cached gradient object that can be manipulated in place - but currently it’s quite a heavy performance hit we’re taking.
More on the gradient issues.
Most of our dynamic gradients have something like this:
ColourGradient::horizontal(color1, value1, color2, value2)
With the gradient constantly changing based on a 60hz timer. What’s the correct way to apply this in Direct2d land?
I can manipulate a class member gradient in place to avoid heap allocations - might need to rewrite JUCE-provided functions like horizontal to do so.
However, I’m not sure how that works with Direct2D caching? Also it seems that similar to Image issues mentioned, switching to the Software Renderer is not really switching gradient to the old way?
That “Golden Rule” might be better worded as a “technical note” for those interested in performance optimizing. It’s definitely not saying you should worry about adding some sophisticated caching mechanism for gradients out of the gate (I wrote this text with Matt’s input, so I’ll clarify it). Having them as class members is always a good idea.
I’ve been doing dozens of animated gradients @ 60fps and things are smooth here. I have them as class members. My perception was that their performance improved on Direct2D? I will do a before/after measurement next time I’m in my app…
The graphs are OpenGL shaders, but the sliders/knobs and other components use gradients.
Although, now that I’m typing this out I just realized I’ll likely still be using the OpenGL pipeline for rendering components even after updating to JUCE 8. So maybe the gradient issue isn’t even applicable. But in general I’m pretty unclear on how Direct2D interacts with the OpenGL pipeline in JUCE 8.
I declare gradient as a class member and update it at about 60~120 fps:
gradient.point1 = juce::Point<float>(x1.load(), 0.f);
gradient.point2 = juce::Point<float>(x2.load(), 0.f);
gradient.isRadial = false;
gradient.clearColours();
gradient.addColour(0.0,
gColour.withMultipliedAlpha(juce::jmax(conflictsP.front().load(), 0.f)));
gradient.addColour(1.0,
gColour.withMultipliedAlpha(juce::jmax(conflictsP.back().load(), 0.f)));
// then add more colours
Not sure whether the gradient is cached in this case. However, it seems to work well. I have only one gradient in my plugin so the situation might be different.
From my testing, using OpenGL in combination with the JUCE 8 Direct2D renderer results in higher CPU/GPU usage compared to using OpenGL with the software renderer, particularly during continuous repaints.
When combining native OpenGL code with JUCE components, CPU and GPU utilization could be much higher with the Direct2D renderer enabled, especially if you have many components that are frequently repainted. Performance deteriorates further if any components use juce::Image, as it defaults to NativeImageType, causing inefficient GPU → CPU → GPU data transfers between the OpenGL and Direct2D renderers. Even with all native OpenGL code, having the Direct2D renderer enabled increases CPU and GPU usage of dwm.exe.
You can achieve JUCE 7-level performance with OpenGL if you disable the Direct2D renderer and use SoftwareImageType for any juce::Image instances in your components. Alternatively, you could also potentially improve performance by doing all rendering with Direct2D, though this might not be feasible if you rely heavily on native OpenGL code and custom shaders.
Performance with OpenGL + Direct2D could be improved if JUCE utilized the WGL_NV_DX_interop2 OpenGL extension on supported hardware and drivers. This extension allows resource sharing between DX11 and OpenGL contexts, eliminating the need for GPU → CPU → GPU copying. However, JUCE does not make use of this extension.
OpenGL for JUCE is usually handled with a child window. Since you’re working with a plugin, your plugin editor is itself a child window inside a parent window created by the plugin host.So ultimately you end up with:
host plugin window : JUCE editor Direct2D child window : OpenGL child window
So OpenGL & Direct2D don’t really interact; your OpenGL graphs are basically running in another window.
Matt
I looked at this previously - it’s specific to Nvidia, right? Not sure if there’s an equivalent for AMD.
Matt
Its also supported by AMD and Intel drivers on newer hardware according to gpuinfo.org.
Native OpenGL code will not interact with Direct2D. However, if you’re doing any component rendering with OpenGL where juce::Image is used (such as for storing graphics assets, caching, or effects), the Direct2D renderer will be used by default on those images before the data is copied to the cached image frame buffer that the OpenGL context uses.
Its also supported by AMD and Intel drivers on newer hardware according to gpuinfo.org.
OK, interesting; good to know.
Native OpenGL code will not interact with Direct2D. However, if you’re doing any component rendering with OpenGL where juce::Image is used (such as for storing graphics assets, caching, or effects), the Direct2D renderer will be used by default on those images before the data is copied to the cached image frame buffer that the OpenGL context uses.
Agreed; those wouldn’t play nice together. I think the JUCE team is looking at all this; not sure what they have in mind for OpenGL.
Matt
At least in my case - looks like the main performance issues came from using setBufferedToImage(true) in combination with a transformed component.
Removing those on Windows only got the performance at least with Direct2D to a decent place - but everything still performs horribly with the software renderer compared to JUCE 7.
I’ll need to investigate more on why that happens.
Maybe try removing any setOpaque(true) call you might have in your code, this made a significant difference in my case.
We’re not using setOpaque in our code at all.
So, I did have quite a long profiling section and this what we’ve found:
We’ve had one case of manipulating image data directly - that made the performance horrible using both the software renderer and the Direct2D renderer.
This is IMO a major JUCE bug - the software renderer should not be affected by this.
We have many SVG based components that were using setBufferedToImage(true) along with a transform. The call to transform an image really dominated the profiling on Windows on both renderers, and removing that on Windows made things tolerable again.
This is also a JUCE bug in my opinion.
After those two were fixed, we’re back into normal (but slower than before) performance on the software renderer, but better performance with Direct2D which I’m generally happy about.
I still see slowdowns on drawing regular images on the software renderer.
I didn’t investigate the gradient issue yet - we’re currently creating some of them dynamically on a timer in animated Components like Meters and I’m not sure what the recommended solution for that is in Direct2D land.