Page 1 of 1

Alloc Block error

Posted: Thu Jul 13, 2017 8:43 pm
by r00k
I'm getting an alloc block error related to loading lightmaps for a specific AD map, foggy mountain or whatever. But if I simply comment out the Host_Error "Alloc Block..." the map loads fine. Should I just make lightmap allocation dynamic or increase the number of lightmaps which is currently 128?

sorry for the brief message im at work didnt have time to actually post a detailed one...

Re: Alloc Block error

Posted: Thu Jul 13, 2017 11:30 pm
by ericw
With the error commented out, I think all the faces from that point onward will just have wrong lightmaps. Might only affect a corner of the map.

Dynamic or increases limit - not sure how much more work it is to make it dynamic, probably not too bad?
In quakespasm I was lazy and just raised the limits, MAX_LIGHTMAPS is 512, and the textures are 128x128.

btw, this is a useful optimization to apply, starts searching at the last block rather than testing all of the filled ones (the original code looks at n^2 lightmaps to fill n lightmaps).
https://github.com/ericwa/Quakespasm/commit/accee12

Re: Alloc Block error

Posted: Thu Jul 13, 2017 11:57 pm
by r00k
Thanks for your reply, I'll give it shot !

Re: Alloc Block error

Posted: Fri Jul 14, 2017 12:10 am
by Spike
if you care about performance, you can try and make guesses about the texture size needed, and potentially pack the entire map into a single 16384*16384 lightmap.
alternatively you may find non-square 16384-high by 128-wide lightmaps are faster to update subregions of.
you can pack 128 128*128 subregions into a single 128*16384 texture. doing so means you can optimise the glTexSubImage2D calls so you're not updating the entire thing, and keeping narrow textures means you don't have to faff around with strides when updating horizontal subregions, because there's only one region horizontally.

this of course assumes you're not updating the entire lightmap between drawing each region a per-surface basis.

anyway, once you've done that, you can render the entire world model without any texture switches due to lightmaps, which can be a speedup thanks to better batching.

note that a few maps were built with little subdivision, which requires that the engine support per-surface lightmaps of up to 256*256 (the -darkplaces option with hmap2 will do this).

Re: Alloc Block error

Posted: Mon Jul 17, 2017 9:16 am
by mh
192 lightmaps, at 128x128, is sufficient to load AD Sepulcher so you can probably just safely increase the max number without worrying about making it fully dynamic. Alternatively increase lightmap size to 256x256 which has the same effect as quadrupling the max.

Either way watch out for "the lightmap texture data needs to be kept in main memory so texsubimage can update properly" - that should go to hunk allocated memory (and increase your default heapsize).

If you increase lightmap size (either width or height) to 256 (or higher) watch out for the definition of the glRect_t struct, which - in a stunning feat of micro-optimization - uses unsigned chars for a 12 byte memory saving per lightmap texture.

An alternative to using a really large texture is to use an array texture but you need to port your surface drawing to shaders for that.

Re: Alloc Block error

Posted: Tue Jul 18, 2017 12:07 am
by r00k
Either way watch out for "the lightmap texture data needs to be kept in main memory so texsubimage can update properly" - that should go to hunk allocated memory (and increase your default heapsize).
Ah so put it on the hunk so it gets cleared after map loads? Ya I kicked up the MAX_LIGHTMAPS to 256 seemed to run fine, but I guess its an over kill.

Re: Alloc Block error

Posted: Tue Jul 18, 2017 1:49 am
by Spike
put it on the hunk so that its not unconditionally sitting in the bss(0-filled heap) wasting address space (and possibly lots of ram). Then you can have a nice big MAX_LIGHTMAPS without wasting any resources on it until its actually needed. All the advantages of a high limit, none of the disadvantages.

You can also reallocate your lightmaps table without reallocating the data (hurrah for being cheap), which avoids quite a bit of memcpy+fragmentation issues.
Personally I'm a fan of just removing limits entirely - eventually someone will make a map that exceeds your choice of limit...

Re: Alloc Block error

Posted: Wed Jul 19, 2017 2:19 am
by ericw
QS's current limit is equal to a 4096x2048 texture and can handle most maps (even e1-4.bsp) so you wouldn't even need to go as high as 16k x 16k. Some time I want to check out the performance difference of 1 lightmap texture over many. IIRC there is a tutorial on here about updating less than the full width of the texture for the glTexSubImage call as well.

Re: Alloc Block error

Posted: Wed Jul 19, 2017 4:37 am
by Spike

Code: Select all

glPixelStorei(GL_UNPACK_ROW_LENGTH, BLOCK_WIDTH);
glTexSubImage2D(GL_TEXTURE_2D, 0, xoffset, yoffset, subwidth, subheight, format, type, (byte*)data + PIXEL_SIZE*(xoffset + yoffset*BLOCK_WIDTH));
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
will update a subregion of your lightmap without you needing to re-pack the data.
the other option is to create a PBO, write your lightmap updates to that, then call glTexSubImage2D for each surface that was actually changed and thereby avoid copying all unchanged data... you're at the mercy of driver optimisations though. from remarks from id about Rage and AMD, I'm assuming that's what Rage does with its megatexturing updates. that said, its probably not worth it when we're talking about only 16 texels at a time.
vulkan allows you to roll up all of those subupdates into a single call, so drivers should be much easier to cope with there.