D3D11 - Bitmap Font Rendering

Started by
10 comments, last by Endurion 7 years, 9 months ago
Hi,

I'm currently working on an D3D11 module for my engine. I've got it to work fine mostly and I can now switch between DX8, DX9 and DX11 (with shaders).

However I have extreme performance problems with text rendering. I'm using bitmap fonts, and the naive approach, that worked fine for DX8 and DX9 used single quads per letter and DrawPrimitiveUP. Obviously that's not available anymore with DX11.

For DX11 my simple implementation creates a vertex buffer, fill it with data, upload it, render it and destroy it. One "optimization" was to reuse the created vertex buffer for every quad, but that didn't help much. It seems DrawPrimitiveUP does some heavy optimization under the hood, but the nature of that is unfortunately not known (to me).

What would be the best approach here? Really create vertex buffers for every string currently displayed and cache them?
I would prefer to stay with bitmap fonts (I'm aware of the downsides of foreign languages, etc..)

Fruny: Ftagn! Ia! Ia! std::time_put_byname! Mglui naflftagn std::codecvt eY'ha-nthlei!,char,mbstate_t>

Advertisement

Do you create a buffer for each quad or are you using a buffer to hold multiple quads? (the text you wrote to me indicates that you create a buffer for each quad so just want to clear that up)

You should discard the content of the old buffer when you are filling it again with new data, you could create a quad data that contains all of the transformed vertex data and then just copy that into the vertex buffer for rendering. You would need a new VB if you change font or scaling size offcourse, and even that is fixable with instanced rendering.

Worked on titles: CMR:DiRT2, DiRT 3, DiRT: Showdown, GRID 2, theHunter, theHunter: Primal, Mad Max, Watch Dogs: Legion

I've has font problem several days ago and i decided to use Direct2D shared surface. It is not perfect but it works well.

Your approach should be fast enough, i use it for my entire gui draw which is rebuilt each frame.

Please report back if you manage to make it work. Tell me if you are somehow able to predict how much space will rendered text take, I cannot find out how to do it.

I just do the naive thing with 2D and it seems quite fast. Even on older hardware I could throw tens of thousands of them around like it was nothing.

I pre-fill a static 16 bit index buffer and create a dynamic vertex buffer for my sprites. I create the sprite geometry each frame and do some basic sorting and batching. It's pretty easy to batch large amounts of the sprites into a single draw call. Buffers for it are created once up front and destroyed only at the end.

Since the index buffer was 16 bit, I capped the number of sprites at 10922 per draw call.

(10922 * 4) * sizeof(Vertex2D)... which was 32. So 1398016 bytes for the vertex buffer. About 1.4mb.

I completely did not understand clashie... :) Are you able to change the text during runtime efficiently?

I highly recommend that you just grab the DirectXTK and use the helpers it provides for bitmap fonts and sprite rendering. If you need something special that it can't handle, at least look at how it solves the problem.

Note that it also provides a number of other very useful utilities like screen grab (screenshot) helpers, a decent math library, texture loading, simplified effects framework, and so on.

Sean Middleditch – Game Systems Engineer – Join my team!

A thanks for the recommendations. Looks like I'm off to implement nice batching then. I thought so, I was just befuddled at what a difference it makes, the little bit of text would cause such tremendous slowdowns.

@NightCreature83: I was creating a buffer for every quad. So that's quite a few reuses per frame for a few lines of text :)

Fruny: Ftagn! Ia! Ia! std::time_put_byname! Mglui naflftagn std::codecvt eY'ha-nthlei!,char,mbstate_t>

A thanks for the recommendations. Looks like I'm off to implement nice batching then. I thought so, I was just befuddled at what a difference it makes, the little bit of text would cause such tremendous slowdowns.

@NightCreature83: I was creating a buffer for every quad. So that's quite a few reuses per frame for a few lines of text :)

Its the number of buffers here that are the problem, you are usually better of creating a fewer vertex buffers and having a few large ones than really small ones, the CPU overhead will cost more on the small buffers than on the large ones.

Worked on titles: CMR:DiRT2, DiRT 3, DiRT: Showdown, GRID 2, theHunter, theHunter: Primal, Mad Max, Watch Dogs: Legion

This topic is closed to new replies.

Advertisement