Access to SceneManager in Hlms::fillBuffersFor Topic is solved

Discussion area about developing with Ogre-Next (2.1, 2.2 and beyond)


User avatar
bishopnator
Gnome
Posts: 361
Joined: Thu Apr 26, 2007 11:43 am
Location: Slovakia / Switzerland
x 16

Access to SceneManager in Hlms::fillBuffersFor

Post by bishopnator »

I am trying to render the fullscreen quad/triangle through my custom implementation of HLMS, but it seems that there is no access to the SceneManager.

  1. The CompositorManager2's constructor creates mSharedTriangleFS and mSharedQuadFS directly without scene manager (see CompositorPassQuad::mFsRect)
  2. Hlms::fillBuffersFor is called from RenderQueue::renderSingleObject - the RenderQueue has access to its SceneManager, but it is not passed to the call
  3. in the Hlms::fillBuffersFor, the queuedRenderable.movableObject->_getManager() returns nullptr because of the construction of the quad/triangle in CompositorManager2
  4. in the Hlms::fillBuffersFor, the Ogre::Root::getSingleton()._getCurrentSceneManager() returns nullptr as well

I need to access the compositor texture(s) via SceneManager::getCompositorTextures(). I see that in HlmsLowLevel where the same logic is needed, the SceneManager is rather cached in the member variable within the call HlmsLowLevel::preparePassHash, but I find it as bad practice. Why the SceneManager is not passed to the calls as the caller (RenderQueue) has always access to it? If the currently used approach is acceptable, why it is not already part of base class Hlms? Every custom implementation of Hlms which implemets the fillBuffersFor, needs the same logic.

Jsut a side note: I want to avoid legacy materials, because my implementation of Hlms automatically translates the shaders to GLSL so I don't need to write separate shaders for GLSL which I find as huge advantage. For the quad rendering I need multiple techniques with different logic so multiple different (relatively) simple shaders.

User avatar
dark_sylinc
OGRE Team Member
OGRE Team Member
Posts: 5560
Joined: Sat Jul 21, 2007 4:55 pm
Location: Buenos Aires, Argentina
x 1403

Re: Access to SceneManager in Hlms::fillBuffersFor

Post by dark_sylinc »

Generally, Hlms should not have access to the SceneManager. If we made a chart, their distance is a diagonal: SceneManager is higher level than Hlms, and Hlms handles shaders while SceneManager handles scene objects.

HlmsLowLevel makes an exception because it handles legacy rendering for legacy objects that have existed for 25 years. But if it makes you feel better, OgreNext guarantees that calls to fillBuffersFor() will have the same SceneManager between Hlms::preparePassHash() and Hlms::postCommandBufferExecution().

bishopnator wrote: Mon May 11, 2026 12:52 pm

I need to access the compositor texture(s) via SceneManager::getCompositorTextures(). I see that in HlmsLowLevel where the same logic is needed, the SceneManager is rather cached in the member variable within the call HlmsLowLevel::preparePassHash, but I find it as bad practice. Why the SceneManager is not passed to the calls as the caller (RenderQueue) has always access to it? If the currently used approach is acceptable, why it is not already part of base class Hlms? Every custom implementation of Hlms which implemets the fillBuffersFor, needs the same logic.

SceneManager is a huge class, getting close to being a god-class. Generally, Hlms::fillBuffersFor should do one job: fill buffers; and make sure the buffers are set by issuing commands (that's 2 jobs!). Giving it access to the SceneManager means a lot of calls can be made. You could theoretically even create more Items (which could crash everything). Making it a const SceneManager* could help, but there's still a lot of non-const data that could be accessed (like the Compositor textures as you say).

Hlms also stands at the gates between two very important questions: "Should I favor performance, or user friendliness?" Those two are often at odds in graphics rendering.

Thus the API tries to force you to think about being careful with accessing the SceneManager from Hlms (i.e. deal with it in preparePassHash).
If you are writing HlmsPbs (basically a module to render potentially millions of objects with physically based shading at decent framerates), then user friendliness is a secondary objective. Please note that if you've got 100k objects and two passes, then it's likely that HlmsPbs::fillBuffersFor will be called 200k times. Efficiency is key. Hence the API design here discourages many footguns.

But if you believe you have legitimate reasons, such as when making an Hlms for handling a low quantity of user-authored shaders / objects, then by all means cache the SceneManager and do something similar to what HlmsLowLevel is doing. Because in this particular case, flexibility beats performance. Nobody cares that your code is 3x slower than it should be if it only needs to handle 20 objects.

User avatar
bishopnator
Gnome
Posts: 361
Joined: Thu Apr 26, 2007 11:43 am
Location: Slovakia / Switzerland
x 16

Re: Access to SceneManager in Hlms::fillBuffersFor

Post by bishopnator »

Yes, this is a good point. I basically need only access to the compositor textures. The HlmsLowLevel accesses them as well, but also other information needed by AutoParamDataSource - but what is important, just reading from SceneManager.

For me it is not a problem to use same approach in my Hlms as in HlmsLowLevel. I tried to point out, that the fillBuffersFor is used only for direct rendering of the renderables (e.g. like full-screen quad) and there is high chance of duplicating code between different implementations of Hlms.