From ebd5f150c16548b83bbb4a4fec9e4430c2fa1309 Mon Sep 17 00:00:00 2001 From: Mathias Agopian Date: Tue, 3 May 2022 14:20:00 -0700 Subject: [PATCH] fix a potential threading/memory corruption We can't call prepareProgram() from any thread, since it is calling into the backend. When we had more than a certain number of commands, we would use the jobsystem to generate them and so prepareProgram() could end up being called from a jobsystem thread. This is fixed by looping through all the commands once they're generated and calling prepareProgram() then. --- filament/src/RenderPass.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/filament/src/RenderPass.cpp b/filament/src/RenderPass.cpp index 4712610045..aef4046f33 100644 --- a/filament/src/RenderPass.cpp +++ b/filament/src/RenderPass.cpp @@ -138,6 +138,15 @@ void RenderPass::appendCommands(CommandTypeFlags const commandTypeFlags) noexcep // "eof" command. these commands are guaranteed to be sorted last in the // command buffer. curr[commandCount - 1].key = uint64_t(Pass::SENTINEL); + + // Go over all the commands and call prepareProgram(). + // This must be done from the main thread. + for (Command const* first = curr, *last = curr + commandCount ; first != last ; ++first) { + if (UTILS_LIKELY((first->key & CUSTOM_MASK) == uint64_t(CustomCommand::PASS))) { + auto ma = first->primitive.mi->getMaterial(); + ma->prepareProgram(first->primitive.materialVariant); + } + } } void RenderPass::appendCustomCommand(Pass pass, CustomCommand custom, uint32_t order, @@ -402,7 +411,6 @@ void RenderPass::generateCommandsImpl(uint32_t extraFlags, if constexpr (isColorPass) { cmdColor.primitive.primitiveHandle = primitive.getHwHandle(); RenderPass::setupColorCommand(cmdColor, variant, mi, inverseFrontFaces); - ma->prepareProgram(cmdColor.primitive.materialVariant); cmdColor.primitive.morphWeightBuffer = morphing.handle; cmdColor.primitive.morphTargetBuffer = morphTargets.buffer->getHwHandle(); @@ -487,7 +495,6 @@ void RenderPass::generateCommandsImpl(uint32_t extraFlags, } if constexpr (isDepthPass) { - ma->prepareProgram(cmdDepth.primitive.materialVariant); const RasterState rs = ma->getRasterState(); const TransparencyMode mode = mi->getTransparencyMode(); const BlendingMode blendingMode = ma->getBlendingMode();