1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one
3  * or more contributor license agreements.  See the NOTICE file
4  * distributed with this work for additional information
5  * regarding copyright ownership.  The ASF licenses this file
6  * to you under the Apache License, Version 2.0 (the
7  * "License"); you may not use this file except in compliance
8  * with the License.  You may obtain a copy of the License at
9  *
10  *   http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing,
13  * software distributed under the License is distributed on an
14  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15  * KIND, either express or implied.  See the License for the
16  * specific language governing permissions and limitations
17  * under the License.
18  */
19 #pragma once
20 
21 #include <dmlc/logging.h>
22 #include <tvm/runtime/c_runtime_api.h>
23 #include <tvm/runtime/device_api.h>
24 #include <tvm/runtime/packed_func.h>
25 #include <vulkan/vulkan.h>
26 
27 #include <memory>
28 #include <mutex>
29 #include <string>
30 #include <vector>
31 
32 namespace tvm {
33 namespace runtime {
34 namespace vulkan {
35 
VKGetErrorString(VkResult error)36 inline const char* VKGetErrorString(VkResult error) {
37   switch (error) {
38     case VK_SUCCESS:
39       return "VK_SUCCESS";
40     case VK_NOT_READY:
41       return "VK_NOT_READY";
42     case VK_TIMEOUT:
43       return "VK_TIMEOUT";
44     case VK_EVENT_SET:
45       return "VK_EVENT_SET";
46     case VK_EVENT_RESET:
47       return "VK_EVENT_RESET";
48     case VK_INCOMPLETE:
49       return "VK_INCOMPLETE";
50     case VK_ERROR_OUT_OF_HOST_MEMORY:
51       return "VK_ERROR_OUT_OF_HOST_MEMORY";
52     case VK_ERROR_OUT_OF_DEVICE_MEMORY:
53       return "VK_ERROR_OUT_OF_DEVICE_MEMORY";
54     case VK_ERROR_INITIALIZATION_FAILED:
55       return "VK_ERROR_INITIALIZATION_FAILED";
56     case VK_ERROR_DEVICE_LOST:
57       return "VK_ERROR_DEVICE_LOST";
58     case VK_ERROR_MEMORY_MAP_FAILED:
59       return "VK_ERROR_MEMORY_MAP_FAILED";
60     case VK_ERROR_LAYER_NOT_PRESENT:
61       return "VK_ERROR_LAYER_NOT_PRESENT";
62     case VK_ERROR_EXTENSION_NOT_PRESENT:
63       return "VK_ERROR_EXTENSION_NOT_PRESENT";
64     case VK_ERROR_FEATURE_NOT_PRESENT:
65       return "VK_ERROR_FEATURE_NOT_PRESENT";
66     case VK_ERROR_INCOMPATIBLE_DRIVER:
67       return "VK_ERROR_INCOMPATIBLE_DRIVER";
68     case VK_ERROR_TOO_MANY_OBJECTS:
69       return "VK_ERROR_TOO_MANY_OBJECTS";
70     case VK_ERROR_FORMAT_NOT_SUPPORTED:
71       return "VK_ERROR_FORMAT_NOT_SUPPORTED";
72     case VK_ERROR_FRAGMENTED_POOL:
73       return "VK_ERROR_FRAGMENTED_POOL";
74     default:
75       return "Unknown Vulkan error code";
76   }
77 }
78 
79 /*!
80  * \brief Protected Vulkan call
81  * \param func Expression to call.
82  */
83 #define VULKAN_CHECK_ERROR(__e)                                     \
84   {                                                                 \
85     CHECK(__e == VK_SUCCESS) << "Vulan Error, code=" << __e << ": " \
86                              << vulkan::VKGetErrorString(__e);      \
87   }
88 
89 #define VULKAN_CALL(func)    \
90   {                          \
91     VkResult __e = (func);   \
92     VULKAN_CHECK_ERROR(__e); \
93   }
94 
95 struct VulkanDescriptorTemplateKHRFunctions {
96   PFN_vkCreateDescriptorUpdateTemplateKHR vkCreateDescriptorUpdateTemplateKHR{nullptr};
97   PFN_vkDestroyDescriptorUpdateTemplateKHR vkDestroyDescriptorUpdateTemplateKHR{nullptr};
98   PFN_vkUpdateDescriptorSetWithTemplateKHR vkUpdateDescriptorSetWithTemplateKHR{nullptr};
99   PFN_vkCmdPushDescriptorSetWithTemplateKHR vkCmdPushDescriptorSetWithTemplateKHR{nullptr};
100 };
101 
102 struct VulkanGetBufferMemoryRequirements2Functions {
103   PFN_vkGetBufferMemoryRequirements2KHR vkGetBufferMemoryRequirements2KHR{nullptr};
104 };
105 
106 struct VulkanStagingBuffer {
107   VkDevice device{nullptr};
108   VkBuffer buffer{VK_NULL_HANDLE};
109   VkDeviceMemory memory{VK_NULL_HANDLE};
110   void* host_addr{nullptr};
111   size_t size{0};
112 };
113 
114 struct VulkanContext {
115   // phyiscal device
116   VkPhysicalDevice phy_device{nullptr};
117   // Phyiscal device property
118   VkPhysicalDeviceProperties phy_device_prop;
119   // Memory type index for staging.
120   uint32_t staging_mtype_index{0};
121   // whether staging is coherent
122   bool coherent_staging{false};
123 
124   std::unique_ptr<VulkanDescriptorTemplateKHRFunctions> descriptor_template_khr_functions{nullptr};
125   std::unique_ptr<VulkanGetBufferMemoryRequirements2Functions>
126       get_buffer_memory_requirements_2_functions{nullptr};
127   // Memory type index for compute
128   uint32_t compute_mtype_index{0};
129   // The logical device
130   VkDevice device{nullptr};
131   // command queue
132 
133   std::unique_ptr<std::mutex> queue_mutex;
134   VkQueue queue{nullptr};
135   // queue family_index;
136   uint32_t queue_family_index{0};
137   // Queue family index.
138   VkQueueFamilyProperties queue_prop;
139 
UseImmediateVulkanContext140   bool UseImmediate() const { return descriptor_template_khr_functions.get() != nullptr; }
141 };
142 
143 }  // namespace vulkan
144 }  // namespace runtime
145 }  // namespace tvm
146