Skip to content

Conversation

@show50726
Copy link
Contributor

@show50726 show50726 commented Nov 3, 2025

To focus on the integration logic added in this PR, please ignore BufferAllocator and UboManager and their related tests. They were introduced in the base PR (#9331).

Changes

  • Engine
    • The engine now owns the UboManager. It initializes it, calls its beginFrame/endFrame methods, and manages MaterialInstance slot retirement on destruction.
  • MaterialInstance
    • Constructors are updated to accept a useUboBatching flag.
    • commit() now writes data to the shared buffer via uboManager->updateSlot.
    • use() now binds the shared buffer using its dynamic offset.
  • Material
    • createInstance() methods are updated to pass the useUboBatching flag to the MaterialInstance.
  • PostProcessManager
    • All calls to mi->commit(driver) are updated to mi->commit(driver, mEngine.getUboManager()) to pass the manager.
  • Renderer
    • At endFrame(), it now notifies the UboManager to create a fence for GPU synchronization.
  • filamat
    • Updated to set the DYNAMIC_OFFSET flag for the material's uniform buffer, so that it could update the offset without recreating the descriptor set.

@show50726 show50726 added the internal Issue/PR does not affect clients label Nov 3, 2025
@show50726 show50726 changed the title [depends on #9331] Integrate UboManager into the engine [depends on #9331] buffer update opt: Integrate UboManager into the engine Nov 3, 2025
Comment on lines 456 to 457
std::optional<UboManager>& uboManager = engine.getUboManager();
assert_invariant(uboManager.has_value());
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no need to return the optional and check isUboBatchingEnabled(). I would keep the isUboBatchingEnabled() check and just write engine.getUboManager()->endFrame()

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.


FMaterialInstance::FMaterialInstance(FEngine& engine,
FMaterialInstance const* other, const char* name)
FMaterialInstance const* other, const char* name, bool useUboBatching)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why is it necessary to add the bool here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess sometimes there is case that we need to create a new MI from a defaultMaterial instance.

Since defaultMaterial instance needs to be committed right after it is created, I exclude it from using UBO batching, but for the MI that is created from the defaultMaterial I think they should have the ability to be using UBO batching.

I'm not sure if this case would really happen though, any thought?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO this is uncommon - to have many instances of the default material. I think it's ok to not offer that option for duplicate() and the duplicate constructor of FMaterialInstance.

But defer to @pixelflinger

Sidenote:
I think to add this, you'd also have to expose the option in the public MaterialInstance::duplicate()?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let me think more about this and get back to you.

# Conflicts:
#	filament/src/details/MaterialInstance.cpp
@show50726 show50726 changed the title [depends on #9331] buffer update opt: Integrate UboManager into the engine buffer update opt: Integrate UboManager into the engine Nov 5, 2025
Copy link
Collaborator

@pixelflinger pixelflinger left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just realized, did you handle FRenderer::renderStandaloneView? I don't think you did.

@show50726
Copy link
Contributor Author

show50726 commented Nov 8, 2025

I just realized, did you handle FRenderer::renderStandaloneView? I don't think you did.

I did (in the latest commit).
In renderStandaloneView, there is engine.prepare(), it already called UboManager::beginFrame() and UboManager::finishBeginFrame(). Now I added UboManager::endFrame() to renderStandaloneView(), so the gpuUseCount will be updated correctly. Everything is working same as the normal render() path.
(Note that the gpuUseCount of the slots will be decreased at the beginning of the next render call)

I also tested with a custom app which calls renderStandaloneView twice and verified it works correctly.

Note: I feel like it makes more sense to add an endFrame to FEngine to wrap the UboManager::endFrame logic so that we could just call engine.endFrame() in both render and renderStandaloneView paths. Updated.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

internal Issue/PR does not affect clients

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants