Vadim recently mentioned that it could be good to use Direct2D to rasterize SVGs in wxBitmapBundle.
This is an attempt to implement this in a class wxBitmapBundleImplSVGD2D. Disclaimer: I have no experience with Direct2D or any other high-performance graphic API nor am I very knowledgeable about SVG format.
I was surprised how limited SVG support in Direct2D is. For example, even the latest version does not support text element, for more information about SVG support in Direct2D see here.
This makes me wonder if using Direct2D renderer is really any better than existing NanoSVG one. I will benchmark the two and see if Direct2D is at least (much) faster but considering its purpose here, the speed may not matter much. I will also finish the program displaying SVGs with both renderers to help check how they cope with different SVGs.
My implementation limitations:
IWICBitmap, the device context and bitmap are shared among all instances of wxBitmapBundle, created upon first use of any wxBitmapBundleImplSVGD2D method and kept alive during the program lifetime. This may be an utterly wrong approach, please feel free to point it out.Known issues
I call Direct2D APIs like this
HRESULT hr = wxD2D1Factory()->CreateWicBitmapRenderTarget(ms_bitmap, props, &target);
if ( FAILED(hr) ) ...
However, anytime such a call fails, a D2D DEBUG ERROR exception is thrown before if ( FAILED(...) is executed. I find this very surprising, similar code I saw actually had to ask for an exception with DX::ThrowIfFailed(). Yet, I do not want exceptions but I still get them. I could wrap the code with try catch, but I think this should be handled differently. Any ideas?
https://github.com/wxWidgets/wxWidgets/pull/22029
(1 file)
—
Reply to this email directly, view it on GitHub, or unsubscribe.
Triage notifications on the go with GitHub Mobile for iOS or Android.
You are receiving this because you are subscribed to this thread.![]()
Thanks! I'm also very surprised that text isn't supported by D2D, I didn't know this at all.
Before looking at this code in details and maybe commenting on it, I think we really need to move it to src/msw/svgd2d.cpp or something like that, i.e. MSW-specific source file instead of mix-and-matching it with the generic code. Or are there some problems with doing this that I'm missing?
—
Reply to this email directly, view it on GitHub, or unsubscribe.
Triage notifications on the go with GitHub Mobile for iOS or Android.
You are receiving this because you are subscribed to this thread.![]()
@PBfordev pushed 1 commit.
—
View it on GitHub or unsubscribe.
You are receiving this because you are subscribed to this thread.![]()
Before looking at this code in details and maybe commenting on it, I think we really need to move .... are there some problems with doing this?
I originally wanted to do that but that would require rebaking which is beyond my reach. Moreover, once other native renderers are added, the could would need to be changed anyway, to some kind of factory.
I think for now it is good enough, at least before a decision whether to even bother with Direct2D SVG support is made and the code design reviewed.
—
Reply to this email directly, view it on GitHub, or unsubscribe.
Triage notifications on the go with GitHub Mobile for iOS or Android.
You are receiving this because you are subscribed to this thread.![]()
I can do the rebaking, we just need to use some preprocessor symbols to define which implementation is to be used (unless we want to have both and choose between them at run-time?).
Also, please don't worry about the commits: I can always redo them later or you can force push, as advised in another comment, at the end (it's better not to do it until the changes are finalized as this would make it impossible to view the diff compared to the previous PR version).
—
Reply to this email directly, view it on GitHub, or unsubscribe.
Triage notifications on the go with GitHub Mobile for iOS or Android.
You are receiving this because you are subscribed to this thread.![]()
@PBfordev pushed 2 commits.
—
View it on GitHub or unsubscribe.
You are receiving this because you are subscribed to this thread.![]()
I have created a simple application comparing appearance and performance of wxWidgets built-in NanoSVG rasterizer and my implementation from this PR: https://github.com/PBfordev/wxtestsvg
After testing with this application, I found that my Direct2D implementation is slower at commonly used bitmap sizes.
Additionally, it can be built only with MSVC, is available only on Win10 v1709+, and does not support significantly more features than NanoSVG.
Based on the above, I am closing the PR.
—
Reply to this email directly, view it on GitHub, or unsubscribe.
Triage notifications on the go with GitHub Mobile for iOS or Android.
You are receiving this because you are subscribed to this thread.![]()
Closed #22029.
—
Reply to this email directly, view it on GitHub, or unsubscribe.
Triage notifications on the go with GitHub Mobile for iOS or Android.
You are receiving this because you are subscribed to this thread.![]()
Thanks for your tests and sorry for wasting your time with this proposal, but I really had no idea it would be so poor. Sorry!
—
Reply to this email directly, view it on GitHub, or unsubscribe.
Triage notifications on the go with GitHub Mobile for iOS or Android.
You are receiving this because you are subscribed to this thread.![]()
No problem.
The poor performance may be on my implementation.
AFAIK, SVG with Direct2D is used for rendering SVGs with WPF and UWP. However, I guess the purpose the is to render them on the screen. I suspect that the D2D render may render it onto GPU memory and reading GPU memory (when copying to wxBitmap) is slow. But maybe there is not like that, as I said, I know nothing about D2D and similar...
—
Reply to this email directly, view it on GitHub, or unsubscribe.
Triage notifications on the go with GitHub Mobile for iOS or Android.
You are receiving this because you are subscribed to this thread.![]()
I stumbled upon this issue and could not let it pass without comment about it. Every microsoft api that used the hardware GPU acceleration, totally disabled it when using WIC Bitmaps, doing video decode is more noticeable.
The most probable thing is that you were comparing between gpu accelerated (nanosvg) and software rasterized (d2d) as @PBfordev pointed out, in my opinion, d2d should perform better and magnitudes ahead of nanosvg in supported features. Just recently implemented nanosvg on bare d3d9 and noticed the huge lack of features in there...
The way to go should be create d2d over a staging dxgi device and map the underliying gpu memory
—
Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you are subscribed to this thread.![]()
gpu accelerated (nanosvg)
Is NanoSVG rasterizer really accelerated in any way? I don't see anything like this, just loops everywhere: https://github.com/wxWidgets/nanosvg/blob/master/src/nanosvgrast.h
in my opinion, d2d should perform better and magnitudes ahead of nanosvg in supported features.
The surprising lack of features in D2D SVG is addressed in my first post in the PR and a link to lists of supported and unsupported features is provided.
The way to go should be create d2d over a staging dxgi device and map the underliying gpu memory
But for a wxBitmap, the bitmap still must be copied from the GPU to system RAM, is that not rather slow itself?
BTW, in case you need an SVG library, there is https://github.com/Samsung/thorvg. I have no personal experience with it but it could be faster and more feature-complete than NanoSVG. However, it is also much more heavier than NanoSVG and thus not that suitable for a simple rasterizer wxWidgets needed.
BTW2, in my experience, the tiger SVG may not be that good for testing SVG parser and rasterizer.
—
Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you are subscribed to this thread.![]()
Is NanoSVG rasterizer really accelerated in any way? I don't see anything like this, just loops everywhere
Yes this is my mistake, i dont know much about the current implementation in wx, just sharing what i saw on my experience using interops with WIC
The surprising lack of features in D2D SVG is addressed in my first post in the PR and a link to lists of supported and unsupported features is provided.
Well Direct2D in its basic CreateSvgDocument/DrawSvgDocument is quite limited but youre suppoused to do your own shaping run using DirectWrite to draw text wich is external to D2D. Windows usually does this step in the DirectComposition API layer, for example in edge.
SVG Rendering should be subclassed in a list of geometry sinks from its path data, this would allow to add missing effects, and also generate geometry sink for text using directwrite's GetGlyphRunOutline, then do the full composition including vector, text, effects and images.
Ill try to work on a example for a complete svg renderer in d2d, and cover the most SVG spec possible. (effects, texts and other missing features)
But for a wxBitmap, the bitmap still must be copied from the GPU to system RAM, is that not rather slow itself?
If you want to take the image to a buffer of bytes, you always have to copy it, this isnt by definition bad, and its only an issue if you have high frame rates to render, but looking at wxBitmap being based on GDI pipeline you could use the d2d->dxgi interface create your d3d11 texture with the bindflag D3D11_RESOURCE_MISC_GDI_COMPATIBLE and access to the texture exposed HDC to paint on your bitmap, wich sometimes get an auto accelerated path inside the windows kernel, something like
HDC gpudc = 0;
IDXGISurface1 *surface = 0;
hr = tex_gpu->QueryInterface(IID_IDXGISurface1, (void **)&surface);
if (SUCCEEDED(hr))
{
hr = surface->GetDC(FALSE, &gpudc);
if (SUCCEEDED(hr))
{
HDC dc = GetDC(hWnd); // <<--your wxBitmap HDC here
BitBlt(dc, 0, 0, width, height, gpudc, 0, 0, SRCCOPY);
ReleaseDC(hWnd, dc);
surface->ReleaseDC(0);
}
surface->Release();
}
a courious anecdote about d3d11 textures with GDI compatible flag, is that you can set the cpu sharing flag to 0, and create the texture as gpu texture that it isnt unmapeable on sysmem, yet it still works, so it seems an accelerated frame copy is being done in the driver. when copiying to GDI resources.
My point all the time, was that using WIC, all the Direct2D pipeline switches from DXGI based rasterizer to WARP software rasterizer, it downgrades the entire pipeline. For example using the IMFMediaEngine video decoder, if you use a wic texture, every step that uses to run in GPU, like scaling, color conversion, h264 decoding etc... happens in the CPU. I think this is not documented as many of the WIC interoperatibility is almost undocumented too, but better see with your own eyes
At the left is the WIC implementation almost spinlocking a single cpu, and in the right, DXGI based decoder using the GDI code from above to render on the window, both samples decoding at same clock, same sources etc...
Thats why i came uninvited to this issue, so you dont waste time where i did :)
BTW, in case you need an SVG library...
Seems nice but theres battle hardened libraries out there like skia or cairo around too i guess... in any case ill go forward to implement it on Direct2D since i think it will be performing fine... i hope
in my experience, the tiger SVG may not be that good for testing SVG parser and rasterizer.
yes, the tiger is the complete baseline test as its just paths and nothing more but heh, it also looks cool :)
—
Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you are subscribed to this thread.![]()