|
Drawing text slows down FPS dramatically |
Aksel Huff
Member #16,201
February 2016
|
EDIT: Unless there is something wrong with my FPS calculation, it seems like a blank screen will give me around 3000 to 5000 FPS, but if I draw even one small bit of text, it drops down to 20 FPS. Drawing a line does not seem to affect FPS. I've only just now noticed that with each call to al_draw_text() my FPS drops dramatically. I noticed it when I had flashing "Press Enter" text, whenever the text was visible, an object that followed my mouse stuttered. I can't think of anything that I might have done to cause this problem. I tried adding several more lines to draw "Main Menu" over and over and with each draw the FPS cut in half for each draw. I believe this is all the applicable code: 1// GAME LOOP
2while (engine->state_manager->running())
3{
4 if (engine->event_handler->handleEvents()) //Function included in post
5 {
6 ALLEGRO_EVENT ev = engine->event_handler->getEvent();
7 engine->input_handler->getInput(ev);
8 engine->state_manager->handleEvents();
9
10 if (engine->input_handler->isKeyPressed(ALLEGRO_KEY_ESCAPE) || engine->event_handler->eventIs(ALLEGRO_EVENT_DISPLAY_CLOSE))
11 {
12 engine->state_manager->quit();
13 }
14 else if (engine->event_handler->eventIs(ALLEGRO_EVENT_TIMER))
15 {
16 engine->state_manager->update();
17 }
18 }
19
20 if (engine->event_handler->eventQueueEmpty()) // Simply calls al_is_event_queue_empty()
21 {
22 uint64_t ms = t.getMilliseconds();
23 elapsed = ms - prev_time;
24 prev_time = ms;
25
26 engine->state_manager->draw(elapsed); // Function included in post
27 engine->draw_engine->flipAndClear(al_map_rgb(0, 0, 0));
28 }
29 engine->state_manager->cleanStates();
30}
31
32bool EventHandler::handleEvents()
33{
34 ALLEGRO_EVENT ev;
35
36 if (!al_get_next_event(event_queue, &ev)) return false;
37
38 if (ev.type == ALLEGRO_EVENT_DISPLAY_SWITCH_OUT)
39 focus = false;
40 else if (ev.type == ALLEGRO_EVENT_DISPLAY_SWITCH_IN)
41 focus = true;
42 else if (ev.type == ALLEGRO_EVENT_DISPLAY_RESIZE)
43 {
44 al_acknowledge_resize(al_get_current_display());
45 axe::log(_MESSAGE, "Display Resized!\n");
46 engine->draw_engine->resized();
47 // Windows has just been resized, let anything know about it.
48 }
49
50 this->ev = ev;
51
52 return true;
53}
54
55void MenuState::draw(uint64 elapsed)
56{
57 //Press Enter will flash once per second
58 el += elapsed;
59 if (el >= 500) draw_text = true;
60 if (el >= 1000)
61 {
62 el -= 1000;
63 draw_text = false;
64 }
65
66 if (font1)
67 {
68 al_draw_text(font1, al_map_rgb(255, 255, 255), w / 2, 64, ALLEGRO_ALIGN_CENTRE, "Main Menu");
69 }
70
71 if (draw_text && font2)
72 {
73 al_draw_text(font1, al_map_rgb(255, 255, 255), w / 2, h - 128, ALLEGRO_ALIGN_CENTRE, "Press Enter");
74 }
75
76 //Draws an X starting at (0,0) moving 90 pixels to the right per second, and 50 pixels down per second
77
78 x += 90.f * elapsed / 1000.f;
79 y += 50.f * elapsed / 1000.f;
80
81 al_draw_line(x - 8, y - 8, x + 8, y + 8, al_map_rgb(255, 0, 0), 2);
82 al_draw_line(x - 8, y + 8, x + 8, y - 8, al_map_rgb(255, 0, 0), 2);
83}
Thanks for the help!
|
Edgar Reynaldo
Major Reynaldo
May 2007
|
Are you loading your fonts before al_create_display? They might be memory bitmaps. Show font and display creation code. All video bitmaps are attached to a display and if you haven't created a display you don't have anything to attach it to so they're memory bitmaps. Or your problem is something else. What version of Allegro are you using? What platform are you on? What's your compiler? My Website! | EAGLE GUI Library Demos | My Deviant Art Gallery | Spiraloid Preview | A4 FontMaker | Skyline! (Missile Defense) Eagle and Allegro 5 binaries | Older Allegro 4 and 5 binaries | Allegro 5 compile guide |
Aksel Huff
Member #16,201
February 2016
|
Thanks for the help! I would not have figured this out if you hadn't have brought up memory/video bitmaps! EDIT2: I added "al_set_new_bitmap_flags(ALLEGRO_VIDEO_BITMAP);" before loading fonts and the problem disappeared! I'm guessing Allegro is defaulting to memory bitmaps for some reason? Or something I've done has changed the bitmap flags. Also I've just now noticed that lines 65 and 67 are using al_set_new_bitmap_flags rather than al_set_new_display_flags(). I haven't tested it yet, but I'm guessing that is the culprit. I'm using Allegro 5.2.2 from NuGet in MSVC Express 2015. Windows 10. The display is created inside "engine->draw_engine->init()", and then near the end of my game initialization I load a font to draw the FPS with Here is essentially the program entry for my game: 1int Game::init()
2{
3 t.start();
4
5 srand(time(NULL));
6 engine = new axe::Engine();
7 const float ticks_per_second = 30.f;
8
9 /*************** SET DEFAULT SETTINGS ***************/
10
11 int width = 1280;
12 int height = 720;
13 bool fullscreen = false;
14 bool music = true;
15 bool sfx = true;
16 bool vsync = true;
17 bool maximized = true;
18
19 engine->settings_handler->set("x_resolution", width);
20 engine->settings_handler->set("y_resolution", height);
21 engine->settings_handler->set("fullscreen", fullscreen);
22 engine->settings_handler->set("maximized", maximized);
23 engine->settings_handler->set("vsync", vsync);
24 engine->settings_handler->set("music", music);
25 engine->settings_handler->set("sfx", sfx);
26
27 engine->settings_handler->loadSettings(".settings");
28 engine->settings_handler->printSettings();
29
30 engine->settings_handler->get("x_resolution", width);
31 engine->settings_handler->get("y_resolution", height);
32 engine->settings_handler->get("fullscreen", fullscreen);
33 engine->settings_handler->get("maximized", maximized);
34 engine->settings_handler->get("vsync", vsync);
35 engine->settings_handler->get("music", music);
36 engine->settings_handler->get("sfx", sfx);
37
38 if (engine->init(ticks_per_second))
39 {
40 axe::crash("Engine failed to initialize!");
41 return 1;
42 }
43 engine->draw_engine->init(width, height, fullscreen, false);
44
45 engine->draw_engine->setWindowIcon(RES::IMG::ICO); //todo add \n to the error report for this function
46 engine->draw_engine->setWindowTitle("The 21st Floor");
47
48 engine->sound_manager->setMusicMute(!music); // true in settings means music is on, true in sound_manager means music is off
49 engine->sound_manager->setSFXMute(!sfx);
50
51 engine->state_manager->changeState(new SplashState(engine));
52
53 fnt = nullptr;
54 fnt = al_load_font(RES::FNT::ARIAL, 18, 0);
55
56 return 0;
57}
And here is my disaster of window initialization! 1int DrawEngine::init(int w, int h, bool fullscreen, bool match_aspect_ratio)
2{
3 ALLEGRO_DISPLAY_MODE display_data;
4
5 this->fullscreen = fullscreen;
6 screenWidth = w;
7 screenHeight = h;
8
9 //Get all possible fullscreen resolutions and calculate aspect ratio
10 int num_display_modes = al_get_num_display_modes();
11 al_get_display_mode(num_display_modes - 1, &display_data);
12 float aspect_ratio = float(display_data.width) / float(display_data.height);
13
14 //Fill vector with all resolutions, removing duplicates and anything not matching aspect ratio
15 printf("Supported Fullscreen Resolutions:\n");
16 for (int i = 0; i < num_display_modes; i++)
17 {
18 al_get_display_mode(i, &display_data);
19
20 bool same_aspect;
21
22 if (match_aspect_ratio)
23 same_aspect = float(display_data.width) / float(display_data.height) == aspect_ratio;
24 else
25 same_aspect = true;
26
27 if (same_aspect)
28 {
29 bool dup = false;
30 for (std::vector<ALLEGRO_DISPLAY_MODE>::iterator it = display_modes.begin(); it != display_modes.end(); ++it)
31 {
32 if (display_data.width == (*it).width && display_data.height == (*it).height)
33 dup = true;
34 }
35 if (!dup)
36 {
37 display_modes.push_back(display_data);
38 printf(" %ix%i\n", display_data.width, display_data.height);
39 }
40 }
41 }
42
43 //Make sure the resolution supplied to this function is supported in fullscreen
44 if (fullscreen)
45 {
46 al_set_new_display_flags(ALLEGRO_FULLSCREEN);
47
48 bool found = false;
49 for (int i = display_modes.size() - 1; i >= 0; i--)
50 {
51 if (display_modes[i].width == screenWidth && display_modes[i].height == screenHeight)
52 {
53 found = true;
54 }
55 }
56 if (!found)
57 {
58 screenWidth = display_modes.back().width;
59 screenHeight = display_modes.back().height;
60 axe::log(axe::_WARNING, "Resolution Settings Invalid: Setting resolution to default: %ix%i\n", screenWidth, screenHeight);
61 }
62 }
63 else if (screenWidth == display_modes.back().width && screenHeight == display_modes.back().height)
64 {
65 al_set_new_bitmap_flags(ALLEGRO_MAXIMIZED);
66 }
67 else al_set_new_bitmap_flags(ALLEGRO_WINDOWED);
68
69 display = al_create_display(screenWidth, screenHeight);
70
71 if (!display)
72 {
73 axe::crash("Unable to create display at resolution %ix%i", screenWidth, screenHeight);
74 return 1;
75 }
76
77 if (!fullscreen) centerWindow();
78
79 al_init_image_addon();
80 al_init_primitives_addon();
81 al_init_font_addon();
82 al_init_ttf_addon();
83
84 al_register_event_source(event_queue, al_get_display_event_source(display));
85
86 printf("DrawEngine Initialized\n");
87
88 return 0;
89}
I'm going to quickly write up a minimal program to see if I can recreate the issue.
|
Edgar Reynaldo
Major Reynaldo
May 2007
|
It's a good idea to initialize every addon before creating a display. Do that all in a single init function once before you use your engine. You call init, and then you create a font. In init you create a display, so the font should be attached to a display. Aksel Huff said: Also I've just now noticed that lines 65 and 67 are using al_set_new_bitmap_flags rather than al_set_new_display_flags(). I haven't tested it yet, but I'm guessing that is the culprit. Yes, that's a problem. You should be calling al_set_new_display_flags there. Calling al_set_new_bitmap_flags with display flags is an error. There's a separate set of flags. My Website! | EAGLE GUI Library Demos | My Deviant Art Gallery | Spiraloid Preview | A4 FontMaker | Skyline! (Missile Defense) Eagle and Allegro 5 binaries | Older Allegro 4 and 5 binaries | Allegro 5 compile guide |
|