Allegro.cc - Online Community

Allegro.cc Forums » Programming Questions » [AL5] Performance issue when drawing large image partially

This thread is locked; no one can reply to it. rss feed Print
[AL5] Performance issue when drawing large image partially
Rqlueless
Member #16,682
June 2017

Hello everyone,

I'm having trouble trying to draw a small region of a large bitmap. The image file I'm using as a map is 10000 by 10000 pixels large, and is about 200 mb big. It was obvious to me that trying to draw that 60 times per second will put a number on my CPU, which it did.

So, just to experiment, I've tried to use al_create_sub_bitmap to create a 500 by 500 big sub bitmap of the larger one, and to my surprise, drawing that instead of the parent-bitmap gave me no performance boost whatsoever.

I've also tried using al_draw_bitmap_region to draw a very small region of the 10000x10000 bitmap, which also didn't help.

To test, I've made a different 500 by 500 big image, which let itself be drawn with ease.

Is it just not a good idea to load an image this big?

Thanks in advance for any advice. :)

Eric Johnson
Member #14,841
January 2013
avatar

10000x10000? That's absolutely massive. I've heard it's best to stick with 1024x1024 or 2048x2048 as a max size for bitmaps/textures. I'm not sure what the average GPU can handle though.

Chris Katko
Member #1,881
January 2002
avatar

- What video card? (and videocard RAM)
- What CPU?
- What operating system?
- OpenGL or Direct3D?
- Why are you using a gigantic texture? What's the purpose of your application?

Megatextures (1M x 1M+) are entirely possible, through a virtual memory setup that swaps chunks of 1024x1024 or 2048x2048, etc into textures on-the-fly. (See ID Tech's Rage game, and the plethora of articles written on megatextures.)

There is a penalty for textures that aren't power-of-two on many older cards. Try 16384x16384. But modern drivers "should" automatically force it to upgrade the size to the nearest power-of-two.

Try with each power-of-two smaller texture and post the results for your card.

Ala try 16384^2, 8192^2, 4096^2, 2048^2, 1024^2, 512^2.

It's definitely interesting that it's not "faster" using a sub-bitmap. My only guess is (and I don't know if this is by design, a design mistake, or what) that either: a sub-bitmap draws the entire bitmap each time, but "clips" it. So you shouldn't use a sub-bitmap into a huge bitmap unless you NEED it--like a sliding window where you can use X =230, 231, 232, 233, .... 10000. That's opposed to a "tile" based setup where you only need every 512x512 chunk. You could easily split 512x512 textures into multiple smaller texture atlases of 2048x2048 or 4096x4096.

The other reason it could be slow is at the driver/hardware level, you can't load a "partial" texture and it HAS to load the entire thing before it can start splitting it up for a sub-bitmap.

--> Are you changing textures often? Or JUST using one? That is, is it "slower" if you draw both a 10K texture and a 128 texture in the same loop and "faster" if you only use the 10K texture? (Ala it has to swap the loaded texture by loading to 10K each time.)

I might run some tests on my own on this, because I'm sure I'm going to run into it at some point.

I'm not sure what the average GPU can handle though.

WAY LARGER than you think. I used to have a website that listed tons of them, but I've lost it. I'll look for it. Mobile is obviously much smaller. But still at least 2048 or 4096. (Especially when you realize their screen resolutions are larger than that on many new phones!)

[edit]

A GTX 1080 supports 131072x65536. I'm guessing they're pushing for higher and higher because CUDA / science benefits from the larger sizes and nVidia has been moving toward science for at least 8 years or so.

GTX 980 is 65536x65536.

It should be noted that when the texture is "layered" (an array?), the max size is lower. GTX 980, for example, is 16K x 16K x 2048 layers.

Depending on what Compute Level the CUDA core is, for example, 8Kx8Kx512 is the requirement for the oldest Compute 1.0 to 1.3. Compute 2.x is 16K x 2048. I would imagine the OpenGL capabilities would be equivalent for an nVidia card. For a AMD/Intel, you could still go by DirectX and OpenGL version. I don't recall the field name, but in OpenGL there is a spec for "minimum [maximum texture size]" mandated to support that OpenGL version. (Almost sure there is also a DirectX one too.)

While this is interesting stuff, it's a little off-topic. The OP's code shouldn't work at all on a card that doesn't support that resolution texture. (Unless you're worrying about selling your game to people with worse specification videocards.)

-----sig:
“Programs should be written for people to read, and only incidentally for machines to execute.” - Structure and Interpretation of Computer Programs
"Political Correctness is fascism disguised as manners" --George Carlin

Rqlueless
Member #16,682
June 2017

- What video card? (and videocard RAM)
- What CPU?
- What operating system?
- OpenGL or Direct3D?
- Why are you using a gigantic texture? What's the purpose of your application?

Hey Chris,

- GTX 960, 2GB
- AMD Phenom(tm) II X6 1100T Processor
- GNU/Linux
- OpenGL
- I wish to create a large scrolling map for an RPG game, where everything is drawn with a lot of detail as opposed to a tile-based map with repeating 'blocks' of bitmaps/textures.

I've created a 8192^2 big texture, and I'm facing the same issue.

I've then isolated the drawing of the texture with nothing else being drawn, and top is still showing me 90-100% CPU usage, with a huge delay in keyboard input handling.

I'm using the .pcx and .tga image formats, and I'm drawing the texture/s 60 times per second directly onto the display backbuffer.

Hope this gives you or anyone else a clue.

Thanks.

Chris Katko
Member #1,881
January 2002
avatar

One more thing:

- Turn on texture compression. Does that improve speed? That means you're memory bandwidth limited.

void al_set_new_bitmap_format(int format);

ALLEGRO_PIXEL_FORMAT_COMPRESSED_RGBA_DXT1 
ALLEGRO_PIXEL_FORMAT_COMPRESSED_RGBA_DXT3 
ALLEGRO_PIXEL_FORMAT_COMPRESSED_RGBA_DXT5

http://allegro5.org/docs/html/refman/graphics.html

Now, even if this is a problem (though I'm still interested in why it's happening...) you can work around it. Your assets can have any size whatsoever. You game should then chop those assets (ala 10000x10000) into textures. (512x512, etc). And then, you only draw the blocks you need for that screen "position" (I use "offset_x" and "offset_y"). It's not hard if you sit back and think about it.

{"name":"hMmzYHX.png","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/9\/d\/9d2e1fd56436e66ad9a2b33b6ebfebcc.png","w":526,"h":302,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/9\/d\/9d2e1fd56436e66ad9a2b33b6ebfebcc"}hMmzYHX.png

Also, PCX and TGA are very outdated formats. Is there any reason you're not using PNG?

-----sig:
“Programs should be written for people to read, and only incidentally for machines to execute.” - Structure and Interpretation of Computer Programs
"Political Correctness is fascism disguised as manners" --George Carlin

André Silva
Member #11,991
May 2010
avatar

I think that, in the past, I tried creating textures that big, and Allegro just failed to create them as video bitmaps, so just returned them as memory bitmaps. Which are much slower to render. So I honestly wouldn't be surprised that trying to draw a 10k by 10k bitmap would only result in massive slowdown!

Sub-bitmaps aren't anything special, really. The only difference between a "normal" bitmap and a sub-bitmap is that the sub has an X/Y and W/H that are different from the parent bitmap's. When you render a sub-bitmap, you're actually rendering the full bitmap, but simply saying that the vertex at the top-right will use the texture coordinates so and so, the vertex and the top-left will use so and so, etc. such that it's truncated.

I say all of this based on personal experience with tinkering with bitmaps. Please correct me if I just said something horribly wrong.

Edgar Reynaldo
Major Reynaldo
May 2007
avatar

SiegeLord
Member #7,827
October 2006
avatar

You can get the max size directly from Allegro: al_get_display_option(disp, ALLEGRO_MAX_BITMAP_SIZE).

"For in much wisdom is much grief: and he that increases knowledge increases sorrow."-Ecclesiastes 1:18
[SiegeLord's Abode][Codes]:[DAllegro5]:[RustAllegro]

Neil Roy
Member #2,229
April 2002
avatar

Sorry, but, creating a single image, that size is simply unreasonable. You won't find ANY 2D games, AAA titles etc... that do that, it's insane. You should divide up your world into larger chunks, you don't have to do tiny tiled. You can also make a HUGE variety of smaller tiles that give enough variation that it looks good. Work on blending your textures to hide seams etc. You can make larger tiles, say 256x256 or 512x512... load them in as you move around. But one huge, 10K texture?! Sorry, in my opinion, that's just plain crazy.

You can still have one huge image, just divide it up into smaller chunks. I would go with 512x512 myself, then load them in as they become visible.

---
“I love you too.” - last words of Wanda Roy

Go to: