blob: fea1947489ba8fe762fe7907ee8715f596240370 [file] [log] [blame]
jvanverth633b3562016-03-23 11:01:22 -07001/*
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
Hal Canary95e3c052017-01-11 12:44:43 -05008#include "SkAutoMalloc.h"
jvanverth633b3562016-03-23 11:01:22 -07009#include "vk/GrVkBackendContext.h"
jvanverthfd7bd452016-03-25 06:29:52 -070010#include "vk/GrVkExtensions.h"
jvanverth633b3562016-03-23 11:01:22 -070011#include "vk/GrVkInterface.h"
12#include "vk/GrVkUtil.h"
13
14////////////////////////////////////////////////////////////////////////////////
15// Helper code to set up Vulkan context objects
16
egdaniel735109c2016-07-27 08:03:57 -070017#ifdef SK_ENABLE_VK_LAYERS
jvanverthfd7bd452016-03-25 06:29:52 -070018const char* kDebugLayerNames[] = {
jvanverth633b3562016-03-23 11:01:22 -070019 // elements of VK_LAYER_LUNARG_standard_validation
egdaniel58a8d922016-04-21 08:03:10 -070020 "VK_LAYER_GOOGLE_threading",
21 "VK_LAYER_LUNARG_parameter_validation",
jvanverth633b3562016-03-23 11:01:22 -070022 "VK_LAYER_LUNARG_object_tracker",
23 "VK_LAYER_LUNARG_image",
egdaniel58a8d922016-04-21 08:03:10 -070024 "VK_LAYER_LUNARG_core_validation",
jvanverth633b3562016-03-23 11:01:22 -070025 "VK_LAYER_LUNARG_swapchain",
egdaniel58a8d922016-04-21 08:03:10 -070026 "VK_LAYER_GOOGLE_unique_objects",
jvanverth633b3562016-03-23 11:01:22 -070027 // not included in standard_validation
28 //"VK_LAYER_LUNARG_api_dump",
jvanverthfd7bd452016-03-25 06:29:52 -070029 //"VK_LAYER_LUNARG_vktrace",
30 //"VK_LAYER_LUNARG_screenshot",
jvanverth633b3562016-03-23 11:01:22 -070031};
jvanverth633b3562016-03-23 11:01:22 -070032#endif
33
jvanverthfd7bd452016-03-25 06:29:52 -070034// the minimum version of Vulkan supported
liyuqianb138fdc2016-04-29 10:00:26 -070035#ifdef SK_BUILD_FOR_ANDROID
36const uint32_t kGrVkMinimumVersion = VK_MAKE_VERSION(1, 0, 3);
37#else
egdaniel58a8d922016-04-21 08:03:10 -070038const uint32_t kGrVkMinimumVersion = VK_MAKE_VERSION(1, 0, 8);
liyuqianb138fdc2016-04-29 10:00:26 -070039#endif
jvanverthfd7bd452016-03-25 06:29:52 -070040
Michael Jurka3251ed82017-04-05 09:52:55 -070041#define ACQUIRE_VK_PROC(name, instance, device) \
42 PFN_vk##name grVk##name = \
43 reinterpret_cast<PFN_vk##name>(getProc("vk" #name, instance, device)); \
44 if (grVk##name == nullptr) { \
45 SkDebugf("Function ptr for vk%s could not be acquired\n", #name); \
46 return nullptr; \
47 }
48
jvanverth633b3562016-03-23 11:01:22 -070049// Create the base Vulkan objects needed by the GrVkGpu object
jvanverthb0d43522016-04-21 11:46:23 -070050const GrVkBackendContext* GrVkBackendContext::Create(uint32_t* presentQueueIndexPtr,
Michael Jurka3251ed82017-04-05 09:52:55 -070051 CanPresentFn canPresent,
52 GrVkInterface::GetProc getProc) {
Brian Salomoncc901742017-04-25 13:28:45 -040053 if (!getProc) {
Michael Jurka3251ed82017-04-05 09:52:55 -070054#ifdef SK_LINK_WITH_VULKAN
Brian Salomoncc901742017-04-25 13:28:45 -040055 return GrVkBackendContext::Create(vkGetInstanceProcAddr, vkGetDeviceProcAddr,
56 presentQueueIndexPtr, canPresent);
Michael Jurka3251ed82017-04-05 09:52:55 -070057#else
Brian Salomoncc901742017-04-25 13:28:45 -040058 return nullptr;
Michael Jurka3251ed82017-04-05 09:52:55 -070059#endif
Brian Salomoncc901742017-04-25 13:28:45 -040060 }
61 SkASSERT(getProc);
Michael Jurka3251ed82017-04-05 09:52:55 -070062
jvanverth633b3562016-03-23 11:01:22 -070063 VkPhysicalDevice physDev;
64 VkDevice device;
65 VkInstance inst;
66 VkResult err;
67
68 const VkApplicationInfo app_info = {
69 VK_STRUCTURE_TYPE_APPLICATION_INFO, // sType
70 nullptr, // pNext
71 "vktest", // pApplicationName
72 0, // applicationVersion
73 "vktest", // pEngineName
74 0, // engineVerison
75 kGrVkMinimumVersion, // apiVersion
76 };
77
Michael Jurka3251ed82017-04-05 09:52:55 -070078 GrVkExtensions extensions(getProc);
jvanverthfd7bd452016-03-25 06:29:52 -070079 extensions.initInstance(kGrVkMinimumVersion);
80
81 SkTArray<const char*> instanceLayerNames;
82 SkTArray<const char*> instanceExtensionNames;
83 uint32_t extensionFlags = 0;
egdaniel735109c2016-07-27 08:03:57 -070084#ifdef SK_ENABLE_VK_LAYERS
ethannicholas384b5e92016-03-25 11:04:06 -070085 for (size_t i = 0; i < SK_ARRAY_COUNT(kDebugLayerNames); ++i) {
jvanverthfd7bd452016-03-25 06:29:52 -070086 if (extensions.hasInstanceLayer(kDebugLayerNames[i])) {
87 instanceLayerNames.push_back(kDebugLayerNames[i]);
88 }
89 }
90 if (extensions.hasInstanceExtension(VK_EXT_DEBUG_REPORT_EXTENSION_NAME)) {
91 instanceExtensionNames.push_back(VK_EXT_DEBUG_REPORT_EXTENSION_NAME);
92 extensionFlags |= kEXT_debug_report_GrVkExtensionFlag;
jvanverth633b3562016-03-23 11:01:22 -070093 }
jvanverth9f372462016-04-06 06:08:59 -070094#endif
95
jvanverthe50f3e72016-03-28 07:03:06 -070096 if (extensions.hasInstanceExtension(VK_KHR_SURFACE_EXTENSION_NAME)) {
97 instanceExtensionNames.push_back(VK_KHR_SURFACE_EXTENSION_NAME);
98 extensionFlags |= kKHR_surface_GrVkExtensionFlag;
99 }
100 if (extensions.hasInstanceExtension(VK_KHR_SWAPCHAIN_EXTENSION_NAME)) {
101 instanceExtensionNames.push_back(VK_KHR_SWAPCHAIN_EXTENSION_NAME);
102 extensionFlags |= kKHR_swapchain_GrVkExtensionFlag;
103 }
104#ifdef SK_BUILD_FOR_WIN
105 if (extensions.hasInstanceExtension(VK_KHR_WIN32_SURFACE_EXTENSION_NAME)) {
106 instanceExtensionNames.push_back(VK_KHR_WIN32_SURFACE_EXTENSION_NAME);
107 extensionFlags |= kKHR_win32_surface_GrVkExtensionFlag;
108 }
djsollen7e731082016-06-09 13:07:13 -0700109#elif defined(SK_BUILD_FOR_ANDROID)
jvanverthe50f3e72016-03-28 07:03:06 -0700110 if (extensions.hasInstanceExtension(VK_KHR_ANDROID_SURFACE_EXTENSION_NAME)) {
111 instanceExtensionNames.push_back(VK_KHR_ANDROID_SURFACE_EXTENSION_NAME);
112 extensionFlags |= kKHR_android_surface_GrVkExtensionFlag;
jvanverth1d155962016-05-23 13:13:36 -0700113 }
Michael Jurka3251ed82017-04-05 09:52:55 -0700114#elif defined(SK_BUILD_FOR_UNIX) && !defined(__Fuchsia__)
jvanverth1d155962016-05-23 13:13:36 -0700115 if (extensions.hasInstanceExtension(VK_KHR_XCB_SURFACE_EXTENSION_NAME)) {
116 instanceExtensionNames.push_back(VK_KHR_XCB_SURFACE_EXTENSION_NAME);
117 extensionFlags |= kKHR_xcb_surface_GrVkExtensionFlag;
jvanverthe50f3e72016-03-28 07:03:06 -0700118 }
119#endif
jvanverth633b3562016-03-23 11:01:22 -0700120
121 const VkInstanceCreateInfo instance_create = {
ethannicholas384b5e92016-03-25 11:04:06 -0700122 VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, // sType
123 nullptr, // pNext
124 0, // flags
125 &app_info, // pApplicationInfo
126 (uint32_t) instanceLayerNames.count(), // enabledLayerNameCount
127 instanceLayerNames.begin(), // ppEnabledLayerNames
128 (uint32_t) instanceExtensionNames.count(), // enabledExtensionNameCount
129 instanceExtensionNames.begin(), // ppEnabledExtensionNames
jvanverth633b3562016-03-23 11:01:22 -0700130 };
131
Michael Jurka3251ed82017-04-05 09:52:55 -0700132 ACQUIRE_VK_PROC(CreateInstance, VK_NULL_HANDLE, VK_NULL_HANDLE);
133 err = grVkCreateInstance(&instance_create, nullptr, &inst);
jvanverth633b3562016-03-23 11:01:22 -0700134 if (err < 0) {
135 SkDebugf("vkCreateInstance failed: %d\n", err);
bsalomondc0fcd42016-04-11 14:21:33 -0700136 return nullptr;
jvanverth633b3562016-03-23 11:01:22 -0700137 }
138
Michael Jurka3251ed82017-04-05 09:52:55 -0700139 ACQUIRE_VK_PROC(DestroyInstance, inst, VK_NULL_HANDLE);
140 ACQUIRE_VK_PROC(EnumeratePhysicalDevices, inst, VK_NULL_HANDLE);
141 ACQUIRE_VK_PROC(GetPhysicalDeviceQueueFamilyProperties, inst, VK_NULL_HANDLE);
142 ACQUIRE_VK_PROC(GetPhysicalDeviceFeatures, inst, VK_NULL_HANDLE);
143 ACQUIRE_VK_PROC(CreateDevice, inst, VK_NULL_HANDLE);
144 ACQUIRE_VK_PROC(GetDeviceQueue, inst, VK_NULL_HANDLE);
145 ACQUIRE_VK_PROC(DeviceWaitIdle, inst, VK_NULL_HANDLE);
146 ACQUIRE_VK_PROC(DestroyDevice, inst, VK_NULL_HANDLE);
147
jvanverth633b3562016-03-23 11:01:22 -0700148 uint32_t gpuCount;
Michael Jurka3251ed82017-04-05 09:52:55 -0700149 err = grVkEnumeratePhysicalDevices(inst, &gpuCount, nullptr);
jvanverth633b3562016-03-23 11:01:22 -0700150 if (err) {
151 SkDebugf("vkEnumeratePhysicalDevices failed: %d\n", err);
Michael Jurka3251ed82017-04-05 09:52:55 -0700152 grVkDestroyInstance(inst, nullptr);
bsalomondc0fcd42016-04-11 14:21:33 -0700153 return nullptr;
jvanverth633b3562016-03-23 11:01:22 -0700154 }
155 SkASSERT(gpuCount > 0);
156 // Just returning the first physical device instead of getting the whole array.
157 // TODO: find best match for our needs
158 gpuCount = 1;
Michael Jurka3251ed82017-04-05 09:52:55 -0700159 err = grVkEnumeratePhysicalDevices(inst, &gpuCount, &physDev);
jvanverth633b3562016-03-23 11:01:22 -0700160 if (err) {
161 SkDebugf("vkEnumeratePhysicalDevices failed: %d\n", err);
Michael Jurka3251ed82017-04-05 09:52:55 -0700162 grVkDestroyInstance(inst, nullptr);
bsalomondc0fcd42016-04-11 14:21:33 -0700163 return nullptr;
jvanverth633b3562016-03-23 11:01:22 -0700164 }
165
166 // query to get the initial queue props size
167 uint32_t queueCount;
Michael Jurka3251ed82017-04-05 09:52:55 -0700168 grVkGetPhysicalDeviceQueueFamilyProperties(physDev, &queueCount, nullptr);
jvanverth633b3562016-03-23 11:01:22 -0700169 SkASSERT(queueCount >= 1);
170
171 SkAutoMalloc queuePropsAlloc(queueCount * sizeof(VkQueueFamilyProperties));
172 // now get the actual queue props
173 VkQueueFamilyProperties* queueProps = (VkQueueFamilyProperties*)queuePropsAlloc.get();
174
Michael Jurka3251ed82017-04-05 09:52:55 -0700175 grVkGetPhysicalDeviceQueueFamilyProperties(physDev, &queueCount, queueProps);
jvanverth633b3562016-03-23 11:01:22 -0700176
177 // iterate to find the graphics queue
jvanverthb0d43522016-04-21 11:46:23 -0700178 uint32_t graphicsQueueIndex = queueCount;
jvanverth633b3562016-03-23 11:01:22 -0700179 for (uint32_t i = 0; i < queueCount; i++) {
180 if (queueProps[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) {
181 graphicsQueueIndex = i;
182 break;
183 }
184 }
185 SkASSERT(graphicsQueueIndex < queueCount);
186
jvanverthb0d43522016-04-21 11:46:23 -0700187 // iterate to find the present queue, if needed
188 uint32_t presentQueueIndex = graphicsQueueIndex;
189 if (presentQueueIndexPtr && canPresent) {
190 for (uint32_t i = 0; i < queueCount; i++) {
bsalomond1bdd1f2016-07-26 12:02:50 -0700191 if (canPresent(inst, physDev, i)) {
jvanverthb0d43522016-04-21 11:46:23 -0700192 presentQueueIndex = i;
193 break;
194 }
195 }
196 SkASSERT(presentQueueIndex < queueCount);
197 *presentQueueIndexPtr = presentQueueIndex;
198 }
199
jvanverthfd7bd452016-03-25 06:29:52 -0700200 extensions.initDevice(kGrVkMinimumVersion, inst, physDev);
201
202 SkTArray<const char*> deviceLayerNames;
203 SkTArray<const char*> deviceExtensionNames;
egdaniel735109c2016-07-27 08:03:57 -0700204#ifdef SK_ENABLE_VK_LAYERS
ethannicholas384b5e92016-03-25 11:04:06 -0700205 for (size_t i = 0; i < SK_ARRAY_COUNT(kDebugLayerNames); ++i) {
jvanverthfd7bd452016-03-25 06:29:52 -0700206 if (extensions.hasDeviceLayer(kDebugLayerNames[i])) {
207 deviceLayerNames.push_back(kDebugLayerNames[i]);
208 }
jvanverth633b3562016-03-23 11:01:22 -0700209 }
210#endif
jvanverth9f372462016-04-06 06:08:59 -0700211 if (extensions.hasDeviceExtension(VK_KHR_SWAPCHAIN_EXTENSION_NAME)) {
212 deviceExtensionNames.push_back(VK_KHR_SWAPCHAIN_EXTENSION_NAME);
213 extensionFlags |= kKHR_swapchain_GrVkExtensionFlag;
214 }
jvanverthfd7bd452016-03-25 06:29:52 -0700215 if (extensions.hasDeviceExtension("VK_NV_glsl_shader")) {
216 deviceExtensionNames.push_back("VK_NV_glsl_shader");
217 extensionFlags |= kNV_glsl_shader_GrVkExtensionFlag;
218 }
219
220 // query to get the physical device properties
221 VkPhysicalDeviceFeatures deviceFeatures;
Michael Jurka3251ed82017-04-05 09:52:55 -0700222 grVkGetPhysicalDeviceFeatures(physDev, &deviceFeatures);
halcanary9d524f22016-03-29 09:03:52 -0700223 // this looks like it would slow things down,
jvanverthfd7bd452016-03-25 06:29:52 -0700224 // and we can't depend on it on all platforms
225 deviceFeatures.robustBufferAccess = VK_FALSE;
226
227 uint32_t featureFlags = 0;
228 if (deviceFeatures.geometryShader) {
229 featureFlags |= kGeometryShader_GrVkFeatureFlag;
230 }
231 if (deviceFeatures.dualSrcBlend) {
232 featureFlags |= kDualSrcBlend_GrVkFeatureFlag;
233 }
234 if (deviceFeatures.sampleRateShading) {
235 featureFlags |= kSampleRateShading_GrVkFeatureFlag;
236 }
jvanverth633b3562016-03-23 11:01:22 -0700237
238 float queuePriorities[1] = { 0.0 };
239 // Here we assume no need for swapchain queue
240 // If one is needed, the client will need its own setup code
jvanverthb0d43522016-04-21 11:46:23 -0700241 const VkDeviceQueueCreateInfo queueInfo[2] = {
242 {
243 VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, // sType
244 nullptr, // pNext
245 0, // VkDeviceQueueCreateFlags
246 graphicsQueueIndex, // queueFamilyIndex
247 1, // queueCount
248 queuePriorities, // pQueuePriorities
249 },
250 {
251 VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, // sType
252 nullptr, // pNext
253 0, // VkDeviceQueueCreateFlags
254 presentQueueIndex, // queueFamilyIndex
255 1, // queueCount
256 queuePriorities, // pQueuePriorities
257 }
jvanverth633b3562016-03-23 11:01:22 -0700258 };
jvanverthb0d43522016-04-21 11:46:23 -0700259 uint32_t queueInfoCount = (presentQueueIndex != graphicsQueueIndex) ? 2 : 1;
260
jvanverth633b3562016-03-23 11:01:22 -0700261 const VkDeviceCreateInfo deviceInfo = {
ethannicholas384b5e92016-03-25 11:04:06 -0700262 VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, // sType
263 nullptr, // pNext
264 0, // VkDeviceCreateFlags
jvanverthb0d43522016-04-21 11:46:23 -0700265 queueInfoCount, // queueCreateInfoCount
266 queueInfo, // pQueueCreateInfos
ethannicholas384b5e92016-03-25 11:04:06 -0700267 (uint32_t) deviceLayerNames.count(), // layerCount
268 deviceLayerNames.begin(), // ppEnabledLayerNames
269 (uint32_t) deviceExtensionNames.count(), // extensionCount
270 deviceExtensionNames.begin(), // ppEnabledExtensionNames
271 &deviceFeatures // ppEnabledFeatures
jvanverth633b3562016-03-23 11:01:22 -0700272 };
273
Michael Jurka3251ed82017-04-05 09:52:55 -0700274 err = grVkCreateDevice(physDev, &deviceInfo, nullptr, &device);
jvanverth633b3562016-03-23 11:01:22 -0700275 if (err) {
276 SkDebugf("CreateDevice failed: %d\n", err);
Michael Jurka3251ed82017-04-05 09:52:55 -0700277 grVkDestroyInstance(inst, nullptr);
278 return nullptr;
279 }
280
281 auto interface =
282 sk_make_sp<GrVkInterface>(getProc, inst, device, extensionFlags);
283 if (!interface->validate(extensionFlags)) {
284 SkDebugf("Vulkan interface validation failed\n");
285 grVkDeviceWaitIdle(device);
286 grVkDestroyDevice(device, nullptr);
287 grVkDestroyInstance(inst, nullptr);
jvanverth633b3562016-03-23 11:01:22 -0700288 return nullptr;
289 }
290
291 VkQueue queue;
Michael Jurka3251ed82017-04-05 09:52:55 -0700292 grVkGetDeviceQueue(device, graphicsQueueIndex, 0, &queue);
jvanverth633b3562016-03-23 11:01:22 -0700293
294 GrVkBackendContext* ctx = new GrVkBackendContext();
295 ctx->fInstance = inst;
296 ctx->fPhysicalDevice = physDev;
297 ctx->fDevice = device;
298 ctx->fQueue = queue;
jvanverthb0d43522016-04-21 11:46:23 -0700299 ctx->fGraphicsQueueIndex = graphicsQueueIndex;
jvanverthfd7bd452016-03-25 06:29:52 -0700300 ctx->fMinAPIVersion = kGrVkMinimumVersion;
301 ctx->fExtensions = extensionFlags;
302 ctx->fFeatures = featureFlags;
Michael Jurka3251ed82017-04-05 09:52:55 -0700303 ctx->fInterface.reset(interface.release());
Brian Salomon290c6902017-04-25 15:03:41 -0400304 ctx->fOwnsInstanceAndDevice = true;
halcanary9d524f22016-03-29 09:03:52 -0700305
jvanverth633b3562016-03-23 11:01:22 -0700306 return ctx;
307}
308
309GrVkBackendContext::~GrVkBackendContext() {
Brian Salomon290c6902017-04-25 15:03:41 -0400310 if (fInterface == nullptr || !fOwnsInstanceAndDevice) {
Michael Jurka3251ed82017-04-05 09:52:55 -0700311 return;
312 }
313
314 fInterface->fFunctions.fDeviceWaitIdle(fDevice);
315 fInterface->fFunctions.fDestroyDevice(fDevice, nullptr);
jvanverth633b3562016-03-23 11:01:22 -0700316 fDevice = VK_NULL_HANDLE;
Michael Jurka3251ed82017-04-05 09:52:55 -0700317 fInterface->fFunctions.fDestroyInstance(fInstance, nullptr);
jvanverth633b3562016-03-23 11:01:22 -0700318 fInstance = VK_NULL_HANDLE;
319}