|
17 | 17 | #ifndef TNT_FILAMENT_BACKEND_VULKANPIPELINECACHE_H |
18 | 18 | #define TNT_FILAMENT_BACKEND_VULKANPIPELINECACHE_H |
19 | 19 |
|
| 20 | +#include "CallbackManager.h" |
| 21 | +#include "CompilerThreadPool.h" |
20 | 22 | #include "VulkanCommands.h" |
21 | 23 |
|
22 | 24 | #include <backend/DriverEnums.h> |
@@ -46,6 +48,12 @@ class VulkanPipelineCache { |
46 | 48 | VulkanPipelineCache(VulkanPipelineCache const&) = delete; |
47 | 49 | VulkanPipelineCache& operator=(VulkanPipelineCache const&) = delete; |
48 | 50 |
|
| 51 | + static inline bool isAsyncPrewarmingSupported(VulkanContext const& context) { |
| 52 | + return context.asyncPipelineCachePrewarmingEnabled() && |
| 53 | + context.isDynamicRenderingSupported() && |
| 54 | + context.isVertexInputDynamicStateSupported(); |
| 55 | + } |
| 56 | + |
49 | 57 | static constexpr uint32_t SHADER_MODULE_COUNT = 2; |
50 | 58 | static constexpr uint32_t VERTEX_ATTRIBUTE_COUNT = MAX_VERTEX_ATTRIBUTE_COUNT; |
51 | 59 |
|
@@ -86,14 +94,21 @@ class VulkanPipelineCache { |
86 | 94 |
|
87 | 95 | static_assert(sizeof(RasterState) == 16, "RasterState must not have implicit padding."); |
88 | 96 |
|
89 | | - VulkanPipelineCache(VkDevice device, VulkanContext const& context); |
| 97 | + VulkanPipelineCache(DriverBase& driver, VkDevice device, VulkanContext const& context); |
90 | 98 |
|
91 | | - void bindLayout(VkPipelineLayout layout) noexcept; |
| 99 | + // Loads a fake pipeline into memory on a separate thread, with the intent of |
| 100 | + // preloading the Vulkan cache with enough information to have a cache hit when |
| 101 | + // compiling the pipeline on the main thread at draw time. This is very dependent |
| 102 | + // on the implementation of the driver on the current device; it's expected to work |
| 103 | + // on devices with VK_EXT_vertex_input_dynamic_state and VK_KHR_dynamic_rendering. |
| 104 | + void asyncPreloadCache(fvkmemory::resource_ptr<VulkanProgram> program, |
| 105 | + VkPipelineLayout layout); |
92 | 106 |
|
93 | 107 | // Creates a new pipeline if necessary and binds it using vkCmdBindPipeline. |
94 | 108 | void bindPipeline(VulkanCommandBuffer* commands); |
95 | 109 |
|
96 | 110 | // Each of the following methods are fast and do not make Vulkan calls. |
| 111 | + void bindLayout(VkPipelineLayout layout) noexcept; |
97 | 112 | void bindProgram(fvkmemory::resource_ptr<VulkanProgram> program) noexcept; |
98 | 113 | void bindRasterState(RasterState const& rasterState) noexcept; |
99 | 114 | void bindRenderPass(VkRenderPass renderPass, int subpassIndex) noexcept; |
@@ -211,6 +226,14 @@ class VulkanPipelineCache { |
211 | 226 | // Current bindings for the pipeline and descriptor sets. |
212 | 227 | PipelineKey mBoundPipeline = {}; |
213 | 228 |
|
| 229 | + // Thread pool that allows us to "prewarm" the pipeline cache, reducing draw-time |
| 230 | + // pipeline compilation time. |
| 231 | + CompilerThreadPool mCompilerThreadPool; |
| 232 | + |
| 233 | + // Callback manager that allows us to notify the frontend when a set of pipelines have |
| 234 | + // been prewarmed, signifying that it is safe to compile pipelines at draw time. |
| 235 | + CallbackManager mCallbackManager; |
| 236 | + |
214 | 237 | [[maybe_unused]] VulkanContext const& mContext; |
215 | 238 | }; |
216 | 239 |
|
|
0 commit comments