Download src/pipeline.cpp from camenduru/ncnn: direct link, hf CLI and curl.
- Browser
- Download file 14.8 kB
-
https://huggingface.co/camenduru/ncnn/resolve/main/src/pipeline.cpp
- Command line
-
hf download hf://camenduru/ncnn/src/pipeline.cpp
-
curl -L -o pipeline.cpp https://huggingface.co/camenduru/ncnn/resolve/main/src/pipeline.cpp
14.8 kB
| // Tencent is pleased to support the open source community by making ncnn available. | |
| // | |
| // Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. | |
| // | |
| // Licensed under the BSD 3-Clause License (the "License"); you may not use this file except | |
| // in compliance with the License. You may obtain a copy of the License at | |
| // | |
| // https://opensource.org/licenses/BSD-3-Clause | |
| // | |
| // Unless required by applicable law or agreed to in writing, software distributed | |
| // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR | |
| // CONDITIONS OF ANY KIND, either express or implied. See the License for the | |
| // specific language governing permissions and limitations under the License. | |
| namespace ncnn { | |
| class PipelinePrivate | |
| { | |
| public: | |
| VkShaderModule shader_module; | |
| VkDescriptorSetLayout descriptorset_layout; | |
| VkPipelineLayout pipeline_layout; | |
| VkPipeline pipeline; | |
| VkDescriptorUpdateTemplateKHR descriptor_update_template; | |
| ShaderInfo shader_info; | |
| uint32_t local_size_x; | |
| uint32_t local_size_y; | |
| uint32_t local_size_z; | |
| }; | |
| Pipeline::Pipeline(const VulkanDevice* _vkdev) | |
| : vkdev(_vkdev), d(new PipelinePrivate) | |
| { | |
| d->shader_module = 0; | |
| d->descriptorset_layout = 0; | |
| d->pipeline_layout = 0; | |
| d->pipeline = 0; | |
| d->descriptor_update_template = 0; | |
| d->local_size_x = 1; | |
| d->local_size_y = 1; | |
| d->local_size_z = 1; | |
| } | |
| Pipeline::~Pipeline() | |
| { | |
| delete d; | |
| } | |
| Pipeline::Pipeline(const Pipeline&) | |
| : d(0) | |
| { | |
| } | |
| Pipeline& Pipeline::operator=(const Pipeline&) | |
| { | |
| return *this; | |
| } | |
| void Pipeline::set_optimal_local_size_xyz(int w, int h, int c) | |
| { | |
| set_optimal_local_size_xyz(Mat(w, h, c, (void*)0)); | |
| } | |
| void Pipeline::set_optimal_local_size_xyz(const Mat& local_size_xyz) | |
| { | |
| int w = local_size_xyz.w; | |
| int h = local_size_xyz.h; | |
| int c = local_size_xyz.c; | |
| if (w == 0 && h == 0 && c == 0) | |
| { | |
| // fallback to the common and safe 4x4x4 | |
| w = 4; | |
| h = 4; | |
| c = 4; | |
| } | |
| w = std::min(w, (int)vkdev->info.max_workgroup_size_x()); | |
| h = std::min(h, (int)vkdev->info.max_workgroup_size_y()); | |
| c = std::min(c, (int)vkdev->info.max_workgroup_size_z()); | |
| if (w * h * c <= (int)vkdev->info.max_workgroup_invocations()) | |
| { | |
| return set_local_size_xyz(w, h, c); | |
| } | |
| int max_local_size_xy = (int)vkdev->info.max_workgroup_invocations() / c; | |
| int wh_max = std::max(1, (int)sqrt(max_local_size_xy)); | |
| while (w * h >= wh_max) | |
| { | |
| w = std::max(1, w / 2); | |
| h = std::max(1, h / 2); | |
| } | |
| set_local_size_xyz(w, h, c); | |
| } | |
| void Pipeline::set_local_size_xyz(int w, int h, int c) | |
| { | |
| d->local_size_x = w; | |
| d->local_size_y = h; | |
| d->local_size_z = c; | |
| // NCNN_LOGE("local size = %d %d %d", local_size_x, local_size_y, local_size_z); | |
| } | |
| int Pipeline::create(const uint32_t* spv_data, size_t spv_data_size, const std::vector<vk_specialization_type>& specializations) | |
| { | |
| const PipelineCache* pipeline_cache = vkdev->get_pipeline_cache(); | |
| // get from pipeline cache | |
| return pipeline_cache->get_pipeline(spv_data, spv_data_size, specializations, d->local_size_x, d->local_size_y, d->local_size_z, | |
| &d->shader_module, &d->descriptorset_layout, &d->pipeline_layout, &d->pipeline, &d->descriptor_update_template, | |
| d->shader_info); | |
| } | |
| int Pipeline::create(int shader_type_index, const Option& opt, const std::vector<vk_specialization_type>& specializations) | |
| { | |
| const PipelineCache* pipeline_cache = opt.pipeline_cache ? opt.pipeline_cache : vkdev->get_pipeline_cache(); | |
| // get from pipeline cache | |
| return pipeline_cache->get_pipeline(shader_type_index, opt, specializations, d->local_size_x, d->local_size_y, d->local_size_z, | |
| &d->shader_module, &d->descriptorset_layout, &d->pipeline_layout, &d->pipeline, &d->descriptor_update_template, | |
| d->shader_info); | |
| } | |
| VkShaderModule Pipeline::shader_module() const | |
| { | |
| return d->shader_module; | |
| } | |
| VkDescriptorSetLayout Pipeline::descriptorset_layout() const | |
| { | |
| return d->descriptorset_layout; | |
| } | |
| VkPipelineLayout Pipeline::pipeline_layout() const | |
| { | |
| return d->pipeline_layout; | |
| } | |
| VkPipeline Pipeline::pipeline() const | |
| { | |
| return d->pipeline; | |
| } | |
| VkDescriptorUpdateTemplateKHR Pipeline::descriptor_update_template() const | |
| { | |
| return d->descriptor_update_template; | |
| } | |
| const ShaderInfo& Pipeline::shader_info() const | |
| { | |
| return d->shader_info; | |
| } | |
| uint32_t Pipeline::local_size_x() const | |
| { | |
| return d->local_size_x; | |
| } | |
| uint32_t Pipeline::local_size_y() const | |
| { | |
| return d->local_size_y; | |
| } | |
| uint32_t Pipeline::local_size_z() const | |
| { | |
| return d->local_size_z; | |
| } | |
| void Pipeline::set_shader_module(VkShaderModule shader_module) | |
| { | |
| d->shader_module = shader_module; | |
| } | |
| void Pipeline::set_descriptorset_layout(VkDescriptorSetLayout descriptorset_layout) | |
| { | |
| d->descriptorset_layout = descriptorset_layout; | |
| } | |
| void Pipeline::set_pipeline_layout(VkPipelineLayout pipeline_layout) | |
| { | |
| d->pipeline_layout = pipeline_layout; | |
| } | |
| void Pipeline::set_pipeline(VkPipeline pipeline) | |
| { | |
| d->pipeline = pipeline; | |
| } | |
| void Pipeline::set_descriptor_update_template(VkDescriptorUpdateTemplateKHR descriptor_update_template) | |
| { | |
| d->descriptor_update_template = descriptor_update_template; | |
| } | |
| void Pipeline::set_shader_info(const ShaderInfo& shader_info) | |
| { | |
| d->shader_info = shader_info; | |
| } | |
| ImportAndroidHardwareBufferPipeline::ImportAndroidHardwareBufferPipeline(const VulkanDevice* _vkdev) | |
| : Pipeline(_vkdev) | |
| { | |
| sampler = 0; | |
| } | |
| ImportAndroidHardwareBufferPipeline::~ImportAndroidHardwareBufferPipeline() | |
| { | |
| destroy(); | |
| } | |
| int ImportAndroidHardwareBufferPipeline::create(VkAndroidHardwareBufferImageAllocator* ahb_im_allocator, int _type_to, int _rotate_from, const Option& opt) | |
| { | |
| int target_width; | |
| int target_height; | |
| if (rotate_from < 5) // 1 2 3 4 | |
| { | |
| target_width = ahb_im_allocator->width(); | |
| target_height = ahb_im_allocator->height(); | |
| } | |
| else // 5 6 7 8 | |
| { | |
| target_width = ahb_im_allocator->height(); | |
| target_height = ahb_im_allocator->width(); | |
| } | |
| return create(ahb_im_allocator, _type_to, _rotate_from, target_width, target_height, opt); | |
| } | |
| int ImportAndroidHardwareBufferPipeline::create(VkAndroidHardwareBufferImageAllocator* ahb_im_allocator, int _type_to, int _rotate_from, int target_width, int target_height, const Option& opt) | |
| { | |
| int w = ahb_im_allocator->width(); | |
| int h = ahb_im_allocator->height(); | |
| type_to = _type_to; | |
| rotate_from = _rotate_from; | |
| need_resize = false; | |
| if (rotate_from < 5) // 1 2 3 4 | |
| { | |
| if (target_width != w || target_height != h) | |
| need_resize = true; | |
| } | |
| else // 5 6 7 8 | |
| { | |
| if (target_width != h || target_height != w) | |
| need_resize = true; | |
| } | |
| // if (type_to == 1 || type_to == 2) | |
| // { | |
| // outc = 3; | |
| // out_elemsize = vkdev->info.support_fp16_storage() && opt.use_fp16_storage ? 2u : 4u; | |
| // out_elempack = 1; | |
| // } | |
| // else if (type_to == 3) | |
| // { | |
| // outc = 1; | |
| // out_elemsize = vkdev->info.support_fp16_storage() && opt.use_fp16_storage ? 2u : 4u; | |
| // out_elempack = 1; | |
| // } | |
| // else // if (type_to == 4 || type_to == 5) | |
| // { | |
| // outc = 1; | |
| // out_elemsize = ((vkdev->info.support_fp16_packed() && opt.use_fp16_packed) || (vkdev->info.support_fp16_storage() && opt.use_fp16_storage)) ? 8u : 16u; | |
| // out_elempack = 4; | |
| // } | |
| set_local_size_xyz(8, 8, 1); | |
| std::vector<vk_specialization_type> specializations(7); | |
| specializations[0].i = ahb_im_allocator->width(); | |
| specializations[1].i = ahb_im_allocator->height(); | |
| specializations[2].i = target_width; | |
| specializations[3].i = target_height; | |
| specializations[4].i = type_to; | |
| specializations[5].i = rotate_from; | |
| specializations[6].i = need_resize; | |
| create_shader_module(opt); | |
| const ShaderInfo& _shader_info = shader_info(); | |
| if ((int)specializations.size() != _shader_info.specialization_count) | |
| { | |
| NCNN_LOGE("pipeline convert_ycbcr specialization count mismatch, expect %d but got %d", _shader_info.specialization_count, (int)specializations.size()); | |
| return -1; | |
| } | |
| create_sampler(ahb_im_allocator); | |
| create_descriptorset_layout(); | |
| VkPipelineLayout pipeline_layout = 0; | |
| VkPipeline pipeline = 0; | |
| VkDescriptorUpdateTemplateKHR descriptor_update_template = 0; | |
| vkdev->create_pipeline_layout(_shader_info.push_constant_count, descriptorset_layout(), &pipeline_layout); | |
| vkdev->create_pipeline(shader_module(), pipeline_layout, specializations, &pipeline); | |
| if (vkdev->info.support_VK_KHR_descriptor_update_template()) | |
| { | |
| vkdev->create_descriptor_update_template(_shader_info.binding_count, _shader_info.binding_types, descriptorset_layout(), pipeline_layout, &descriptor_update_template); | |
| } | |
| set_pipeline_layout(pipeline_layout); | |
| set_pipeline(pipeline); | |
| set_descriptor_update_template(descriptor_update_template); | |
| return 0; | |
| } | |
| void ImportAndroidHardwareBufferPipeline::destroy() | |
| { | |
| if (sampler) | |
| { | |
| vkDestroySampler(vkdev->vkdevice(), sampler, 0); | |
| sampler = 0; | |
| } | |
| } | |
| int ImportAndroidHardwareBufferPipeline::create_shader_module(const Option& opt) | |
| { | |
| int shader_type_index = LayerShaderType::convert_ycbcr; | |
| std::vector<uint32_t> spirv; | |
| int retc = compile_spirv_module(shader_type_index, opt, spirv); | |
| if (retc != 0) | |
| { | |
| NCNN_LOGE("compile_spirv_module failed %d", retc); | |
| return -1; | |
| } | |
| const uint32_t* spv_data = spirv.data(); | |
| size_t spv_data_size = spirv.size() * 4; | |
| ShaderInfo shader_info; | |
| int ret = resolve_shader_info(spv_data, spv_data_size, shader_info); | |
| if (ret != 0) | |
| { | |
| NCNN_LOGE("resolve_shader_info failed %d", ret); | |
| return -1; | |
| } | |
| set_shader_info(shader_info); | |
| VkShaderModule shader_module = vkdev->compile_shader_module(spv_data, spv_data_size, local_size_x(), local_size_y(), local_size_z()); | |
| set_shader_module(shader_module); | |
| return 0; | |
| } | |
| int ImportAndroidHardwareBufferPipeline::create_sampler(VkAndroidHardwareBufferImageAllocator* ahb_im_allocator) | |
| { | |
| VkResult ret; | |
| VkExternalFormatANDROID externalFormatANDROID; | |
| externalFormatANDROID.sType = VK_STRUCTURE_TYPE_EXTERNAL_FORMAT_ANDROID; | |
| externalFormatANDROID.pNext = 0; | |
| externalFormatANDROID.externalFormat = ahb_im_allocator->external_format(); | |
| VkSamplerYcbcrConversionInfoKHR samplerYcbcrConversionInfo; | |
| samplerYcbcrConversionInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_INFO_KHR; | |
| samplerYcbcrConversionInfo.pNext = &externalFormatANDROID; | |
| samplerYcbcrConversionInfo.conversion = ahb_im_allocator->samplerYcbcrConversion; | |
| VkSamplerCreateInfo samplerCreateInfo; | |
| samplerCreateInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO; | |
| samplerCreateInfo.pNext = &samplerYcbcrConversionInfo; | |
| samplerCreateInfo.magFilter = need_resize ? VK_FILTER_LINEAR : VK_FILTER_NEAREST; | |
| samplerCreateInfo.minFilter = need_resize ? VK_FILTER_LINEAR : VK_FILTER_NEAREST; | |
| samplerCreateInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_NEAREST; | |
| samplerCreateInfo.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; | |
| samplerCreateInfo.addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; | |
| samplerCreateInfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; | |
| samplerCreateInfo.mipLodBias = 0.0f; | |
| samplerCreateInfo.anisotropyEnable = VK_FALSE; | |
| samplerCreateInfo.maxAnisotropy = 1; | |
| samplerCreateInfo.compareEnable = VK_FALSE; | |
| samplerCreateInfo.compareOp = VK_COMPARE_OP_NEVER; | |
| samplerCreateInfo.minLod = 0.0f; | |
| samplerCreateInfo.maxLod = 0.0f; | |
| samplerCreateInfo.borderColor = VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK; //VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE; FIXME | |
| samplerCreateInfo.unnormalizedCoordinates = VK_TRUE; //VK_FALSE; FIXME ? | |
| ret = vkCreateSampler(vkdev->vkdevice(), &samplerCreateInfo, 0, &sampler); | |
| if (ret != VK_SUCCESS) | |
| { | |
| NCNN_LOGE("vkCreateSampler failed %d", ret); | |
| return -1; | |
| } | |
| return 0; | |
| } | |
| int ImportAndroidHardwareBufferPipeline::create_descriptorset_layout() | |
| { | |
| VkDescriptorSetLayoutBinding descriptorSetLayoutBindings[3]; | |
| descriptorSetLayoutBindings[0].binding = 0; | |
| descriptorSetLayoutBindings[0].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; | |
| descriptorSetLayoutBindings[0].descriptorCount = 1; | |
| descriptorSetLayoutBindings[0].stageFlags = VK_SHADER_STAGE_COMPUTE_BIT; | |
| descriptorSetLayoutBindings[0].pImmutableSamplers = &sampler; | |
| descriptorSetLayoutBindings[1].binding = 1; | |
| descriptorSetLayoutBindings[1].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; | |
| descriptorSetLayoutBindings[1].descriptorCount = 1; | |
| descriptorSetLayoutBindings[1].stageFlags = VK_SHADER_STAGE_COMPUTE_BIT; | |
| descriptorSetLayoutBindings[1].pImmutableSamplers = 0; | |
| descriptorSetLayoutBindings[2].binding = 2; | |
| descriptorSetLayoutBindings[2].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; | |
| descriptorSetLayoutBindings[2].descriptorCount = 1; | |
| descriptorSetLayoutBindings[2].stageFlags = VK_SHADER_STAGE_COMPUTE_BIT; | |
| descriptorSetLayoutBindings[2].pImmutableSamplers = 0; | |
| VkDescriptorSetLayoutCreateInfo descriptorSetLayoutCreateInfo; | |
| descriptorSetLayoutCreateInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; | |
| descriptorSetLayoutCreateInfo.pNext = 0; | |
| descriptorSetLayoutCreateInfo.flags = 0; | |
| descriptorSetLayoutCreateInfo.bindingCount = 3; | |
| descriptorSetLayoutCreateInfo.pBindings = descriptorSetLayoutBindings; | |
| if (vkdev->info.support_VK_KHR_push_descriptor()) | |
| { | |
| descriptorSetLayoutCreateInfo.flags |= VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR; | |
| } | |
| VkDescriptorSetLayout descriptorset_layout = 0; | |
| VkResult ret = vkCreateDescriptorSetLayout(vkdev->vkdevice(), &descriptorSetLayoutCreateInfo, 0, &descriptorset_layout); | |
| if (ret != VK_SUCCESS) | |
| { | |
| NCNN_LOGE("vkCreateDescriptorSetLayout failed %d", ret); | |
| return -1; | |
| } | |
| set_descriptorset_layout(descriptorset_layout); | |
| return 0; | |
| } | |
| } // namespace ncnn | |