|
Content Loading and Render problem |
Addison Elliott
Member #12,394
November 2010
|
I currently have a program that has four content loading threads(to reduce lag), and one rendering thread. I just found out that the reason why my program was using 20% more CPU was because the ALLEGRO_FONT does not have the current display set, because it's loaded in the content thread, which does not have a current display. So I set the display and then I start to see a lot of crashing. Well, now I have just found out this is because I call al_hold_bitmap_drawing(true) in the rendering thread, and that interferes when loading bitmaps/fonts. So, my whole method is screwed now, and I pretty much need to redo my whole base of the program, woohoo! Since the four content threads are pretty much useless, I'm going to get rid of those and do the content loading in the rendering thread. Now, before I went and jumped on programming that, I was thinking about how I can make sure that lag doesn't happen here. This is where my problem comes in. How can I make sure that whenever the redrawTimer is set off that it will stop loading the bitmap, if its trying to load one, and redraw? A friend of mine mentioned making a queue to set priorities on, or even having two queues, checking the first one first since it has higher priority. That solves that but I still need to make sure that the al_load_bitmap or al_load_font function won't take longer than needed. Since the FPS is 20, if it starts loading a bitmap right when a redraw event is emitted, it could stop the thread and it'd have to wait a bit longer to be redrawn. Is there anyway to do this? I do apologize about the title of this thread, I was not sure what to name the topic. |
Matthew Leverton
Supreme Loser
January 1999
|
The way to do it is via threads. I'd figure out how to fix whatever is causing you grief. The only other way to do it without writing your own loading functions would be to write your own file interface that was stacked on top of the normal one. If you override the reading function to look like: size_t my_read(ALLEGRO_FILE *f, void *ptr, size_t size) { if (timer_ticked) { do_logic(); do_gfx(); } // read data into buffer return read_bytes; } Then if you loaded a bitmap, it would periodically call your logic / graphics while in the middle. I don't know what horrible side effects this might cause. |
l j
Member #10,584
January 2009
|
I doubt having that many loading threads would actually increase performance anyway. Are you trying to remove loading screens while in-game perhaps?
|
AMCerasoli
Member #11,955
May 2010
|
Now that's premature optimization. Four threads? do you really need all those threads?, and do you know that you can't access to the memory at the same time using different threads right?, the main thread it also counts. Indeed the hard disk will be the bottleneck anyway. Addison Elliott said: I was thinking about how I can make sure that lag doesn't happen here. Place a loading screen, and start loading your resource, that at least your are loading the textures and meshes of "Heavy Rain" it shouldn't take much time anyway. Quote: How can I make sure that whenever the redrawTimer is set off that it will stop loading the bitmap Now that's premature optimization... I had to say it... Believe me, you don't want to do that. Load everything you can before using it. Quote: Since the FPS is 20 20 FPS?... Why such low refresh rate? are you developing a game for a really really old computer?. Quote: Is there anyway to do this? Yes, there is... But I think that is not the right question .
|
Matthew Leverton
Supreme Loser
January 1999
|
Don't try this at home: 1#include <allegro5/allegro.h>
2#include <allegro5/allegro_image.h>
3
4
5
6/* hack to expose the ->vtable part of the file.
7 not strictly necessary if you hard code the interface details */
8#define ALLEGRO_UNGETC_SIZE 16
9struct ALLEGRO_FILE
10{
11 const ALLEGRO_FILE_INTERFACE *vtable;
12 void *userdata;
13 unsigned char ungetc[ALLEGRO_UNGETC_SIZE];
14 int ungetc_len;
15};
16
17
18typedef struct INTERRUPTABLE_FILE_INTERFACE INTERRUPTABLE_FILE_INTERFACE;
19
20struct INTERRUPTABLE_FILE_INTERFACE
21{
22 ALLEGRO_FILE_INTERFACE fi;
23 size_t (*old_fread)(ALLEGRO_FILE *f, void *ptr, size_t size);
24 ALLEGRO_EVENT_QUEUE *queue;
25 void (*gfx)();
26 void (*logic)(ALLEGRO_EVENT *);
27};
28
29size_t interruptable_fread(ALLEGRO_FILE *f, void *ptr, size_t size)
30{
31 INTERRUPTABLE_FILE_INTERFACE *fi = (INTERRUPTABLE_FILE_INTERFACE *)f->vtable;
32 ALLEGRO_EVENT event;
33 bool draw = false;
34
35 while (al_get_next_event(fi->queue, &event))
36 {
37 fi->logic(&event);
38 draw = true;
39 }
40
41 if (draw)
42 fi->gfx();
43
44 al_rest(0.10); // sleep to slow things down for testing
45
46 return fi->old_fread(f, ptr, size);
47}
48
49INTERRUPTABLE_FILE_INTERFACE *create_interruptable_fi(const ALLEGRO_FILE_INTERFACE *fi_parent)
50{
51 INTERRUPTABLE_FILE_INTERFACE *fi_loader = al_malloc(sizeof(*fi_loader));
52
53 memcpy(fi_loader, fi_parent, sizeof(*fi_parent));
54 fi_loader->old_fread = fi_parent->fi_fread;
55 fi_loader->fi.fi_fread = interruptable_fread;
56
57 return fi_loader;
58}
59
60
61ALLEGRO_BITMAP *bmp = NULL;
62int c = 0;
63int loading_bmp = false;
64
65void logic(ALLEGRO_EVENT *e)
66{
67 if (e->type == ALLEGRO_EVENT_KEY_CHAR)
68 {
69 if (!bmp && !loading_bmp)
70 {
71 loading_bmp = true;
72 bmp = al_load_bitmap("test.png");
73 loading_bmp = false;
74 }
75 }
76 else if (e->type == ALLEGRO_EVENT_TIMER)
77 ++c;
78}
79
80void gfx()
81{
82 al_clear_to_color((c % 60) < 30 ? al_map_rgb(255,255,255) : al_map_rgb(0,0,0));
83 if (bmp)
84 al_draw_bitmap(bmp, 0, 0, 0);
85 al_flip_display();
86}
87
88int main(int argc, const char *argv[])
89{
90 INTERRUPTABLE_FILE_INTERFACE *fi_loader;
91 ALLEGRO_TIMER *timer;
92 ALLEGRO_EVENT_QUEUE *queue;
93 ALLEGRO_EVENT event;
94
95 al_init();
96 al_init_image_addon();
97 al_install_keyboard();
98
99 fi_loader = create_interruptable_fi(al_get_new_file_interface());
100 fi_loader->queue = queue = al_create_event_queue();
101 fi_loader->logic = logic;
102 fi_loader->gfx = gfx;
103
104 al_set_new_file_interface(&fi_loader->fi);
105
106 al_create_display(640, 480);
107
108 timer = al_create_timer(1 / 60.0);
109
110 al_register_event_source(queue, al_get_timer_event_source(timer));
111 al_register_event_source(queue, al_get_keyboard_event_source());
112 al_start_timer(timer);
113
114 while (true)
115 {
116 al_wait_for_event(queue, &event);
117 if (event.type == ALLEGRO_EVENT_KEY_CHAR && event.keyboard.unichar == 'q') break;
118
119 logic(&event);
120 gfx();
121 }
122
123 al_free(fi_loader);
124
125 return 0;
126}
A poorly implemented demo of loading a bitmap in the main thread without interrupting the flow of the game. Press any key to start loading "test.png". It should continue to flash black/white every second. Press 'q' to quit. |
|