1 /* 2 * Copyright 2015 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8 #include "SkAutoMalloc.h" 9 #include "vk/GrVkBackendContext.h" 10 #include "vk/GrVkExtensions.h" 11 #include "vk/GrVkInterface.h" 12 #include "vk/GrVkUtil.h" 13 14 //////////////////////////////////////////////////////////////////////////////// 15 // Helper code to set up Vulkan context objects 16 17 #ifdef SK_ENABLE_VK_LAYERS 18 const char* kDebugLayerNames[] = { 19 // elements of VK_LAYER_LUNARG_standard_validation 20 "VK_LAYER_GOOGLE_threading", 21 "VK_LAYER_LUNARG_parameter_validation", 22 "VK_LAYER_LUNARG_object_tracker", 23 "VK_LAYER_LUNARG_image", 24 "VK_LAYER_LUNARG_core_validation", 25 "VK_LAYER_LUNARG_swapchain", 26 "VK_LAYER_GOOGLE_unique_objects", 27 // not included in standard_validation 28 //"VK_LAYER_LUNARG_api_dump", 29 //"VK_LAYER_LUNARG_vktrace", 30 //"VK_LAYER_LUNARG_screenshot", 31 }; 32 #endif 33 34 // the minimum version of Vulkan supported 35 #ifdef SK_BUILD_FOR_ANDROID 36 const uint32_t kGrVkMinimumVersion = VK_MAKE_VERSION(1, 0, 3); 37 #else 38 const uint32_t kGrVkMinimumVersion = VK_MAKE_VERSION(1, 0, 8); 39 #endif 40 41 // Create the base Vulkan objects needed by the GrVkGpu object 42 const GrVkBackendContext* GrVkBackendContext::Create(uint32_t* presentQueueIndexPtr, 43 CanPresentFn canPresent) { 44 VkPhysicalDevice physDev; 45 VkDevice device; 46 VkInstance inst; 47 VkResult err; 48 49 const VkApplicationInfo app_info = { 50 VK_STRUCTURE_TYPE_APPLICATION_INFO, // sType 51 nullptr, // pNext 52 "vktest", // pApplicationName 53 0, // applicationVersion 54 "vktest", // pEngineName 55 0, // engineVerison 56 kGrVkMinimumVersion, // apiVersion 57 }; 58 59 GrVkExtensions extensions; 60 extensions.initInstance(kGrVkMinimumVersion); 61 62 SkTArray<const char*> instanceLayerNames; 63 SkTArray<const char*> instanceExtensionNames; 64 uint32_t extensionFlags = 0; 65 #ifdef SK_ENABLE_VK_LAYERS 66 for (size_t i = 0; i < SK_ARRAY_COUNT(kDebugLayerNames); ++i) { 67 if (extensions.hasInstanceLayer(kDebugLayerNames[i])) { 68 instanceLayerNames.push_back(kDebugLayerNames[i]); 69 } 70 } 71 if (extensions.hasInstanceExtension(VK_EXT_DEBUG_REPORT_EXTENSION_NAME)) { 72 instanceExtensionNames.push_back(VK_EXT_DEBUG_REPORT_EXTENSION_NAME); 73 extensionFlags |= kEXT_debug_report_GrVkExtensionFlag; 74 } 75 #endif 76 77 if (extensions.hasInstanceExtension(VK_KHR_SURFACE_EXTENSION_NAME)) { 78 instanceExtensionNames.push_back(VK_KHR_SURFACE_EXTENSION_NAME); 79 extensionFlags |= kKHR_surface_GrVkExtensionFlag; 80 } 81 if (extensions.hasInstanceExtension(VK_KHR_SWAPCHAIN_EXTENSION_NAME)) { 82 instanceExtensionNames.push_back(VK_KHR_SWAPCHAIN_EXTENSION_NAME); 83 extensionFlags |= kKHR_swapchain_GrVkExtensionFlag; 84 } 85 #ifdef SK_BUILD_FOR_WIN 86 if (extensions.hasInstanceExtension(VK_KHR_WIN32_SURFACE_EXTENSION_NAME)) { 87 instanceExtensionNames.push_back(VK_KHR_WIN32_SURFACE_EXTENSION_NAME); 88 extensionFlags |= kKHR_win32_surface_GrVkExtensionFlag; 89 } 90 #elif defined(SK_BUILD_FOR_ANDROID) 91 if (extensions.hasInstanceExtension(VK_KHR_ANDROID_SURFACE_EXTENSION_NAME)) { 92 instanceExtensionNames.push_back(VK_KHR_ANDROID_SURFACE_EXTENSION_NAME); 93 extensionFlags |= kKHR_android_surface_GrVkExtensionFlag; 94 } 95 #elif defined(SK_BUILD_FOR_UNIX) 96 if (extensions.hasInstanceExtension(VK_KHR_XCB_SURFACE_EXTENSION_NAME)) { 97 instanceExtensionNames.push_back(VK_KHR_XCB_SURFACE_EXTENSION_NAME); 98 extensionFlags |= kKHR_xcb_surface_GrVkExtensionFlag; 99 } 100 #endif 101 102 const VkInstanceCreateInfo instance_create = { 103 VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, // sType 104 nullptr, // pNext 105 0, // flags 106 &app_info, // pApplicationInfo 107 (uint32_t) instanceLayerNames.count(), // enabledLayerNameCount 108 instanceLayerNames.begin(), // ppEnabledLayerNames 109 (uint32_t) instanceExtensionNames.count(), // enabledExtensionNameCount 110 instanceExtensionNames.begin(), // ppEnabledExtensionNames 111 }; 112 113 err = vkCreateInstance(&instance_create, nullptr, &inst); 114 if (err < 0) { 115 SkDebugf("vkCreateInstance failed: %d\n", err); 116 return nullptr; 117 } 118 119 uint32_t gpuCount; 120 err = vkEnumeratePhysicalDevices(inst, &gpuCount, nullptr); 121 if (err) { 122 SkDebugf("vkEnumeratePhysicalDevices failed: %d\n", err); 123 vkDestroyInstance(inst, nullptr); 124 return nullptr; 125 } 126 SkASSERT(gpuCount > 0); 127 // Just returning the first physical device instead of getting the whole array. 128 // TODO: find best match for our needs 129 gpuCount = 1; 130 err = vkEnumeratePhysicalDevices(inst, &gpuCount, &physDev); 131 if (err) { 132 SkDebugf("vkEnumeratePhysicalDevices failed: %d\n", err); 133 vkDestroyInstance(inst, nullptr); 134 return nullptr; 135 } 136 137 // query to get the initial queue props size 138 uint32_t queueCount; 139 vkGetPhysicalDeviceQueueFamilyProperties(physDev, &queueCount, nullptr); 140 SkASSERT(queueCount >= 1); 141 142 SkAutoMalloc queuePropsAlloc(queueCount * sizeof(VkQueueFamilyProperties)); 143 // now get the actual queue props 144 VkQueueFamilyProperties* queueProps = (VkQueueFamilyProperties*)queuePropsAlloc.get(); 145 146 vkGetPhysicalDeviceQueueFamilyProperties(physDev, &queueCount, queueProps); 147 148 // iterate to find the graphics queue 149 uint32_t graphicsQueueIndex = queueCount; 150 for (uint32_t i = 0; i < queueCount; i++) { 151 if (queueProps[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) { 152 graphicsQueueIndex = i; 153 break; 154 } 155 } 156 SkASSERT(graphicsQueueIndex < queueCount); 157 158 // iterate to find the present queue, if needed 159 uint32_t presentQueueIndex = graphicsQueueIndex; 160 if (presentQueueIndexPtr && canPresent) { 161 for (uint32_t i = 0; i < queueCount; i++) { 162 if (canPresent(inst, physDev, i)) { 163 presentQueueIndex = i; 164 break; 165 } 166 } 167 SkASSERT(presentQueueIndex < queueCount); 168 *presentQueueIndexPtr = presentQueueIndex; 169 } 170 171 extensions.initDevice(kGrVkMinimumVersion, inst, physDev); 172 173 SkTArray<const char*> deviceLayerNames; 174 SkTArray<const char*> deviceExtensionNames; 175 #ifdef SK_ENABLE_VK_LAYERS 176 for (size_t i = 0; i < SK_ARRAY_COUNT(kDebugLayerNames); ++i) { 177 if (extensions.hasDeviceLayer(kDebugLayerNames[i])) { 178 deviceLayerNames.push_back(kDebugLayerNames[i]); 179 } 180 } 181 #endif 182 if (extensions.hasDeviceExtension(VK_KHR_SWAPCHAIN_EXTENSION_NAME)) { 183 deviceExtensionNames.push_back(VK_KHR_SWAPCHAIN_EXTENSION_NAME); 184 extensionFlags |= kKHR_swapchain_GrVkExtensionFlag; 185 } 186 if (extensions.hasDeviceExtension("VK_NV_glsl_shader")) { 187 deviceExtensionNames.push_back("VK_NV_glsl_shader"); 188 extensionFlags |= kNV_glsl_shader_GrVkExtensionFlag; 189 } 190 191 // query to get the physical device properties 192 VkPhysicalDeviceFeatures deviceFeatures; 193 vkGetPhysicalDeviceFeatures(physDev, &deviceFeatures); 194 // this looks like it would slow things down, 195 // and we can't depend on it on all platforms 196 deviceFeatures.robustBufferAccess = VK_FALSE; 197 198 uint32_t featureFlags = 0; 199 if (deviceFeatures.geometryShader) { 200 featureFlags |= kGeometryShader_GrVkFeatureFlag; 201 } 202 if (deviceFeatures.dualSrcBlend) { 203 featureFlags |= kDualSrcBlend_GrVkFeatureFlag; 204 } 205 if (deviceFeatures.sampleRateShading) { 206 featureFlags |= kSampleRateShading_GrVkFeatureFlag; 207 } 208 209 float queuePriorities[1] = { 0.0 }; 210 // Here we assume no need for swapchain queue 211 // If one is needed, the client will need its own setup code 212 const VkDeviceQueueCreateInfo queueInfo[2] = { 213 { 214 VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, // sType 215 nullptr, // pNext 216 0, // VkDeviceQueueCreateFlags 217 graphicsQueueIndex, // queueFamilyIndex 218 1, // queueCount 219 queuePriorities, // pQueuePriorities 220 }, 221 { 222 VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, // sType 223 nullptr, // pNext 224 0, // VkDeviceQueueCreateFlags 225 presentQueueIndex, // queueFamilyIndex 226 1, // queueCount 227 queuePriorities, // pQueuePriorities 228 } 229 }; 230 uint32_t queueInfoCount = (presentQueueIndex != graphicsQueueIndex) ? 2 : 1; 231 232 const VkDeviceCreateInfo deviceInfo = { 233 VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, // sType 234 nullptr, // pNext 235 0, // VkDeviceCreateFlags 236 queueInfoCount, // queueCreateInfoCount 237 queueInfo, // pQueueCreateInfos 238 (uint32_t) deviceLayerNames.count(), // layerCount 239 deviceLayerNames.begin(), // ppEnabledLayerNames 240 (uint32_t) deviceExtensionNames.count(), // extensionCount 241 deviceExtensionNames.begin(), // ppEnabledExtensionNames 242 &deviceFeatures // ppEnabledFeatures 243 }; 244 245 err = vkCreateDevice(physDev, &deviceInfo, nullptr, &device); 246 if (err) { 247 SkDebugf("CreateDevice failed: %d\n", err); 248 vkDestroyInstance(inst, nullptr); 249 return nullptr; 250 } 251 252 VkQueue queue; 253 vkGetDeviceQueue(device, graphicsQueueIndex, 0, &queue); 254 255 GrVkBackendContext* ctx = new GrVkBackendContext(); 256 ctx->fInstance = inst; 257 ctx->fPhysicalDevice = physDev; 258 ctx->fDevice = device; 259 ctx->fQueue = queue; 260 ctx->fGraphicsQueueIndex = graphicsQueueIndex; 261 ctx->fMinAPIVersion = kGrVkMinimumVersion; 262 ctx->fExtensions = extensionFlags; 263 ctx->fFeatures = featureFlags; 264 ctx->fInterface.reset(GrVkCreateInterface(inst, device, extensionFlags)); 265 266 return ctx; 267 } 268 269 GrVkBackendContext::~GrVkBackendContext() { 270 vkDeviceWaitIdle(fDevice); 271 vkDestroyDevice(fDevice, nullptr); 272 fDevice = VK_NULL_HANDLE; 273 vkDestroyInstance(fInstance, nullptr); 274 fInstance = VK_NULL_HANDLE; 275 } 276