15
#include "pipelinecache.h"
23
static uint32_t murmur3_32(const uint32_t* data, int size)
27
for (int i = 0; i < size; i++)
32
k = (k << 15) | (k >> (32 - 15));
36
h = (h << 13) | (h >> (32 - 13));
37
h = (h * 5) + 0xe6546b64;
52
static uint32_t fnv1a_32(const uint8_t* data, int size)
54
uint32_t h = 0x811c9dc5;
56
for (int i = 0; i < size; i++)
58
h ^= (uint32_t)*data++;
65
class PipelineCachePrivate
69
struct pipeline_cache_digest
71
pipeline_cache_digest(const uint32_t* spv_data, size_t spv_data_size, const std::vector<vk_specialization_type>& specializations,
72
uint32_t local_size_x, uint32_t local_size_y, uint32_t local_size_z);
73
pipeline_cache_digest(int shader_type_index, const Option& opt, const std::vector<vk_specialization_type>& specializations,
74
uint32_t local_size_x, uint32_t local_size_y, uint32_t local_size_z);
76
bool operator==(const pipeline_cache_digest& rhs) const
78
return d0 == rhs.d0 && d1 == rhs.d1;
81
bool operator!=(const pipeline_cache_digest& rhs) const
83
return d0 != rhs.d0 || d1 != rhs.d1;
92
uint32_t spv_data_murmur3;
93
int shader_type_index;
95
unsigned char opt_local_size_bits[4];
105
uint32_t specializations_murmur3;
106
uint32_t specializations_fnv1a;
113
struct pipeline_cache_artifact
115
VkShaderModule shader_module;
116
VkDescriptorSetLayout descriptorset_layout;
117
VkPipelineLayout pipeline_layout;
119
VkDescriptorUpdateTemplateKHR descriptor_update_template;
120
ShaderInfo shader_info;
123
mutable std::vector<pipeline_cache_digest> cache_digests;
124
mutable std::vector<pipeline_cache_artifact> cache_artifacts;
125
mutable Mutex cache_lock;
128
PipelineCachePrivate::pipeline_cache_digest::pipeline_cache_digest(const uint32_t* spv_data, size_t spv_data_size, const std::vector<vk_specialization_type>& specializations,
129
uint32_t local_size_x, uint32_t local_size_y, uint32_t local_size_z)
131
spv_data_murmur3 = murmur3_32(spv_data, spv_data_size / 4);
134
opt_local_size_bits[0] = 0;
137
opt_local_size_bits[1] = local_size_x;
138
opt_local_size_bits[2] = local_size_y;
139
opt_local_size_bits[3] = local_size_z;
142
const int specialization_count = specializations.size();
143
specializations_murmur3 = murmur3_32((const uint32_t*)specializations.data(), specialization_count);
144
specializations_fnv1a = fnv1a_32((const uint8_t*)specializations.data(), specialization_count * sizeof(vk_specialization_type));
147
PipelineCachePrivate::pipeline_cache_digest::pipeline_cache_digest(int _shader_type_index, const Option& opt, const std::vector<vk_specialization_type>& specializations,
148
uint32_t local_size_x, uint32_t local_size_y, uint32_t local_size_z)
150
shader_type_index = _shader_type_index;
153
opt_local_size_bits[0] = opt.use_image_storage << 7
154
| opt.use_fp16_packed << 6
155
| opt.use_fp16_storage << 5
156
| opt.use_fp16_arithmetic << 4
157
| opt.use_int8_storage << 3
158
| opt.use_int8_arithmetic << 2;
161
opt_local_size_bits[1] = local_size_x;
162
opt_local_size_bits[2] = local_size_y;
163
opt_local_size_bits[3] = local_size_z;
166
const int specialization_count = specializations.size();
167
specializations_murmur3 = murmur3_32((const uint32_t*)specializations.data(), specialization_count);
168
specializations_fnv1a = fnv1a_32((const uint8_t*)specializations.data(), specialization_count * sizeof(vk_specialization_type));
171
PipelineCache::PipelineCache(const VulkanDevice* _vkdev)
172
: vkdev(_vkdev), d(new PipelineCachePrivate)
176
PipelineCache::~PipelineCache()
183
PipelineCache::PipelineCache(const PipelineCache&)
188
PipelineCache& PipelineCache::operator=(const PipelineCache&)
193
void PipelineCache::clear()
195
MutexLockGuard lock(d->cache_lock);
197
for (size_t i = 0; i < d->cache_artifacts.size(); i++)
199
const PipelineCachePrivate::pipeline_cache_artifact& cc = d->cache_artifacts[i];
201
if (vkdev->info.support_VK_KHR_descriptor_update_template())
203
if (cc.descriptor_update_template)
205
vkdev->vkDestroyDescriptorUpdateTemplateKHR(vkdev->vkdevice(), cc.descriptor_update_template, 0);
211
vkDestroyPipeline(vkdev->vkdevice(), cc.pipeline, 0);
214
if (cc.pipeline_layout)
216
vkDestroyPipelineLayout(vkdev->vkdevice(), cc.pipeline_layout, 0);
219
if (cc.descriptorset_layout)
221
vkDestroyDescriptorSetLayout(vkdev->vkdevice(), cc.descriptorset_layout, 0);
224
if (cc.shader_module)
226
vkDestroyShaderModule(vkdev->vkdevice(), cc.shader_module, 0);
230
d->cache_digests.clear();
231
d->cache_artifacts.clear();
234
int PipelineCache::get_pipeline(const uint32_t* spv_data, size_t spv_data_size, const std::vector<vk_specialization_type>& specializations,
235
uint32_t local_size_x, uint32_t local_size_y, uint32_t local_size_z,
236
VkShaderModule* _shader_module,
237
VkDescriptorSetLayout* descriptorset_layout,
238
VkPipelineLayout* pipeline_layout,
239
VkPipeline* pipeline,
240
VkDescriptorUpdateTemplateKHR* descriptor_update_template,
241
ShaderInfo& shader_info) const
243
MutexLockGuard lock(d->cache_lock);
245
PipelineCachePrivate::pipeline_cache_digest key(spv_data, spv_data_size, specializations, local_size_x, local_size_y, local_size_z);
247
if (!vkdev->info.bug_corrupted_online_pipeline_cache())
250
for (size_t i = 0; i < d->cache_digests.size(); i++)
252
if (d->cache_digests[i] != key)
256
const PipelineCachePrivate::pipeline_cache_artifact& cc = d->cache_artifacts[i];
258
*_shader_module = cc.shader_module;
259
*descriptorset_layout = cc.descriptorset_layout;
260
*pipeline_layout = cc.pipeline_layout;
261
*pipeline = cc.pipeline;
262
*descriptor_update_template = cc.descriptor_update_template;
263
shader_info = cc.shader_info;
273
ret = resolve_shader_info(spv_data, spv_data_size, shader_info);
276
NCNN_LOGE("resolve_shader_info failed %d", ret);
280
VkShaderModule shader_module = vkdev->compile_shader_module(spv_data, spv_data_size, local_size_x, local_size_y, local_size_z);
283
NCNN_LOGE("create_shader_module failed");
287
ret = new_pipeline(shader_module, shader_info, specializations, descriptorset_layout, pipeline_layout, pipeline, descriptor_update_template);
290
NCNN_LOGE("new_pipeline failed");
291
vkDestroyShaderModule(vkdev->vkdevice(), shader_module, 0);
295
*_shader_module = shader_module;
299
PipelineCachePrivate::pipeline_cache_artifact cc;
301
cc.shader_module = *_shader_module;
302
cc.descriptorset_layout = *descriptorset_layout;
303
cc.pipeline_layout = *pipeline_layout;
304
cc.pipeline = *pipeline;
305
cc.descriptor_update_template = *descriptor_update_template;
306
cc.shader_info = shader_info;
308
d->cache_digests.push_back(key);
309
d->cache_artifacts.push_back(cc);
317
int PipelineCache::get_pipeline(int shader_type_index, const Option& opt, const std::vector<vk_specialization_type>& specializations,
318
uint32_t local_size_x, uint32_t local_size_y, uint32_t local_size_z,
319
VkShaderModule* _shader_module,
320
VkDescriptorSetLayout* descriptorset_layout,
321
VkPipelineLayout* pipeline_layout,
322
VkPipeline* pipeline,
323
VkDescriptorUpdateTemplateKHR* descriptor_update_template,
324
ShaderInfo& shader_info) const
326
MutexLockGuard lock(d->cache_lock);
328
PipelineCachePrivate::pipeline_cache_digest key(shader_type_index, opt, specializations, local_size_x, local_size_y, local_size_z);
330
if (!vkdev->info.bug_corrupted_online_pipeline_cache())
333
for (size_t i = 0; i < d->cache_digests.size(); i++)
335
if (d->cache_digests[i] != key)
339
const PipelineCachePrivate::pipeline_cache_artifact& cc = d->cache_artifacts[i];
341
*_shader_module = cc.shader_module;
342
*descriptorset_layout = cc.descriptorset_layout;
343
*pipeline_layout = cc.pipeline_layout;
344
*pipeline = cc.pipeline;
345
*descriptor_update_template = cc.descriptor_update_template;
346
shader_info = cc.shader_info;
357
VkShaderModule shader_module = 0;
358
ret = create_shader_module(shader_type_index, opt, local_size_x, local_size_y, local_size_z, &shader_module, shader_info);
361
NCNN_LOGE("create_shader_module failed");
365
ret = new_pipeline(shader_module, shader_info, specializations, descriptorset_layout, pipeline_layout, pipeline, descriptor_update_template);
368
NCNN_LOGE("new_pipeline failed");
369
vkDestroyShaderModule(vkdev->vkdevice(), shader_module, 0);
373
*_shader_module = shader_module;
377
PipelineCachePrivate::pipeline_cache_artifact cc;
379
cc.shader_module = *_shader_module;
380
cc.descriptorset_layout = *descriptorset_layout;
381
cc.pipeline_layout = *pipeline_layout;
382
cc.pipeline = *pipeline;
383
cc.descriptor_update_template = *descriptor_update_template;
384
cc.shader_info = shader_info;
386
d->cache_digests.push_back(key);
387
d->cache_artifacts.push_back(cc);
395
int PipelineCache::create_shader_module(int shader_type_index, const Option& opt, uint32_t local_size_x, uint32_t local_size_y, uint32_t local_size_z,
396
VkShaderModule* _shader_module, ShaderInfo& si) const
398
std::vector<uint32_t> spirv;
399
int retc = compile_spirv_module(shader_type_index, opt, spirv);
402
NCNN_LOGE("compile_spirv_module failed %d", retc);
406
const uint32_t* spv_data = spirv.data();
407
size_t spv_data_size = spirv.size() * 4;
409
int ret = resolve_shader_info(spv_data, spv_data_size, si);
412
NCNN_LOGE("resolve_shader_info failed %d", ret);
416
VkShaderModule shader_module = vkdev->compile_shader_module(spv_data, spv_data_size, local_size_x, local_size_y, local_size_z);
420
NCNN_LOGE("create_shader_module failed");
424
*_shader_module = shader_module;
429
int PipelineCache::new_pipeline(VkShaderModule shader_module, const ShaderInfo& shader_info, const std::vector<vk_specialization_type>& specializations,
430
VkDescriptorSetLayout* _descriptorset_layout,
431
VkPipelineLayout* _pipeline_layout,
432
VkPipeline* _pipeline,
433
VkDescriptorUpdateTemplateKHR* _descriptor_update_template) const
437
VkDescriptorSetLayout descriptorset_layout = 0;
438
VkPipelineLayout pipeline_layout = 0;
439
VkPipeline pipeline = 0;
440
VkDescriptorUpdateTemplateKHR descriptor_update_template = 0;
443
if ((int)specializations.size() != shader_info.specialization_count)
445
NCNN_LOGE("pipeline specialization count mismatch, expect %d but got %d", shader_info.specialization_count, (int)specializations.size());
446
goto ERROR_PipelineCache;
449
ret = vkdev->create_descriptorset_layout(shader_info.binding_count, shader_info.binding_types, &descriptorset_layout);
451
goto ERROR_PipelineCache;
453
ret = vkdev->create_pipeline_layout(shader_info.push_constant_count, descriptorset_layout, &pipeline_layout);
455
goto ERROR_PipelineCache;
457
ret = vkdev->create_pipeline(shader_module, pipeline_layout, specializations, &pipeline);
459
goto ERROR_PipelineCache;
461
if (vkdev->info.support_VK_KHR_descriptor_update_template())
463
ret = vkdev->create_descriptor_update_template(shader_info.binding_count, shader_info.binding_types, descriptorset_layout, pipeline_layout, &descriptor_update_template);
465
goto ERROR_PipelineCache;
468
*_descriptorset_layout = descriptorset_layout;
469
*_pipeline_layout = pipeline_layout;
470
*_pipeline = pipeline;
471
*_descriptor_update_template = descriptor_update_template;
477
if (vkdev->info.support_VK_KHR_descriptor_update_template())
479
if (descriptor_update_template)
481
vkdev->vkDestroyDescriptorUpdateTemplateKHR(vkdev->vkdevice(), descriptor_update_template, 0);
487
vkDestroyPipeline(vkdev->vkdevice(), pipeline, 0);
492
vkDestroyPipelineLayout(vkdev->vkdevice(), pipeline_layout, 0);
495
if (descriptorset_layout)
497
vkDestroyDescriptorSetLayout(vkdev->vkdevice(), descriptorset_layout, 0);