emscripten-core / emscripten

Emscripten: An LLVM-to-WebAssembly Compiler
Other
25.43k stars 3.25k forks source link

library_webgl.js wrong(?) assumption #21921

Open caiiiycuk opened 2 months ago

caiiiycuk commented 2 months ago

glGen* in library_webgl.js implemented with assumption that it called rarely:

https://github.com/emscripten-core/emscripten/blob/619f08d9498f417eae94deab129f3e97df8995eb/src/library_webgl.js#L303-L311

I'm not a 3D developer, so I really don't know, but I think this assumption is correct for most quality made games.

However recently we ported 3d game which have fully changable terrain. It generates a lot of buffers for each frame. The GL.textures/buffers/programs/etc arrays grows very fast. Usually after ~1 hour plaing game took 2GB memory and then crash because can't create more.

Maybe this is ridiculous behavior for modern 3D (e.g. it shouldn't generate new buffers in every frame), but at least it works natively just fine. Is it also a requirement of GL? Fortunately, we have control over the sources and we can implement buffer pooling. And we will.

BUT, I also checked random Unity game that we ported, and for Unity games situation is same, the pools is constantly growing (not so fast). Not sure how much this affects performance on mobile, but from my experience Unity games degrade performance while playing (maybe related, maybe not)

I looked at the sources, it seems that arrays can be easily converted to hashmaps with minimal changes. Is it worth doing, what are the drawbacks?

Examples:

1st. The PERIMETER game:

https://d13m0wt5um9hyu.cloudfront.net/repository/perimeter/v7/web/release/index.html

it grows very fast

2nd. City Police (typical unity game):

https://d146hdyl1gi3hn.cloudfront.net/repository/city-police-simulation/v2/web/release/index.html
sbc100 commented 2 months ago

I have a WIP PR convert GL to using the handle allocator: https://github.com/emscripten-core/emscripten/pull/18874. I think that would solve the problem here.

caiiiycuk commented 2 months ago

18874 looks like massive change and it's not clear why it is not landed yet. It need more testing or what the blocker?

Actually I have something like #18668 in mind. Hashmap have same semantic so they can replace each other, only need to introduce freeId and use it in place where we do table[id] = null;

The idea to add link time option which contianer to use. And use arrays as default container, if you provide -s GL_TABLES=MAP then map will be used. We can also introduce -s GL_TABLES=ALLOCATORS. Btw, I don't care much about perfomrance degradation regarding to switching from array to map, I think implementing caching layer will reduce performance more.