al_draw_prim filled in with color
Artelis

I'd like to draw a custom polygon and fill it in. I'm using al_draw_prim like so:

for(int i = 0; i < 4; i++) {
    //some stuff to define realX and realY - it makes a square
    backgroundColor_ = al_map_rgb(255,0,0);
    v[i] = { .x = realX, .y = realY, .z = 0, .color = backgroundColor_ };
}
al_draw_prim(v, NULL, NULL, 0, 4, ALLEGRO_PRIM_LINE_LOOP);

This draws an outline of a square, but I'd like it colored in. Any thoughts?

Arthur Kalliokoski
Artelis

Since: 5.1.0

Thanks, but I'm on the latest stable build (5.0.10)

Arthur Kalliokoski

If all you need is a square, 5.0 has al_draw_filled_rectangle(). Other shapes could be drawn with al_draw_filled_triangle(), albeit with more complexity.

Artelis

No, I'm drawing all sorts of polygons. I suppose I COULD do triangles, but that would be a lot of annoying.

Can I do something like load a 1x1px bitmap of the desired color and stretch it over the whole prim?

Arthur Kalliokoski

The ex_prim.c in the examples shows textured polygons of arbitrary shape, so I'd say yes.

Artelis

Ok, we'll see what happens. Thanks.

Aikei_c

If you want to draw square, draw it as two triangles:

al_draw_prim([your array with six vertices, from 0 to 5], 0, NULL, 0, 6, ALLEGRO_PRIM_TRIANGLE_LIST);

Kris Asick
Artelis said:

No, I'm drawing all sorts of polygons.

In that case, be very careful if you continue to use al_draw_prim() at any step of the way. It's very expensive in terms of CPU overhead to call and calling it more than just a few times per frame of your gameplay could kill your framerate. On the flip side, you can prep everything you intend to draw into one massive array and just draw that with a single al_draw_prim() call.

Artelis

Aikei_c: My shapes are much more complicated than that.

Kris: Thanks for the insight. I'll look out for that. Why is it so CPU intensive?

Edgar Reynaldo

In that case, be very careful if you continue to use al_draw_prim() at any step of the way. It's very expensive in terms of CPU overhead to call and calling it more than just a few times per frame of your gameplay could kill your framerate. On the flip side, you can prep everything you intend to draw into one massive array and just draw that with a single al_draw_prim() call.

You say this all the time, but I've never seen any profiling to back it up.

Kris Asick

You say this all the time, but I've never seen any profiling to back it up.

You're welcome to write some up and test it yourself, but the situation I ran into was basically this:

Drawing 5,000 sprites/sec with al_draw_bitmap() > 60 FPS

Drawing 5,000 quads/sec with a single al_draw_prim() call > 60 FPS

Drawing 5,000 quads/sec with 5,000 al_draw_prim() calls < 1 FPS

In fact, it doesn't take that many calls to kill the framerate. Don't take my word for it and try it for yourself.

Now, I should point out, the last time I tested this was with Allegro 5.0.8, so maybe things have changed since then, but considering the way al_draw_prim() works in general, sending everything to draw in a single call is just better for performance regardless of anything. :B

Thomas Fjellstrom

I remember doing some tests as well, and the setup overhead of the al_draw_prim code is rather high, and most of it is spent in the opengl driver itself validating GL state. It's a known GL problem, one which we can try and mitigate by reducing the amount of state that the primitives addon touches, but it'll probably still be a problem.

The current way to reduce overhead in GL is to change as little state, and do as few individual draw calls as possible. Usually that's done by batching as much data into a single buffer object as you can and dispatching some gl*Array/gl*List calls.

SiegeLord
#SelectExpand
1#include <allegro5/allegro5.h> 2#include <allegro5/allegro_image.h> 3#include <allegro5/allegro_primitives.h> 4#include "stdio.h" 5 6int main(int argc, char** argv) 7{ 8 int N = 10; 9 if(argc > 1) 10 { 11 N = atoi(argv[1]); 12 } 13 else 14 { 15 printf("Usage: bench 100000\n"); 16 return 0; 17 } 18 19 20 al_init(); 21 al_init_image_addon(); 22 al_init_primitives_addon(); 23 24 ALLEGRO_DISPLAY* disp = al_create_display(800, 600); 25 26 ALLEGRO_BITMAP* bmp = al_load_bitmap("cow2.png"); 27 ALLEGRO_BITMAP* buffer = al_create_bitmap(400, 400); 28 al_set_target_bitmap(buffer); 29 30 int w = al_get_bitmap_width(bmp); 31 int h = al_get_bitmap_height(bmp); 32 33 ALLEGRO_COLOR col = al_map_rgb_f(1,1,1); 34 ALLEGRO_VERTEX vtx[4]; 35 36 double t1 = al_current_time(); 37 for(int ii = 0; ii < N; ii++) 38 { 39 vtx[0].x = 0; 40 vtx[0].y = 0; 41 vtx[0].u = 0; 42 vtx[0].v = 0; 43 vtx[0].color = col; 44 45 vtx[1].x = w; 46 vtx[1].y = 0; 47 vtx[1].u = w; 48 vtx[1].v = 0; 49 vtx[1].color = col; 50 51 vtx[2].x = w; 52 vtx[2].y = h; 53 vtx[2].u = w; 54 vtx[2].v = h; 55 vtx[2].color = col; 56 57 vtx[3].x = 0; 58 vtx[3].y = w; 59 vtx[3].u = 0; 60 vtx[3].v = h; 61 vtx[3].color = col; 62 63 al_draw_prim(vtx, 0, bmp, 0, 4, ALLEGRO_PRIM_TRIANGLE_FAN); 64 } 65 double delta1 = al_current_time() - t1; 66 67 double t2 = al_current_time(); 68 for(int ii = 0; ii < N; ii++) 69 { 70 al_draw_bitmap(bmp, 0, 0, 0); 71 } 72 double delta2 = al_current_time() - t2; 73 74 printf("Primitives: %f\nAllegro: %f\nRatio:%f\n", delta1, delta2, delta1 / delta2); 75 76 return 0; 77}

:PrimBench ./bench 100000
Primitives: 0.172736
Allegro: 0.151638
Ratio:1.139134
:PrimBench ./bench 100000
Primitives: 0.182917
Allegro: 0.158097
Ratio:1.156992
:PrimBench ./bench 1000000
Primitives: 1.439983
Allegro: 1.421288
Ratio:1.013154
:PrimBench ./bench 10000000
Primitives: 13.877668
Allegro: 14.003940
Ratio:0.990983

There is no appreciable difference in performance.

Also: https://www.allegro.cc/forums/thread/613609/993692#target but I don't feel like repeating that test.

Thomas Fjellstrom

I have to admit that its been a long time since I last did my test, the primitive performance may have improved.. but I was drawing a lot of circles. It was kinda slow :(

But here's a couple tests on my laptop:

Original code:

moose@balsa:~/projects$ ./prim-test 100000
Primitives: 0.480269
Allegro: 0.550363
Ratio:0.872640
moose@balsa:~/projects$ ./prim-test 1000000
Primitives: 4.643804
Allegro: 7.965119
Ratio:0.583018

Heald drawing:

moose@balsa:~/projects$ ./prim-test 100000
Primitives: 0.480745
Allegro: 0.028070
Ratio:17.126648
moose@balsa:~/projects$ ./prim-test 1000000
Primitives: 4.584236
Allegro: 0.255358
Ratio:17.952193

Not exactly no appreciable difference. I'd try it on my nvidia gpu, but the nvidia drivers are currently broken on linux with this gpu.

SiegeLord

Heald drawing:

Do you seriously not see the problem with that comparison? Really?

But thanks for showing that al_draw_prim is 2x as fast as al_draw_bitmap ;).

Thomas Fjellstrom
SiegeLord said:

Do you seriously not see the problem with that comparison? Really?

No, but then I didn't look all that closely at the code. I assumed the higher the number the slower it was. And with held drawing, the primitives number is clearly bigger.

I'm guessing you're complaining that with held drawing it isn't an "apples to apples" comparison. It doesn't need to be though. Setting up al_draw_prim to batch all of the calls would be rather annoying ;)

SiegeLord

It doesn't need to be though.

Yes it does, if you want to make a claim about al_draw_prim being slow.

It is not slow, and is the fastest method of drawing polygons available in Allegro.

EDIT: Well, aside from al_draw_indexed_prim, al_draw_vertex_buffer and al_draw_indexed_buffer which are all faster, but a little bit harder to use.

Thomas Fjellstrom

I'm not trying to put you down or anything. You seem to be touchy on this subject. When people try using the primitives functions, they do a small test and draw X number of shapes. Then they see that they can only draw say a few thousand and go "wtf?". That is the "slow" we're talking about.

And just because something is "the fastest available" doesn't mean it isn't slow :P

And, as I mentioned earlier, it isn't allegro's or the primitive addon's fault. It's a GL thing.

SiegeLord

That is the "slow" we're talking about.

Oh really? How about this?

setup overhead of the al_draw_prim code is rather high

It's lower than al_draw_bitmap 's. Why single out al_draw_prim?

Then they see that they can only draw say a few thousand and go "wtf?".

They go like that to al_draw_bitmap just as much if not more, and we don't say al_draw_bitmap is slow. We say, use a helper function explicitly designed to minimize the overhead. We say, it's not how it is supposed to be used.

There is absolutely no problem (that anybody has shown) with al_draw_prim and its brethren. If there are optimizations to be made, they are to be made in the code using it, whether it be user code or library code.

Thomas Fjellstrom
SiegeLord said:

It's lower than al_draw_bitmap 's. Why single out al_draw_prim?

A bunch of individual bitmap draws is pretty darn inefficient too. We do say it is slow ;) it's said over and over again, if you do call it a lot, make sure to use an atlas and held drawing, or even batch stuff up in buffer objects to use gl*Array's.

Quote:

There is absolutely no problem (that anybody has shown) with al_draw_prim and its brethren.

I still think you're taking this personally. It is not a slight against you, or allegro. It's just how this kind of usage is. Lots of individual drawing calls is slow. period.

Edgar Reynaldo

Drawing 5,000 quads/sec with 5,000 al_draw_prim() calls < 1 FPS

In fact, it doesn't take that many calls to kill the framerate. Don't take my word for it and try it for yourself.

Now, I should point out, the last time I tested this was with Allegro 5.0.8, so maybe things have changed since then, but considering the way al_draw_prim() works in general, sending everything to draw in a single call is just better for performance regardless of anything. :B

The reason I asked you to provide proof is because the burden is on you. You're the one who says it is deficient, so you should be the one to provide proof.

A better test would be to change the # of prims drawn per second until the fps drops. That would give you a better gauge of the capabilities of allegro.

And using 5.0.8 is not a good test. That's two versions behind the latest stable release, and probably miles away from the latest unstable release. 5.1.8 would be a better test or at least 5.0.10.

I'm not at home now, so I can't test anything, but maybe tomorrow I will be able to try things out.

Artelis

You guys are awesome. On an unrelated note, any word on when 5.1 stable will come out? (Cause you know.. still want to fill in my primitives).

beoran

5.1 stable will be 5.2... It will be out when it is ready. But there's still a lot of wok to be done, so I fear it might be a long time before we see 5.2. If you feel motivated then you could help out, though and speed this up a bit... :)

Edgar Reynaldo

Just so you know, just because 5.1 is called unstable doesn't mean it is unusable. 5.1.8 is perfectly usable, and if you want filled primitives I don't see any reason not to use it.

pkrcel

Absolutel what Edgar said.

"Unstable" refers to the API, not the stability of the library itself. It means roughy that anything that's in 5.1 and NOT in 5.0 release is suject to change at any moment.

Kris Asick

The reason I asked you to provide proof is because the burden is on you. You're the one who says it is deficient, so you should be the one to provide proof.
A better test would be to change the # of prims drawn per second until the fps drops. That would give you a better gauge of the capabilities of allegro.
And using 5.0.8 is not a good test. That's two versions behind the latest stable release, and probably miles away from the latest unstable release. 5.1.8 would be a better test or at least 5.0.10.
I'm not at home now, so I can't test anything, but maybe tomorrow I will be able to try things out.

Well, as Tomasu pointed out earlier, it's an OpenGL thing, and I've been stuck using OpenGL exclusively because I'm working with fragment shaders using the 5.0.x branch, thus I didn't know (and no one told me) that it only affected the OpenGL side of things. I mean, I COULD go up to the 5.1.x branch, but for making something I intend to sell it makes more sense to go with the stable branch and work within and around its limitations.

So yeah, Artelis, unless you're using OpenGL graphics exclusively (or intend to give the end-user the ability to choose between Direct3D and OpenGL) you don't seem to need to worry about al_draw_prim() performance. ;)

Thomas Fjellstrom

it only affected the OpenGL side of things.

It's also a D3D thing. The APIs have a fair amount of overhead per draw call.

Quote:

for making something I intend to sell it makes more sense to go with the stable branch and work within and around its limitations.

Not sure I believe that when the actual stability is good, and has lots of bug fixes and new functionality you might want or need.

beoran

Actually, if you're making a game and you plan to sell it in the next year or so, Allegro 5.1.x should be fine. API stability only matters if you're writing an application that will need very long term support.

And besides, I want to push for allegro 5.2 a bit more. Time for me to get cracking again.

Thread #614089. Printed from Allegro.cc