Page 1 of 1

Performance problem about "createShaderCacheEntry"

Posted: Mon Jan 21, 2019 3:39 am
by yisky
Hi!

In Ogre 2.1 I use "HlmsPbs" to render models and I meet a performance problem that when ogre first time rendering an object, it will dynamically create shader through "createShaderCacheEntry", and I found that this function takes a little more time which low down the frame. Btw, I create mesh in background thread as this viewtopic.php?f=25&t=94764&p=543982#p543982 topic mentioned.

Re: Performance problem about "createShaderCacheEntry"

Posted: Mon Jan 21, 2019 4:33 am
by dark_sylinc
Hi!

You need to use the microcode cache so the shaders are saved to disk so the next time it is used, it won't cause a stutter. You can also use the HlmsDiskCache which complements it. See Starting my app takes forever! in the FAQ.

Recently this code was added to the samples to handle it. See GraphicsSystem::loadHlmsDiskCache and GraphicsSystem::saveHlmsDiskCache.

Cheers

Re: Performance problem about "createShaderCacheEntry"

Posted: Wed Jan 23, 2019 3:24 am
by yisky
Hi!
Thanks for your reply, I start to use the microcode cache and it works well. But there is still a problem confiuse me that how to handle lots of texture in Ogre 2.1. Currently, I use Image::load to load texutre in background thread and then pass the loaded image to HlmsTextureManager::createOrRetrieveTexture to create texture in main thread, but this still causes a stutter.

Re: Performance problem about "createShaderCacheEntry"

Posted: Wed Jan 23, 2019 3:52 am
by dark_sylinc
Creating a texture has multiple stages:

1. Loading from file (you're using Image for that in a worker thread)
2. Creating the internal GPU API handle/resource. This could cause a mini-stutter (that can add up). If the texture is a power of 2, it will be placed in a texture array. So if the texture array had already been created and has free available space, then this cost won't be paid.
3. Some preprocessing stuff. In certain cases Image::generateMipmaps or PixelUtil::convertForNormalMapping may end up getting called while inside HlmsTextureManager::createOrRetrieve. If you want to avoid stutter, make sure these are not getting called (i.e. mipmaps were already set, and format was already ideal for normal mapping).
4. Uploading from Image to the GPU RAM. This could take time (not much, but adds up).
5. Sometimes a shader needs to be recompiled. If it's cached, it's not a problem, but if it's new, it will add stutter. To minimize this issue if textures are loaded in the same order every time, it will maximize the cache efficiency (so that they always arrive in the same pool of texture arrays); if you can't do this, then it's just a matter of time until the cache has seen all variants.

There's little you can do for point 2, however you should monitor your texture batching efficiency.
You can do a lot for step 3.
There's not much you can do for step 4 (in Ogre 2.2 this also happens in a background thread, but in 2.1 it happens in the main thread)
As for step 5, that depends on your design.

If you're using D3D11, another issue that causes stutter is that texture uploads call 3D11RenderSystem::_clearStateAndFlushCommandBuffer because on NVIDIA drivers it is prone to OoM (Out of Memory situations), particularly 32-bit builds. But if you remove that call and it still works fine for you on NVIDIA cards, then you may see a boost in texture loading time.

Cheers
Matias

Re: Performance problem about "createShaderCacheEntry"

Posted: Wed Jan 23, 2019 4:11 am
by yisky
Thank you very much! I will try as you say!

Re: Performance problem about "createShaderCacheEntry"

Posted: Fri Jan 25, 2019 2:35 am
by yisky
dark_sylinc wrote: Wed Jan 23, 2019 3:52 am Creating a texture has multiple stages:

1. Loading from file (you're using Image for that in a worker thread)
2. Creating the internal GPU API handle/resource. This could cause a mini-stutter (that can add up). If the texture is a power of 2, it will be placed in a texture array. So if the texture array had already been created and has free available space, then this cost won't be paid.
3. Some preprocessing stuff. In certain cases Image::generateMipmaps or PixelUtil::convertForNormalMapping may end up getting called while inside HlmsTextureManager::createOrRetrieve. If you want to avoid stutter, make sure these are not getting called (i.e. mipmaps were already set, and format was already ideal for normal mapping).
4. Uploading from Image to the GPU RAM. This could take time (not much, but adds up).
5. Sometimes a shader needs to be recompiled. If it's cached, it's not a problem, but if it's new, it will add stutter. To minimize this issue if textures are loaded in the same order every time, it will maximize the cache efficiency (so that they always arrive in the same pool of texture arrays); if you can't do this, then it's just a matter of time until the cache has seen all variants.

There's little you can do for point 2, however you should monitor your texture batching efficiency.
You can do a lot for step 3.
There's not much you can do for step 4 (in Ogre 2.2 this also happens in a background thread, but in 2.1 it happens in the main thread)
As for step 5, that depends on your design.

If you're using D3D11, another issue that causes stutter is that texture uploads call 3D11RenderSystem::_clearStateAndFlushCommandBuffer because on NVIDIA drivers it is prone to OoM (Out of Memory situations), particularly 32-bit builds. But if you remove that call and it still works fine for you on NVIDIA cards, then you may see a boost in texture loading time.

Cheers
Matias
Sorry to trouble again! I had to call Image::generateMinmaps out the HlmsTextureManager::createOrRetrieve in a background thread and this improves the performance. But, I got an exception:
"OGRE EXCEPTION(3:RenderingAPIException): D3D11 device cannot Clear State
Error Description:ID3D11DeviceContext::Map: First parameter is corrupt or NULL. in D3D11RenderSystem::_setRenderTarget...."

And this exception does not happen every time.