Skip to content

Commit 675d8bc

Browse files
authored
Prevent compilation of redundant pipelines (#9681)
If we've already destroyed a program, we shouldn't run prewarm for it, as that could entail five pipeline compilations.
1 parent a90019b commit 675d8bc

File tree

3 files changed

+28
-2
lines changed

3 files changed

+28
-2
lines changed

filament/backend/src/vulkan/VulkanDriver.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -902,6 +902,7 @@ void VulkanDriver::destroyProgram(Handle<HwProgram> ph) {
902902
return;
903903
}
904904
auto vprogram = resource_ptr<VulkanProgram>::cast(&mResourceManager, ph);
905+
vprogram->cancelParallelCompilation();
905906
vprogram.dec();
906907
}
907908

filament/backend/src/vulkan/VulkanHandles.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -262,6 +262,14 @@ struct VulkanProgram : public HwProgram, fvkmemory::Resource {
262262
VulkanProgram(VkDevice device, Program const& builder) noexcept;
263263
~VulkanProgram();
264264

265+
/**
266+
* Cancels any parallel compilation jobs that have not yet run for this
267+
* program.
268+
*/
269+
inline void cancelParallelCompilation() {
270+
mParallelCompilationCanceled.store(true, std::memory_order_release);
271+
}
272+
265273
/**
266274
* Writes out any queued push constants using the provided VkPipelineLayout.
267275
*
@@ -284,6 +292,17 @@ struct VulkanProgram : public HwProgram, fvkmemory::Resource {
284292
return mInfo->pushConstantDescription.getVkRanges();
285293
}
286294

295+
/**
296+
* Returns true if parallel compilation is canceled, false if not. Parallel
297+
* compilation will be canceled if this program is destroyed before relevant
298+
* pipelines are created.
299+
*
300+
* @return true if parallel compilation should run for this program, false if not
301+
*/
302+
inline bool isParallelCompilationCanceled() const {
303+
return mParallelCompilationCanceled.load(std::memory_order_acquire);
304+
}
305+
287306
inline void writePushConstant(VkCommandBuffer cmdbuf, VkPipelineLayout layout,
288307
backend::ShaderStage stage, uint8_t index, backend::PushConstantVariant const& value) {
289308
// It's possible that we don't have the layout yet. When external samplers are used, bindPipeline()
@@ -320,6 +339,7 @@ struct VulkanProgram : public HwProgram, fvkmemory::Resource {
320339

321340
PipelineInfo* mInfo;
322341
VkDevice mDevice = VK_NULL_HANDLE;
342+
std::atomic<bool> mParallelCompilationCanceled { false };
323343
std::vector<PushConstantInfo> mQueuedPushConstants;
324344
};
325345

filament/backend/src/vulkan/VulkanPipelineCache.cpp

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -178,9 +178,14 @@ void VulkanPipelineCache::asyncPrewarmCache(
178178
CallbackManager::Handle cmh = mCallbackManager.get();
179179
auto token = std::make_shared<ProgramToken>();
180180
// Note: we keep a ref to vprogram in this lambda so that the shader modules don't get
181-
// destroyed before we call createPipeline(). This is rare enough that we are ok with
182-
// occasionally creating pipelines for destroyed materials.
181+
// destroyed before we call createPipeline(). We can catch this in some cases, to avoid
182+
// compiling too many unnecessary already-destroyed-materials.
183183
mCompilerThreadPool.queue(priority, token, [this, vprogram, key, dynamicOptions, cmh]() mutable {
184+
if (vprogram->isParallelCompilationCanceled()) {
185+
FVK_LOGD << "Skipping prewarm for a program that has been destroyed already.";
186+
return;
187+
}
188+
184189
VkPipeline pipeline = createPipeline(key, dynamicOptions);
185190
mCallbackManager.put(cmh);
186191
// We don't actually need this pipeline, we just wanted to force the driver to cache

0 commit comments

Comments
 (0)