From 1f8d79a441d7bbd04527fc8915d5b468c81bd7e9 Mon Sep 17 00:00:00 2001 From: Michael Vigovsky Date: Thu, 17 Oct 2024 03:17:57 +0300 Subject: [PATCH 1/3] Fix #5741 don't crash when vkCreateDevice fails --- src/gpu.cpp | 44 +++++++++++++++++++++++++++++++++++--------- src/gpu.h | 1 + src/net.cpp | 2 +- 3 files changed, 37 insertions(+), 10 deletions(-) diff --git a/src/gpu.cpp b/src/gpu.cpp index 5b34c224da08..fac6bf226066 100644 --- a/src/gpu.cpp +++ b/src/gpu.cpp @@ -2212,10 +2212,7 @@ class VkDummyCompute : public VkCompute class VulkanDevicePrivate { public: - VulkanDevicePrivate(VulkanDevice* _vkdev) - : vkdev(_vkdev) - { - } + VulkanDevicePrivate(VulkanDevice* _vkdev); VulkanDevice* const vkdev; // dummy buffer and image @@ -2270,8 +2267,22 @@ class VulkanDevicePrivate // to pack1 | pack4 | pack8 mutable ncnn::Packing_vulkan* uop_packing[2][2][3][3][3]; mutable Mutex uop_lock; + + // device is valid and sucessfully initialized + bool valid; }; +VulkanDevicePrivate::VulkanDevicePrivate(VulkanDevice* _vkdev) + : vkdev(_vkdev) +{ + device = 0; + texelfetch_sampler = 0; + dummy_allocator = 0; + pipeline_cache = 0; + valid = false; + memset(uop_packing, 0, sizeof(uop_packing)); +} + int VulkanDevicePrivate::create_dummy_buffer_image() { dummy_allocator = new VkDummyAllocator(vkdev); @@ -2310,7 +2321,10 @@ void VulkanDevicePrivate::destroy_dummy_buffer_image() dummy_image_readonly.release(); #endif - delete dummy_allocator; + if (dummy_allocator) { + delete dummy_allocator; + dummy_allocator = 0; + } } const ncnn::Packing_vulkan* VulkanDevicePrivate::get_utility_operator(int storage_type_from, int storage_type_to, int cast_type_from_index, int cast_type_to_index, int packing_type_to_index) const @@ -2653,6 +2667,7 @@ VulkanDevice::VulkanDevice(int device_index) if (ret != VK_SUCCESS) { NCNN_LOGE("vkCreateDevice failed %d", ret); + return; } init_device_extension(); @@ -2712,7 +2727,6 @@ VulkanDevice::VulkanDevice(int device_index) samplerCreateInfo.borderColor = VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK; samplerCreateInfo.unnormalizedCoordinates = VK_TRUE; - d->texelfetch_sampler = 0; ret = vkCreateSampler(d->device, &samplerCreateInfo, 0, &d->texelfetch_sampler); if (ret != VK_SUCCESS) { @@ -2724,11 +2738,12 @@ VulkanDevice::VulkanDevice(int device_index) if (cret != 0) { NCNN_LOGE("VulkanDevice create_dummy_buffer_image failed %d", cret); + return; } d->pipeline_cache = new PipelineCache(this); - memset(d->uop_packing, 0, sizeof(d->uop_packing)); + d->valid = true; } VulkanDevice::~VulkanDevice() @@ -2753,9 +2768,15 @@ VulkanDevice::~VulkanDevice() } d->staging_allocators.clear(); - delete d->pipeline_cache; + if (d->pipeline_cache) + { + delete d->pipeline_cache; + } - vkDestroyDevice(d->device, 0); + if (d->device) + { + vkDestroyDevice(d->device, 0); + } delete d; } @@ -2775,6 +2796,11 @@ VkDevice VulkanDevice::vkdevice() const return d->device; } +bool VulkanDevice::is_valid() const +{ + return d->valid; +} + VkShaderModule VulkanDevice::compile_shader_module(const uint32_t* spv_data, size_t spv_data_size) const { VkShaderModuleCreateInfo shaderModuleCreateInfo; diff --git a/src/gpu.h b/src/gpu.h index 4d131f71c8bd..92c854d1c005 100644 --- a/src/gpu.h +++ b/src/gpu.h @@ -336,6 +336,7 @@ class NCNN_EXPORT VulkanDevice const GpuInfo& info; VkDevice vkdevice() const; + bool is_valid() const; VkShaderModule compile_shader_module(const uint32_t* spv_data, size_t spv_data_size) const; diff --git a/src/net.cpp b/src/net.cpp index 3574944e726e..36958b59b0ed 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -1381,7 +1381,7 @@ int Net::load_param(const DataReader& dr) if (opt.use_vulkan_compute) { if (!d->vkdev) d->vkdev = get_gpu_device(); - if (!d->vkdev) opt.use_vulkan_compute = false; // no vulkan device, fallback to cpu + if (!d->vkdev || !d->vkdev->is_valid()) opt.use_vulkan_compute = false; // no valid vulkan device, fallback to cpu } if (opt.use_vulkan_compute) { From c15d3450b1e273a29a165bfbc0b9fe3d582b36d6 Mon Sep 17 00:00:00 2001 From: Upliner Date: Thu, 17 Oct 2024 00:36:30 +0000 Subject: [PATCH 2/3] apply code-format changes --- src/gpu.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/gpu.cpp b/src/gpu.cpp index fac6bf226066..5bb186fc2703 100644 --- a/src/gpu.cpp +++ b/src/gpu.cpp @@ -2321,7 +2321,8 @@ void VulkanDevicePrivate::destroy_dummy_buffer_image() dummy_image_readonly.release(); #endif - if (dummy_allocator) { + if (dummy_allocator) + { delete dummy_allocator; dummy_allocator = 0; } From a326f0884d50f2c8c2143e4c4f17146e47643cea Mon Sep 17 00:00:00 2001 From: Michael Vigovsky Date: Thu, 17 Oct 2024 17:13:48 +0300 Subject: [PATCH 3/3] Add Vulkan device validation to Net::load_param_bin --- src/net.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/net.cpp b/src/net.cpp index 36958b59b0ed..32b5b2abd601 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -1677,7 +1677,7 @@ int Net::load_param_bin(const DataReader& dr) if (opt.use_vulkan_compute) { if (!d->vkdev) d->vkdev = get_gpu_device(); - if (!d->vkdev) opt.use_vulkan_compute = false; // no vulkan device, fallback to cpu + if (!d->vkdev || !d->vkdev->is_valid()) opt.use_vulkan_compute = false; // no valid vulkan device, fallback to cpu } if (opt.use_vulkan_compute) {